Advanced Istio features you can safely enable during upgrade
Istio upgrade is usually treated as a version bump and nothing else: move the control plane, restart the gateways and sidecars, and it’s done. But a major release quietly ships features you can turn on in the same change window, most of them additive and low-risk. Here are six worth feature that you can enable during upgrade:
1. Post-quantum key exchange on your gateways
Latest Istio version offer a hybrid post-quantum key exchange, X25519MLKEM768 (classical X25519 combined with ML-KEM-768), for TLS. A client that supports it negotiates a quantum-resistant handshake. a client that does not falls back to plain X25519. It is additive: nothing breaks, you just gain the option.
meshConfig:
tlsDefaults:
ecdhCurves:
- X25519MLKEM768 # hybrid PQC, preferred
- X25519 # classical fallback
- P-256
tlsDefaults.ecdhCurves applies to your ingress and egress gateways, and TLS to external services. It does not touch mesh-internal mTLS between sidecars, which uses Istio’s own mTLS stack.
So this hardens your edge against “harvest now, decrypt later”, not pod-to-pod traffic. List the hybrid curve first so it is preferred, and keep X25519 so older clients still connect.
2. Move your image hub off gcr.io
Istio is retiring gcr.io/istio-release and registry.istio.io/release, with the old location working until late 2026 and a hard cutoff on January 1, 2027. An upgrade is the natural moment to repoint your hub, and a good moment to mirror it into your own registry so a public-registry outage or rate limit can never block a rollout.
# IstioOperator
spec:
hub: ghcr.io/zufardhiyaulhaq/istio-mirror
# or pull through your own mirror:
# hub: <your-registry>/istio
With Helm, the same setting is global.hub=ghcr.io/zufardhiyaulhaq/istio-mirror. If you mirror, make sure it has the exact tags for the version you are installing (proxyv2, pilot, and so on) before you cut over. Otherwise this is as safe as it gets: it only changes where images are pulled from.
3. Emit both B3 and W3C trace headers
Latest Istio exposes traceContextOption on the Zipkin tracing provider. USE_B3_WITH_W3C_PROPAGATION reads trace context from B3, falls back to the W3C traceparent header when B3 is missing, and emits both upstream.
meshConfig:
extensionProviders:
- name: zipkin
zipkin:
service: zipkin.istio-system.svc.cluster.local
port: 9411
traceContextOption: USE_B3_WITH_W3C_PROPAGATION
This is a migration bridge. Your existing B3 apps (Zipkin, Jaeger) keep working, and any OpenTelemetry-instrumented service, which reads traceparent and not x-b3-*, stops orphaning its spans at the mesh hop.
The cost is one extra header upstream, a fixed traceparent line of about 55 bytes, and it does not accumulate across hops because each proxy overwrites its own span. But it is only worth turning on if something in your mesh actually reads W3C. On an all-B3 stack it just carries a header nobody consumes, so enable it when you have, or are adding, OTel services, not reflexively.
4. Raise the header size and count limits
Envoy caps request headers by size (default 60 KiB) and by count (default 100). Cross either limit and the request is rejected with 431 Request Header Fields Too Large before it ever reaches your application.you can raise both gateway and sidecar with an EnvoyFilter pinned to the proxy version.
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: header-size-and-count-1.28-ef
namespace: istio-system
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: ANY
listener:
filterChain:
filter:
name: envoy.filters.network.http_connection_manager
proxy:
proxyVersion: ^1\.28.*
patch:
operation: MERGE
value:
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
max_request_headers_kb: 128
common_http_protocol_options:
max_headers_count: 200
proxyVersion: ^1\.28.* binds this filter only to 1.28 proxies, so keep the equivalent EnvoyFilter for your previous version in place during the sidecar rollout.
Sidecars restart over days or weeks, and both proxy versions need to be covered the whole time. Size and count are independent limits: raise both. I wrote up why both axes matter, and the CVEs behind them, in a separate note on HTTP header limits.
5. HTTP/3 (QUIC) on the ingress gateway
Latest Istio can serve HTTP/3 over QUIC at the gateway. Clients still connect first over HTTPS on TCP, receive an Alt-Svc header advertising HTTP/3, and then switch to QUIC over UDP.
There are three pieces. Enable the listener through the pilot env:
spec:
values:
pilot:
env:
PILOT_ENABLE_QUIC_LISTENERS: "true"
Add a UDP port to the ingress-gateway Service, alongside the existing TCP one:
ports:
- name: https
port: 443
targetPort: 8443
protocol: TCP
- name: http3
port: 443
targetPort: 8443
protocol: UDP
The Gateway resource itself stays HTTPS on 443 with your normal TLS; QUIC negotiation happens at the Envoy layer.
This is the one feature here that is experimental, not in the same safe tier as the rest. Your load balancer must forward UDP/443, which many L4 load balancers do not do by default, and QUIC requires TLS 1.3. Verify with curl --http3 -v https://<host>/ and the Envoy http3.downstream stats before trusting it. Try it in staging, and leave it off in production until you have confirmed the load-balancer path and measured a real benefit.
6. Tune the sidecar DNS refresh rate
Any host resolved by DNS (a ServiceEntry, an external endpoint) becomes a STRICT_DNS cluster, and every sidecar re-resolves it on a fixed interval: dnsRefreshRate. The default is aggressive (Istio issue 27329 flags it defaulting to 5 seconds as too short), and at scale that is thousands of pods each firing DNS queries every few seconds.
It is a single knob with a clear tradeoff: raise it to relieve DNS load, lower it for faster reaction to endpoint changes.
meshConfig:
defaultConfig:
dnsRefreshRate: 240s
At 240s the DNS traffic drops sharply, at the cost of taking up to four minutes to notice an external endpoint moving IPs. Because it is a ProxyConfig field, you can relax the mesh-wide default and still override a handful of DNS-sensitive workloads back to a lower value with a per-workload ProxyConfig.
Sources
- Istio: retirement of gcr.io and the Global Mesh Options reference (covers
tlsDefaults.ecdhCurves, the ZipkintraceContextOption, anddefaultConfig.dnsRefreshRate). - Red Hat OpenShift Service Mesh: post-quantum cryptography (the
X25519MLKEM768hybrid curve). - Istio: DNS proxying.
- How to configure Istio for HTTP/3 (QUIC).