Open-Source Wikis

/

Istio

/

Features

/

Ambient mode

istio/istio

Ambient mode

Active contributors: howardjohn, stevenctl, hzxuzhonghu, keithmattix, costinm

What users do

Run Istio without sidecars. Workloads stay un-modified; mesh features are delivered by:

  • Ztunnel — a per-node Rust proxy that handles L4 mTLS and basic identity-based authorization.
  • Waypoints — optional per-namespace or per-service Envoy proxies that handle L7 features (HTTP routing, L7 authorization, retries, fault injection).

The user-visible model is "label a namespace istio.io/dataplane-mode=ambient and traffic gets mTLS for free; create a Gateway of class istio.io/waypoint to add L7".

The user-facing docs are at https://istio.io/latest/docs/ambient/. This page is the implementation map.

Two layers

graph TD
    subgraph Node["Node"]
        cni[istio-cni node-agent]
        zt[ztunnel]
        pod1[Pod A] -.-|netns redirect via veth| zt
        pod2[Pod B] -.-|netns redirect via veth| zt
    end
    subgraph Mesh["Mesh"]
        wp[Waypoint Envoy<br/>per-ns or per-service]
    end
    zt -->|HBONE| zt2[ztunnel on remote node]
    zt -->|HBONE for L7-marked traffic| wp
    wp --> zt
    cni -->|ZDS| zt

The CNI node-agent watches Pods, decides which need ambient redirection, configures iptables/socket inside the Pod's network namespace, and notifies ztunnel via ZDS (pkg/zdsapi/). Once a Pod is "in", all its TCP traffic flows through ztunnel.

Where the work happens in this repo

The Istio repo holds:

  • istio-cni node-agent: cni/. See applications/istio-cni.
  • istiod-side ambient registry: pilot/pkg/serviceregistry/kube/controller/ambient/. See systems/ambient-mesh.
  • Workload API: pkg/workloadapi/workload.proto and the xDS generator at pilot/pkg/xds/workload.go.
  • Waypoint config: pilot/pkg/networking/core/listener_waypoint.go, cluster_waypoint.go, waypoint.go.
  • HBONE library: pkg/hbone/.
  • ZDS protocol: pkg/zdsapi/.

The ztunnel binary itself lives in istio/ztunnel (Rust). This repo references the upstream ztunnel via istio.deps.

Lifecycle of a packet

sequenceDiagram
    participant App as App pod (no sidecar)
    participant ZT1 as Local ztunnel
    participant ZT2 as Remote ztunnel
    participant Dest as Destination pod
    App->>ZT1: TCP to <svc-IP>:<port>
    Note over ZT1: Look up Workload by IP from cached wDS
    ZT1->>ZT2: HBONE (HTTP/2 CONNECT) over mTLS<br/>SAN = source SPIFFE URI
    ZT2->>ZT2: validate AuthorizationPolicy
    ZT2->>Dest: plaintext to dest IP:port
    Dest-->>ZT2: response
    ZT2-->>ZT1: response (HBONE)
    ZT1-->>App: response (TCP)

If either source or destination has a waypoint configured, the packet path includes a redirect through the waypoint Envoy.

Workload API

Ztunnel does not speak Envoy CDS/EDS. It speaks an Istio-specific xDS surface:

  • Workload — keyed by IP. Identity, namespace, labels, mTLS mode, optional waypoint reference.
  • Service — keyed by hostname/VIP. Ports, endpoints, optional waypoint reference.
  • Address — the polymorphic oneof Workload|Service actually subscribed to.
  • Authorization — compiled L4 policy.

All defined in pkg/workloadapi/workload.proto. Served from pilot/pkg/xds/workload.go.

The data model is denormalized: a Workload contains everything ztunnel needs to make a decision (identity, network, waypoint reference, mode). This is intentional — ztunnel does not have to do graph walks at decision time.

Waypoint provisioning

Waypoints are provisioned via the Kubernetes Gateway API:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-waypoint
  namespace: my-app
spec:
  gatewayClassName: istio-waypoint
  listeners:
    - name: mesh
      port: 15008
      protocol: HBONE

Istiod's Gateway API translator (pilot/pkg/config/kube/gateway/) recognizes the class and reconciles a Deployment + Service for the waypoint. Workloads attach to the waypoint via:

  • istio.io/use-waypoint=<name> label on the namespace, service, or workload.
  • The WaypointsCollection in the ambient registry resolves the binding.

The waypoint Envoy itself is configured with a special listener stack (listener_waypoint.go) that:

  • Terminates HBONE on port 15008.
  • Applies L7 routing, L7 authorization, retries, and any other L7 feature.
  • Re-originates HBONE to the destination ztunnel.

L4 vs L7 split

Ambient's value proposition is "you only pay the cost of the features you use":

Feature Where it runs Cost
mTLS, identity Ztunnel Per-node, shared across all workloads
L4 authorization Ztunnel Per-node, shared
HTTP routing Waypoint Per-namespace or per-service Envoy
HTTP authn (JWT) Waypoint Same
L7 authorization Waypoint Same
Retries / faults / mirroring Waypoint Same
Tracing Waypoint Same

The L4 layer is "always on" once a namespace is in ambient. The L7 layer is opt-in by deploying a waypoint.

Mode interop

Ambient and sidecar modes can coexist in the same mesh. A workload is in one mode at a time, but workloads in different modes can call each other freely. The xDS generators handle both modes off the same PushContext; the difference is in which proxies subscribe to which surfaces.

The selection rule:

  • If a Pod has the istio.io/dataplane-mode=ambient label (or its namespace does, and the Pod doesn't override) → ambient.
  • If a Pod has a sidecar (injected via webhook) → sidecar.
  • Sidecar-injected pods in an ambient namespace stay sidecar (the sidecar wins).

Trade-offs

  • Per-node identity — ztunnel speaks for every workload on its node. A compromised ztunnel impersonates every workload on the node. Sidecars limit blast radius to one workload per sidecar.
  • L7 features cost — to use any L7 feature, deploy a waypoint, which is an Envoy. The cost compares to "every pod has a sidecar" only when most pods need L7 features.
  • Visibility — Envoy access logs and tracing are at the waypoint, not at each workload. Out-of-mesh traffic and L4-only traffic don't show in HTTP-level traces.
  • Newness — Ambient went GA in 2024 (1.24); the surrounding tooling (istioctl analyzers, dashboards) is still catching up to sidecar-mode parity.

Key source files

File Purpose
pilot/pkg/serviceregistry/kube/controller/ambient/index.go Top-level Index
pilot/pkg/serviceregistry/kube/controller/ambient/workloads.go Workload collection
pilot/pkg/serviceregistry/kube/controller/ambient/waypoints.go Waypoint resolution
pilot/pkg/serviceregistry/kube/controller/ambient/authorization.go L4 policy compiler
pilot/pkg/xds/workload.go Workload API generator
pkg/workloadapi/workload.proto The wire format
pilot/pkg/networking/core/listener_waypoint.go Waypoint listeners
pkg/hbone/ HBONE library
pkg/zdsapi/ ZDS protocol
cni/pkg/nodeagent/ CNI node agent for ambient

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Ambient mode – Istio wiki | Factory