diff --git a/01-Getting_Started/README.md b/01-Getting_Started/README.md index 9ce55a6..d1fe4ea 100755 --- a/01-Getting_Started/README.md +++ b/01-Getting_Started/README.md @@ -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. diff --git a/02-Traffic_management/01-2_deployments_method/README.md b/02-Traffic_management/01-2_deployments_method/README.md deleted file mode 100755 index 575c5da..0000000 --- a/02-Traffic_management/01-2_deployments_method/README.md +++ /dev/null @@ -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 diff --git a/02-Traffic_management/01-2_deployments_method/deployment.yaml b/02-Traffic_management/01-header_routing/Deployment.yaml similarity index 85% rename from 02-Traffic_management/01-2_deployments_method/deployment.yaml rename to 02-Traffic_management/01-header_routing/Deployment.yaml index de79e86..124c391 100755 --- a/02-Traffic_management/01-2_deployments_method/deployment.yaml +++ b/02-Traffic_management/01-header_routing/Deployment.yaml @@ -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: diff --git a/02-Traffic_management/01-header_routing/DestinationRoute.yaml b/02-Traffic_management/01-header_routing/DestinationRoute.yaml new file mode 100644 index 0000000..dbb5d89 --- /dev/null +++ b/02-Traffic_management/01-header_routing/DestinationRoute.yaml @@ -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 diff --git a/02-Traffic_management/01-header_routing/Gateway.yaml b/02-Traffic_management/01-header_routing/Gateway.yaml new file mode 100755 index 0000000..bbd9d67 --- /dev/null +++ b/02-Traffic_management/01-header_routing/Gateway.yaml @@ -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: + - "*" \ No newline at end of file diff --git a/02-Traffic_management/01-header_routing/README.md b/02-Traffic_management/01-header_routing/README.md new file mode 100755 index 0000000..b322519 --- /dev/null +++ b/02-Traffic_management/01-header_routing/README.md @@ -0,0 +1,446 @@ +--- +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 +

It works!

+``` + +### Firefox browser + +Through using the Firefox web browser, the page accessed is the Nginx deployment. + +![firefox.png](src%2Ffirefox.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-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 +virtualservice.networking.istio.io "helloworld-vs" deleted +``` diff --git a/02-Traffic_management/01-header_routing/Service.yaml b/02-Traffic_management/01-header_routing/Service.yaml new file mode 100644 index 0000000..271ce25 --- /dev/null +++ b/02-Traffic_management/01-header_routing/Service.yaml @@ -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 \ No newline at end of file diff --git a/02-Traffic_management/01-2_deployments_method/gateway.yaml b/02-Traffic_management/01-header_routing/VirtualService.yaml old mode 100755 new mode 100644 similarity index 55% rename from 02-Traffic_management/01-2_deployments_method/gateway.yaml rename to 02-Traffic_management/01-header_routing/VirtualService.yaml index 2f3c8a8..5083686 --- a/02-Traffic_management/01-2_deployments_method/gateway.yaml +++ b/02-Traffic_management/01-header_routing/VirtualService.yaml @@ -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: "/" \ No newline at end of file diff --git a/02-Traffic_management/01-header_routing/src/firefox.png b/02-Traffic_management/01-header_routing/src/firefox.png new file mode 100644 index 0000000..e5dd48c Binary files /dev/null and b/02-Traffic_management/01-header_routing/src/firefox.png differ diff --git a/02-Traffic_management/02-DirectResponse-HTTP-Body/deployment.yaml b/02-Traffic_management/02-DirectResponse-HTTP-Body/Deployment.yaml similarity index 63% rename from 02-Traffic_management/02-DirectResponse-HTTP-Body/deployment.yaml rename to 02-Traffic_management/02-DirectResponse-HTTP-Body/Deployment.yaml index 01dd2b0..233fd2c 100755 --- a/02-Traffic_management/02-DirectResponse-HTTP-Body/deployment.yaml +++ b/02-Traffic_management/02-DirectResponse-HTTP-Body/Deployment.yaml @@ -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: diff --git a/02-Traffic_management/02-DirectResponse-HTTP-Body/Gateway.yaml b/02-Traffic_management/02-DirectResponse-HTTP-Body/Gateway.yaml new file mode 100644 index 0000000..bbd9d67 --- /dev/null +++ b/02-Traffic_management/02-DirectResponse-HTTP-Body/Gateway.yaml @@ -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: + - "*" \ No newline at end of file diff --git a/02-Traffic_management/02-DirectResponse-HTTP-Body/Services.yaml b/02-Traffic_management/02-DirectResponse-HTTP-Body/Services.yaml new file mode 100644 index 0000000..9a68f29 --- /dev/null +++ b/02-Traffic_management/02-DirectResponse-HTTP-Body/Services.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: helloworld + labels: + app: helloworld + service: helloworld +spec: + ports: + - port: 80 + name: http + selector: + app: helloworld +--- \ No newline at end of file diff --git a/02-Traffic_management/02-DirectResponse-HTTP-Body/gateway.yaml b/02-Traffic_management/02-DirectResponse-HTTP-Body/VirtualService.yaml similarity index 61% rename from 02-Traffic_management/02-DirectResponse-HTTP-Body/gateway.yaml rename to 02-Traffic_management/02-DirectResponse-HTTP-Body/VirtualService.yaml index 0c4e274..8581813 100755 --- a/02-Traffic_management/02-DirectResponse-HTTP-Body/gateway.yaml +++ b/02-Traffic_management/02-DirectResponse-HTTP-Body/VirtualService.yaml @@ -1,18 +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