From adbad99a71234f1f570133c36c1961c7dd383e94 Mon Sep 17 00:00:00 2001 From: Brendan Kamp Date: Fri, 9 Jun 2023 13:58:15 +0200 Subject: [PATCH] docs: canary weighted deployments example (#10067) Signed-off-by: Spazzy --- docs/examples/canary/README.md | 231 +++++++++++++++++++++++++++++++++ docs/examples/index.md | 1 + 2 files changed, 232 insertions(+) create mode 100644 docs/examples/canary/README.md diff --git a/docs/examples/canary/README.md b/docs/examples/canary/README.md new file mode 100644 index 000000000..4124faf6f --- /dev/null +++ b/docs/examples/canary/README.md @@ -0,0 +1,231 @@ +# Canary + +Ingress Nginx Has the ability to handle canary routing by setting specific +annotations, the following is an example of how to configure a canary +deployment with weighted canary routing. + +## Create your main deployment and service + +This is the main deployment of your application with the service that will be +used to route to it + +```bash +echo " +--- +# Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: production + labels: + app: production +spec: + replicas: 1 + selector: + matchLabels: + app: production + template: + metadata: + labels: + app: production + spec: + containers: + - name: production + image: registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:6fc5aa2994c86575975bb20a5203651207029a0d28e3f491d8a127d08baadab4 + ports: + - containerPort: 80 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP +--- +# Service +apiVersion: v1 +kind: Service +metadata: + name: production + labels: + app: production +spec: + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: http + selector: + app: production +" | kubectl apply -f - +``` + +## Create the canary deployment and service + +This is the canary deployment that will take a weighted amount of requests +instead of the main deployment + +```bash +echo " +--- +# Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: canary + labels: + app: canary +spec: + replicas: 1 + selector: + matchLabels: + app: canary + template: + metadata: + labels: + app: canary + spec: + containers: + - name: canary + image: registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:6fc5aa2994c86575975bb20a5203651207029a0d28e3f491d8a127d08baadab4 + ports: + - containerPort: 80 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP +--- +# Service +apiVersion: v1 +kind: Service +metadata: + name: canary + labels: + app: canary +spec: + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: http + selector: + app: canary +" | kubectl apply -f - +``` + +## Create Ingress Pointing To Your Main Deployment + +Next you will need to expose your main deployment with an ingress resource, +note there are no canary specific annotations on this ingress + +```bash +echo " +--- +# Ingress +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: production + annotations: +spec: + ingressClassName: nginx + rules: + - host: echo.prod.mydomain.com + http: + paths: + - pathType: Prefix + path: / + backend: + service: + name: production + port: + number: 80 +" | kubectl apply -f - +``` + +## Create Ingress Pointing To Your Canary Deployment + +You will then create an Ingress that has the canary specific configuration, +please pay special notice of the following: + +- The host name is identical to the main ingress host name +- The `nginx.ingress.kubernetes.io/canary: "true"` annotation is required and + defines this as a canary annotation (if you do not have this the Ingresses + will clash) +- The `nginx.ingress.kubernetes.io/canary-weight: "50"` annotation dictates the + weight of the routing, in this case there is a "50%" chance a request will + hit the canary deployment over the main deployment +```bash +echo " +--- +# Ingress +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: canary + annotations: + nginx.ingress.kubernetes.io/canary: \"true\" + nginx.ingress.kubernetes.io/canary-weight: \"50\" +spec: + ingressClassName: nginx + rules: + - host: echo.prod.mydomain.com + http: + paths: + - pathType: Prefix + path: / + backend: + service: + name: canary + port: + number: 80 +" | kubectl apply -f - +``` + +## Testing your setup + +You can use the following command to test your setup (replacing +INGRESS_CONTROLLER_IP with your ingresse controllers IP Address) + +```bash +for i in $(seq 1 10); do curl -s --resolve echo.prod.mydomain.com:80:$INGRESS_CONTROLLER_IP echo.prod.mydomain.com | grep "Hostname"; done +``` + +You will get the following output showing that your canary setup is working as +expected: + +```bash +Hostname: production-5c5f65d859-phqzc +Hostname: canary-6697778457-zkfjf +Hostname: canary-6697778457-zkfjf +Hostname: production-5c5f65d859-phqzc +Hostname: canary-6697778457-zkfjf +Hostname: production-5c5f65d859-phqzc +Hostname: production-5c5f65d859-phqzc +Hostname: production-5c5f65d859-phqzc +Hostname: canary-6697778457-zkfjf +Hostname: production-5c5f65d859-phqzc +``` diff --git a/docs/examples/index.md b/docs/examples/index.md index 8a5fd5f51..3af4266ff 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -23,6 +23,7 @@ Customization | [External authentication with response header propagation](custo Customization | [Sysctl tuning](customization/sysctl/README.md) | TODO | TODO Features | [Rewrite](rewrite/README.md) | TODO | TODO Features | [Session stickiness](affinity/cookie/README.md) | route requests consistently to the same endpoint | Advanced +Features | [Canary Deployments](canary/README.md) | weigthed canary routing to a seperate deployment | Intermediate Scaling | [Static IP](static-ip/README.md) | a single ingress gets a single static IP | Intermediate TLS | [Multi TLS certificate termination](multi-tls/README.md) | TODO | TODO TLS | [TLS termination](tls-termination/README.md) | TODO | TODO