@@ -10,7 +10,7 @@ categories:
1010 - load-balancer
1111tags : kubernetes load-balancer proxy-protocol istio
1212dates :
13- validation : 2025-02-18
13+ validation : 2025-03-13
1414 posted : 2025-02-18
1515---
1616
@@ -33,77 +33,243 @@ This tutorial describes the steps required to deploy Istio on a Scaleway Kuberne
3333 helm repo add istio https://istio-release.storage.googleapis.com/charts
3434 helm repo update
3535 ```
36+ 2 . Create a Kubernetes namespace for Istio:
37+ ```
38+ kubectl create namespace istio-system
39+ ```
3640
37- 2 . Install the Istio control plane:
41+ 3 . Install the Istio base and control plane into the previously created namesapce :
3842
3943 ```
40- helm install istiod istio/istiod -n istio-system --create-namespace
44+ helm install istio-base istio/base -n istio-system
45+ helm install istiod istio/istiod -n istio-system --wait
4146 ```
4247
43- 3 . Install the Istio ingress Gateway:
48+ 4 . Install the Istio ingress Gateway:
4449
4550 ```
46- helm install istio-ingressgateway istio/gateway -n istio-system
51+ helm install istio-ingressgateway istio/gateway -n istio-system --wait
4752 ```
4853
49- ## Verify the ingress Gateway Service
50-
51- An ingress gateway service acts as an entry point for external traffic into the cluster. It is exposed via a Kubernetes LoadBalancer Service, which, in our case, uses a Scaleway Load Balancer. The Load Balancer forwards external traffic to the ingress Gateway Pod.
54+ ## Install a test application (httpbin)
5255
53- 1 . Run the following command to retrieve the service configuration
56+ Deploy a simple application to test how Istio works with a Load Balancer.
57+ In this tutorial we use ` httpbin ` as test application.
5458
59+ 1 . Create and label a new namespace for the test application:
5560 ```
56- kubectl get svc istio-ingressgateway -n istio-system -o yaml
61+ kubectl create namespace test-app
62+ kubectl label namespace test-app istio-injection=enabled
5763 ```
5864
59- 2 . Verify that the service is of type ` LoadBalancer ` , and that a Scaleway Load Balancer is associated with it.
65+ 2 . Apply the following configuration using ` kubectl ` :
6066
61- ## Add annotations for Proxy Protocol
67+ ``` yaml
68+ kubectl apply -n test-app -f - <<EOF
69+ apiVersion : apps/v1
70+ kind : Deployment
71+ metadata :
72+ name : httpbin
73+ spec :
74+ replicas : 1
75+ selector :
76+ matchLabels :
77+ app : httpbin
78+ template :
79+ metadata :
80+ labels :
81+ app : httpbin
82+ spec :
83+ containers :
84+ - name : httpbin
85+ image : kennethreitz/httpbin
86+ ports :
87+ - containerPort : 80
88+ ---
89+ apiVersion : v1
90+ kind : Service
91+ metadata :
92+ name : httpbin
93+ spec :
94+ selector :
95+ app : httpbin
96+ ports :
97+ - name : http
98+ port : 80
99+ targetPort : 80
100+ EOF
101+ ```
62102
63- Add the necessary annotations for Proxy Protocol:
103+ ## Creating an Istio Gateway and a VirtualService
104+ Define a Gateway and a VirtualService to expose the application via the Istio IngressGateway.
105+
106+ 1 . Run the following command to apply the configuration using ` kubectl ` :
107+
108+ ``` yaml
109+ kubectl apply -n test-app -f - <<EOF
110+ apiVersion : networking.istio.io/v1beta1
111+ kind : Gateway
112+ metadata :
113+ name : httpbin-gateway
114+ namespace : test-app
115+ spec :
116+ selector :
117+ istio : ingressgateway
118+ servers :
119+ - port :
120+ number : 80
121+ name : http
122+ protocol : HTTP
123+ hosts :
124+ - " *"
125+ ---
126+ # virtualservice.yaml
127+ apiVersion : networking.istio.io/v1beta1
128+ kind : VirtualService
129+ metadata :
130+ name : httpbin
131+ namespace : test-app
132+ spec :
133+ hosts :
134+ - " *"
135+ gateways :
136+ - httpbin-gateway
137+ http :
138+ - route :
139+ - destination :
140+ host : httpbin
141+ port :
142+ number : 80
143+ EOF
144+ ```
145+
146+ 2 . Run the following command to retrieve the IP of your Load Balancer and save it in the ` $LB_IP ` variable:
147+ ``` bash
148+ export LB_IP=$( kubectl get svc -n istio-system istio-ingressgateway -o
149+ jsonpath=' {.status.loadBalancer.ingress[0].ip}' )
150+ echo $LB_IP
151+ ```
64152
153+ 2 . Run the following command to do a test before proxy forward is configured:
154+ ``` bash
155+ curl -v http://$LB_IP /get
65156 ```
66- kubectl annotate -n istio-system svc istio-ingressgateway "service.beta.kubernetes.io/scw-load-balancer-proxy-protocol-v2=false" --overwrite
67- kubectl patch svc istio-ingressgateway -n istio-system -p '{"spec": {"externalTrafficPolicy": "Local"}}'
157+ You will get an output similar to the following example:
158+ ``` bash
159+ curl -v
160+ http://$LB_IP /get
161+ * Trying 51.159.112.157:80...
162+ * Connected to 51.159.112.157 (51.159.112.157) port 80
163+ > GET /get HTTP/1.1
164+ > Host: 51.159.112.157
165+ > User-Agent: curl/8.7.1
166+ > Accept: * /*
167+ >
168+ * Request completely sent off
169+ < HTTP/1.1 200 OK
170+ < server: istio-envoy
171+ < date: Mon, 24 Feb 2025 09:06:45 GMT
172+ < content-type: application/json
173+ < content-length: 491
174+ < access-control-allow-origin: *
175+ < access-control-allow-credentials: true
176+ < x-envoy-upstream-service-time: 19
177+ <
178+ {
179+ " args" : {},
180+ " headers" : {
181+ " Accept" : " */*" ,
182+ " Host" : " 51.159.112.157" ,
183+ " User-Agent" : " curl/8.7.1" ,
184+ " X-Envoy-Attempt-Count" : " 1" ,
185+ " X-Envoy-Internal" : " true" ,
186+ " X-Forwarded-Client-Cert" : " By=spiffe://cluster.local/ns/testapp/sa/default;Hash=ddf3ba6fee32a74f9a83efd752df7960c9f3139fa1fe979370becddad3def062;Subject=\"\" ;URI=spiffe://cluster.local/ns/istiosystem/sa/istio-ingressgateway"
187+ },
188+ " origin" : " 172.16.16.5" ,
189+ " url" : " http://51.159.112.157/get"
190+ }
191+ * Connection # 0 to host 51.159.112.157 left intact
68192 ```
69193
70- ## Configure Envoy to support Proxy Protocol
194+ ## Configuring the Scaleway Load Balancer
195+ When you deploy a LoadBalancer service in Kubernetes, Scaleway automatically creates a Load Balancer and associates it with your service. You now need to activate ` Proxy Protocol V2 ` for this Load Balancer.
71196
72- Envoy is a proxy server used by Istio to manage and control the flow of traffic between services in the Kubernetes cluster. It is responsible for routing the traffic between services.
197+ Modify the ` istio-ingressgateway ` service to add the necessary annotations:
198+ ``` bash
199+ kubectl annotate -n istio-system services istio-ingressgateway \
200+ service.beta.kubernetes.io/scw-loadbalancer-proxy-protocol-v2=true
201+ kubectl annotate -n istio-system services istio-ingressgateway \
202+ service.beta.kubernetes.io/scw-loadbalancer-use-hostname=true
203+ ```
73204
74- 1 . Create an EnvoyFilter to enable Proxy Protocol support:
205+ ## Configure Proxy protocol and the X-Forwarded-For header to retrieve the source IP
75206
207+ 1 . Create an ` EnvoyFilter ` to enable Proxy Protocol support:
76208 ``` yaml
209+ kubectl apply -f - <<EOF
77210 apiVersion : networking.istio.io/v1alpha3
78211 kind : EnvoyFilter
79212 metadata :
80- name : proxy-protocol
81- namespace : istio-system
213+ name : proxy-protocol
214+ namespace : istio-system
82215 spec :
83- workloadSelector :
84- labels :
85- istio : ingressgateway
86- configPatches :
87- - applyTo : LISTENER
216+ workloadSelector :
217+ labels :
218+ istio : ingressgateway
219+ configPatches :
220+ - applyTo : LISTENER
88221 patch :
89- operation : MERGE
90- value :
222+ operation : MERGE
223+ value :
91224 listener_filters :
92225 - name : envoy.filters.listener.proxy_protocol
226+ typed_config :
227+ ' @type ' : type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol
93228 - name : envoy.filters.listener.tls_inspector
229+ typed_config :
230+ ' @type ' : type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
231+ EOF
94232 ```
95233
96- 2. Apply the configuration:
97-
234+ 2 . Run the ` curl -v http://$LB_IP/get ` command again and watch the output. You will get an output similar to the following example:
235+ ``` bash
236+ curl -v http://$LB_IP /get
237+ * Trying 51.159.112.157:80...
238+ * Connected to 51.159.112.157 (51.159.112.157) port 80
239+ > GET /get HTTP/1.1
240+ > Host: 51.159.112.157
241+ > User-Agent: curl/8.7.1
242+ > Accept: * /*
243+ >
244+ * Request completely sent off
245+ < HTTP/1.1 200 OK
246+ < server: istio-envoy
247+ < date: Mon, 24 Feb 2025 09:11:46 GMT
248+ < content-type: application/json
249+ < content-length: 510
250+ < access-control-allow-origin: *
251+ < access-control-allow-credentials: true
252+ < x-envoy-upstream-service-time: 4
253+ <
254+ {
255+ " args" : {},
256+ " headers" : {
257+ " Accept" : " */*" ,
258+ " Host" : " 51.159.112.157" ,
259+ " User-Agent" : " curl/8.7.1" ,
260+ " X-Envoy-Attempt-Count" : " 1" ,
261+ " X-Envoy-External-Address" : " 62.210.16.37" ,
262+ " X-Forwarded-Client-Cert" : " By=spiffe://cluster.local/ns/test-app/sa/default;Hash=ddf3ba6fee32a74f9a83efd752df7960c9f3139fa1fe979370becddad3def062;Subject=\"\" ;URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway"
263+ },
264+ " origin" : " 62.210.16.37" ,
265+ " url" : " http://51.159.112.157/get"
266+ }
267+ * Connection # 0 to host 51.159.112.157 left intact
98268 ```
99- kubectl apply -f proxy-protocol.yaml
100- ```
101-
102- ## Enable X-Forwarded-For
103-
104- 1 . Create a file named ` ingressgateway-settings.yaml ` with the following content:
105269
106- ``` yaml
270+ 3 . Configure Istio using ` kubectl ` to ensure that the source IP is correctly transmitted via the ` X-Forwarded-For ` header.
271+ ``` bash
272+ kubectl apply -f - << EOF
107273 apiVersion: networking.istio.io/v1alpha3
108274 kind: EnvoyFilter
109275 metadata:
@@ -116,54 +282,57 @@ Envoy is a proxy server used by Istio to manage and control the flow of traffic
116282 listener:
117283 filterChain:
118284 filter:
119- name : envoy.http_connection_manager
120- patch :
121- operation : MERGE
122- value :
123- name : envoy.http_connection_manager
124- typed_config :
125- " @type " : " type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager"
126- skip_xff_append : false
127- use_remote_address : true
128- xff_num_trusted_hops : 1
129- ` ` `
130-
131- 2. Apply the configuration:
132-
133- ` ` `
134- kubectl apply -f ingressgateway-settings.yaml
135- ```
136-
137- 3 . Update the ingress Gateway service to use the new configuration:
138-
139- ```
140- kubectl annotate -n istio-system svc istio-ingressgateway "service.beta.kubernetes.io/scw-load-balancer-proxy-protocol-v2=false" --overwrite
141- kubectl patch svc istio-ingressgateway -n istio-system -p '{"spec": {"externalTrafficPolicy": "Local"}}'
285+ name: envoy.filters.network.http_connection_manager
286+ patch:
287+ operation: MERGE
288+ value:
289+ name: envoy.filters.network.http_connection_manager
290+ typed_config:
291+ "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
292+ skip_xff_append: false
293+ use_remote_address: true
294+ xff_num_trusted_hops: 1
295+ EOF
142296 ` ` `
143-
144- ## Restart the Istio ingress gateway pod
145-
146- Restart the pod to apply the changes:
147-
148- ```
149- kubectl delete pod -l istio=ingressgateway -n istio-system
150- ```
151-
152- ## Verify the configuration
153-
154- 1 . Retrieve the public IP address of the Load Balancer:
155-
156- ```
157- kubectl get svc istio-ingressgateway -n istio-system
158- ```
159-
160- 2 . Test access using curl:
297+ You will get an output similar to the following one, after you have configured proxy forward and ` X-Forward-For`
298+ ` ` ` bash
299+ curl -v http://$LB_IP /get
300+ * Trying 51.159.112.157:80...
301+ * Connected to 51.159.112.157 (51.159.112.157) port 80
302+ > GET /get HTTP/1.1
303+ > Host: 51.159.112.157
304+ > User-Agent: curl/8.7.1
305+ > Accept: */*
306+ >
307+ * Request completely sent off
308+ < HTTP/1.1 200 OK
309+ < server: istio-envoy
310+ < date: Mon, 24 Feb 2025 09:14:32 GMT
311+ < content-type: application/json
312+ < content-length: 522
313+ < access-control-allow-origin: *
314+ < access-control-allow-credentials: true
315+ < x-envoy-upstream-service-time: 2
316+ <
317+ {
318+ "args": {},
319+ "headers": {
320+ "Accept": "*/*",
321+ "Host": "51.159.112.157",
322+ "User-Agent": "curl/8.7.1",
323+ "X-Envoy-Attempt-Count": "1",
324+ "X-Envoy-External-Address": "62.210.16.37",
325+ "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/test-app/sa/default;Hash=7e20594ba5421aa9df88b0d025498a5c51d02b0224daa3faea319c13a106d8b6;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway"
326+ },
327+ "origin": "62.210.16.37,100.64.2.46",
328+ "url": "http://51.159.112.157/get"
329+ }
330+ * Connection #0 to host 51.159.112.157 left intact
161331 ` ` `
162- curl -v http://<LOAD_BALANCER_IP>/get
163- ```
164-
165- If the configuration is correct, the response should include the ` X-Forwarded-For ` and ` X-Envoy-External-Address ` headers.
166-
332+ # ## It may be necessary to restart the Istio IngressGateway Pods
333+ Once you have added the configurations, you may need to restart the IngressGateway pods so that the changes to take effect.
167334
168- For further support with Istio, read their [ dedicated documentation] ( https://istio.io/latest/docs/ ) .
169-
335+ Run the following command to delete the existing pods using ` kubectl` . Kubernetes will spin up new ones automatically after you launch the command:
336+ ` ` ` bash
337+ kubectl delete pod -n istio-system -l istio=ingressgateway
338+ ` ` `
0 commit comments