Examples update 04/05/2023 #48

Merged
ofilter merged 5 commits from dev into main 2023-05-04 03:27:33 +02:00
14 changed files with 816 additions and 99 deletions

View File

@ -23,6 +23,11 @@ On these examples you will find the following Istio resources:
- 04-hello_world_1_service_2_deployments_managed_version_foo_namespace
## Requirements:
- A Kubernetes cluster (with a CNI network plugin, on my environment I have used [Calico](https://docs.tigera.io/calico/))
- Istio installed
# How to get started?
@ -30,7 +35,7 @@ On these examples you will find the following Istio resources:
Follow [this](https://istio.io/latest/docs/setup/getting-started/) guide to install the `default` profile.
Specifically, the steps of [Download Istio](https://istio.io/latest/docs/setup/getting-started/#download) and [Install Istio][https://istio.io/latest/docs/setup/getting-started/#install).
Specifically, the steps of [Download Istio](https://istio.io/latest/docs/setup/getting-started/#download) and [Install Istio](https://istio.io/latest/docs/setup/getting-started/#install).
Once this is set, proceed with the rest of the installation.

View File

@ -1,11 +0,0 @@
##### https://github.com/istio/istio/tree/master/samples/helloworld
https://istio.io/latest/blog/2017/0.1-canary/
# Note, VirtualService match rule order MATTERS
Leave the "default/wildcard" rule at the bottom
# Continues from
- 03-hello_world_1_service_1_deployment

View File

@ -1,18 +1,3 @@
# https://github.com/istio/istio/blob/master/samples/helloworld/helloworld.yaml
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 80
name: http
selector:
app: helloworld
---
apiVersion: apps/v1
kind: Deployment
metadata:

View File

@ -0,0 +1,16 @@
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: helloworld.default.svc.cluster.local # Destination that will "interject"
spec:
host: helloworld.default.svc.cluster.local # Full destination service, lil better for consistency
subsets:
- name: default
labels:
version: v0
- name: nginx
labels:
version: v1
- name: apache
labels:
version: v2

View File

@ -0,0 +1,14 @@
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"

View File

@ -0,0 +1,456 @@
---
gitea: none
include_toc: true
---
# Description
The [previous example](../../01-Getting_Started/03-hello_world_1_service_2_deployments_managed_version), we use the values set in the headers from the `HTTP` request received to route the traffic to different backends.
Additionally, we configure a default rule where the unmatched traffic will go.
This example configures:
Generic Kubernetes resources:
- 1 Namespace
- 1 Service
- 3 Deployments
Istio resources:
- 1 Gateway
- 1 Virtual Service
- 1 Destination rule
# Based on
- [03-hello_world_1_service_2_deployments_managed_version](../../01-Getting_Started/03-hello_world_1_service_2_deployments_managed_version)
# Configuration
## Service
Creates a service named `helloworld`.
This service listens for the port `80` expecting `HTTP` traffic and will forward the incoming traffic towards the port `80` from the destination pod.
```yaml
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 80
name: http
selector:
app: helloworld
```
## Deployment
We will create 3 different deployments where the traffic will be distributed, targeting the labels set to the pods.
Deployments created:
- helloworld-v0
- helloworld-v1
- helloworld-v2
### helloworld-v0
Deploys a Whoami server that listens for the port `80`.
On this deployment, we attributed the label `version` set to `v0`, this will be used by the [DestinationRule](#destinationrule) resource to target this deployment.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-v0
labels:
app: helloworld
version: v0
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
version: v0
template:
metadata:
labels:
app: helloworld
version: v0
spec:
containers:
- name: helloworld
image: containous/whoami
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
```
### helloworld-v1
Deploys a Nginx server that listens for the port `80`.
On this deployment, we attributed the label `version` set to `v1`, this will be used by the [DestinationRule](#destinationrule) resource to target this deployment.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-v1
labels:
app: helloworld
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
version: v1
template:
metadata:
labels:
app: helloworld
version: v1
spec:
containers:
- name: helloworld
image: nginx
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
```
### helloworld-v2
Deploys an Apache server that listens for the port `80`.
On this deployment, we attributed the label `version` set to `v2`, this will be used by the [DestinationRule](#destinationrule) resource to target this deployment.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-v2
labels:
app: helloworld
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
version: v2
template:
metadata:
labels:
app: helloworld
version: v2
spec:
containers:
- name: helloworld
image: httpd
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
```
## Gateway
Deploys an Istio gateway that's listening to the port `80` for `HTTP` traffic.
It doesn't filter for any specific host.
The `selector` field is used to "choose" which Istio Load Balancers will have this gateway assigned to.
The Istio `default` profile creates a Load Balancer in the namespace `istio-system` that has the label `istio: ingressgateway` set, allowing us to target that specific Load Balancer and assign this gateway resource to it.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
namespace: default
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
```
## VirtualService
The configuration set, targets the [gateway created](#gateway) as well of not limiting the traffic to any specific host.
We will create 3 rules that target `HTTP` (including `HTTPS` and `HTTP2` traffic), which are declared with the following names:
- firefox
- curl
- default
The `firefox` rule is intended to receive traffic coming from a Firefox web browser.
The `curl` rule is intended to receive traffic coming from the `curl` command line package/command.
The `default` rule is intended to receive traffic not matched by the 2 rules of above (as long meets certain criteria).
All the rules created will match on the following topics:
- The path directory will be `/helloworld`.
- The destination service will be `helloworld.default.svc.cluster.local` to the port `80`.
- Rewrite URL path to `/` to not create conflicts with the backend.
The rules will differ on the following topics:
- Each rule will target a specific content from the header `user-agent`, except of default.
- Each rule will target a different `subset` to distribute the traffic between the [Deployment resources created](#deployment).
> **Note**\
> If you usage not familiar with the usage of `subsets`, I strongly recommend to check the following example:
> - [03-hello_world_1_service_2_deployments_managed_version](../../01-Getting_Started/03-hello_world_1_service_2_deployments_managed_version)
> **Note**\
> The declaration order from the resources is important, as the elements created further above on the list will have priority over the rules set under them.\
> This would mean that if we declared the `default` matching rule first, it would overtake the traffic meant to reach the rules `firefox` and `curl`.
> For more information regarding this matter, refer to the following Official Istio documentation regarding [the HttpMatchRequest field from Istio VirtualServices](https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPMatchRequest).
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-vs
spec:
hosts:
- "*"
gateways:
- helloworld-gateway
http:
- name: firefox
match:
- uri:
exact: /helloworld
headers:
user-agent:
regex: '.*Firefox.*'
route:
- destination:
host: helloworld.default.svc.cluster.local
port:
number: 80
subset: nginx
rewrite:
uri: "/"
- name: curl
match:
- headers:
user-agent:
regex: '.*curl.*'
uri:
exact: /helloworld
route:
- destination:
host: helloworld.default.svc.cluster.local
port:
number: 80
subset: apache
rewrite:
uri: "/"
- name: default
match:
- uri:
exact: /helloworld
route:
- destination:
host: helloworld.default.svc.cluster.local
port:
number: 80
subset: default
rewrite:
uri: "/"
```
## DestinationRule
This `DestinationRule` interferes with the traffic with destination `helloworld.default.svc.cluster.local`.
Contains 3 subsets defined, where each one will target a different backend.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: helloworld.default.svc.cluster.local # Destination that will "interject"
spec:
host: helloworld.default.svc.cluster.local # Full destination service, lil better for consistency
subsets:
- name: default
labels:
version: v0
- name: nginx
labels:
version: v1
- name: apache
labels:
version: v2
```
# Walkthrough
## Deploy resources
Deploy the resources.
```shell
kubectl apply -f ./
```
```text
deployment.apps/helloworld-v0 created
deployment.apps/helloworld-v1 created
deployment.apps/helloworld-v2 created
destinationrule.networking.istio.io/helloworld.default.svc.cluster.local created
gateway.networking.istio.io/helloworld-gateway created
service/helloworld created
virtualservice.networking.istio.io/helloworld-vs created
```
## Wait for the pods to be ready
Wait for the Apache and Nginx deployments to be up and ready.
```shell
watch -n 2 kubectl get deployment helloworld-v{0..2}
```
```text
NAME READY UP-TO-DATE AVAILABLE AGE
helloworld-v0 1/1 1 1 23s
helloworld-v1 1/1 1 1 23s
helloworld-v2 1/1 1 1 23s
```
## Test the service
Now it's time to test the rules created in the [VirtualService configuration](#virtualservice), for such reminder that:
- Curl should return traffic from the Apache deployment.
- Firefox should return traffic from the Nginx deployment.
- The rest of the traffic should return us a response from the Whoami deployment. (as long it matches the rest of criteria set in the rule).
### Get LB IP
To perform the desired tests, we will need to obtain the IP Istio Load Balancer that we selected in the [Gateway section](#gateway).
On my environment, the IP is the `192.168.1.50`.
```shell
kubectl get svc -l istio=ingressgateway -A
```
```text
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.97.47.216 192.168.1.50 15021:31316/TCP,80:32012/TCP,443:32486/TCP 39h
```
### Curl
Using the command `curl`, results in receiving content from the Apache deployment.
```text
curl 192.168.1.50/helloworld -s
```
```text
<html><body><h1>It works!</h1></body></html>
```
### Firefox browser
Through using the Firefox web browser, the page accessed is the Nginx deployment.
![firefox.png](./src/firefox.png)
### Default
To trigger the "default" rule, you can be quite creative there, like using another browser some other tool.
In my case I will be using the package `wget` as it is more simple for myself.
```shell
wget 192.168.1.50/helloworld -O /dev/stdout -q
```
```text
Hostname: helloworld-v0-64fc7d6ccb-vdljp
IP: 127.0.0.1
IP: ::1
IP: 172.17.247.19
IP: fe80::dc11:59ff:fe15:f6c3
RemoteAddr: 127.0.0.6:51179
GET / HTTP/1.1
Host: 192.168.1.50
User-Agent: Wget/1.21.3
Accept: */*
Accept-Encoding: identity
X-B3-Parentspanid: 7a17876e5182b4a1
X-B3-Sampled: 0
X-B3-Spanid: 0aa085397844c696
X-B3-Traceid: 3c9474b384a9f33c7a17876e5182b4a1
X-Envoy-Attempt-Count: 1
X-Envoy-Internal: true
X-Envoy-Original-Path: /helloworld
X-Forwarded-Client-Cert: By=spiffe://cluster.local/ns/default/sa/default;Hash=bf05b3ab5654afeecc50ea6b136708517bcfdec088978a2a675759d52aa207aa;Subject="";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account
X-Forwarded-For: 192.168.1.10
X-Forwarded-Proto: http
X-Request-Id: 46d7dbe8-ba46-4703-b1a3-cdecf2f93d1e
```
## Cleanup
Finally, a cleanup from the resources deployed.
```shell
kubectl delete -f ./
```
```text
deployment.apps "helloworld-v0" deleted
deployment.apps "helloworld-v1" deleted
deployment.apps "helloworld-v2" deleted
destinationrule.networking.istio.io "helloworld.default.svc.cluster.local" deleted
gateway.networking.istio.io "helloworld-gateway" deleted
service "helloworld" deleted
```
# Links of interest
- https://istio.io/latest/docs/reference/config/networking/virtual-service/
- https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPMatchRequest
- https://istio.io/latest/docs/reference/config/networking/destination-rule/#

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 80
name: http
selector:
app: helloworld

View File

@ -1,19 +1,3 @@
# https://github.com/istio/istio/blob/master/samples/helloworld/helloworld-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
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:
@ -56,8 +40,8 @@ spec:
uri: "/"
- name: default
match:
- uri:
exact: /helloworld
- uri:
exact: /helloworld
route:
- destination:
host: helloworld.default.svc.cluster.local
@ -65,21 +49,4 @@ spec:
number: 80
subset: default
rewrite:
uri: "/"
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: helloworld.default.svc.cluster.local # Destination that will "interject"
spec:
host: helloworld.default.svc.cluster.local # Full destination service, lil better for consistency
subsets:
- name: default
labels:
version: v0
- name: nginx
labels:
version: v1
- name: apache
labels:
version: v2
uri: "/"

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -1,18 +1,3 @@
# https://github.com/istio/istio/blob/master/samples/helloworld/helloworld.yaml
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 80
name: http
selector:
app: helloworld
---
apiVersion: apps/v1
kind: Deployment
metadata:

View File

@ -0,0 +1,14 @@
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"

View File

@ -1,7 +1,283 @@
https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPDirectResponse
https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPBody
---
gitea: none
include_toc: true
---
# Description
Based on the [previous example](../../01-Getting_Started/01-hello_world_1_service_1_deployment), we configure the [VirtualService](#virtualservice) to return a specific response to the client with the contents of our choice.
This example configures:
Generic Kubernetes resources:
- 1 Service
- 1 Deployments
Istio resources:
- 1 Gateway
- 1 Virtual Service
# Continues from
# Based on
- 01-hello_world_1_service_1_deployment
- [01-hello_world_1_service_1_deployment](../../01-Getting_Started/01-hello_world_1_service_1_deployment)
# Configuration
## Service
Creates a service named `helloworld`.
This service listens for the port `80` expecting `HTTP` traffic and will forward the incoming traffic towards the port `80` from the destination pod.
```yaml
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 80
name: http
selector:
app: helloworld
```
## Deployment
Deploys a Nginx server that listens for the port `80`.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-nginx
labels:
app: helloworld
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: helloworld
image: nginx
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent #Always
ports:
- containerPort: 80
```
## Gateway
Deploys an Istio gateway that's listening to the port `80` for `HTTP` traffic.
It doesn't filter for any specific host.
The `selector` field is used to "choose" which Istio Load Balancers will have this gateway assigned to.
The Istio `default` profile creates a Load Balancer in the namespace `istio-system` that has the label `istio: ingressgateway` set, allowing us to target that specific Load Balancer and assign this gateway resource to it.
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
```
## VirtualService
The configuration set, targets the [gateway created](#gateway) as well of not limiting the traffic to any specific host.
We configure 2 rules for HTTP traffic (this includes `HTTPS` and `HTTP2`, this will be my last warning about this).
The first rule configure will match when the requested path is `/helloworld`.
This traffic will be forwarded to the service `helloworld.default.svc.cluster.local` with port `80`.
The second rule, which will manage the rest of the traffic, will return a response with status code `404`, and body content set to `Page Not Found`.
Additionally, for consistency and good practices purposes, we also specified the content type of the page to `text/plain`.
```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: helloworld-vs
spec:
hosts:
- "*"
gateways:
- helloworld-gateway
http:
- name: helloworld
match:
- uri:
exact: /helloworld
route:
- destination:
host: helloworld.default.svc.cluster.local
port:
number: 80
rewrite:
uri: "/"
- name: default
directResponse:
status: 404
body:
string: "Page Not Found"
headers:
response:
set:
content-type: "text/plain"
```
# Walkthrough
## Deploy resources
Deploy the resources.
```shell
kubectl apply -f ./
```
```text
deployment.apps/helloworld-nginx created
gateway.networking.istio.io/helloworld-gateway created
service/helloworld created
virtualservice.networking.istio.io/helloworld-vs created
```
## Wait for the pods to be ready
Wait for the Apache and Nginx deployments to be up and ready.
```shell
kubectl get deployment helloworld-nginx -w
```
```text
NAME READY UP-TO-DATE AVAILABLE AGE
helloworld-v1 1/1 1 1 4m1s
helloworld-v2 1/1 1 1 4m1s
```
## Test the service
### Get LB IP
To perform the desired tests, we will need to obtain the IP Istio Load Balancer that we selected in the [Gateway section](#gateway).
On my environment, the IP is the `192.168.1.50`.
```shell
kubectl get svc -l istio=ingressgateway -A
```
```text
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.97.47.216 192.168.1.50 15021:31316/TCP,80:32012/TCP,443:32486/TCP 39h
```
### helloworld
As expected, we receive the contents from the Nginx contents
```shell
curl 192.168.1.50/helloworld -s | grep "<h1>.*</h1>"
```
```text
<h1>Welcome to nginx!</h1>
```
### other paths
#### /
We receive the contents "Page Not Found".
```shell
curl 192.168.1.50/
```
```text
Page Not Found
```
Checking the headers, we also can see the status code is set to `404`, as well of the content-type we specified on the [VirtualService configuration](#virtualservice).
```shell
curl 192.168.1.50/ -I
```
```text
HTTP/1.1 404 Not Found
content-type: text/plain
content-length: 14
date: Thu, 04 May 2023 01:18:50 GMT
server: istio-envoy
```
#### /found
We can confirm that this behavior applies to other paths (as it is matching the "default" rule we set in [VirtualService configuration]).
```shell
curl 192.168.1.50/found
```
```text
Page Not Found
```
```shell
curl 192.168.1.50/found -I
```
```text
HTTP/1.1 404 Not Found
content-type: text/plain
content-length: 14
date: Thu, 04 May 2023 01:20:40 GMT
server: istio-envoy
```
## Cleanup
Finally, a cleanup from the resources deployed.
```shell
kubectl delete -f ./
```
```text
deployment.apps "helloworld-nginx" deleted
gateway.networking.istio.io "helloworld-gateway" deleted
service "helloworld" deleted
virtualservice.networking.istio.io "helloworld-vs" deleted
```
# Links of interest
- https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPDirectResponse
- https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPBody

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 80
name: http
selector:
app: helloworld

View File

@ -1,19 +1,3 @@
# https://github.com/istio/istio/blob/master/samples/helloworld/helloworld-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
@ -30,7 +14,7 @@ spec:
exact: /helloworld
route:
- destination:
host: helloworld
host: helloworld.default.svc.cluster.local
port:
number: 80
rewrite: