EnvoyPatchPolicy¶
EnvoyPatchPolicy provides low-level control over Envoy's xDS configuration through JSON patches. It's an escape hatch for advanced customization when standard CRDs don't provide the needed functionality.
Overview¶
- API Group:
gateway.envoyproxy.io/v1alpha1 - Kind:
EnvoyPatchPolicy - Attachment: Gateway via
targetRef - Use Case: Advanced Envoy configuration, emergency fixes, experimental features
⚠️ Warnings¶
- Use as last resort: Standard CRDs should be preferred
- Breaking changes: Direct xDS patches may break across Envoy Gateway versions
- Complexity: Requires deep knowledge of Envoy's xDS API
- Validation: Limited validation compared to standard policies
- Maintenance: Harder to maintain and troubleshoot
Key Features¶
- JSON Patch (RFC 6902) operations
- Patch any xDS resource (Listener, Route, Cluster, Endpoint)
- Multiple patch operations per policy
- Patch ordering and priority
- Target specific resources by name
Basic Example¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: custom-patch
namespace: default
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
- type: Listener
name: default/my-gateway/http
operation:
op: add
path: /filter_chains/0/filters/0/typed_config/common_http_protocol_options/idle_timeout
value: "300s"
xDS Resource Types¶
Available resource types for patching:
Listener- Listener configurationRouteConfiguration- HTTP route configurationCluster- Upstream cluster configurationClusterLoadAssignment- Endpoint configuration (EDS)Secret- TLS certificate configuration
JSON Patch Operations¶
Add Operation¶
jsonPatches:
- type: Listener
name: default/my-gateway/https
operation:
op: add
path: /filter_chains/0/filters/0/typed_config/stat_prefix
value: "custom_prefix"
Remove Operation¶
jsonPatches:
- type: Listener
name: default/my-gateway/http
operation:
op: remove
path: /filter_chains/0/filters/0/typed_config/use_remote_address
Replace Operation¶
jsonPatches:
- type: Cluster
name: default/my-service
operation:
op: replace
path: /connect_timeout
value: "10s"
Copy Operation¶
jsonPatches:
- type: RouteConfiguration
name: default/my-route
operation:
op: copy
from: /virtual_hosts/0/routes/0
path: /virtual_hosts/0/routes/1
Move Operation¶
jsonPatches:
- type: RouteConfiguration
name: default/my-route
operation:
op: move
from: /virtual_hosts/0/routes/1
path: /virtual_hosts/0/routes/0
Test Operation¶
jsonPatches:
- type: Cluster
name: default/my-service
operation:
op: test
path: /connect_timeout
value: "5s"
Use Cases¶
Custom HTTP Filter¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: custom-http-filter
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
- type: Listener
name: default/my-gateway/http
operation:
op: add
path: /filter_chains/0/filters/0/typed_config/http_filters/0
value:
name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inline_code: |
function envoy_on_request(request_handle)
request_handle:headers():add("X-Custom-Header", "custom-value")
end
Modify Cluster Settings¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: cluster-patches
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
# Increase connect timeout
- type: Cluster
name: default/backend-service/http
operation:
op: replace
path: /connect_timeout
value: "30s"
# Add upstream connection pool settings
- type: Cluster
name: default/backend-service/http
operation:
op: add
path: /upstream_connection_options
value:
tcp_keepalive:
keepalive_probes: 3
keepalive_time: 300
keepalive_interval: 60
Custom Access Log Format¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: custom-access-log
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
- type: Listener
name: default/my-gateway/http
operation:
op: add
path: /filter_chains/0/filters/0/typed_config/access_log/-
value:
name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: /dev/stdout
log_format:
json_format:
timestamp: "%START_TIME%"
method: "%REQ(:METHOD)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
response_code: "%RESPONSE_CODE%"
duration: "%DURATION%"
client_ip: "%DOWNSTREAM_REMOTE_ADDRESS%"
Enable TCP Stats¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: tcp-stats
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
- type: Listener
name: default/my-gateway/tcp
operation:
op: add
path: /filter_chains/0/filters/0/typed_config/stat_prefix
value: "ingress_tcp"
Add Custom Listener Filter¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: tls-inspector
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
- type: Listener
name: default/my-gateway/https
operation:
op: add
path: /listener_filters/-
value:
name: envoy.filters.listener.tls_inspector
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
Modify Route Configuration¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: route-patches
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
# Add request mirroring
- type: RouteConfiguration
name: default/my-route
operation:
op: add
path: /virtual_hosts/0/routes/0/route/request_mirror_policies
value:
- cluster: mirror-cluster
runtime_fraction:
default_value:
numerator: 10
denominator: HUNDRED
Enable Original Source IP¶
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: original-src-ip
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
type: JSONPatch
jsonPatches:
- type: Cluster
name: default/backend-service/http
operation:
op: add
path: /upstream_bind_config
value:
source_address:
address: "0.0.0.0"
port_value: 0
Resource Naming Conventions¶
Listener Names¶
Format: <namespace>/<gateway-name>/<listener-name>
Example: default/my-gateway/http
Route Names¶
Format: <namespace>/<httproute-name>
Example: default/my-route
Cluster Names¶
Format: <namespace>/<service-name>/<port-name-or-number>
Example: default/backend-service/http or default/backend-service/8080
Finding Resource Names¶
Use Envoy Admin API to discover resource names:
# Port-forward to Envoy proxy
kubectl port-forward -n envoy-gateway-system \
deploy/envoy-gateway 19000:19000
# List listeners
curl -s localhost:19000/config_dump | jq '.configs[] | select(.["@type"] | contains("Listener"))'
# List routes
curl -s localhost:19000/config_dump | jq '.configs[] | select(.["@type"] | contains("Route"))'
# List clusters
curl -s localhost:19000/config_dump | jq '.configs[] | select(.["@type"] | contains("Cluster"))'
Best Practices¶
- Avoid if possible - Use standard CRDs first
- Document thoroughly - Explain why the patch is needed
- Test extensively - Patches can break in unexpected ways
- Version carefully - Test patches across Envoy Gateway upgrades
- Use specific paths - Avoid broad wildcards
- Monitor closely - Watch for rejected patches
- Validate offline - Test patches in non-production first
- Keep simple - Multiple simple patches better than one complex patch
Troubleshooting¶
Patch Not Applied¶
Check Envoy Gateway logs:
kubectl logs -n envoy-gateway-system deploy/envoy-gateway -f
Finding the Correct Path¶
Use config_dump to inspect current configuration:
kubectl port-forward -n envoy-gateway-system \
deploy/envoy-gateway 19000:19000
curl localhost:19000/config_dump | jq '.'
Validation Errors¶
Patches must conform to Envoy's protobuf definitions. Check Envoy documentation for the specific filter or configuration.
Migration Path¶
When Envoy Gateway adds native support for a feature:
- Test the native CRD in non-production
- Compare behavior with patch-based implementation
- Gradually migrate to native CRD
- Remove EnvoyPatchPolicy after validation
Related Resources¶
- EnvoyProxy - Proxy infrastructure configuration
- BackendTrafficPolicy - Backend traffic policies
- ClientTrafficPolicy - Client traffic policies
- Envoy Documentation - xDS API reference