'Add Custom Header to HTTP request in Load Balancer
I have an containerized application/service deployed in openshift container platform with istio service mesh. In istio virtual service yaml, i wanted to validate if the http request is having a header(for ex: version) and with value v1. i have added below config in virtual service yaml which validates header. But i am looking for available options to inject this header in HTTP request using loadbalancer/ingress/openshif route etc. As my istio-ingressgateway service is deployed with ClusterIp. i have used openshift route to send the external traffic to ingressgateway. please share the possible ways to add headers to http request
http:
- match:
- headers: # Match header
version: # header that we decided for dark release
exact: v1 # exact match
Solution 1:[1]
You can use envoy filter to do that.
Below envoy filter add request header called customer-id
with alice
value to all request going though istio ingress gateway. I also commented code for response headers if someone would like to use it.
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: lua-filter
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
inlineCode: |
function envoy_on_request(request_handle)
request_handle:headers():add("customer-id", "alice")
end
# function envoy_on_response(response_handle)
# response_handle:headers():add("customer-id", "alice")
# end
There are yamls I've used to test that, it might be useful for testing above filter.
- If you use above filter with alice header then all requests goes to nginx-v1
- If you use above filter with bob header then all requests goes to nginx-v2
- If you delete this filter then it's 50/50 between nginx-v1 and nginx-v2
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v1
spec:
selector:
matchLabels:
run: nginx1
replicas: 1
template:
metadata:
labels:
run: nginx1
app: frontend
spec:
containers:
- name: nginx1
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello nginx1 > /usr/share/nginx/html/index.html"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v2
spec:
selector:
matchLabels:
run: nginx2
replicas: 1
template:
metadata:
labels:
run: nginx2
app: frontend
spec:
containers:
- name: nginx2
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello nginx2 > /usr/share/nginx/html/index.html"]
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: frontend
spec:
ports:
- name: http-front
port: 80
protocol: TCP
selector:
app: frontend
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gatewayx
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginxvirt
spec:
hosts:
- '*'
gateways:
- gatewayx
http:
- name: "route-1"
match:
- headers:
customer-id:
exact: alice
route:
- destination:
host: nginx
subset: v1
- name: "route-2"
match:
- headers:
customer-id:
exact: bob
route:
- destination:
host: nginx
subset: v2
- route:
- destination:
host: nginx
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginxdest
spec:
host: nginx
subsets:
- name: v1
labels:
run: nginx1
- name: v2
labels:
run: nginx2
Solution 2:[2]
It should be possible to use virtualService like
spec:
hosts:
- "example.com"
gateways:
- your-gateway
http:
-
name: remove-headers
headers:
request:
remove:
- yourHeader
But I can't make it works. Please share if you can :)
Solution 3:[3]
Pretty late to answer this but hope it helps someone.
We can use istio virtual service for adding custom headers to request as well as response.
I am using bookinfo-gateway provided by Istio as an example here:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
route:
- destination:
host: productpage
port:
number: 9080
headers:
request:
set:
X-Frame-Options: deny # if request header has X-Frame-Options, it will be overwritten
response:
add:
hello: world # add "hello" with value world in response header
remove:
- "foo" # remove foo from response header
I have tested this locally using Minikube v1.25.2, and Istio v1.13, it is working as per expectations.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Jakub |
Solution 2 | terrasson marc |
Solution 3 | bhushan pathak |