Skip to content

fix(monitoring): strip infrastructure metadata from tenant logs - #2196

Merged
myasnikovdaniil merged 1 commit into
cozystack:mainfrom
mattia-eleuteri:monitoring/strip-infra-metadata
Sep 4, 2026
Merged

myasnikovdaniil merged 1 commit into
cozystack:mainfrom
mattia-eleuteri:monitoring/strip-infra-metadata

Conversation

@mattia-eleuteri

@mattia-eleuteri mattia-eleuteri commented Mar 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a modify filter in fluent-bit that removes kubernetes_node_name and kubernetes_host from all container logs
  • Prevents infrastructure topology (node names, hosts) from leaking to tenant users

Problem

kubernetes_node_name is exposed in log metadata, leaking node topology to end-users. Other sensitive fields like kubernetes_host are also visible.

Relates to #2194

Test plan

  • helm template monitoring-agents and verify Remove kubernetes_node_name filter is present
  • Deploy and verify kubernetes_node_name is absent from logs in tenant Grafana
Strip infrastructure metadata (node name, host) from tenant logs

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Improved Kubernetes monitoring log processing by filtering out most kubernetes_* fields for kube.* events, while preserving the key Kubernetes identity fields (such as pod, namespace, and container-related names) for clearer, more consistent log output.

@coderabbitai

coderabbitai Bot commented Mar 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Two new Fluent Bit modify filter blocks are added to the monitoring-agents values file, targeting Kubernetes-related logs (kube.*). The first filter temporarily preserves specific kubernetes_* name fields (pod, namespace, container) by renaming them with a keep_ prefix. The second filter removes all remaining kubernetes_ wildcard fields and then restores the preserved fields to their original names, effectively filtering which Kubernetes metadata is retained.

Changes

Fluent Bit Filter Configuration

Layer / File(s) Summary
Kubernetes field preservation and cleanup filters
packages/system/monitoring-agents/values.yaml
Two [FILTER] modify blocks are added for kube.\* logs to preserve specific Kubernetes name fields (pod, namespace, container) while removing other kubernetes_ wildcard fields from events.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 Two filters dance, a careful waltz,
Keep the names, remove the vaults,
Kubernetes fields pruned just right,
Clean logs flowing through the night! 🌙

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the change to remove infrastructure metadata from tenant logs.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dosubot dosubot Bot added the size/XS This PR changes 0-9 lines, ignoring generated files label Mar 10, 2026
@dosubot dosubot Bot added the kind/feature Categorizes issue or PR as related to a new feature label Mar 10, 2026
@mattia-eleuteri
mattia-eleuteri force-pushed the monitoring/strip-infra-metadata branch from 7dbdcd4 to d70e4c3 Compare March 10, 2026 15:58

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOT LGTM — one of the two stripped fields doesn't exist in this pipeline, and the two-field block-list doesn't fully meet the stated goal.

Business context: stop tenants from seeing infrastructure topology (which node a pod ran on) in their container logs, by stripping fields in the fluent-bit pipeline.

Blockers

B1: Remove kubernetes_node_name is a no-op — the field never exists here

File: packages/system/monitoring-agents/values.yaml:429

The fluent-bit Kubernetes filter emits the node name as host, not node_name. The nest/lift at lines 385-391 promotes the whole kubernetes map to top-level kubernetes_*, so the real field is kubernetes_host. The kubernetes filter (lines 378-384) runs with defaults (no Use_Kubelet On), so no node_name is ever produced — nothing in the log pipeline emits it. Remove kubernetes_host does the work; Remove kubernetes_node_name silently does nothing. Drop the dead line, or identify the config that actually produces kubernetes_node_name and explain it.

B2: a two-field block-list doesn't meet "strip infrastructure metadata"

File: packages/system/monitoring-agents/values.yaml:426-430

The lift promotes the entire kubernetes map, so removing only host leaves other lifted infra fields tenant-visible (e.g. kubernetes_docker_id, kubernetes_container_image, kubernetes_annotations, kubernetes_pod_id). A block-list also silently leaks any field a future fluent-bit upgrade adds. The OUTPUT only streams kubernetes_pod_name, kubernetes_container_name, kubernetes_namespace_name (the _stream_fields allow-list at line 350), so prefer an allow-list — keep just those three — over block-listing individual fields.

Non-blocking

  1. Two near-duplicate Signed-off-by trailers for the same email (different display name) — collapse to one before merge.
  2. No coverage: a rendered-ConfigMap assertion that Remove kubernetes_host is present and no kubernetes_node_name line is emitted would pin the real behavior (chart ships no helm-unittest, and this is a vendored-subchart values file so per-chart unit tests aren't the norm here — not blocking on that alone).

[FILTER]
Name modify
Match kube.*
Remove kubernetes_node_name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is a no-op — kubernetes_node_name never exists in this pipeline. The Kubernetes filter emits the node name as host (lifted to kubernetes_host by the nest/lift above), and it runs with defaults (no Use_Kubelet On), so nothing produces a node_name field. Remove kubernetes_host below does the actual work. Drop this line, or point to the config that produces kubernetes_node_name.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, confirmed — kubernetes_node_name is never produced in this pipeline. The kubernetes filter runs with defaults (no Use_Kubelet On) so it emits the node name as host, which the nest/lift above promotes to kubernetes_host. The Remove kubernetes_node_name line was a no-op based on a wrong field-name assumption.

Dropped it in 61fb19d — only Remove kubernetes_host remains, which does the actual stripping. Thanks!

@github-actions github-actions Bot added area/monitoring Issues or PRs related to the monitoring stack (vlogs, vmstack, grafana, workloadmonitor) size/S This PR changes 10-29 lines, ignoring generated files and removed size/XS This PR changes 0-9 lines, ignoring generated files labels Jun 16, 2026
@mattia-eleuteri

Copy link
Copy Markdown
Collaborator Author

Addressed the review across two commits (61fb19d, 8977ca6):

B1 — Remove kubernetes_node_name no-op: confirmed and dropped. The kubernetes filter runs with defaults (no Use_Kubelet On) and emits the node name as host, which the nest/lift promotes to kubernetes_host; nothing ever produces node_name.

B2 — block-list insufficient: reworked into an allow-list. One clarification on the premise: _stream_fields in the VictoriaLogs output only defines the stream labels, not a stored-field projection — every field in the JSON line is ingested and tenant-visible regardless. So the leak was actually broader than host (docker_id, container_image, annotations, pod_id, container_hash, ...), which makes the filter-level allow-list the right fix.

I scoped the allow-list to the kubernetes_ prefix rather than a record-level Allowlist_key, because the pipeline runs Merge_Log On and a whole-record allow-list would also strip tenants' own merged JSON log fields. Implementation: rename the three keepers (kubernetes_pod_name, kubernetes_namespace_name, kubernetes_container_name) out of the way, Remove_wildcard kubernetes_, then rename them back. Any future kubernetes_* field is dropped by default. Verified the rendered ConfigMap with helm template.

Non-blocking 1 — duplicate Signed-off-by: noted, only on the first commit. I'll collapse it on a pre-merge rebase (or it folds away on a squash-merge) — can force-push the cleanup now if you'd rather have it resolved immediately.

Non-blocking 2 — test coverage: skipping per your own note that this is a vendored-subchart values file where per-chart helm-unittest isn't the norm here. Happy to add a rendered-ConfigMap assertion if you'd like it after all.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both prior blockers are resolved and the approach is now correct. B1: the dead Remove kubernetes_node_name line is gone — nothing in this pipeline ever produced that field. B2: the two-field block-list is replaced by a prefix-scoped allow-list — rename the three keepers out of the way, Remove_wildcard kubernetes_, then rename them back — so only kubernetes_pod_name, kubernetes_namespace_name and kubernetes_container_name survive, matching the OUTPUT _stream_fields, and any future kubernetes_* field is dropped by default. Scoping the new filters to kube.* and the wildcard to the kubernetes_ prefix leaves merged application-log fields (Merge_Log On) and the events/audit streams untouched, so there is no regression.

Non-blocking: the first commit still carries two Signed-off-by trailers for the same email, and the branch is three commits where the last two just fix the first — since this repo merges without squashing, please rebase into one clean commit before merge so the duplicate trailer and the iteration history don't land in main.

@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the monitoring/strip-infra-metadata branch from 8977ca6 to 2052e53 Compare July 3, 2026 16:14
@lexfrei

Copy link
Copy Markdown
Contributor

This is code-approved and CI is green now, but one thing before it can merge: the branch is three commits where the last two only fix the first, and that first commit carries a duplicate Signed-off-by trailer. Since this repo merges without squashing, please rebase it into a single clean commit so the iteration history and the duplicate trailer don't land on main. After that it's good to go.

Allow-list the kubernetes_ fields kept on kube.* records so that
infrastructure topology (node name, host) no longer leaks to tenant
users, while preserving pod/namespace/container identity fields.

Relates to cozystack#2194

Signed-off-by: Mattia Eleuteri <[email protected]>
@mattia-eleuteri mattia-eleuteri changed the title [monitoring] Strip infrastructure metadata from tenant logs fix(monitoring): strip infrastructure metadata from tenant logs Jul 9, 2026
@mattia-eleuteri
mattia-eleuteri force-pushed the monitoring/strip-infra-metadata branch from 2052e53 to 0356cde Compare July 9, 2026 07:20
@github-actions github-actions Bot added the kind/bug Categorizes issue or PR as related to a bug label Jul 9, 2026
@mattia-eleuteri

Copy link
Copy Markdown
Collaborator Author

Squashed to a single clean commit (one Signed-off-by) and rebased onto current main; title moved to Conventional Commits as well.

Heads-up on CI: after the rebase, Pre-Commit and the new API Review Gate pass, but every Build <pkg> job on this and our other fork PRs fails in ~20s pushing to iad.ocir.io with denied: Anonymous users are only allowed read access on public repos, e.g. this Build Talos job. Looks like the registry credentials aren't available to pull_request runs from forks, so these PRs can't go green regardless of rebasing — needs a fix (or an override) on your side.

@myasnikovdaniil
myasnikovdaniil merged commit b7e5100 into cozystack:main Sep 4, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/monitoring Issues or PRs related to the monitoring stack (vlogs, vmstack, grafana, workloadmonitor) kind/bug Categorizes issue or PR as related to a bug kind/feature Categorizes issue or PR as related to a new feature size/S This PR changes 10-29 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants