Repository navigation
feat(chart): one logs.collection switch sends container logs to ClickHouse and reports it - #670
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new configuration option logs.collection to the Helm chart to manage container log collection modes (none or node-agent). It adds validation logic in _helpers.tpl to ensure proper configuration when node-agent is selected, updates the daemonset to set the appropriate log endpoint and node name, and propagates the collection status (ClickHouseLogsCollected) through the runner agent's configuration and telemetry. The review feedback suggests robustly handling cases where logs is defined as a flat string in the Helm values, avoiding redundant nil guards for nodeAgent in the helper template, and safely accessing nodeAgent properties in the daemonset template to prevent potential nil pointer errors.
mayankpande88
left a comment
There was a problem hiding this comment.
The chart and runner side looks right:
logs.collectionvalidates its value and fails with a clear message for each unsupported setup.- The runner reports
clickhouseLogsCollectedfrom the switch only. - The key is sent on every heartbeat, so
falseoverwrites a staletrue.
Three things before merge:
- Blocked on nudgebee/node-agent#405. That PR is still open and
nodeAgent.image.tagisn't bumped here. As the description says, without it the log rows have no namespace or pod labels. Order: merge and release #405, then bump the tag in this PR, then merge this. NODE_NAMEis added in every mode. TheNODE_NAMEblock indaemonset.yamlsits outside thenode-agentmode check, so every install gets a changed node-agent pod spec. Every cluster's node-agent DaemonSet then restarts on upgrade, including clusters onnone. If only the log exporter needs it, gate it oneq (include "nudgebee-agent.logsCollection" .) "node-agent". If the restart is intended, say so in the description.- Disk. All container stdout lands on the same 50Gi ClickHouse volume, with the same 168h TTL as traces, and nothing filters it. On a busy cluster, logs can fill the disk, and then trace ingestion stops too. That risk is listed, but before this mode gets turned on for real clusters, add an exclude list (at least
kube-systemand the agent's own namespace) or a separate, shorter logs TTL. A follow-up is fine if you track it.
cd58956 to
ebd49a3
Compare
|
@mayankpande88 thanks. Updated in ebd49a3, rebased on main and still one commit.
|
…House and reports it logs.collection picks where a cluster's container logs are collected, one mode per cluster: none (default, as before) or node-agent. node-agent points the node-agent's log push at the bundled OpenTelemetry collector, whose logs pipeline already writes to ClickHouse, and gives the runner CLICKHOUSE_LOGS_COLLECTED, which it reports as clickhouseLogsCollected (always sent, so false overwrites a stale true). The flag comes from the switch only, so it can't say logs are collected where the chart doesn't collect them. The render fails for node-agent without the collector or the node-agent, or with a LOGS_ENDPOINT of the operator's own (nodeAgent.logsEndpoint or nodeAgent.env: two sources), for the reserved otel-daemonset, and for unknown values. An empty or missing value (--reuse-values from an older release) means none. In node-agent mode the node-agent also gets NODE_NAME from spec.nodeName for its k8s.node.name, unless nodeAgent.env already sets it. Only the log push reads it, so other modes render the node-agent pod spec as before and an upgrade doesn't restart the node-agents. The collector's logs pipeline drops records from kube-system and the release namespace (filter/drop_log_namespaces), so their logs don't fill the ClickHouse disk that traces also use. In none mode nothing in the chart sends logs there, but the collector's config changes, so it restarts once on upgrade.
ebd49a3 to
811a75b
Compare
Summary
One values key,
logs.collection, chooses where a cluster's container logs are collected:none(default): nothing changes, apart from one collector restart on upgrade.node-agent: the node-agent ships container stdout/stderr through the bundled OpenTelemetry collector into ClickHouse, except fromkube-systemand the agent's own namespace, and the heartbeat reportsclickhouseLogsCollected: true.The flag comes only from the switch, so it can't claim logs the chart doesn't collect (follow-up 1 from the #660 review).
Before merge: bump
nodeAgent.image.tagto the release with nudgebee/node-agent#405, which adds the namespace/pod/container labels.How to verify
clickhouseLogsCollected: false, and the node-agent pod spec is unchanged (noLOGS_ENDPOINTorNODE_NAME), so node-agents don't restart.--set logs.collection=node-agent: the node-agent getsLOGS_ENDPOINT(the bundled collector) andNODE_NAME, the heartbeat reportstrue, andotel_logsfills with pod logs, none fromkube-systemor the release namespace.LOGS_ENDPOINT, the render fails and names the fix.Risks
Type of change
Chart version
versionincharts/nudgebee-agent/Chart.yaml(0.1.30; feat(chart,runner): query_data reads through a read-only ClickHouse user with query limits #671 took 0.1.29)Test plan
helm lint/ct lint(CI)helm templateoutput reviewed; the newhelm-dev-lintstep asserts each mode (an empty value included), each refusal,NODE_NAMEonly innode-agent, and the namespace filter in the logs pipelineRelated issues
Details
filter/drop_log_namespaces, so the collector restarts once on upgrade in every mode; the subchart's config is plain values, so the filter can't follow the mode. Innoneit drops onlykube-systemand release-namespace logs an operator sends the collector themselves (e.g.nodeAgent.logsEndpointpointed at it).--reuse-valuesfrom an older release keeps that release's collector config, without the filter. Use--reset-then-reuse-values(Helm 3.14+) or pass the values file.ttlfor all its tables and applies it only when it creates them.nudgebee-agent.logsCollectionvalidates the value. The runner template always calls it, so a bad value fails even with the node-agent off.otel-daemonsetis reserved and fails with "not available yet".--reuse-valuesfrom an older release) meansnone.nodeAgent.logsEndpointundernonestill works, but nothing reports it as collected.node-agentmode only, the node-agent getsNODE_NAMEfromspec.nodeName, unlessnodeAgent.envalready sets it. With defaults, withnone, and withnoneplusnodeAgent.logsEndpoint, the node-agent DaemonSet's.specrenders byte-identical to main's.filter/drop_log_namespacesaftermemory_limiter. It drops records whosek8s.namespace.nameiskube-systemor the release namespace; the subchart fills in{{ .Release.Namespace }}. Checked withotelcol-contrib validate(0.157.0). In a local run of that collector with the rendered config, of logs sent fromkube-system, the release namespace,shopand no namespace, onlyshopand the unlabelled one came out.CLICKHOUSE_LOGS_COLLECTEDbecomesclickhouseLogsCollectedon the heartbeat. It is always sent, sofalseoverwrites a staletrue.go test -race ./...), again after the rebase onto feat(chart,runner): query_data reads through a read-only ClickHouse user with query limits #671, as did everyhelm-dev-lintstep (this PR's and feat(chart,runner): query_data reads through a read-only ClickHouse user with query limits #671's read-only user step).checkoutin namespaceshopwrote to stdout and stderr.LOGS_ENDPOINT=http://nudgebee-agent-opentelemetry-collector:4318/v1/logs,NODE_NAMEfromspec.nodeNameCLICKHOUSE_LOGS_COLLECTED=trueclickhouseLogsCollected: true,clickhouseLogsConnection: true,clickhouseLogsTable: default.otel_logsotel_logsrows by namespace (before the namespace filter)shop42,nudgebee-agent28,kube-system11shopstderr lineshop, podcheckout-…, containerapp,k8s.deployment.name=checkout,log.iostream=stderr, time =kubectl logs --timestampsto the ns