kuadrantctl - CI/CD with Tekton and Argo CD¶
This guide demonstrates setting up a CI/CD pipeline using Tekton to deploy Kubernetes Gateway API and Kuadrant resources generated by kuadrantctl
, from an OpenAPI specification. In this example, these resources are applied directly to the cluster where Tekton is running.
Prerequisites¶
- Kuadrant, and all of its pre-requisites, is installed onto a cluster
- Tekton Pipelines installed on your Kubernetes or OpenShift cluster.
kubectl
configured to communicate with your cluster (i.e you have a kubectl config available with access to your cluster)- Tekton CLI
tkn
(optional) for easier interaction with Tekton resources.
Setup¶
First, create a dedicated namespace:
Create a Persistent Volume Claim¶
To store Tekton build artifacts, create a PVC in the petstore namespace:
kubectl apply -n petstore -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: tekton-kuadrantctl-pvc
namespace: petstore
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
EOF
Define the Tekton Task¶
Define the task that outlines steps to clone a repository, generate Kuadrant and Kubernetes resources using kuadrantctl
, and apply them directly to the cluster:
kubectl apply -f - <<'EOF'
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: run-kuadrantctl
namespace: petstore
spec:
params:
- name: gitRepoUrl
description: URL of the git repository to clone
- name: gitRevision
description: Git revision to checkout (branch, tag, sha)
workspaces:
- name: source
description: Workspace to checkout the git repo
- name: kubeconfig
description: Workspace containing kubeconfig for Kubernetes cluster access
steps:
- name: clean-workspace
image: alpine:latest
script: |
sh -c 'rm -rf $(workspaces.source.path)/* $(workspaces.source.path)/.[!.]* $(workspaces.source.path)/..?*'
- name: clone
image: alpine/git:latest
script: |
git clone $(params.gitRepoUrl) $(workspaces.source.path)
cd $(workspaces.source.path)
git checkout $(params.gitRevision)
- name: download-kuadrantctl
image: curlimages/curl:latest
script: |
ARCH=$(uname -m)
case $ARCH in
x86_64) BIN_ARCH="amd64";;
arm64) BIN_ARCH="arm64";;
aarch64) BIN_ARCH="arm64";;
*) echo "Unsupported architecture: $ARCH" && exit 1 ;;
esac
cd $(workspaces.source.path)
curl -LO "https://github.com/Kuadrant/kuadrantctl/releases/download/v0.2.0/kuadrantctl-v0.2.0-linux-$BIN_ARCH.tar.gz"
tar -xzf kuadrantctl-v0.2.0-linux-$BIN_ARCH.tar.gz
- name: run-kuadrantctl
image: alpine:latest
script: |
# Install yq silently
apk add --no-cache curl > /dev/null
curl -s -L https://github.com/mikefarah/yq/releases/download/v4.6.1/yq_linux_arm64 -o /usr/bin/yq > /dev/null && chmod +x /usr/bin/yq
cd $(workspaces.source.path)
mkdir -p generated-resources
./kuadrantctl generate kuadrant authpolicy --oas openapi.yaml | yq eval -P | tee generated-resources/authpolicy.yaml
./kuadrantctl generate kuadrant ratelimitpolicy --oas openapi.yaml | yq eval -P | tee generated-resources/ratelimitpolicy.yaml
./kuadrantctl generate gatewayapi httproute --oas openapi.yaml | yq eval -P | tee generated-resources/httproute.yaml
- name: apply-resources
image: lachlanevenson/k8s-kubectl
script: |
apk add --no-cache gettext > /dev/null
cd $(workspaces.source.path)
export KUADRANT_ZONE_ROOT_DOMAIN=example.com # domain name used in the HTTPRoute for the petstore sample app
for file in ./generated-resources/*.yaml; do
envsubst < "$file" | kubectl apply -n petstore -f -
done
EOF
We're using Tekton here with kubectl
to apply resources to a cluster. We recommend looking at a tool such as (ArgoCD)[https://argo-cd.readthedocs.io/en/stable/] to implement continuous delivery via a GitOps approach. In this scenario, you would:
- Use
kuadrantctl
to generate Kubernetes/Kuadrant resources as part a Tekton pipeline - Commit these new resources in to a git respository
- Use ArgoCD to sync these changes via a Git respository to a Kubernetes or OpenShift cluster
Create a Kubeconfig Secret¶
Provide Tekton access to your Kubernetes cluster by creating a secret with your kubeconfig in the petstore
namespace:
kubectl create secret generic kubeconfig-secret --from-file=kubeconfig=/path/to/.kube/config -n petstore
Create an associated ClusterRole
and ClusterRoleBinding
:
kubectl apply -n petstore -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kuadrant-ci-example-full-access
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kuadrant-ci-example-full-access-binding
subjects:
- kind: ServiceAccount
name: default
namespace: petstore
roleRef:
kind: ClusterRole
name: kuadrant-ci-example-full-access
apiGroup: rbac.authorization.k8s.io
EOF
Trigger the TaskRun
¶
Execute the task within the petstore
namespace, referencing the kubeconfig secret for cluster access:
In this example, we'll run this task with our Kuadrant Petstore app: https://github.com/kuadrant/api-petstore
kubectl apply -n petstore -f - <<EOF
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: run-kuadrantctl-taskrun
namespace: petstore
spec:
taskRef:
name: run-kuadrantctl
params:
- name: gitRepoUrl
value: "https://github.com/kuadrant/api-petstore.git"
- name: gitRevision
value: "main"
workspaces:
- name: source
persistentVolumeClaim:
claimName: tekton-kuadrantctl-pvc
- name: kubeconfig
secret:
secretName: kubeconfig-secret
EOF
Cleanup¶
To cleanup, remove the petstore
namespace.