From 6efa631ed17faf2ab7835651daa8d2f7b107ab8a Mon Sep 17 00:00:00 2001 From: Alon Gluz Date: Thu, 26 Sep 2024 16:57:09 +0300 Subject: [PATCH] Add Linkerd example (#81) * work on l5d example Signed-off-by: Alon Gluz * add files for example and work on the readme.md Signed-off-by: Alon Gluz * add ns as well Signed-off-by: Alon Gluz * small patches to make sure it is working Signed-off-by: Alon Gluz * update provider status as well Signed-off-by: Alon Gluz * align examples Signed-off-by: Alon Gluz --------- Signed-off-by: Alon Gluz --- docs/provider-status.md | 1 + examples/linkerd/README.md | 92 ++++++++++++++++++++++ examples/linkerd/argo-rollouts-plugin.yaml | 10 +++ examples/linkerd/cluster-role-binding.yaml | 13 +++ examples/linkerd/cluster-role.yaml | 13 +++ examples/linkerd/httproute.yaml | 22 ++++++ examples/linkerd/kind-cluster.yaml | 17 ++++ examples/linkerd/namespace.yaml | 8 ++ examples/linkerd/rollout.yaml | 48 +++++++++++ examples/linkerd/service.yaml | 33 ++++++++ examples/linkerd/setup.sh | 18 +++++ examples/linkerd/steps.sh | 11 +++ 12 files changed, 286 insertions(+) create mode 100644 examples/linkerd/README.md create mode 100644 examples/linkerd/argo-rollouts-plugin.yaml create mode 100644 examples/linkerd/cluster-role-binding.yaml create mode 100644 examples/linkerd/cluster-role.yaml create mode 100644 examples/linkerd/httproute.yaml create mode 100644 examples/linkerd/kind-cluster.yaml create mode 100644 examples/linkerd/namespace.yaml create mode 100644 examples/linkerd/rollout.yaml create mode 100644 examples/linkerd/service.yaml create mode 100755 examples/linkerd/setup.sh create mode 100644 examples/linkerd/steps.sh diff --git a/docs/provider-status.md b/docs/provider-status.md index 14b94ff..f55894d 100644 --- a/docs/provider-status.md +++ b/docs/provider-status.md @@ -17,6 +17,7 @@ For convenience we are including here a list of those actually tested with the p | [Kong](https://docs.konghq.com/kubernetes-ingress-controller/latest/concepts/gateway-api/) | yes | [Example](https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/tree/main/examples/kong) | | [NGINX Gateway](https://github.com/nginxinc/nginx-gateway-fabric) | yes | [Example](https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/tree/main/examples/nginx) | | [Traefik](https://doc.traefik.io/traefik/providers/kubernetes-gateway/) | yes | [Example](https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/tree/main/examples/traefik) | +| [Linkerd](https://linkerd.io/) | yes | [Example](https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/tree/main/examples/linkerd) | Note that these examples are included just for completeness. You should be able to use any solution that implements the Gateway API. diff --git a/examples/linkerd/README.md b/examples/linkerd/README.md new file mode 100644 index 0000000..643dbd9 --- /dev/null +++ b/examples/linkerd/README.md @@ -0,0 +1,92 @@ +# Using Linkerd with Argo Rollouts + +[Linkerd](https://linkerd.io/) is a service mesh for Kubernetes. It makes running services easier and safer by giving you runtime debugging, observability, reliability, and security—all without requiring any changes to your code. + +## Prerequisites + +A Kubernetes cluster. If you do not have one, you can create one using [kind](https://kind.sigs.k8s.io/), [minikube](https://minikube.sigs.k8s.io/), or any other Kubernetes cluster. This guide will use Kind. + +Linkerd installed in your Kubernetes cluster. + + +## Step 1 - Create a Kind cluster by running the following command: + +```shell +kind delete cluster &>/dev/null +kind create cluster --config ./kind-cluster.yaml +``` + +## Step 2 - Install Linkerd and Linkerd Viz by running the following commands: + +I will use the Linkerd CLI to install Linkerd in the cluster. You can also install Linkerd using Helm or kubectl. +I tested this guide with Linkerd version 2.13.0 + +```shell +linkerd install --crds | kubectl apply -f - +linkerd install | kubectl apply -f - && linkerd check +linkerd viz install | kubectl apply -f - && linkerd check +``` + + +## Step 3 - Install Argo Rollouts and Argo Rollouts plugin to allow Linkerd to manage the traffic: + +```shell +kubectl create namespace argo-rollouts +kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml +kubectl apply -k https://github.com/argoproj/argo-rollouts/manifests/crds\?ref\=stable +kubectl apply -f argo-rollouts-plugin.yaml +kubectl rollout restart deploy -n argo-rollouts +``` + +## Step 4 - Grant Argo Rollouts SA access to the Gateway/Http Route +```shell +kubectl apply -f cluster-role.yaml +``` +__Note:__ These permission are very permissive. You should lock them down according to your needs. + +With the following role we allow Argo Rollouts to have Admin access to HTTPRoutes and Gateways. + +```shell +kubectl apply -f cluster-role-binding.yaml +``` +## Step 5 - Create HTTPRoute that defines a traffic split between two services + +Create HTTPRoute and connect to the created Gateway resource + +```shell +kubectl apply -f httproute.yaml +``` +## Step 6 - Create the services required for traffic split + +Create three Services required for canary based rollout stratedy + +```shell +kubectl apply -f service.yaml +``` + +## Step 7 - Create the services required for traffic split + +Add Linkerd annotaions to the namespace where the services are deployed + +```shell +kubectl apply -f namespace.yaml +``` + +## Step 8 - Create an example Rollout + +Deploy a rollout to get the initial version. +```shell +kubectl apply -f rollout.yaml +``` + +## Step 9 - Watch the rollout +```shell +watch "kubectl -n default get httproute.gateway.networking.k8s.io/argo-rollouts-http-route -o custom-columns=NAME:.metadata.name,PRIMARY_SERVICE:.spec.rules[0].backendRefs[0].name,PRIMARY_WEIGHT:.spec.rules[0].backendRefs[0].weight,CANARY_SERVICE:.spec.rules[0].backendRefs[1].name,CANARY_WEIGHT:.spec.rules[0].backendRefs[1].weight" +``` + +## Step 10 - Patch the rollout to see the canary deployment +```shell +kubectl patch rollout rollouts-demo --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/env/0/value", "value": "1.1.0"}]' +``` + + diff --git a/examples/linkerd/argo-rollouts-plugin.yaml b/examples/linkerd/argo-rollouts-plugin.yaml new file mode 100644 index 0000000..ad86316 --- /dev/null +++ b/examples/linkerd/argo-rollouts-plugin.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-rollouts-config # must be so name + namespace: argo-rollouts # must be in this namespace +data: + trafficRouterPlugins: |- + - name: "argoproj-labs/gatewayAPI" + location: "https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/releases/download/v0.2.0/gateway-api-plugin-linux-arm64" diff --git a/examples/linkerd/cluster-role-binding.yaml b/examples/linkerd/cluster-role-binding.yaml new file mode 100644 index 0000000..5231076 --- /dev/null +++ b/examples/linkerd/cluster-role-binding.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: gateway-admin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: gateway-controller-role +subjects: + - namespace: argo-rollouts + kind: ServiceAccount + name: argo-rollouts diff --git a/examples/linkerd/cluster-role.yaml b/examples/linkerd/cluster-role.yaml new file mode 100644 index 0000000..d07d490 --- /dev/null +++ b/examples/linkerd/cluster-role.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: gateway-controller-role + namespace: argo-rollouts +rules: + - apiGroups: + - "*" + resources: + - "*" + verbs: + - "*" diff --git a/examples/linkerd/httproute.yaml b/examples/linkerd/httproute.yaml new file mode 100644 index 0000000..edc6f45 --- /dev/null +++ b/examples/linkerd/httproute.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: argo-rollouts-http-route + namespace: default +spec: + parentRefs: + - group: "core" + name: argo-rollouts-service + kind: Service + port: 80 + rules: + - backendRefs: + - name: argo-rollouts-stable-service + group: "core" + port: 80 + kind: Service + - name: argo-rollouts-canary-service + group: "core" + port: 80 + kind: Service diff --git a/examples/linkerd/kind-cluster.yaml b/examples/linkerd/kind-cluster.yaml new file mode 100644 index 0000000..89ded6b --- /dev/null +++ b/examples/linkerd/kind-cluster.yaml @@ -0,0 +1,17 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: + - role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP diff --git a/examples/linkerd/namespace.yaml b/examples/linkerd/namespace.yaml new file mode 100644 index 0000000..71ac206 --- /dev/null +++ b/examples/linkerd/namespace.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: default + annotations: + linkerd.io/inject: enabled +spec: {} diff --git a/examples/linkerd/rollout.yaml b/examples/linkerd/rollout.yaml new file mode 100644 index 0000000..774049c --- /dev/null +++ b/examples/linkerd/rollout.yaml @@ -0,0 +1,48 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: rollouts-demo +spec: + replicas: 5 + strategy: + canary: + canaryService: argo-rollouts-canary-service # our created canary service + stableService: argo-rollouts-stable-service # our created stable service + trafficRouting: + plugins: + argoproj-labs/gatewayAPI: + httpRoute: argo-rollouts-http-route # our created httproute + namespace: default # namespace where this rollout resides + steps: + - setWeight: 30 + - pause: { duration: 10 } + - setWeight: 40 + - pause: { duration: 10 } + - setWeight: 60 + - pause: { duration: 10 } + - setWeight: 80 + - pause: { duration: 10 } + revisionHistoryLimit: 2 + selector: + matchLabels: + app: rollouts-demo + template: + metadata: + labels: + app: rollouts-demo + spec: + containers: + - name: rollouts-demo + image: argoproj/rollouts-demo:red + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: APP_VERSION + value: "1.0.0" + resources: + requests: + memory: 32Mi + cpu: 5m diff --git a/examples/linkerd/service.yaml b/examples/linkerd/service.yaml new file mode 100644 index 0000000..86d8a3a --- /dev/null +++ b/examples/linkerd/service.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: argo-rollouts-service +spec: + ports: + - port: 80 + targetPort: http + selector: + app: rollouts-demo +--- +apiVersion: v1 +kind: Service +metadata: + name: argo-rollouts-canary-service +spec: + ports: + - port: 80 + targetPort: http + selector: + app: rollouts-demo +--- +apiVersion: v1 +kind: Service +metadata: + name: argo-rollouts-stable-service +spec: + ports: + - port: 80 + targetPort: http + selector: + app: rollouts-demo diff --git a/examples/linkerd/setup.sh b/examples/linkerd/setup.sh new file mode 100755 index 0000000..4813bf0 --- /dev/null +++ b/examples/linkerd/setup.sh @@ -0,0 +1,18 @@ +#!/bin/bash +kind delete cluster &>/dev/null +kind create cluster --config manifests/kind-cluster.yaml +kubectl ns default + +linkerd install --crds | kubectl apply -f - + +linkerd install | kubectl apply -f - && linkerd check + +linkerd viz install | kubectl apply -f - && linkerd check + +kubectl create namespace argo-rollouts +kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml +kubectl apply -k https://github.com/argoproj/argo-rollouts/manifests/crds\?ref\=stable + +kubectl apply -k manifests/ +kubectl rollout restart deploy -n argo-rollouts + diff --git a/examples/linkerd/steps.sh b/examples/linkerd/steps.sh new file mode 100644 index 0000000..540c61f --- /dev/null +++ b/examples/linkerd/steps.sh @@ -0,0 +1,11 @@ + +# watch Route +kubectl -n argo-demo get httproute.gateway.networking.k8s.io/argo-rollouts-http-route -o custom-columns=NAME:.metadata.name,PRIMARY_SERVICE:.spec.rules[0].backendRefs[0].name,PRIMARY_WEIGHT:.spec.rules[0].backendRefs[0].weight,CANARY_SERVICE:.spec.rules[0].backendRefs[1].name,CANARY_WEIGHT:.spec.rules[0].backendRefs[1].weight + +# View traffic +linkerd viz -n argo-demo stat rs --from deploy/slow-cooker + +# View Rollout +kubectl argo rollouts -n argo-demo get rollout rollouts-demo + +watch k argo rollouts -n argo-demo get rollout rollouts-demo