Kubernetes DaemonSet
Kubernetes DaemonSet deployment of the LinuxGuard agent — copy-pasteable YAML with PSS profile comment, line-by-line securityContext rationale, eBPF prerequisites, and RBAC.
The DaemonSet shape runs one LinuxGuard agent pod per node. The agent observes every workload on that node through host PID + tracefs, so a single DaemonSet covers all containerized and host-native workloads on the cluster. This page provides a complete, copy-pasteable manifest with line-by-line rationale for every privilege the Pod requests.
Important: The manifest below is classified
# Pod Security Standard: privilegedbecause it requestsCAP_BPF,CAP_PERFMON,hostPID: true, and host-path volumes for/sys/kernel/tracingand/sys/fs/bpf. These cannot be granted under thebaselineorrestrictedPSS profiles. Clusters that enforcerestrictedcluster-wide require an explicitAdmissionPolicywaiver — see Pod Security Standard compatibility below.
Prerequisites
Before applying the manifest, verify the cluster meets the following requirements. Skipping any of these produces a DaemonSet that admits but does not produce eBPF telemetry — the agent runs in DEGRADED_PROBES_PARTIAL mode and the cluster's evidence chain has a silent gap.
Kernel version
The agent's eBPF probes require Linux kernel 5.8 or later (the kernel that introduced CAP_BPF and CAP_PERFMON). On older kernels the agent falls back to CAP_SYS_ADMIN-based loading, but the file-cap transition baked into the binary does not include SYS_ADMIN and the loader degrades. Verify per-node:
kubectl get nodes -o wide # check KERNEL-VERSION columnkernel.perf_event_paranoid sysctl
kernel.perf_event_paranoid sysctlThe agent calls perf_event_open(2) via link.Tracepoint() to attach the eBPF programs. This syscall is gated by the host sysctl kernel.perf_event_paranoid. The required value is <= 2.
Ubuntu 24.04 ships with kernel.perf_event_paranoid = 4 by default. SET THIS AT NODE LEVEL — it CANNOT be enforced from the Pod spec.
echo 'kernel.perf_event_paranoid = 2' | sudo tee /etc/sysctl.d/99-linuxguard-ebpf.conf
sudo sysctl --systemSeccomp + AppArmor profiles installed on every node
The reference seccomp profile (linuxguard-agent.seccomp.json) and AppArmor profile (linuxguard-agent.apparmor) MUST be present on every node before the agent DaemonSet schedules. The recommended pattern is a sibling DaemonSet that runs an init container with privileged: true to write the profiles to the host's /var/lib/kubelet/seccomp/profiles/ and /etc/apparmor.d/ directories.
The profile-installer DaemonSet (reference manifest available in the agent packaging artifacts shipped with each release) follows the same shape used by KubeArmor and Falco. Adapt your existing profile-installer if your cluster already runs one.
Image-registry pull access
The published image at packages.linuxguard.io/linuxguard-agent:v3.0.0 is signed; verify the signature once at build time per Distroless image § Image signing. If your cluster pulls from a mirrored registry, mirror the digest (not the tag) so the deployed bytes match the signed bytes.
The manifest
Line-by-line rationale
Each privilege the Pod requests is documented below with the rationale and the consequence of removing it.
hostPID: true
hostPID: trueRequired for the node-level coverage shape. With hostPID: true, the agent's /proc view exposes every process on the node — including processes inside other containers. Without it, the agent sees only its own PID namespace (the Pod's /proc) and produces telemetry only about itself, defeating the DaemonSet purpose.
If your cluster forbids hostPID, use the sidecar shape instead.
hostNetwork: false
hostNetwork: falseThe agent does NOT need host networking. It makes outbound HTTPS to the LinuxGuard API via the Pod's own network namespace; the Pod's CNI handles the outbound routing. Setting hostNetwork: true would put the agent on the host network namespace unnecessarily and expand blast radius.
capabilities.add: [BPF, PERFMON, DAC_READ_SEARCH, SYS_PTRACE, SETPCAP]
capabilities.add: [BPF, PERFMON, DAC_READ_SEARCH, SYS_PTRACE, SETPCAP]These five capabilities are the bounding-set requirement that lets the file-cap transition (baked into the agent ELF) succeed at execve:
BPF— load eBPF programs.PERFMON— callperf_event_open(2)for tracepoint attach.DAC_READ_SEARCH— read/proc/<pid>/exeand/proc/<pid>/mapsfor arbitrary PIDs (process introspection).SYS_PTRACE— required by the BTF resolution path on older kernels.SETPCAP— required forDropCapabilitiesPostAttach(). WithoutSETPCAP, the post-attachPR_CAPBSET_DROPcalls returnEPERM(non-fatal, but the agent silently holdsCAP_BPFfor its full lifetime).
capabilities.drop: [ALL]
capabilities.drop: [ALL]Drop every capability not explicitly added. Defense-in-depth: a future binary that gains additional caps via image rebuild does not silently get to use them at runtime.
appArmorProfile.localhostProfile: linuxguard-agent
appArmorProfile.localhostProfile: linuxguard-agentThe AppArmor profile is installed by the profile-installer DaemonSet (sibling deployment, not shown above). The profile constrains the agent's filesystem access patterns so a compromised binary cannot, for example, write to /etc/sudoers or read /root/.ssh/.
runAsNonRoot: true + runAsUser: 65532
runAsNonRoot: true + runAsUser: 65532The distroless base image runs as nonroot UID 65532 by default. Enforcing it at the Pod level produces an admission rejection rather than a silent base-image override — protective against a downstream layer that sets USER root.
allowPrivilegeEscalation: false
allowPrivilegeEscalation: falseThe agent does not need to setuid or setgid at runtime. The file caps baked into the binary provide the required privileges through execve's standard cap-transition rules.
readOnlyRootFilesystem: true
readOnlyRootFilesystem: trueThe agent writes only to /run/linuxguard (the tls-cache tmpfs) and /tmp (writable in the distroless base). The image filesystem is fully read-only at runtime.
seccompProfile.localhostProfile: profiles/linuxguard-agent.json
seccompProfile.localhostProfile: profiles/linuxguard-agent.jsonThe default Docker / containerd seccomp profile blocks perf_event_open(2) regardless of CAP_PERFMON. The custom profile shipped with the agent (linuxguard-agent.seccomp.json in the agent packaging artifacts) adds perf_event_open to the allowlist. Without this override, probe attach trips "opening tracepoint perf event: permission denied" and the agent degrades.
Security context
The DaemonSet Pod requests the following security context — every field has the same rationale as the equivalent setting on the Distroless image reference; the table below summarizes what the manifest above sets and links each setting to its full rationale in Line-by-line rationale.
capabilities.add
[BPF, PERFMON, DAC_READ_SEARCH, SYS_PTRACE, SETPCAP]
Bounding-set caps for the file-cap execve transition. See capabilities.add.
seccompProfile
Localhost: profiles/linuxguard-agent.json
Custom profile permits perf_event_open(2). See seccompProfile.
appArmorProfile
Localhost: linuxguard-agent
AppArmor constraints on filesystem access. See appArmorProfile.
runAsUser / runAsGroup
65532 / 65532
Distroless nonroot UID/GID.
allowPrivilegeEscalation
false
File caps make setuid unnecessary. See allowPrivilegeEscalation: false.
readOnlyRootFilesystem
true
Agent does not write to image filesystem. See readOnlyRootFilesystem: true.
The manifest's security context corresponds to PSS privileged — see § Pod Security Standard compatibility below for the classification and the restricted-cluster guidance.
Pod Security Standard compatibility
The manifest above is classified as privileged under the Kubernetes Pod Security Standards.
privileged
Yes
No PSS-level constraints.
baseline
No
baseline disallows hostPID: true, host-path volumes for /sys/kernel/tracing and /proc, and the BPF + PERFMON capabilities.
restricted
No
restricted requires runAsNonRoot: true (satisfied), but ALSO disallows ALL added capabilities, host namespaces, and most hostPath volumes.
Running under restricted clusters
restricted clustersIf your cluster enforces restricted cluster-wide and the policy CANNOT be relaxed at the namespace level, two options exist:
AdmissionPolicy waiver. Carve out the
linuxguardnamespace via aValidatingAdmissionPolicythat exempts the agent's specific privileges. This is the auditable path: the waiver lives in cluster config, is reviewable in change management, and applies only to the agent's namespace + ServiceAccount.Consult support. v4.0 does not ship a
restricted-compatible deployment shape. If your environment requires one, open a support case so the alternative deployment patterns (e.g., a host-installed agent reaching into the cluster's container runtime) can be evaluated.
Do NOT attempt to run the manifest with capabilities stripped to fit restricted — the agent will start and silently produce no behavioral telemetry, and the cluster's evidence chain will have a silent gap.
Host paths
/sys/kernel/tracing
read-only hostPath
link.Tracepoint() reads /sys/kernel/tracing/events/<group>/<name>/id to resolve tracepoint IDs at probe-attach time. The distroless image does not include /sys mounts.
No — without this, probe attach fails with "neither debugfs nor tracefs are mounted" and the agent degrades.
/sys/fs/bpf
read-write hostPath
BPF pinned maps. Required when the in-process loader pins maps for cross-process sharing.
No — pinned-map creation fails without write access.
/proc
read-only hostPath (mounted at /host/proc)
Process introspection. The agent walks the host's /proc for the workload-discovery pass when hostPID is set.
No — without it, the agent observes only its own PID namespace.
/run/linuxguard
tmpfs (emptyDir medium: Memory)
TLS cert cache when --tls-cache is set. Tmpfs (not durable storage) so cert material never reaches disk.
Only if --tls-cache is removed from args.
Security Note: All host-path mounts are read-only except
/sys/fs/bpf(which requires write for pinned-map creation) and/run/linuxguard(which is a tmpfs, not a host path). Do NOT mount the host root (/) — the agent does not need it; mounting it expands the blast radius of a container escape to the entire node. See the anti-patterns hub section.
RBAC
The agent makes no Kubernetes apiserver calls at runtime. Workload identity is derived from the Downward API env vars (injected at admission time, no apiserver lookups), and telemetry ships via outbound mTLS to the LinuxGuard API.
The minimal RBAC is therefore just a ServiceAccount with no Role or ClusterRole:
The Pod runs under this ServiceAccount. No RoleBinding or ClusterRoleBinding is required because no Role exists to bind.
Profile-installer DaemonSet RBAC
The sibling profile-installer DaemonSet (which writes seccomp + AppArmor profiles to host paths) DOES require its own ServiceAccount + RBAC for the init-container's privileged host-path writes. Its RBAC ships in the agent packaging artifacts.
linuxguard-enroll Secret
linuxguard-enroll SecretThe Secret referenced by the valueFrom.secretKeyRef env block above must be created out-of-band before the DaemonSet rolls out:
The token is single-use per pod identity — rotate it on every DaemonSet roll if you want each pod to enrol with a fresh identity. See Enrollment tokens for the rotation pattern.
Sidecar alternative
The DaemonSet shape is preferred. The sidecar shape exists for the narrow case where pod-level isolation is mandated by policy and a node-level pod is explicitly rejected.
Differences from the DaemonSet manifest:
hostPID: false— the sidecar observes only its sibling containers in the same Pod.No
tolerations— sidecars run alongside the application.The agent runs as an additional container in the application's Pod spec, not in a dedicated namespace.
Resource cost is per-pod, not per-node — at 100 application pods, you run 100 agent sidecars instead of one agent per node.
Important: Do NOT run both a DaemonSet AND a per-pod sidecar. The DaemonSet's
hostPID: truealready observes every process on the node, including the sidecar's host. Double-deploying produces duplicate events that double-count in console alerts and SIEM ingestion. See the anti-patterns hub section.
Node selection and tolerations
The manifest above selects kubernetes.io/os: linux and tolerates all taints. Common adjustments:
Exclude control-plane nodes — if your security model excludes the control plane from coverage, replace the
Existstoleration with aNoScheduletoleration that lists only the worker-node taints.Restrict to a specific node pool — add a
nodeSelectorornodeAffinityrule.Exclude legacy kernel nodes — the agent degrades cleanly on kernels older than 5.8, but excluding those nodes via affinity makes the coverage gap explicit.
Verification
After applying the manifest, verify the DaemonSet is fully ready and the agent is producing heartbeats:
A healthy DaemonSet produces a heartbeat log line within 20 seconds of pod start and probe reports kernel/bpf/fanotify/netlink/audit/caps all green. A degraded probe report points to a missing prerequisite — most commonly kernel.perf_event_paranoid > 2 or a missing seccomp profile.
Next Step: Downward API integration →
Related: Container deployment hub | Distroless image reference | Ephemeral mode | Enrollment tokens | probe CLI reference
Last updated
Was this helpful?