Skip to content

feat(talos-log-collector): add talos-log-collector package - #3260

Open
IvanHunters wants to merge 12 commits into
mainfrom
feat/talos-log-collector
Open

feat(talos-log-collector): add talos-log-collector package#3260
IvanHunters wants to merge 12 commits into
mainfrom
feat/talos-log-collector

Conversation

@IvanHunters

@IvanHunters IvanHunters commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds talos-log-collector, an optional system package: a node-local Vector
DaemonSet that receives Talos machine and kernel logs and forwards them to the
tenant VictoriaLogs (vlinsert), alongside the container/audit/event logs
already collected by monitoring-agents.

Talos keeps system and kernel (kmsg) logs inside the OS and does not write them
to a host file the Fluent Bit tail input could read, so these logs are
currently never collected. Vector receives them over the node loopback
(Talos pushes to 127.0.0.1:5170). Talos exposes the two streams through
independent config paths, and both must point at the loopback socket:
machine.logging.destinations forwards the JSON-lines service logs, and a
KmsgLogConfig document forwards the kernel (kmsg) stream (including DRBD
kmsg). The node-side setup for both is in the README.

Design notes:

  • The pod stays on the pod network so cluster DNS resolves vlinsert with no
    extra config. Talos pushes to 127.0.0.1:5170; a hostPort bound to
    hostIP: 127.0.0.1 publishes that loopback socket into the pod via portmap,
    keeping the receiver off the host network (no node-wide pod exposure).
  • The receiver binds inside the pod netns, so a NetworkPolicy is load-bearing:
    a CiliumNetworkPolicy restricts ingress to the host entity when Cilium is
    present, otherwise a default-deny-ingress networking.k8s.io/v1 fallback
    keeps the socket protected on non-Cilium variants.
  • Runs non-root, read-only root filesystem, all capabilities dropped.
  • Optional package (opt-in via bundles.enabledPackages): inert until each
    Talos node is configured to push logs. Node-side setup is in the README.

Verified end-to-end on a Talos v1.12 dev cluster: service and kernel logs
(including DRBD kmsg) reach VictoriaLogs; pods run non-root with 0 restarts.

Release note

feat(talos-log-collector): add talos-log-collector package to collect Talos machine and kernel logs into VictoriaLogs

Summary by CodeRabbit

  • New Features
    • Added an optional node-local Talos log collector (via system bundle packages) that forwards Talos service and kernel logs over loopback to the platform log ingestion endpoint.
    • Introduced the collector Helm chart (Vector-based) with configurable log level, loopback TCP receive port, digest-pinned image, default resources, and routing target.
    • Added conditional Cilium network policy support with a safe deny-by-default fallback.
  • Security
    • Hardened the collector to run non-root with reduced privileges, read-only filesystem, and dropped Linux capabilities (and disabled service account token automount).
  • Documentation
    • Documented configuration requirements (including kernel log enablement), operational behavior, and teardown steps.
  • Build & Release
    • Extended the build to include building the collector’s image.
  • Tests
    • Added Helm rendering/contract tests covering daemonset, configmap, service account, and network policy.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a Talos log collector system package using a Vector DaemonSet. It includes Helm resources, configurable values and schema, rendered-template tests, documentation, a mirrored image, and platform/build integration.

Changes

Talos Log Collector Package

Layer / File(s) Summary
Platform source and bundle wiring
Makefile, packages/core/platform/sources/..., packages/core/platform/templates/bundles/system.yaml
Build now includes the collector image; the package is registered as a platform source and exposed through the optional system bundle.
Chart packaging and image build
packages/system/talos-log-collector/Chart.yaml, packages/system/talos-log-collector/Makefile, packages/system/talos-log-collector/images/vector/Dockerfile
Defines chart metadata, package automation targets, and a mirrored Vector image Dockerfile.
Collector runtime templates
packages/system/talos-log-collector/templates/*
Adds the Vector pipeline, DaemonSet, loopback host port, VictoriaLogs sink, service account, network policies, scheduling, and hardened security settings.
Values and rendered template validation
packages/system/talos-log-collector/values.yaml, packages/system/talos-log-collector/values.schema.json, packages/system/talos-log-collector/tests/*
Defines configurable defaults and schema validation, with tests covering rendering, routing, ports, resources, security, liveness, and ingress policy.
Package documentation
packages/system/talos-log-collector/README.md
Documents architecture, Talos logging configuration, operational behavior, teardown, and parameters.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Talos
  participant Vector
  participant VictoriaLogs
  Talos->>Vector: Send JSON logs to 127.0.0.1:5170
  Vector->>VictoriaLogs: POST compressed NDJSON to vlinsert-generic
Loading

Possibly related PRs

  • cozystack/cozystack#1316: Updates related Makefile flows to use cozyvalues-gen, matching the new package’s values-generation target.

Suggested labels: area/networking

Suggested reviewers: kvaps

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding the talos-log-collector package.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/talos-log-collector

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.

@github-actions github-actions Bot added area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review kind/feature Categorizes issue or PR as related to a new feature size/L This PR changes 100-499 lines, ignoring generated files labels Jul 9, 2026
@IvanHunters
IvanHunters force-pushed the feat/talos-log-collector branch from bddc1d5 to cf184fe Compare July 9, 2026 14:28
@github-actions github-actions Bot added size/XL This PR changes 500-999 lines, ignoring generated files and removed size/L This PR changes 100-499 lines, ignoring generated files labels Jul 9, 2026
@IvanHunters
IvanHunters marked this pull request as ready for review July 9, 2026 14:48
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request adds the talos-log-collector system package to the platform. The collector fills a gap in log visibility by capturing Talos machine and kernel logs that are not otherwise accessible to standard monitoring agents. It utilizes a node-local Vector instance that receives logs over the loopback interface and forwards them to VictoriaLogs, ensuring secure and efficient log aggregation while maintaining strict security practices such as non-root execution and network ingress restrictions.

Highlights

  • New Package Addition: Introduced the talos-log-collector package, a node-local Vector DaemonSet designed to collect Talos machine and kernel logs.
  • Log Forwarding: Configured the collector to forward logs to the in-cluster VictoriaLogs (vlinsert) service.
  • Security and Network: Implemented a CiliumNetworkPolicy to restrict ingress to the host entity and configured the pod to run with a read-only root filesystem and dropped capabilities.
  • Integration: Added the package to the system bundle and updated the Makefile to support image building for the new component.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot Bot added the area/platform Issues or PRs related to platform infrastructure (bundle, flux, talos, installer) label Jul 9, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/system/talos-log-collector/tests/talos-log-collector_test.yaml (1)

88-102: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding test coverage for ServiceAccount and CiliumNetworkPolicy.

The suite covers the receive/forward wiring well, but the ServiceAccount (disabled token automount) and CiliumNetworkPolicy (ingress restricted to host entity) are security-relevant templates with no test coverage. A separate test suite or expanded suite-level templates: list would guard these against regression.

💡 Suggested additional test cases
+  - it: "ServiceAccount has token automount disabled"
+    template: templates/serviceaccount.yaml
+    asserts:
+      - equal:
+          path: automountServiceAccountToken
+          value: false
+
+  - it: "CiliumNetworkPolicy restricts ingress to host entity on listen port"
+    template: templates/networkpolicy.yaml
+    asserts:
+      - hasDocuments:
+          count: 1
+      - matchRegex:
+          path: spec.ingresss[0].toPorts[0].ports[0].port
+          pattern: "5170"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/tests/talos-log-collector_test.yaml`
around lines 88 - 102, Add test coverage for the security-relevant templates
that are currently untested: the ServiceAccount should assert token automount is
disabled, and the CiliumNetworkPolicy should assert ingress is restricted to the
host entity. Update the talos-log-collector test suite in
talos-log-collector_test.yaml by either expanding the suite-level templates list
or adding a separate suite that targets the ServiceAccount and
CiliumNetworkPolicy templates, using their template names to keep the checks
stable against refactors.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/system/talos-log-collector/README.md`:
- Around line 65-66: Update the resources table in README so the `resources.cpu`
entry matches `daemonset.yaml`: it is request-only, not request-and-limit. Keep
the `resources.memory` description unchanged, and make sure the wording for
`resources.cpu` reflects the actual behavior of the `resources` settings in
`packages/system/talos-log-collector/templates/daemonset.yaml`.

---

Nitpick comments:
In `@packages/system/talos-log-collector/tests/talos-log-collector_test.yaml`:
- Around line 88-102: Add test coverage for the security-relevant templates that
are currently untested: the ServiceAccount should assert token automount is
disabled, and the CiliumNetworkPolicy should assert ingress is restricted to the
host entity. Update the talos-log-collector test suite in
talos-log-collector_test.yaml by either expanding the suite-level templates list
or adding a separate suite that targets the ServiceAccount and
CiliumNetworkPolicy templates, using their template names to keep the checks
stable against refactors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 35325edd-dd66-4e0f-9c52-c7e9ab51d4f9

📥 Commits

Reviewing files that changed from the base of the PR and between 6b1e170 and cf184fe.

📒 Files selected for processing (15)
  • Makefile
  • packages/core/platform/sources/talos-log-collector.yaml
  • packages/core/platform/templates/bundles/system.yaml
  • packages/system/talos-log-collector/Chart.yaml
  • packages/system/talos-log-collector/Makefile
  • packages/system/talos-log-collector/README.md
  • packages/system/talos-log-collector/images/vector/Dockerfile
  • packages/system/talos-log-collector/templates/_helpers.tpl
  • packages/system/talos-log-collector/templates/configmap.yaml
  • packages/system/talos-log-collector/templates/daemonset.yaml
  • packages/system/talos-log-collector/templates/networkpolicy.yaml
  • packages/system/talos-log-collector/templates/serviceaccount.yaml
  • packages/system/talos-log-collector/tests/talos-log-collector_test.yaml
  • packages/system/talos-log-collector/values.schema.json
  • packages/system/talos-log-collector/values.yaml

Comment thread packages/system/talos-log-collector/README.md Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces the talos-log-collector package, which deploys a node-local Vector DaemonSet to collect Talos machine and kernel logs and forward them to VictoriaLogs. The feedback suggests using the dig function in the ConfigMap template to safely access .Values.global.target and avoid nil pointer errors, updating the PR scope to comply with the repository's conventional commit guidelines, and adding the CriticalAddonsOnly toleration to the DaemonSet to ensure proper scheduling on control-plane nodes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

victorialogs:
type: http
inputs: [tag]
uri: "http://vlinsert-generic.{{ .Values.global.target }}.svc:9481/insert/jsonline?_stream_fields=node,log_source,talos-service,facility&_msg_field=msg&_time_field=talos-time"

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.

medium

Directly accessing .Values.global.target can cause a nil pointer evaluation error if .Values.global is overridden or not defined in the parent chart or values. Using the Sprig dig function provides a safe fallback and prevents template rendering failures.

        uri: "http://vlinsert-generic.{{ dig \"global\" \"target\" \"tenant-root\" .Values }}.svc:9481/insert/jsonline?_stream_fields=node,log_source,talos-service,facility&_msg_field=msg&_time_field=talos-time"

Comment on lines +1 to +5
---
apiVersion: cozystack.io/v1alpha1
kind: PackageSource
metadata:
name: cozystack.talos-log-collector

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.

low

The PR title and release note block use the scope system (e.g., feat(system): ...). According to the Cozystack Review Guidelines, system is not a valid scope. Please update the PR title and release note to use a valid scope, such as the package-specific scope talos-log-collector or platform.

References
  1. Each commit must follow Conventional Commits format: type(scope): brief description. Valid scopes include package-specific scopes matching a directory under packages/. (link)

Comment on lines +70 to +74
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists

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.

low

For system-critical DaemonSets running on all nodes, it is recommended to explicitly tolerate the CriticalAddonsOnly taint. This ensures the log collector can schedule and run on control-plane nodes that have this taint applied.

      tolerations:
      - effect: NoSchedule
        operator: Exists
      - effect: NoExecute
        operator: Exists
      - key: CriticalAddonsOnly
        operator: Exists

@IvanHunters
IvanHunters force-pushed the feat/talos-log-collector branch from cf184fe to 0513194 Compare July 9, 2026 15:19

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
packages/system/talos-log-collector/templates/daemonset.yaml (1)

35-69: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider adding a liveness probe for the system-node-critical DaemonSet.

Without a livenessProbe, Kubernetes cannot detect a hung Vector process. A TCP probe on the listen port is a minimal safeguard; enabling Vector's internal API for an HTTP health check would be more thorough.

♻️ Suggested liveness probe
         args: ["--config", "/etc/vector/vector.yaml"]
+        livenessProbe:
+          tcpSocket:
+            port: talos
+          initialDelaySeconds: 10
+          periodSeconds: 30
         env:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/templates/daemonset.yaml` around lines 35
- 69, Add a livenessProbe to the DaemonSet container in the vector template so
Kubernetes can detect a hung Vector process. Use the existing VECTOR listener
port on the vector container (the same listenPort/hostPort target) and wire it
into the containers spec near the current ports/resources settings. If you
choose a more thorough check later, enable Vector’s internal API and switch to
an HTTP health probe, but for now a TCP probe is the minimal fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/system/talos-log-collector/templates/daemonset.yaml`:
- Around line 35-69: Add a livenessProbe to the DaemonSet container in the
vector template so Kubernetes can detect a hung Vector process. Use the existing
VECTOR listener port on the vector container (the same listenPort/hostPort
target) and wire it into the containers spec near the current ports/resources
settings. If you choose a more thorough check later, enable Vector’s internal
API and switch to an HTTP health probe, but for now a TCP probe is the minimal
fix.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ac821759-03db-45f1-81ad-6c592bafb079

📥 Commits

Reviewing files that changed from the base of the PR and between cf184fe and 0513194.

📒 Files selected for processing (15)
  • Makefile
  • packages/core/platform/sources/talos-log-collector.yaml
  • packages/core/platform/templates/bundles/system.yaml
  • packages/system/talos-log-collector/Chart.yaml
  • packages/system/talos-log-collector/Makefile
  • packages/system/talos-log-collector/README.md
  • packages/system/talos-log-collector/images/vector/Dockerfile
  • packages/system/talos-log-collector/templates/_helpers.tpl
  • packages/system/talos-log-collector/templates/configmap.yaml
  • packages/system/talos-log-collector/templates/daemonset.yaml
  • packages/system/talos-log-collector/templates/networkpolicy.yaml
  • packages/system/talos-log-collector/templates/serviceaccount.yaml
  • packages/system/talos-log-collector/tests/talos-log-collector_test.yaml
  • packages/system/talos-log-collector/values.schema.json
  • packages/system/talos-log-collector/values.yaml
✅ Files skipped from review due to trivial changes (3)
  • packages/system/talos-log-collector/templates/_helpers.tpl
  • packages/system/talos-log-collector/values.yaml
  • packages/system/talos-log-collector/README.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/core/platform/sources/talos-log-collector.yaml
  • packages/system/talos-log-collector/Chart.yaml
  • packages/system/talos-log-collector/values.schema.json
  • Makefile
  • packages/system/talos-log-collector/images/vector/Dockerfile
  • packages/core/platform/templates/bundles/system.yaml
  • packages/system/talos-log-collector/tests/talos-log-collector_test.yaml

@sircthulhu

Copy link
Copy Markdown
Contributor

I think we should use already existing package monitoring-agents and add opt-in (default disabled) parameter to enable enpoints for accepting talos jsonlines logs.

Additionaly, I don't think using vector is justified. It's another technology and possible new problems. On the other hand, using fluent-bit would be more straight-forward and we'd know what to expect.

Add a node-local Vector DaemonSet that receives Talos machine and kernel
logs (pushed via machine.logging over the node loopback) and forwards them
to the tenant VictoriaLogs. Talos keeps its system and kernel logs inside
the OS and does not expose them as host files, so the tail-based Fluent Bit
in monitoring-agents never collects them.

The receiver stays on the pod network so cluster DNS resolves the vlinsert
service, and accepts Talos logs via a hostPort bound to hostIP 127.0.0.1,
avoiding the host-network DNS breakage a hostNetwork receiver would hit.
Shipped as an optional system package.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
@IvanHunters
IvanHunters force-pushed the feat/talos-log-collector branch from 0513194 to 1fb4bcf Compare July 10, 2026 12:34

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (3)
packages/system/talos-log-collector/tests/talos-log-collector_test.yaml (2)

41-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Tolerations test only covers NoSchedule; NoExecute is unverified.

The suite comment states "runs on every node (tolerate everything)" but the assertion only checks the NoSchedule toleration. The DaemonSet template also includes a NoExecute toleration. Adding an assertion for it would complete the coverage claim.

♻️ Suggested additional assertion
       - contains:
           path: spec.template.spec.tolerations
           content:
             effect: NoSchedule
             operator: Exists
+      - contains:
+          path: spec.template.spec.tolerations
+          content:
+            effect: NoExecute
+            operator: Exists
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/tests/talos-log-collector_test.yaml`
around lines 41 - 51, Add an assertion to the “runs on every node and is
node-critical” test verifying that the DaemonSet tolerations also include
effect: NoExecute with operator: Exists, alongside the existing NoSchedule
assertion.

20-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a digest-pinning assertion for the image.

The regex verifies the first-party repository but doesn't assert that the image is digest-pinned (sha256:). Other system packages in the repo use patterns like vector:.+sha256: to enforce immutability without coupling to a specific digest. A separate assertion would guard against accidental non-pinned tags.

Based on learnings, in the cozystack/cozystack repo it is acceptable and intentional for image-pin assertions to use tag/digest-agnostic regexes that verify digest pinning (e.g., :.+sha256:) rather than a specific full digest value.

♻️ Suggested additional assertion
   - it: "DaemonSet pulls the first-party vector image from the cozystack registry"
     template: templates/daemonset.yaml
     asserts:
       - isKind:
           of: DaemonSet
       - matchRegex:
           path: spec.template.spec.containers[0].image
           pattern: "^ghcr\\.io/cozystack/cozystack/vector:"
+      - matchRegex:
+          path: spec.template.spec.containers[0].image
+          pattern: "sha256:"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/tests/talos-log-collector_test.yaml`
around lines 20 - 27, Add a separate matchRegex assertion for
spec.template.spec.containers[0].image in the DaemonSet test, using a pattern
such as `:.+sha256:` to require a digest-pinned image while remaining
independent of the specific digest.

Source: Learnings

packages/system/talos-log-collector/templates/daemonset.yaml (1)

35-69: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider adding a liveness probe for hang detection.

No liveness probe is configured. If Vector hangs (e.g., deadlock or resource exhaustion), the pod stays Running but silently stops collecting logs — particularly impactful for a system-node-critical DaemonSet. Enabling Vector's built-in health endpoint and adding an HTTP liveness probe is a small change with significant reliability benefit.

💡 Proposed liveness probe addition

In configmap.yaml, enable the Vector API (bound to loopback so it's not exposed to other pods):

     data_dir: /vector-data
+    api:
+      enabled: true
+      address: 127.0.0.1:52000
     sources:

In daemonset.yaml, add the probe:

         args: ["--config", "/etc/vector/vector.yaml"]
+        livenessProbe:
+          httpGet:
+            path: /health
+            port: 52000
+            host: 127.0.0.1
+          initialDelaySeconds: 10
+          periodSeconds: 30
         env:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/templates/daemonset.yaml` around lines 35
- 69, Add Vector’s built-in health API configuration to the chart’s configmap
and add an HTTP liveness probe to the vector container in the DaemonSet,
targeting the loopback API health endpoint and the configured listen port.
Ensure the probe uses appropriate delay, timeout, and failure thresholds without
exposing the API beyond the node.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/system/talos-log-collector/templates/daemonset.yaml`:
- Around line 35-69: Add Vector’s built-in health API configuration to the
chart’s configmap and add an HTTP liveness probe to the vector container in the
DaemonSet, targeting the loopback API health endpoint and the configured listen
port. Ensure the probe uses appropriate delay, timeout, and failure thresholds
without exposing the API beyond the node.

In `@packages/system/talos-log-collector/tests/talos-log-collector_test.yaml`:
- Around line 41-51: Add an assertion to the “runs on every node and is
node-critical” test verifying that the DaemonSet tolerations also include
effect: NoExecute with operator: Exists, alongside the existing NoSchedule
assertion.
- Around line 20-27: Add a separate matchRegex assertion for
spec.template.spec.containers[0].image in the DaemonSet test, using a pattern
such as `:.+sha256:` to require a digest-pinned image while remaining
independent of the specific digest.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4f6d193b-785b-41b2-99cd-1df5f125107f

📥 Commits

Reviewing files that changed from the base of the PR and between 0513194 and 1fb4bcf.

📒 Files selected for processing (15)
  • Makefile
  • packages/core/platform/sources/talos-log-collector.yaml
  • packages/core/platform/templates/bundles/system.yaml
  • packages/system/talos-log-collector/Chart.yaml
  • packages/system/talos-log-collector/Makefile
  • packages/system/talos-log-collector/README.md
  • packages/system/talos-log-collector/images/vector/Dockerfile
  • packages/system/talos-log-collector/templates/_helpers.tpl
  • packages/system/talos-log-collector/templates/configmap.yaml
  • packages/system/talos-log-collector/templates/daemonset.yaml
  • packages/system/talos-log-collector/templates/networkpolicy.yaml
  • packages/system/talos-log-collector/templates/serviceaccount.yaml
  • packages/system/talos-log-collector/tests/talos-log-collector_test.yaml
  • packages/system/talos-log-collector/values.schema.json
  • packages/system/talos-log-collector/values.yaml
✅ Files skipped from review due to trivial changes (6)
  • packages/system/talos-log-collector/values.yaml
  • packages/system/talos-log-collector/Chart.yaml
  • packages/system/talos-log-collector/templates/_helpers.tpl
  • Makefile
  • packages/system/talos-log-collector/images/vector/Dockerfile
  • packages/system/talos-log-collector/README.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/system/talos-log-collector/values.schema.json
  • packages/core/platform/templates/bundles/system.yaml
  • packages/core/platform/sources/talos-log-collector.yaml

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 — the documented Talos config does not deliver kernel logs (the package's headline promise), and the CiliumNetworkPolicy that the comment calls optional is in fact the only thing preventing log injection from any pod in the cluster.

Business context: Talos keeps machine and kernel logs inside the OS, where the existing file-tail collector cannot reach them, so this package adds a node-local receiver that Talos pushes into and that forwards to the platform's VictoriaLogs.

Blockers

B1: The required Talos config delivers service logs only — kernel/kmsg logs never arrive

File: packages/system/talos-log-collector/README.md:20-22 (and the config block at :29-35)

Issue: The README states that machine.logging "already forwards the runtime kernel (kmsg) stream as the kernel service ... so no separate KmsgLogConfig is needed". Talos does not work that way.

Evidence: Checked against Talos v1.12.0 and v1.13.0 source (v1.13.6 is what this platform ships, packages/apps/kubernetes/values.yaml:291). KmsgLogConfigController builds its destination list from exactly two sources — the talos.logging.kernel kernel command-line parameter, and cfg.Config().Runtime().KmsgLogURLs() (internal/app/machined/pkg/controllers/runtime/kmsg_log_config.go). KmsgLogURLs() is aggregated across config documents, and the only document returning a non-empty list is KmsgLogV1Alpha1, i.e. the KmsgLogConfig document (pkg/machinery/config/types/runtime/kmsg_log.go); EventSinkV1Alpha1 and WatchdogTimerV1Alpha1 both return nil. The v1alpha1 config type that owns machine.logging.destinations does not implement KmsgLogURLs at all — grepping it across pkg/machinery/config/types/v1alpha1/ returns nothing on both tags. machine.logging.destinations feeds only updateLoggingConfig → the JSON-lines service-log senders (internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go:586), and the string kernel does not appear anywhere under internal/app/machined/pkg/runtime/logging/. The chart itself assumes both streams share the socket: facility is a kmsg-only field, and it is listed in _stream_fields (templates/configmap.yaml:29).

Impact: An operator applying exactly the "Talos configuration (required)" block gets service logs and nothing else. Kernel logs — including the DRBD kmsg case named in the PR description, which is the operationally interesting one here — silently never arrive, while Chart.yaml:3, the README opening, the package name and the PR title all promise them. If kernel logs did show up on the dev cluster, that node almost certainly also carried talos.logging.kernel= in its kernel args, or a KmsgLogConfig document from earlier setup; the README snippet alone cannot produce them.

Fix: Add the kmsg destination to the required-config section — a KmsgLogConfig document, or talos.logging.kernel=tcp://127.0.0.1:5170/ in the kernel args, either of which can point at the same port — or drop the kernel-log claim from the README, Chart.yaml and _stream_fields.

B2: The comment calls the network policy optional; it is the only thing preventing any pod from injecting logs

File: packages/system/talos-log-collector/templates/networkpolicy.yaml:5-8

Issue: "even without this policy the loopback hostPort is not reachable from the pod network, so its absence is safe" is false, and it contradicts the sentence three lines above it.

Evidence: Vector binds every address inside the pod network namespace — address: 0.0.0.0:{{ .Values.listenPort }} (templates/configmap.yaml:15), exposed as containerPort (templates/daemonset.yaml:49). The pod's own IP is routable from every pod in the cluster; the hostPort is irrelevant to that path. Any workload can open a TCP connection to <podIP>:5170 and push JSON lines, which the tag transform stamps with .log_source = "talos_system" and the real .node name (templates/configmap.yaml:22-24) before inserting them into the platform's VictoriaLogs. The policy is load-bearing, not defence-in-depth. It is also conditional — {{- if .Capabilities.APIVersions.Has "cilium.io/v2/CiliumNetworkPolicy" }} (networkpolicy.yaml:1); helm template with default capabilities renders only ServiceAccount, ConfigMap and DaemonSet. The isp-hosted system-bundle variant installs the noop networking variant (packages/core/platform/templates/bundles/system.yaml:32) — no Cilium, hence no cilium.io/v2 CRD — and the optional-package line this PR adds (system.yaml:229) sits in the variant-agnostic tail of that file, so the package is offerable there with no ingress protection whatsoever.

Impact: Forged log records attributed to a trusted source label and a real node name in the platform's log store — an audit and forensic integrity problem, reachable from any tenant workload wherever the policy does not render.

Fix: Correct the comment, and ship a CNI-agnostic networking.k8s.io/v1 NetworkPolicy as a fallback so the socket is never unprotected — or make Cilium a hard requirement of the package and fail rendering without it.

B3: resources.cpu is documented as a request and a limit; only a request is set

File: packages/system/talos-log-collector/values.yaml:23

Issue: ## @field {quantity} [cpu] - CPU request and limit. — but the DaemonSet sets requests.cpu with no CPU limit (templates/daemonset.yaml:53-58); only memory is request-and-limit. The wrong description propagates into values.schema.json:43 and README.md:65.

Evidence: templates/daemonset.yaml:53-58 — the limits: block contains memory only.

Impact: The generated user-facing docs and the values schema describe behaviour the chart does not implement.

Fix: Reword the annotation to "CPU request." and regenerate (make generate in the package). Omitting the CPU limit is the right call; only the description is wrong.

The package ships a helm-unittest suite, so each of the three needs a case that fails without the fix — a resources assertion for B3, and for B2 an assertion pinning what renders when the Cilium CRD is absent.

Non-blocking follow-ups

  1. The loopback hostIP works only because the platform chains the portmap CNI plugin ahead of Cilium (packages/system/cilium/templates/cni.yaml: "type": "portmap", "snat": true, pulled in via values-kubeovn.yaml on the kubeovn-cilium* variants). Cilium's own eBPF hostPort implementation does not support binding a hostPort to the loopback address. The cilium, cilium-generic and cilium-kilo variants in packages/core/platform/sources/networking.yaml are not selected by any bundle today, but if one ever is, this receiver silently stops receiving. Worth stating in the DaemonSet comment.

  2. Every record from the existing node agent carries tenant and cluster (packages/system/monitoring-agents/values.yaml:440-444); records from this pipeline carry neither. Same log store, two schemas — operators filtering on those fields will not see Talos logs.

  3. No liveness probe on a system-node-critical DaemonSet with a hard 128Mi limit. A wedged or OOM-looping Vector is invisible and never restarted. Enabling Vector's health endpoint and probing it would let the DaemonSet self-heal.

  4. values.schema.json carries no constraints: logLevel lists its valid values in prose but has no enum, and listenPort has no minimum/maximum, so 0 or 70000 validate and then render an invalid DaemonSet.

  5. make update (Makefile:10-12) rewrites the Dockerfile's ARG VERSION but leaves Chart.yaml's appVersion: "0.56.0" untouched, so the two drift on the next bump.

  6. The README never says why the existing node-level agent was not extended instead. The answer looks legitimate — the vendored fluent-bit chart renders only name/containerPort/protocol for extraPorts (charts/fluent-bit/templates/_pod.tpl:72-78), so a loopback receiver there would need a chart patch — but every reader will ask, and one sentence in the README would preempt it.

For what it is worth, the parts that are right are right: registration matches the hetzner-robotlb precedent exactly, install.privileged: true is genuinely required (PSA baseline forbids a non-zero hostPort), the generated schema and README are free of codegen drift, and the chart lints and its unit tests pass.

network, the outbound path to vlinsert keeps working; the inbound loopback
socket is provided by the hostPort. `machine.logging` already forwards the
runtime kernel (kmsg) stream as the `kernel` service (verified on Talos v1.12),
so no separate `KmsgLogConfig` is needed for runtime kernel logs.

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 is not how Talos delivers kmsg. In Talos v1.12/v1.13, KmsgLogConfigController takes its destinations only from the talos.logging.kernel kernel parameter and from Runtime().KmsgLogURLs() — and the only config document that returns a URL there is KmsgLogConfig (KmsgLogV1Alpha1). The v1alpha1 type that owns machine.logging.destinations does not implement KmsgLogURLs at all; that setting feeds only the JSON-lines service-log senders.

So an operator who applies exactly the config block below gets service logs and no kernel logs — including the DRBD kmsg case the PR description calls out. Note the chart already assumes otherwise: facility is a kmsg-only field and it is in _stream_fields (templates/configmap.yaml:29).

Either add the kmsg destination to the required config (a KmsgLogConfig document, or talos.logging.kernel=tcp://127.0.0.1:5170/ — it can point at the same port), or drop the kernel-log claim from the README, Chart.yaml:3 and _stream_fields. If kernel logs did arrive on your dev cluster, that node very likely already had one of those two in place.

# the "host" entity. Restrict ingress on the listen port to host only, so other
# pods on the pod network cannot inject spoofed talos_system log lines.
# Defense-in-depth and Cilium-only: even without this policy the loopback
# hostPort is not reachable from the pod network, so its absence is safe.

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.

"its absence is safe" is not true, and it contradicts the sentence three lines up.

Vector binds 0.0.0.0 inside the pod netns (templates/configmap.yaml:15) and it is exposed as containerPort (templates/daemonset.yaml:49). The pod IP is routable from every pod in the cluster — the hostPort is irrelevant to that path. Any workload can connect to <podIP>:5170 and push JSON lines that the tag transform stamps with .log_source = "talos_system" and the real node name, straight into VictoriaLogs.

This policy is load-bearing, not defence-in-depth — and it is gated on the Cilium CRD being present (line 1). The isp-hosted bundle variant runs the noop networking variant (bundles/system.yaml:32, no Cilium), while the optional-package line this PR adds sits in the variant-agnostic tail of the same file — so the package can ship there with no ingress protection at all.

Please fix the comment and add a CNI-agnostic networking.k8s.io/v1 NetworkPolicy fallback, or make Cilium a hard requirement and fail rendering without it.

pullPolicy: IfNotPresent

## @typedef {struct} Resources - Compute resources for the collector.
## @field {quantity} [cpu] - CPU request and limit.

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.

cpu is a request only — templates/daemonset.yaml:53-58 puts just memory under limits:. (Only memory is genuinely request-and-limit.) This description propagates into values.schema.json:43 and README.md:65, so both currently document behaviour the chart does not implement.

Not setting a CPU limit is the right call; just reword to "CPU request." and re-run make generate.

…lue constraints

cpu is a request only (the DaemonSet sets no cpu limit), so the annotation
now reads "CPU request." instead of "CPU request and limit.". Add an enum
for logLevel and a 1-65535 range for listenPort so an invalid value is
rejected at schema validation instead of rendering a broken DaemonSet.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
…el logs

machine.logging.destinations only carries the JSON-lines service logs; Talos
builds its kmsg destination list solely from KmsgLogConfig documents and the
talos.logging.kernel= kernel argument. The previous README claimed
machine.logging alone forwarded the kernel stream, so an operator following it
collected service logs only and the kernel (kmsg) logs, including the DRBD
messages this package targets, silently never arrived. Add the required
KmsgLogConfig document to the node configuration and explain both paths.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
Vector binds 0.0.0.0 inside the pod netns and exposes it as a containerPort,
so any pod could reach <podIP>:<listenPort> and inject forged talos_system
log lines. The ingress restriction is therefore load-bearing, not
defence-in-depth as the comment claimed. The CiliumNetworkPolicy only rendered
when the Cilium CRD was present, leaving the receiver unprotected on non-Cilium
variants (e.g. isp-hosted / noop networking). Correct the comment and, when the
Cilium CRD is absent, fall back to a default-deny-ingress networking.k8s.io/v1
NetworkPolicy so the socket is never offered without protection.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
Records from monitoring-agents carry tenant and cluster fields; records from
this pipeline carried neither, so operators filtering the shared log store on
those fields did not see Talos logs. Stamp .tenant (the destination tenant) and
.cluster (root-cluster, matching monitoring-agents) and add both to the vlinsert
_stream_fields. Guard the target lookup with a default so a missing global.target
does not break rendering.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
…pendency

Without a liveness probe a wedged Vector on this system-node-critical DaemonSet
is never restarted. Add a tcpSocket probe on the listen port, which the ingress
policy already permits from the node. Document that the loopback hostPort
depends on the portmap CNI plugin chained ahead of Cilium: the plain
cilium/cilium-generic/cilium-kilo variants cannot bind a hostPort to 127.0.0.1.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
make update bumped the Dockerfile ARG VERSION but left Chart.yaml appVersion
untouched, so the two drifted on every upstream bump. Update appVersion in the
same target.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
…nd probe

Add cases that fail without the accompanying fixes: the default-deny
networking.k8s.io/v1 NetworkPolicy rendered when the Cilium CRD is absent, cpu
being request-only while memory is request-and-limit, the tcpSocket liveness
probe, the tenant/cluster stream fields, and the NoExecute toleration.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
@IvanHunters IvanHunters changed the title feat(system): add talos-log-collector package feat(talos-log-collector): add talos-log-collector package Jul 22, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/system/talos-log-collector/tests/talos-log-collector_test.yaml (1)

78-86: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Assert the tenant label alongside the destination override.

This test verifies that global.target changes the vlinsert hostname, but not that Vector stamps records with the same tenant. Add an assertion for .tenant = "tenant-ktj" to prevent routing and stream-label mismatches.

Suggested assertion
       - matchRegex:
           path: data["vector.yaml"]
           pattern: "vlinsert-generic\\.tenant-ktj\\.svc:9481"
+      - matchRegex:
+          path: data["vector.yaml"]
+          pattern: '\.tenant = "tenant-ktj"'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/tests/talos-log-collector_test.yaml`
around lines 78 - 86, Add a second assertion to the “destination tenant is
overridable via global.target” test that verifies Vector’s generated
configuration sets the tenant label to “tenant-ktj” alongside the existing
vlinsert hostname assertion. Keep the current destination override assertion
unchanged.
packages/system/talos-log-collector/README.md (1)

8-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep ordinary Markdown prose on one physical line.

The changed prose paragraphs are wrapped across multiple source lines. Reflow these paragraphs while retaining meaningful breaks in lists, blockquotes, tables, and fenced code.

As per coding guidelines, Markdown prose paragraphs must use one continuous line.

Also applies to: 18-22, 24-25, 38-40

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/README.md` around lines 8 - 14, Reflow
the ordinary Markdown prose paragraphs in the README, including the paragraphs
at the referenced sections, so each paragraph occupies one physical source line.
Preserve meaningful line breaks in lists, blockquotes, tables, and fenced code
blocks, and do not alter the prose content.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/system/talos-log-collector/README.md`:
- Around line 55-57: Remove the blank line within the blockquote warning in the
KmsgLogConfig documentation so the service-log and kernel-log statements remain
one continuous blockquote and satisfy markdownlint MD028.

In `@packages/system/talos-log-collector/templates/networkpolicy.yaml`:
- Around line 11-13: Replace the .Capabilities.APIVersions.Has gate in the
network policy template with an explicit prerequisite that verifies Cilium
policy enforcement is active, not merely that its CRD is installed. Ensure
unsupported, NOOP, or BYO networking configurations do not render an unprotected
listener; fail closed or select only a known-enforcing network path before
allowing the Cilium-specific policy.

---

Nitpick comments:
In `@packages/system/talos-log-collector/README.md`:
- Around line 8-14: Reflow the ordinary Markdown prose paragraphs in the README,
including the paragraphs at the referenced sections, so each paragraph occupies
one physical source line. Preserve meaningful line breaks in lists, blockquotes,
tables, and fenced code blocks, and do not alter the prose content.

In `@packages/system/talos-log-collector/tests/talos-log-collector_test.yaml`:
- Around line 78-86: Add a second assertion to the “destination tenant is
overridable via global.target” test that verifies Vector’s generated
configuration sets the tenant label to “tenant-ktj” alongside the existing
vlinsert hostname assertion. Keep the current destination override assertion
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0f25d9ef-7118-47de-a580-9224bac3b0e9

📥 Commits

Reviewing files that changed from the base of the PR and between 1fb4bcf and 34f164e.

📒 Files selected for processing (8)
  • packages/system/talos-log-collector/Makefile
  • packages/system/talos-log-collector/README.md
  • packages/system/talos-log-collector/templates/configmap.yaml
  • packages/system/talos-log-collector/templates/daemonset.yaml
  • packages/system/talos-log-collector/templates/networkpolicy.yaml
  • packages/system/talos-log-collector/tests/talos-log-collector_test.yaml
  • packages/system/talos-log-collector/values.schema.json
  • packages/system/talos-log-collector/values.yaml
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/system/talos-log-collector/values.yaml
  • packages/system/talos-log-collector/templates/configmap.yaml
  • packages/system/talos-log-collector/values.schema.json
  • packages/system/talos-log-collector/Makefile
  • packages/system/talos-log-collector/templates/daemonset.yaml

Comment thread packages/system/talos-log-collector/README.md
Comment on lines +11 to +13
{{- if .Capabilities.APIVersions.Has "cilium.io/v2/CiliumNetworkPolicy" }}
# Cilium is present: restrict ingress on the listen port to the host entity, so
# only the node-local push path is allowed and other pods are denied.

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

kubectl api-resources --api-group=cilium.io
kubectl get pods --all-namespaces -l k8s-app=cilium

Repository: cozystack/cozystack

Length of output: 202


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== candidate files =="
fd -a 'networkpolicy\.yaml$|.*cilium.*|.*network.*|.*talos-log-collector.*|README\.md|.*docs.*' . | sed 's#^\./##' | head -200

echo
echo "== target file outline/size =="
wc -l packages/system/talos-log-collector/templates/networkpolicy.yaml 2>/dev/null || true
sed -n '1,120p' packages/system/talos-log-collector/templates/networkpolicy.yaml 2>/dev/null || true

Repository: cozystack/cozystack

Length of output: 16196


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== docs relevant =="
fd -a 'README\.md$|.*docs.*|contributing\.md$|overview\.md$|releasing\.md$|changelog\.md$|e2e-testing\.md$' docs packages README.md | sed 's#^\./##' | while read -r f; do
  if rg -n "Talos|talos-log-collector|NetworkPolicy|Cilium|noop|CNI|BYO|networking|VictoriaLogs|vector" "$f" >/dev/null 2>&1; then
    echo "--- $f"
    rg -n "Talos|talos-log-collector|NetworkPolicy|Cilium|noop|CNI|BYO|networking|VictoriaLogs|vector" "$f"
  fi
done

echo
echo "== talos-log-collector package =="
sed -n '1,220p' packages/system/talos-log-collector/README.md
python3 - <<'PY'
from pathlib import Path
for p in Path('packages/system/talos-log-collector').rglob('*.yaml'):
    print(f'--- {p}')
    text = p.read_text()
    for i,line in enumerate(text.splitlines(),1):
        if 'cilium' in line.lower() or 'networkpolicy' in line.lower() or 'capabilities' in line.lower() or 'talos' in line.lower() or 'noop' in line.lower():
            print(f'{i}: {line}')
PY

echo
echo "== supported talos docs mentions =="
rg -n --glob 'README\.md' --glob '*.md' 'packages/system/talos-log-collector|talos-log-collector|talos.*network|networking\.yaml|cilium' packages docs README.md | head -300

Repository: cozystack/cozystack

Length of output: 50376


Gate on policy enforcement, not API discovery.

.Capabilities.APIVersions.Has only proves that the Cilium CRDs are installed; it does not prove that Cilium’s control/data planes are active. The fallback still depends on the CNI enforcing Kubernetes NetworkPolicy; as the template notes, unsupported/NOOP/BYO networking paths leave the 0.0.0.0 listener reachable. Fail closed or add an explicit supported-networking prerequisite so “never offered without protection” is guaranteed.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 11-11: syntax error: expected the node content, but found '-'

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/talos-log-collector/templates/networkpolicy.yaml` around
lines 11 - 13, Replace the .Capabilities.APIVersions.Has gate in the network
policy template with an explicit prerequisite that verifies Cilium policy
enforcement is active, not merely that its CRD is installed. Ensure unsupported,
NOOP, or BYO networking configurations do not render an unprotected listener;
fail closed or select only a known-enforcing network path before allowing the
Cilium-specific policy.

… kmsg time

global.target is not platform-injected for this optional package (the bundle
emits a Package CR with no component values), it comes from the chart default
tenant-root; reword the misleading "platform-injected" description. Also note
that kernel (kmsg) records carry no wall-clock timestamp, so VictoriaLogs uses
the ingest time rather than talos-time for them.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
…I-specific

The fallback NetworkPolicy comment presented node-local traffic bypassing a
default-deny policy as a universal guarantee; it is CNI-specific behaviour.
Reword to state the dependency explicitly and note that the only non-Cilium
variant shipped today (noop) does not enforce NetworkPolicy, so the fallback is
inert there.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
@IvanHunters

Copy link
Copy Markdown
Collaborator Author

Thanks for the thorough review. All three blockers are fixed, plus the non-blocking follow-ups.

B1 (kernel logs): The required-config section now ships a KmsgLogConfig document (url: tcp://127.0.0.1:5170/) alongside machine.logging.destinations, and the README explains the two independent paths. Verified against Talos v1.13 source that machine.logging.destinations feeds only the service-log senders and kmsg comes solely from KmsgLogConfig / talos.logging.kernel=.

B2 (network policy): Corrected the misleading comment and added a CNI-agnostic networking.k8s.io/v1 default-deny-ingress fallback that renders when the Cilium CRD is absent, so the socket is never offered without protection. Added a unit case pinning what renders when the CRD is absent.

B3 (cpu request-only): Reworded to "CPU request." in values.yaml, regenerated schema + README, and added a notExists limits.cpu assertion.

Non-blocking follow-ups also addressed: tenant/cluster stream fields (parity with monitoring-agents), a tcpSocket liveness probe, the portmap/Cilium hostPort caveat in the DaemonSet comment, logLevel enum + listenPort range in the schema, and make update now bumps Chart.yaml appVersion. Corrected the global.target "platform-injected" wording (it is the chart default for this optional package).

helm unittest 14/14, helm lint clean, no codegen drift.

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 — every blocker from the previous review is resolved, but the generated values.schema.json now carries a first-party image reference that the image-ref enumeration guard rejects, so the required "Unit & controller tests" check is red and the branch cannot merge as-is.

Disposition of the previous review's blockers (all resolved on f96d0ec):

  • B1 (kernel/kmsg logs never arrive): resolved. The README now documents that machine.logging.destinations carries only service logs and that a separate KmsgLogConfig document is required for the kmsg stream, and the required-config block ships both (README.md:24-56). This matches how Talos builds its kmsg destination list.
  • B2 (network policy wrongly called optional): resolved. The comment is corrected to state the policy is load-bearing (networkpolicy.yaml:1-10), and a CNI-agnostic default-deny networking.k8s.io/v1 fallback now renders whenever the Cilium CRD is absent — helm template with default capabilities emits it. See non-blocking note 1 for the residual noop case.
  • B3 (resources.cpu documented as request-and-limit): resolved. The annotation, schema and README now read "CPU request." and a test pins that only memory carries a limit (values.yaml:32, values.schema.json:52, README.md:90, test cpu is a request only).

All six non-blocking follow-ups from the previous review are also addressed: portmap dependency documented (daemonset.yaml:28-32), tenant/cluster labels stamped with the same convention as the existing node agent (configmap.yaml:25-26; tenant=global.target, cluster=root-cluster, matching monitoring-agents/values.yaml:440,444), liveness probe added (daemonset.yaml:45-49), schema constraints added (logLevel enum, listenPort min/max), Chart.yaml appVersion synced on make update (Makefile:13), and the README explains why the existing node agent was not extended.

Blockers

B1: values.schema.json carries a first-party image ref that the enumeration guard rejects

File: packages/system/talos-log-collector/values.schema.json:34-43 (root cause in values.yaml:20-29)

Issue: The required "Unit & controller tests" check is failing. The image-ref enumeration guard greps packages/** for ghcr.io/cozystack/cozystack/ and requires every match to be either enumerated by the promote-retag rewriter or allowlisted with a reason; values.schema.json is neither, so the check exits non-zero.

Evidence: The failing job ends with files carry a first-party image ref but are neither enumerated nor allowlisted: packages/system/talos-log-collector/values.schema.json then make: *** [Makefile:167: bats-unit-tests] Error 1. This schema is the only system-package values.schema.json in the tree containing ghcr.io/cozystack/cozystack/. It lands there because values.yaml annotates the image struct (@typedef Image + @field repository/tag), so the schema generator bakes the ref into the generated default; metallb and every other package leave the image block un-annotated, so their schema never carries the ref. The guard was added to main after this branch's merge-base, which is why a local helm unittest passes while the merge check fails.

Impact: A required check is red; the branch is not mergeable until it goes green.

Fix: Drop the @typedef Image / @field annotations from the image block in values.yaml and regenerate, so the schema no longer carries the ref — this matches every other package and needs no change on main. Alternatively, add packages/system/talos-log-collector/values.schema.json to the guard's allowlist with a reason (the schema default is not a runtime ref; the runtime ref lives in values.yaml, which the rewriter already handles). Rebasing onto current main first surfaces the failure locally.

Non-blocking follow-ups

  1. On the noop networking variant — the only non-Cilium variant shipped, and the one the template comment itself names — the fallback NetworkPolicy is inert, because noop enforces no NetworkPolicy at all. An operator who opts the package in there gets the log-injection socket with no protection. The template documents this honestly (networkpolicy.yaml:9-10,32-41). If protecting that path matters, make a policy-enforcing CNI a hard requirement of the package or don't offer it on noop; otherwise the current documented posture is defensible, since noop is a deliberately policy-free environment where nothing is netpol-protected.
  2. The new README prose is hard-wrapped (README.md:3-14, 24-34, and the other prose paragraphs); the repository convention is one continuous line per prose paragraph. Not CI-enforced, but worth reflowing while the file is new. There is also an MD028 blank-line-in-blockquote run at README.md:55-63.
  3. The tcpSocket liveness probe detects only a dead listener, not a Vector process that is alive but has stopped forwarding (for example a wedged HTTP sink). Vector's health endpoint over an HTTP probe would catch more; the current probe is an acceptable minimum.

The rest of the package is sound: registration mirrors the hetzner-robotlb opt-in precedent, install.privileged: true is genuinely required for the loopback hostPort under PSA baseline, the helm-unittest suite is substantive (14 cases pinning both NetworkPolicy branches, the resources split, the liveness probe and the tenant override), and the generated schema and README are free of codegen drift.

## @maximum 65535
listenPort: 5170

## @typedef {struct} Image - Vector container image.

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.

Annotating the image struct here makes the schema generator emit ghcr.io/cozystack/cozystack/vector as a default into values.schema.json, which is the only system-package schema in the tree carrying a first-party image ref. That trips the image-ref enumeration guard on main and turns the required "Unit & controller tests" check red. Every other package (e.g. metallb) leaves image un-annotated so the ref stays out of the schema. Dropping these @typedef/@field annotations and regenerating fixes the check without touching the guard on main.

The first-party image-ref guard rejects values.schema.json: the annotated
image struct baked ghcr.io/cozystack/cozystack/vector into the generated
schema default, an unenumerated second copy of the runtime ref that the
promote and mirror tooling never touches. Move the reference into
images/vector.tag (the enumerated .tag storage shape, read via
.Files.Get) so the schema no longer carries it, matching every other
package. Stamp the tag from make image and regenerate schema and README.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
…kPolicy port

The Cilium NetworkPolicy suite asserted the ingress port only at the
default 5170, so a regression hard-coding the port would still pass. Add a
listenPort-override case mirroring the DaemonSet host/containerPort test,
pinning that the override flows into spec.ingress[0].toPorts.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/platform Issues or PRs related to platform infrastructure (bundle, flux, talos, installer) area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review kind/feature Categorizes issue or PR as related to a new feature size/XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants