🎉 Emissary v4.2.0-rc.0 🎉
Emissary-ingress is an open source, Kubernetes-native microservices API gateway built on the Envoy Proxy.
Get started with Emissary-ingress - https://emissary-ingress.dev/docs/4.1/quick-start/ (use --version=4.2.0-rc.0 for both charts to try this release candidate)
View changelog - https://github.com/emissary-ingress/emissary/blob/v4.2.0-rc.0/CHANGELOG.md
Changes
- Update: Upgrade from Envoy 1.37.2 to Envoy 1.40.2 (1.38.0 release notes,
1.39.0 release notes, 1.40.0 release notes, 1.40.2 release notes). Envoy
1.40 changes some defaults that are visible through Emissary:- When
ENVOY_CONCURRENCYis not set, Envoy now sizes its worker threads to
the container's cgroup CPU limit rather than to the node's CPU count. Set
ENVOY_CGROUP_CPU_DETECTION=falseon the Emissary container to keep the old
behaviour. - The
x-envoy-upstream-stream-duration-msrequest header is now stripped from
external requests, like the otherx-envoy-*timeout and retry headers. - The HTTP/1
QUERYmethod is now forwarded upstream rather than rejected with
a 400. - Regular expressions in
Mappings (prefix_regex,regex_headers,
regex_rewrite, and so on) are now matched in Latin-1 mode rather than UTF-8
(CVE-2026-73552). X25519MLKEM768is now one of the default TLS ECDH curves forHosts and
TLSContexts that do not setecdh_curves.- The image's CA bundle no longer trusts the compromised eMudhra intermediate
CAs.
- When
-
Update: Emissary is now built with Go 1.27.3 and the Kubernetes 1.37 client
libraries, and its other Go and Python dependencies are updated to their
current releases.diagdnow postsIngressand other resource status
updates from threads rather than from forked worker processes, so the
Emissary pod no longer runs five extradiagdprocesses once the first
status update is posted. -
Security:
diagd's internal API -- most importantlyPOST /_internal/v0/watt,
which hands Emissary a new configuration snapshot -- is no longer reachable
through the admin port (8877).diagdnow listens on a Unix-domain socket
(AMBASSADOR_DIAGD_SOCKET, default$AMBASSADOR_CONFIG_BASE_DIR/diagd.sock)
rather than on TCP, and the server on 8877 refuses to proxy/_internal/at
all, so submitting a snapshot now requires being on the pod. Health checks and
the diagnostics UI on 8877 are unchanged. Note that bindingdiagdto
127.0.0.1 would not have been sufficient, sincekubectl port-forwardmakes
off-pod traffic appear to originate from 127.0.0.1.This removes the
AMBASSADOR_DIAGD_BIND_PORTandAMBASSADOR_DIAGD_BIND_ADDREASS
environment variables, which no longer have anything to configure. -
Security: The snapshot is now handed to
diagddirectly, as the body of the
/_internal/v0/wattrequest, rather than as a URL fordiagdto go fetch.
This removes the snapshot server that used to listen onlocalhost:9696,
which served the unsanitized snapshot -- secrets and all -- and which was
reachable withkubectl port-forward. (The sanitized snapshot is still
available on 8005 as before.) It also removes an attacker-controlled fetch
from the/_internal/v0/watthandler. -
Fix: Completely disable the Ambassador Labs
error_response_overridesmechanism;
you'll now see an error posted if you try to use it. (This shouldn't affect anyone
running Emissary.) -
Fix: Weighted
TCPMappings now divide traffic in the ratio they are configured with.
Their weights were reaching Envoy as running totals rather than as each cluster's own
share, so a pair weighted 70 and 30 actually split about 77/23. If you had tuned
weights around the old behaviour, your split will change. -
Fix: A
ConsulResolver'sdatacenteris now honored. It was being ignored, so
every lookup went to the datacenter of the Consul agent ataddress, and a
resolver naming a datacenter that agent does not serve (or serves under another
name) still resolved. Lookups now query the named datacenter; if you had a
wrongdatacenterthat happened to work, it will stop resolving. -
Fix:
apiextnow eagerly generates its webhook server certificate for its
well-known Service hostname as part of its readiness check, rather than
generating it lazily on the first incoming TLS handshake. Previously, the
first CRD-conversion request from the Kubernetes apiserver afterapiext
reported itself ready could be the one paying for certificate generation,
occasionally causing that request to time out (#4275).
-
Fix: Two
ConsulResolvers in different datacenters that watch services with the
same name no longer overwrite each other's endpoints. Previously only one of
the two Mappings got endpoints (the other returned 503), and which one could
change as either watch updated. -
Fix: The Helm chart no longer declares the same
containerPorttwice when several
service.portsshare atargetPort(for examplehttpandhttpsboth targeting 8080
when TLS is terminated at the load balancer). Duplicate entries can make the Deployment fail to apply.
AhostPortset on any of those service ports is kept, and differenthostPortvalues for the
sametargetPortare rejected. (#5802)
-
Fix: Two Mappings for the same service, one using the default Kubernetes service
resolver and one using an endpoint resolver, no longer share one Envoy cluster.
Whichever loaded first decided the cluster type for both, so one Mapping could lose
per-pod endpoints and its health checks, or gain them unasked. Clusters for Mappings
with a non-default resolver now include the resolver name, so Envoy recreates them
once on upgrade; stats names are unchanged. -
Fix: An
add_request_headersoradd_response_headersentry written as an object
with novalue(for examplecache-control: {append: true}) no longer crashes
Emissary. The header is skipped and an error is logged (#4760).
- Feature:
TLSContexts and thetlssettings of aHostnow accept
signature_algorithms, which is passed to Envoy alongsidecipher_suitesand
ecdh_curves. Envoy's default list leaves outed25519, so this is how to accept
Ed25519 client certificates (#5871).
- Feature: The
emissary-crdschart can now schedule theemissary-apiext
Deployment withapiext.nodeSelectorandapiext.tolerations. Both default to
empty, so existing installs render the same.