Skip to main content
Version: 2.30

Choose between the sidecar and the node-agent

Telepresence can place its traffic-agent next to your application in two ways. Both provide the same client experience — intercepts, wiretaps, ingests, environment, and volume mounts — but they differ in how the agent reaches the workload, what privileges they need, and what they leave behind.

  • The injected sidecar (the default): a mutating webhook rewrites the workload's pod template, and the pods restart with the agent container inside. See the Traffic Agent Sidecar reference.
  • The node-agent: the traffic-manager creates a node-pinned agent that attaches to the existing pod's Linux namespaces from the outside. The workload is never modified and its pods never restart. See the Node-hosted Traffic Agent reference.

Pros and cons

Injected sidecarNode-agent
Workload modificationPod template is rewritten; pods restart once when the agent is first injectedNone; the node-agent attaches to the existing pod as-is
Privileges requiredNone beyond the webhook; works under restrictive Pod Security Standards and on clusters like GKE AutopilotPrivileged: hostPID, SYS_ADMIN/SYS_PTRACE/NET_ADMIN/NET_RAW, and a read-only mount of the node's container-runtime socket. The traffic-manager's namespace must permit the privileged Pod Security Standard
Agent-injector webhookRequired (the API server must be able to reach it)Not used; works with agentInjector.enabled=false
ReplicasThe agent is injected into every pod of the workloadOne node-agent Job per replica; every replica is attached, at the cost of one privileged Job per replica
replaceSupportedNot supported
CleanupThe sidecar remains in the pods after the attachment ends (removed by telepresence uninstall or helm uninstall)The agent Job is reaped as soon as nothing uses it, and on helm uninstall
Service meshFull support, including names only resolvable inside the meshTraffic interception coexists with a mesh, but mesh-only DNS names (e.g. Istio ServiceEntry hosts) do not resolve during the attachment
User-namespaced pods (hostUsers: false)SupportedNot supported yet
Environment fidelityThe webhook copies the container's declared Env/EnvFromThe actual runtime environment is read from the running process

Rules of thumb:

  • Prefer the sidecar when the cluster restricts privileged pods, when you need replace, or when you depend on mesh-internal DNS.
  • Prefer the node-agent when restarting the workload is expensive or disallowed, when an operator reconciles the pod spec and fights the webhook, or when the agent-injector webhook cannot be used at all.

The two modes coexist in one cluster, but never on the same workload at the same time — the traffic-manager rejects mixing them (see Coexistence rules).

Configuration examples

Default: sidecar only

Nothing to configure. The agent-injector is enabled by default and node-agent mode is off:

Terminal
$ telepresence helm install
$ telepresence intercept my-service --port 8080

Both modes available, the developer chooses

The administrator enables node-agent mode; the sidecar remains the default:

Terminal
$ telepresence helm install --set nodeAgent.enabled=true

A developer picks the node-agent per attachment:

Terminal
$ telepresence intercept my-service --port 8080 --node-agent

or makes it their personal default in config.yml:

nodeAgent:
enabled: true

The administrator makes the node-agent the cluster-wide default

Everything under the Helm chart's client section flows into the client configuration that connecting workstations receive, so the client-side default can be set centrally too:

# values.yaml
nodeAgent:
enabled: true
client:
nodeAgent:
enabled: true
Terminal
$ telepresence helm install -f values.yaml

Developers now attach through node-agents without passing any flag. A workstation can still opt out of a single attachment with --node-agent=false (falling back to the sidecar), but cannot opt out through its local config.yml — for booleans, an explicit false is indistinguishable from unset in the configuration merge.

Node-agent only

Adding agentInjector.enabled=false removes the mutating webhook entirely, so nothing can ever be injected:

# values.yaml
nodeAgent:
enabled: true
client:
nodeAgent:
enabled: true
agentInjector:
enabled: false

With this configuration replace is unavailable (it requires the sidecar), and a per-attachment --node-agent=false fails with an "agent-injector is disabled" error instead of falling back.

The node's container runtime is detected automatically: containerd, CRI-O, k3s, and cri-dockerd (the docker runtime) are all recognized. Only when the runtime listens on a nonstandard socket path does nodeAgent.criSocket need to point at it explicitly.

Flag and configuration precedence

From highest to lowest:

  1. An explicit --node-agent flag (either value).
  2. The workstation's config.yml nodeAgent.enabled (when set to a non-default value).
  3. The cluster-provided client.nodeAgent.enabled from the Helm chart.
  4. Off — the sidecar is used.

Further reading