March 8, 2018·4 min read·engineeringistioenvoyconfiguration

Istio 0.6 exposes Pilot configuration through a webhook

Custom Envoy configuration in Istio 0.6 works through Pilot's generated discovery responses. Caching and fallback behavior determine when a custom transformation reaches the proxy.

A mesh abstraction cannot anticipate every Envoy configuration a deployment may need. Istio 0.6 adds a way for Pilot to carry custom configuration to its proxies, as described in the March 8 release announcement. The implementation operates on generated discovery responses. That gives customization access to the output Envoy consumes while introducing dependencies on Pilot's generation and caching behavior.

I regard this as a useful capability with an operational cost. Moving traffic policy into shared configuration helps a mixed-language application, but custom proxy configuration requires understanding the proxy's representation as well. Once a deployment changes Pilot's generated output, debugging has to account for both the standard generator and the custom transformation.

Transformation follows configuration generation

The 0.6.0 discovery implementation stores a webhook endpoint and HTTP client alongside discovery caches. When generating cluster, listener or route responses, it can invoke the webhook after serializing the ordinary response. The custom code receives the representation which Pilot has generated, rather than a request to implement all discovery behavior from scratch.

The invocation posts JSON to the configured endpoint combined with the discovery request path. It reads the response body and returns those bytes as the transformed output. When no webhook client is configured, the method returns the original payload. This preserves the standard generation path for deployments that do not select custom transformation.

That placement has a specific consequence for ownership of behavior. Pilot still computes its default view of the mesh and serializes it. The webhook can then change that output before it reaches the proxy. A problem may originate in the standard mesh inputs, in generation, or in the transform. Treating all resulting configuration as though it came directly from a routing rule would omit one of those stages.

Failure can return the unmodified response

The cluster and route handlers fall back to their generated output when invoking the webhook returns an error. The listener handler does the same and logs the error. This behavior keeps the ordinary generated response available when the transform cannot complete. It also means a customization failure does not necessarily appear as a failed discovery request.

That distinction matters if an operator expects a custom filter to be present. A working proxy can have received ordinary Pilot output after the transform failed. The success of the discovery HTTP exchange is therefore insufficient evidence that the customization took effect. The actual returned configuration has to be consistent with the intended transform.

The invocation method records calls and errors through dedicated counter helpers. Network-post errors and response-body read errors increment the webhook error counter. The source thereby treats the transform as a distinct operation within discovery. Its failure behavior deserves examination independently of whether Pilot can still produce its own configuration.

There is another boundary visible in the method. It returns the response bytes after reading them, without decoding a complete Envoy configuration object in that function. The transformation service's output is consequently part of what an operator must validate. A byte response from that service does not establish that the resulting Envoy configuration expresses the intended behavior.

Caching controls when the webhook runs

The discovery handlers first check their respective caches. They generate and transform output when a cached response is unavailable. On a cache hit, the stored response is used directly. A change to the transform's code is therefore different from a mesh change which causes Pilot to regenerate configuration.

The constructor registers handlers which clear cached discovery responses when services, instances or routing configuration change. Its comments describe a broad cache flush rather than selective invalidation. Those inputs give Pilot a reason to recompute its output. A separate script edit in a transformation service does not automatically appear among those registered mesh events.

This explains a limitation documented by the customization example linked from the release. Updating its Lua script does not automatically refresh the generated configuration. The example requires a service with endpoints for listener, route and cluster discovery transformations and configures Pilot with the webhook endpoint. Its cache limitation follows directly from when the implementation invokes that service.

The distinction is useful during iteration. Seeing the new script mounted into its container establishes that the script file changed. It does not establish that Pilot ran the script against a newly generated response. The cache can still hold an earlier transformed result, which explains why a configuration edit and an observable proxy change may occur at different times.

Resource accounting also reflects the original generator

Comments in the cluster and listener handlers identify a further limitation. Their resource counts come from the original generated objects, without accounting for resources added by the webhook. Cache updates are conditional on those counts being positive. If the generator produced no resources but the webhook added some, the comments note that the cache would not update as intended.

This is a concrete example of the integration work required by a low-level extension. Changing the serialized output can affect more than the proxy. Pilot's surrounding bookkeeping also reasons about the resources it generated. A custom transform may produce valid data while leaving that bookkeeping based on a different count.

Route handling has corresponding comments about virtual-host counts and the same general cache concern. The resource histogram records the count known to the handler when writing its response. That count should consequently be interpreted as Pilot's accounting in this implementation. It is not an independent inventory of every resource the transformation may have inserted into the serialized bytes.

I find the documented limitations useful because they identify the level at which this extension operates. It is a modification of generated responses, with caching and accounting still controlled by Pilot. The release also adds egress policy and telemetry support, but this customization path has its own lifecycle. An operator using it needs to examine the cached discovery response and the transformation service together to explain the configuration Envoy receives.