Release notes
Review the release notes for kgateway. For a detailed list of changes between tags, use the GitHub Compare changes tool.
v2.3.0
🔥 Breaking changes
Classic transformation removed
The C++ classic transformation filter is removed in 2.3.x. Rustformation, which became the default in 2.2.x, is now the only transformation engine. The useRustFormations Helm value and the USE_RUST_FORMATIONS environment variable on the controller have no effect.
If your 2.2.x install has useRustFormations: false set, migrate your TrafficPolicy transformation templates to rustformation (MiniJinja) syntax before you upgrade. Any policy that relies on classic-only behavior silently misbehaves or fails to render after the upgrade. Common patterns to watch for include:
- The
.0accessor on JSON header fields (for example,{{ headers.X-Incoming-Stuff.0 }}). Rustformation requires bracket notation:{{ headers["X-Incoming-Stuff"][0] }}. - Templates that rely on the body being auto-parsed as JSON. The classic engine auto-parses whenever a transformation is configured; rustformation defaults to
AsString. Setbody.parseAs: AsJsonexplicitly to keep dot-notation access working. - Templates that use a JSON field name that collides with a built-in template function (such as
context). WithparseAs: AsJson, MiniJinja shadows the function with the field value and fails to render.
For the full comparison and migration table, see Transformation engine.
🌟 New features
Control plane changes
- Common labels: Add custom labels to all resources that are created by the Helm charts by using the
commonLabelsfield, including the Deployment, Service, and ServiceAccount of the control plane. This allows you to better organize your resources or integrate with external tools. For more information, see Common labels. - PriorityClass support: Assign a PriorityClassName to control plane pods using the
controller.priorityClassNameHelm field. Priority indicates the importance of a pod relative to other pods and allows higher priority pods to preempt lower priority ones when scheduling. - Topology spread constraints: Distribute kgateway controller pods across failure domains such as zones or nodes by using the
topologySpreadConstraintsHelm field. For more information, see Topology spread constraints. - The default
app.kubernetes.io/component: controllerlabel is added to the controller deployment. Similarly, theapp.kubernetes.io/component: proxyis added to all gateway proxies.
Static IPs for Gateways
Assign a static IP address to the Kubernetes service that exposes your Gateway using the spec.addresses field with type: IPAddress.
For more information, see Static IP address.
Local rate limit filter options
The TrafficPolicy resource now supports the percentEnabled and percentEnforced optional fields to control the percentage of requests for which the local rate limit filter is enabled or enforced. If not set, both fields default to 100, which enables and enforces the local rate limiting filter for 100% of all requests.
Use these fields for gradual rollouts or to run the filter in shadow mode (percentEnabled: 100, percentEnforced: 0), where rate limiting statistics are collected without blocking any requests.
For more information, see Gradual rollout and shadow mode.
Envoy application log format
Configure how Envoy formats its application logs by using the logFormat field in the GatewayParameters resource. You can choose between structured JSON or text output. This setting controls the Envoy application log format only and does not affect access logs.
For more information, see Change proxy settings.
Gateway proxy customization with overlays
The GatewayParameters resource now supports gateway proxy customization via overlay fields. Overlays use strategic merge patch (SMP) semantics to apply advanced customizations to the Kubernetes resources that are generated for gateway proxies, including the Service, ServiceAccount, and Deployment.
The following overlays are supported:
- Use
deploymentOverlay,serviceOverlay, andserviceAccountOverlayto patch the generated Deployment, Service, and ServiceAccount. - Use
horizontalPodAutoscaler,verticalPodAutoscaler, andpodDisruptionBudgetto automatically create and configure these resources targeting the proxy Deployment.
For more information, see Change proxy settings and Overlay examples.
Additional Envoy container arguments
Use spec.kube.envoyContainer.extraArgs to pass additional Envoy CLI arguments to the managed proxy container. User-supplied arguments are appended after the default built-in Envoy arguments.
The following example sets a custom base ID and enables CPU set threading:
kubectl apply --server-side -f- <<'EOF'
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayParameters
metadata:
name: gw-params
namespace: kgateway-system
spec:
kube:
envoyContainer:
extraArgs:
- --base-id
- "7"
- --cpuset-threads
EOFUpstream proxy protocol
The BackendConfigPolicy resource now supports an upstreamProxyProtocol field. When configured, the gateway proxy prepends a PROXY protocol header to outbound TCP connections to the upstream backend, allowing the backend to see the original client IP address and port. Both PROXY protocol V1 (human-readable) and V2 (binary) are supported.
For more information, see Outbound proxy protocol.
Allow requests without proxy protocol
The ListenerPolicy proxy protocol configuration now supports an allowRequestsWithoutProxyProtocol field. When set to true, a single listener accepts connections with or without a PROXY protocol header. By default, the field is set to false and the listener strictly requires a PROXY protocol header on all incoming connections.
For more information, see Allow connections without proxy protocol headers.
Circuit breaker remaining capacity metrics
The BackendConfigPolicy circuit breakers configuration now supports a trackRemaining field. When set to true, Envoy emits gauge metrics for the remaining capacity of each circuit breaker threshold group: remaining_cx, remaining_pending, remaining_rq, and remaining_retries. Note that enabling this field has a small performance overhead.
For more information, see Track remaining capacity.
IP-based access control (ACL)
The TrafficPolicy resource now supports an acl field for IP-based access control. You can define allow and deny rules by using CIDR blocks or bare IP addresses, set a defaultAction for unmatched requests, and customize denial responses with a custom HTTP status code and headers.
For more information, see IP-based access control (ACL).
Fault injection
The TrafficPolicy resource now supports a faultInjection field for chaos engineering and resiliency testing. You can inject the following fault types into a percentage of requests:
- Delays: Inject a fixed latency before forwarding the request upstream to simulate slow networks or overloaded backends.
- Aborts: Return an HTTP or gRPC error code without forwarding the request to simulate upstream failures.
- Response rate limiting: Throttle the response body data rate to simulate degraded upstream connections.
Fault injection can be applied at the route level by targeting an HTTPRoute, or at the gateway level by targeting a Gateway. A route-level policy can use disable: {} to opt out of a gateway-level fault injection policy.
For more information, see Fault injection.
OpenTelemetry tracing
Configure distributed tracing for your gateway by using the ListenerPolicy resource, and override tracing settings per route with a TrafficPolicy resource.
The following tracing improvements are included in this release:
- Listener-level tracing: Configure the OTel provider, sampling rates (
clientSampling,randomSampling,overallSampling), and custom span attributes in a ListenerPolicy that targets your Gateway. - Per-route tracing overrides: Use a TrafficPolicy that targets an HTTPRoute or GRPCRoute to override sampling rates, add route-specific span attributes, or disable tracing for specific routes.
- Auto-populated resource attributes: OTel semantic convention resource attributes are automatically added to all spans, including
service.name,service.namespace,service.instance.id,service.version, and Kubernetes identity attributes such ask8s.pod.name,k8s.node.name, andk8s.deployment.name.
For more information, see Tracing.
Dynamic direct response bodies
The DirectResponse resource now supports a bodyFormat field for returning dynamic response bodies by using Envoy format strings. Format strings use %VARIABLE% placeholders that Envoy substitutes at request time, such as request headers or dynamic metadata. You can choose between returning a text or JSON body. Both formats are mutually exclusive.
For more information, see Dynamic text body and Dynamic JSON body.
GRPCRoute support
Route traffic to gRPC services by using the GRPCRoute resource for protocol-aware routing. Unlike the HTTPRoute, which requires matching on HTTP paths and methods, the GRPCRoute allows you to define routing rules by using gRPC-native concepts, such as service and method names.
For more information, see gRPC routing.
TLS termination for TLSRoutes and TCPRoutes
Terminate TLS traffic at the gateway by using a TLS listener in Terminate mode with either a TLSRoute or a TCPRoute. The gateway decrypts incoming TLS traffic using a server-side certificate and forwards the plain traffic to the backend service via TCP proxy.
- TLSRoute: Supports SNI-based hostname matching. Use this when you need to route traffic to different backends based on the requested hostname.
- TCPRoute: Routes traffic based on listener port only, without SNI hostname matching. Use this listener for simpler port-based routing.
For more information, see TLS termination for TLSRoutes and TLS termination for TCPRoutes.
Transformation enhancements
The rustformation engine, which is the only transformation engine in 2.3.x, gains several new capabilities:
parseAs: None: A new value fortransformation.<request|response>.body.parseAsthat skips body buffering and body processing entirely. Use this for routes that should not buffer request or response bodies. WhenparseAs: Noneis set, thebody()andcontext()template functions return an empty string, and any attempt to read JSON variables from a header template returns a 400 response.- WebSocket and tunnel auto-detect: The rustformation filter now automatically bypasses body buffering for
CONNECTrequests and WebSocket upgrade requests. This prevents long-lived tunnels from stalling on body buffering, regardless of the configuredparseAsvalue. - Dynamic metadata transformation: A new
transformation.<request|response>.dynamicMetadatafield lets you populate Envoy dynamic metadata from a MiniJinja template. The rendered string value is stored under the configured namespace and key, and is available to downstream filters and to access log formatters. addheader now works onarm64: The 2.2.x workaround that disabled theaddheader operation onarm64builds is removed. Envoy v1.37 adds the corresponding function to the upstream dynamic-module SDK, sotransformation.<request|response>.addworks on bothx86_64andarm64in 2.3.x.
For details about each capability and a comparison with the classic transformation behavior, see Transformation engine.