v1.8.6

Date: October 26, 2026

Upgrading Envoy Proxy to v1.38.9

Changing the image rolls out the Envoy Proxy pods. Pick the option that matches how you configure the Envoy Proxy image.

Helm. Set the default Envoy Proxy image for the release:

helm upgrade eg oci://docker.io/envoyproxy/gateway-helm --version v1.8.6 -n envoy-gateway-system --reuse-values \
  --set global.images.envoyProxy.image=docker.io/envoyproxy/envoy:distroless-v1.38.9

See the Helm chart values for details on global.images.envoyProxy.image.

EnvoyGateway configuration without Helm. Set the image under envoyProxy in the envoy-gateway-config ConfigMap (use envoyDaemonSet instead of envoyDeployment if you run Envoy as a DaemonSet):

envoyProxy:
  provider:
    type: Kubernetes
    kubernetes:
      envoyDeployment:
        container:
          image: docker.io/envoyproxy/envoy:distroless-v1.38.9

EnvoyProxy resource. The two options above set a default image only. An EnvoyProxy attached through a GatewayClass or Gateway parametersRef replaces that default unless its mergeType is StrategicMerge or JSONMerge. If you attach an EnvoyProxy with no mergeType, or one that already pins an Envoy image, set the image on that EnvoyProxy:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: custom-proxy-config
  namespace: default
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyDeployment:
        container:
          image: docker.io/envoyproxy/envoy:distroless-v1.38.9

See Customize EnvoyProxy Image for details.

To check the image each Envoy Proxy Deployment is running:

kubectl get deployments -A -l app.kubernetes.io/managed-by=envoy-gateway,app.kubernetes.io/component=proxy \
  -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\t"}{.spec.template.spec.containers[?(@.name=="envoy")].image}{"\n"}{end}'

Breaking changes

Security updates

New features

Bug fixes

  • Fixed the shutdown-manager failing to create /tmp/shutdown-ready (breaking graceful shutdown and delaying proxy pod termination by the full grace period) when the Envoy container’s securityContext sets readOnlyRootFilesystem: true, by mounting a writable emptyDir at /tmp on the shutdown-manager.
  • Fixed obsolete resource snapshots being retained by the backing array of coalesced subscription updates.
  • Fixed HTTPS listeners referencing non-existent RouteConfigurations when they share a container port with an HTTP listener that is translated first (for example HTTPS on port 443 and HTTP on port 10443). The HTTPS virtual hosts were added to the HTTP listener’s RouteConfiguration, leaving the HTTPS filter chains without routes.
  • Fixed route status conditions being reported in a non-deterministic order when a route parent had errors of more than one condition type, which caused unnecessary route status updates.
  • Fixed the listener-level api_key_auth filter being built from the first route that uses API key auth. Rotating that route’s keys no longer forces a listener update that drains long-lived connections on every route of the listener, and a route whose credential Secret has no usable keys now rejects requests instead of accepting the first route’s keys.
  • Fixed Service and ServiceImport backends whose EndpointSlices carry both kubernetes.io/service-name and multicluster.kubernetes.io/service-name (as Cilium ClusterMesh creates them): ServiceImport backends no longer report EndpointsNotFound, and Service backends now pick up endpoint changes.
  • Fixed an HTTPRoute not being reconciled when an HTTPRouteFilter that it references only from backendRef filters is created or updated, if the rule has no rule-level filters.
  • Fixed the Kubernetes provider’s cache scope being random on each start when watch.type is Namespaces, which could leave the controller unable to become Ready or unable to see its own namespace’s Secrets and ConfigMaps in Gateway Namespace Mode; the Helm chart now also grants EndpointSlice read in the controller namespace for this mode.
  • Fixed the Helm chart not granting Secret and EndpointSlice read in the controller namespace when watch.namespaces is set in the default deploy mode, which kept the controller from becoming Ready unless the controller namespace was listed in watch.namespaces.
  • Fixed a BackendTrafficPolicy with mergeType being recorded twice in a route’s policy metadata when two of the route’s parentRefs reach the same listener.
  • Fixed route status.parents accumulating duplicate entries until the 32-entry limit when another controller writes status for the same parentRef, by matching parent status entries on both parentRef and controllerName.
  • Fixed HTTPRoute, GRPCRoute, TLSRoute and UDPRoute parentRefs being processed in a random order, which could make the translation result non-deterministic when several parentRefs compete for the same listener. ParentRefs are now processed in spec.parentRefs order.

Performance improvements

Deprecations

Other changes