eBPF Daemonset Installation¶
The cloudtaser eBPF agent is a DaemonSet deployed on every node in the cluster. It provides runtime enforcement and secret leak detection by monitoring syscalls via eBPF kprobes and tracepoints. The agent blocks exfiltration vectors such as /proc/pid/environ reads, /proc/pid/mem access, and ptrace attach attempts on cloudtaser-protected processes.
Purpose¶
Without the eBPF agent, cloudtaser protects secrets at the infrastructure level -- secrets bypass etcd and Kubernetes Secrets entirely. The eBPF agent adds runtime protection on the node itself:
- Blocks
/procaccess -- Prevents reading/proc/<pid>/environand/proc/<pid>/memof protected processes, even by root - Blocks
ptrace-- Prevents debugger attach and memory inspection of protected processes - Exfiltration detection -- Monitors for suspicious syscall patterns that indicate secret extraction attempts
- Reactive kill -- Optionally terminates processes that attempt to read protected memory regions
Defense in depth
The eBPF agent is a defense-in-depth layer. Even without it, secrets never touch etcd or disk. The agent protects against a compromised node or container escape scenario where an attacker has root access on the host.
Kernel Requirements¶
The eBPF agent requires a Linux kernel with BPF support. The following table summarizes compatibility.
| Kernel Version | Support Level | Notes |
|---|---|---|
| < 5.8 | Not supported | Missing required BPF features |
| 5.8 -- 5.13 | Basic | Minimum for the agent to load; readiness depends on the conditions below |
| 5.14+ | Recommended | Includes memfd_secret integration. Kernel version alone does not make the install ready |
| 6.1+ | Recommended | Long-term support kernel |
Kernel version is necessary but not sufficient. With the default chart the agent is ready only on kernels with CONFIG_BPF_KPROBE_OVERRIDE=y. BPF LSM hooks cover only some of the required vectors, so BPF LSM alone does not make the agent ready. Otherwise /healthz returns HTTP 503 and protected workloads are refused. See Kernel Compatibility.
Check your node kernel version
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.kernelVersion}{"\n"}{end}'
All nodes must run Linux 5.8 or later, and each must also provide a synchronous deny path for every required vector (see above).
Managed Kubernetes Kernel Versions¶
| Node Image | Kernel | Supported |
|---|---|---|
| Container-Optimized OS (COS), measured 29 October | 6.12.105+ | Tier 1 lsm+fmod_ret, Ready with default strict settings on the tested cohort |
| Measured Ubuntu 24.04.5 | 6.8.0-1062-gke | Refused by default: BPF LSM is built but inactive |
Qualify the exact image and agent release. See the recorded COS cohort and platform matrix; kernel version or a GKE label alone does not establish readiness.
| AMI | Kernel | Supported |
|---|---|---|
| Amazon Linux 2023 | 6.1+ | Yes |
| Amazon Linux 2 | 5.10+ | Yes (basic) |
| Ubuntu 22.04 | 5.15+ | Yes |
Amazon Linux 2023 is recommended for EKS deployments.
| Node Image | Kernel | Supported |
|---|---|---|
| Ubuntu 22.04 | 5.15+ | Yes |
| Azure Linux (Mariner) | 5.15+ | Yes |
AKS with Ubuntu node images meets kernel requirements by default.
Managed Kubernetes Compatibility¶
Serverless/Autopilot environments are not supported
The eBPF agent requires hostPID: true and privileged container access, which are not available on serverless Kubernetes platforms.
| Platform | Supported | Reason |
|---|---|---|
| GKE Standard | Yes | Full host access available |
| GKE Autopilot | No | Cannot run privileged DaemonSets |
| EKS (managed nodes) | Yes | Full host access available |
| EKS (self-managed nodes) | Yes | Full host access available |
| AWS Fargate | No | No host access, no DaemonSet support |
| AKS (regular node pools) | Yes | Full host access available |
| AKS (Virtual Nodes) | No | Backed by Azure Container Instances, no host access |
Installation¶
The eBPF agent is part of the unified cloudtaser Helm chart and is enabled by default. If you already installed cloudtaser following the operator installation guide, the eBPF DaemonSet is already running.
Before deploying protected applications, enroll their workload namespaces
with label cloudtaser.io/inject=true and retain pod injection annotations.
A running node agent alone does not enroll a namespace or inject its workloads.
Verify Default Installation¶
Expected output:
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
cloudtaser-ebpf 3 3 3 3 3 <none> 2m
Enable or Disable via Helm Values¶
To explicitly control the eBPF agent during installation (the examples use the direct secret-store profile; see Operator Installation):
helm repo add cloudtaser https://charts.cloudtaser.io
helm repo update
helm install cloudtaser cloudtaser/cloudtaser \
--namespace cloudtaser-system \
--create-namespace \
--set operator.secretBackend=vault \
--set operator.enableReverseConnect=false \
--set operator.broker.beacon.enabled=false \
--set operator.secretstore.address=https://vault.eu.example.com \
--set networkPolicy.vaultCIDR=<secret-store CIDR> \
--set ebpf.enabled=true
helm repo add cloudtaser https://charts.cloudtaser.io
helm repo update
helm install cloudtaser cloudtaser/cloudtaser \
--namespace cloudtaser-system \
--create-namespace \
--set operator.secretBackend=vault \
--set operator.enableReverseConnect=false \
--set operator.broker.beacon.enabled=false \
--set operator.secretstore.address=https://vault.eu.example.com \
--set networkPolicy.vaultCIDR=<secret-store CIDR> \
--set ebpf.enabled=false
Warning
Disabling the eBPF agent removes runtime enforcement. Secrets are still protected at the infrastructure level (memory-only, no etcd), but node-level exfiltration attacks are not blocked. The protection score for workloads will be reduced.
Helm Values¶
ebpf:
enabled: true
image:
repository: europe-west4-docker.pkg.dev/skipopsmain/cloudtaser/cloudtaser-ebpf
tag: "v0.13.164"
pullPolicy: IfNotPresent
# Block exfiltration attempts (vs. log-only)
enforceMode: true
# Log all syscall events (verbose, for debugging only)
logAll: false
# Terminate processes that attempt to read protected memory
reactiveKill: true
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
| Value | Default | Description |
|---|---|---|
ebpf.enabled |
true |
Deploy the eBPF DaemonSet |
ebpf.enforceMode |
true |
Block exfiltration attempts. Set to false for audit-only mode |
ebpf.logAll |
false |
Log all monitored syscalls. Enable only for debugging |
ebpf.reactiveKill |
true |
Kill processes that attempt to read protected process memory |
Seccomp Profile Root¶
The agent writes the profiles/cloudtaser-memfd.json Localhost seccomp profile that injected containers use by default (operator.seccomp.localhostProfile). The kubelet resolves Localhost profiles under <kubelet --root-dir>/seccomp, so ebpf.seccompHostDir must be that directory on every node. It follows the kubelet's --root-dir, not the distribution name:
| Kubelet | ebpf.seccompHostDir |
|---|---|
| kubeadm, GKE, EKS, AKS | /var/lib/kubelet/seccomp (chart default) |
| K3s, rootful (default) | /var/lib/kubelet/seccomp (chart default). K3s passes no --root-dir, so the kubelet default applies |
| K3s rootless | <data-dir>/agent/kubelet/seccomp |
| k0s | /var/lib/k0s/kubelet/seccomp |
Any kubelet started with --root-dir=<dir> (K3s: --kubelet-arg=root-dir=<dir>) |
<dir>/seccomp |
Do not use /var/lib/rancher/k3s/agent/kubelet/seccomp on rootful K3s
Earlier guidance listed this path for K3s. Current rootful K3s never reads it: the agent writes the profile there, the runtime looks under /var/lib/kubelet/seccomp, and every injected pod stays in CreateContainerError.
To check a node, read the kubelet's --root-dir flag. On kubeadm-style nodes run ps -o args= -C kubelet. On K3s run journalctl -u k3s | grep -o -- '--root-dir=[^ ]*'; no match means the default /var/lib/kubelet. A wrong root shows up as:
cannot load seccomp profile "/var/lib/kubelet/seccomp/profiles/cloudtaser-memfd.json": open ...: no such file or directory
The directory before /profiles/ in that message is the value to set:
helm upgrade cloudtaser cloudtaser/cloudtaser -n cloudtaser-system --reuse-values \
--set ebpf.seccompHostDir=/var/lib/kubelet/seccomp
Keep the Localhost profile. Do not switch workloads to Unconfined to get past the error.
Verify Installation¶
Check DaemonSet Status¶
Ensure the DaemonSet is running on all schedulable nodes:
The DESIRED, CURRENT, and READY counts should all match and equal the number of nodes in your cluster.
Check Node Coverage¶
Verify every node has a running eBPF agent pod:
Each node should have exactly one eBPF agent pod in Running state.
Check Agent Logs¶
Look for log lines confirming BPF programs have been loaded and the agent is monitoring protected PIDs.
Check Health Endpoints¶
The eBPF agent exposes HTTP health endpoints:
# Liveness
kubectl exec -n cloudtaser-system daemonset/cloudtaser-ebpf -- wget -qO- http://localhost:9090/healthz
# Readiness
kubectl exec -n cloudtaser-system daemonset/cloudtaser-ebpf -- wget -qO- http://localhost:9090/readyz
Validate with CLI¶
If you have the cloudtaser CLI installed:
The output includes eBPF enforcement coverage -- the percentage of nodes with a healthy eBPF agent.
Required Capabilities¶
The eBPF agent runs as a privileged DaemonSet with the following security context:
Required Linux capabilities:
| Capability | Purpose |
|---|---|
SYS_ADMIN |
Load and attach BPF programs |
SYS_PTRACE |
Access process information for PID monitoring |
NET_ADMIN |
Attach network-related BPF programs |
SYS_RESOURCE |
Increase locked memory limits for BPF maps |
The agent uses priorityClassName: system-node-critical to ensure scheduling even under resource pressure.
Compliance note: enforcement modes
The eBPF agent supports two operational modes: detect (audit-only) and enforce (active blocking). In detect mode, exfiltration attempts are logged but not prevented -- suitable for initial assessment. In enforce mode, the agent actively blocks syscalls that would leak secrets, providing a verifiable runtime protection guarantee. For regulated environments, enforce mode with reactiveKill enabled provides the strongest protection posture. All events are logged and can be streamed to the cloudtaser Platform for centralized audit trails.
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
DaemonSet pods in CrashLoopBackOff |
Kernel too old or BPF not enabled | Check kernel version is 5.8+; verify /sys/fs/bpf is mounted |
DESIRED != READY |
Agent failing on specific nodes | Check logs on the failing node's pod; likely a kernel compatibility issue |
Injected pods in CreateContainerError: cannot load seccomp profile ".../profiles/cloudtaser-memfd.json" |
ebpf.seccompHostDir is not the kubelet's seccomp root |
Set it to the directory before /profiles/ in the error; see Seccomp Profile Root |
| Agent running but no enforcement | enforceMode: false |
Set ebpf.enforceMode=true in Helm values and upgrade |
| Low protection score despite agent running | Agent not receiving PID registrations from operator | Check connectivity between eBPF agent and operator on port 8199 |
For more details, see Troubleshooting and Kernel Compatibility.
Next Steps¶
- Configure the S3 encryption proxy for client-side encryption of stored data
- Production deployment guide for HA, monitoring, and network policies
- eBPF enforcement details for the full list of monitored syscalls and enforcement actions