如何配置Istio Envoy代理作为出站装饰器?Pod内实现思路咨询
Alright, let's break down exactly how to set up this outbound decorator using Istio's EnvoyFilter—your approach is spot-on, using an internal-only port keeps things clean without extra Gateway or VirtualService overhead, and Lua gives you all the flexibility you need for request decoration.
1. Expose the Internal Port on the Sidecar
First, we need to make sure the Istio sidecar is allowed to listen on port 8101 internally. You can do this either via pod annotations (per-workload) or a Sidecar CR (namespace/global level):
Option A: Pod Annotations
Add these annotations to your application pod spec:
annotations: sidecar.istio.io/inject: "true" sidecar.istio.io/extraPort: "8101"
Option B: Sidecar CR (Namespace-Wide)
Create a Sidecar resource to configure all workloads in your namespace:
apiVersion: networking.istio.io/v1alpha3 kind: Sidecar metadata: name: default-decorator-port namespace: your-target-namespace spec: egress: - port: number: 8101 protocol: HTTP name: decorator-internal captureMode: NONE # Critical: We don't want Istio to intercept other traffic to this port
The captureMode: NONE ensures this port is only for direct internal calls from the pod to its sidecar.
2. Add Listener & Lua Filter with EnvoyFilter
Next, we'll use an EnvoyFilter to add a listener on port 8101 to the sidecar, and attach a Lua script to decorate requests before forwarding them to your target service.
Here's the full EnvoyFilter YAML—be sure to replace placeholders like your-app-label, your-target-service, etc., with your actual values:
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: outbound-request-decorator namespace: your-target-namespace spec: workloadSelector: labels: app: your-app-label # Match only your application pods configPatches: # Patch 1: Add listener for port 8101 (localhost-only) - applyTo: LISTENER match: context: SIDECAR_INBOUND patch: operation: INSERT_BEFORE value: name: internal_decorator_listener_8101 address: socket_address: address: 127.0.0.1 port_value: 8101 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: decorator_http route_config: name: decorator_route_config virtual_hosts: - name: decorator_vhost domains: ["*"] routes: - match: prefix: "/" route: cluster: outbound|80||your-target-service.your-target-namespace.svc.cluster.local # Target service cluster http_filters: # Add Lua filter for request decoration - 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) -- Add your custom decoration logic here request_handle:headers():add("X-Decorated-By", "Istio-Envoy-Internal-Decorator") request_handle:headers():add("X-Pod-Name", os.getenv("POD_NAME")) -- Example: Modify query parameters local query = request_handle:headers():get(":path") if query:find("?") then request_handle:headers():replace(":path", query .. "&decorated=true") else request_handle:headers():replace(":path", query .. "?decorated=true") end end # Router filter to forward the modified request - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router # Optional: Ensure target service cluster has basic config (if not auto-created by Istio) - applyTo: CLUSTER match: cluster: service: your-target-service.your-target-namespace.svc.cluster.local patch: operation: MERGE value: connect_timeout: 5s lb_policy: ROUND_ROBIN
3. Verify the Setup
Once you've applied the configs, exec into your application pod and test the internal port:
kubectl exec -it your-app-pod-name -- curl -v localhost:8101/your-service-endpoint
Check the request headers in the output—you should see your custom decorated headers (X-Decorated-By, X-Pod-Name) and the modified query parameters.
- Internal-Only Access: The listener binds to
127.0.0.1, so only processes requests from within the pod—no external exposure means no need for Gateways or VirtualServices. - Lua Flexibility: The inline Lua script can be extended to modify request bodies, add authentication tokens, or any other custom logic you need.
- Target Cluster: If your target service is inside the Istio mesh, the cluster name (like
outbound|80||your-service...) is auto-generated by Istio. For external services, you'll need to define aServiceEntryfirst. - Workload Selection: Use the
workloadSelectorto ensure the EnvoyFilter only applies to your target pods—avoid applying it to all sidecars in the namespace unless intended.
内容的提问来源于stack exchange,提问作者Max Usanin

