June 1, 2018·6 min read·engineeringistioroutingenvoy

Istio 0.8 streams the redesigned traffic configuration to Envoy

Istio 0.8 makes the new routing model available alongside streaming proxy configuration. The ADS implementation shows how declared mesh changes become updates to connected proxies.

Changing a routing object and changing a proxy's active configuration are different operations. Istio 0.8 addresses both sides of that relationship. The June 1 release introduces the revised traffic management model and makes Pilot's streaming Envoy configuration the default. The API expresses the desired routing relationships, while the discovery stream carries generated configuration to connected proxies.

I consider the delivery mechanism as important as the routing vocabulary. A mesh can make retries and traffic splits consistent across application languages, but that consistency depends on distributing changes successfully. Understanding which proxies are connected and what updates they receive is part of operating the additional distributed system introduced by the mesh.

The release describes its streaming mechanism as Envoy's Aggregated Discovery Service, or ADS. Its stated goals include reducing rollout delay and avoiding spurious missing-route responses. Those goals concern coordination of configuration delivery. They do not mean that accepting an Istio resource immediately proves every proxy has accepted the corresponding generated configuration.

ADS maintains a connection for proxy discovery

The 0.8.0 ADS implementation maintains connection records for clients. Each record includes the peer address, connection time and an identifier derived from the proxy's node identity. It also tracks which clusters and routes the client watches and whether it has requested listener or cluster discovery.

The stream handler receives discovery requests while also waiting for configuration-change pushes. Because receiving from the stream blocks, a separate goroutine reads requests and forwards them through a channel. The main loop can then select between a client request and a push event. This connects the proxy's subscription state with Pilot's observation of mesh changes.

A request must carry a node identifier which the implementation can parse. The handler extracts proxy metadata and stores the resulting proxy model on the connection. Its generated configuration is consequently associated with a particular proxy identity, not just an anonymous open socket. That matters because different workloads can need different listeners, routes and destinations.

The connection record also holds generated HTTP listeners, route configurations and clusters. These fields give the discovery implementation somewhere to associate configuration work with the connected proxy. The source distinguishes a sidecar identity from an individual connection identifier because an old proxy can reconnect around the same time as a replacement proxy. One workload identity does not always imply exactly one transport connection during a restart.

Resource requests and acknowledgements share the stream

The handler dispatches requests by resource type. Cluster and listener requests establish watch flags and trigger initial pushes. Subsequent requests for those established watches are treated as acknowledgements. When a request contains error details, the implementation logs a rejection and updates the corresponding rejection metric.

Routes and endpoints also track the lists the client requests. The implementation stores route names and cluster names on the connection and uses them to generate the responses for that client. A route response includes its resource type, version information and nonce along with serialized route resources. These fields belong to the delivery protocol surrounding the actual routing content.

This makes acknowledgement information operationally distinct from connection health. A proxy can remain connected while reporting an error for a resource update. The source exposes rejection counters for several resource types because the fact that a stream exists is insufficient to describe whether its configuration is usable. The error details provide another observation within the delivery process.

The send helper also has a specific boundary. It waits for the stream's send operation to finish or for a timeout. A source comment explicitly leaves waiting for acknowledgement as further work in that helper. Completing a send therefore cannot be interpreted as that helper proving that Envoy accepted the response. Transport delivery and configuration acceptance remain separate stages.

Mesh changes trigger regeneration for connected proxies

The implementation's global push function responds to rule or endpoint changes. It first updates endpoint load assignments, then iterates through a snapshot of the connected-client map. Copying the map allows the code to perform the push work without holding the connection-map lock across the whole operation. New and departing connections still have their own lifecycle.

For each client, the function sends a push event through the connection's channel. The stream loop responds by pushing the resource categories that client watches. In this implementation, the order on that path is clusters, routes, endpoints and then listeners. The code retains each client's watch state so it can select which operations apply.

A comment states that the path does not yet selectively push only the particular resources which changed. The global event can therefore trigger broader configuration work for connected proxies. Streaming changes when updates travel to clients, but it does not by itself make every update minimal. Regeneration scope is another part of scalability.

The source pushes through clients serially and explains that this avoids large CPU and memory spikes. It bounds how long it waits to queue a push to a client and records timeout failures. This is a deliberate resource tradeoff in the control plane. Sending everything concurrently could reduce waiting for one client while increasing instantaneous generation and delivery work.

Each connection records its last push time and the beginning of a push-failure period. A successful enqueue clears the failure timestamp, while repeated timeouts can produce a separate long-failure metric. This distinguishes a temporary busy client from a connection which repeatedly prevents push work from proceeding. The measurement concerns queueing the update, so it should be read alongside the send result and acknowledgement information.

I find that tradeoff relevant to fleet-scale adoption. The mesh has to distribute policy across many proxies while preserving enough resources to continue processing subsequent changes. The implementation makes that pressure visible through timeouts and push metrics. A configured route can require operational attention at the delivery layer even when the routing object itself is valid.

The API separates listeners from request routing

The routing model explanation published in April supplies the conceptual counterpart to ADS. Gateway describes listener-facing settings such as ports and TLS. VirtualService defines ordered routing for addressed hosts, while DestinationRule supplies subsets and forwarding policy. ServiceEntry represents additional destinations in the internal registry.

The June release makes Gateway the supported way to combine Istio's advanced routing with ingress and egress proxies. It explicitly ends support for combining Kubernetes Ingress specifications with Istio routing rules, citing bugs and reliability problems. This is a concrete change for an existing deployment whose edge traffic depends on that combination. Translating only internal routing objects would leave part of the configuration model unconverted.

Gateway also supports SNI-based routing and certificate selection based on the server name presented by the client. That gives listener configuration a way to express TLS decisions before HTTP routing. The Gateway and VirtualService still need a coherent host and binding relationship. The new resource names do not eliminate those dependencies between configuration objects.

The release supplies a conversion tool through istioctl to help translate old networking configuration. It also documents a namespace problem in that experimental tool, where the output may use istio-system instead of the intended namespace. That limitation affects the resulting resource placement. Conversion output is therefore part of the migration artifact whose semantics must be understood.

Streaming is one part of a selectable installation

Istio 0.8 also supports installing selected functionality through Helm or istioctl gen-deploy. The announcement specifically identifies a Pilot-only installation as a way to use traffic management without Mixer or Citadel. This permits an organization to select the responsibilities it wants the mesh to assume, while still operating the discovery relationship between Pilot and its proxies.

Citadel is the new name for the component previously called Istio-Auth or Istio-CA. The release also introduces a recommended authentication policy API. Those choices remain distinct from whether the proxy receives a listener or route update over ADS. Routing delivery does not establish that an application has the intended authentication policy or certificate configuration.

The ADS implementation records connected clients and removes them as streams end. It also removes endpoint subscriptions associated with a departing connection and updates the connection count. These cleanup operations keep the control plane's delivery state aligned with active proxies. The routing resources describe intended traffic behavior, while this connection state describes which proxy processes are currently participating in configuration delivery.