Skip to content

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:

kubectl create namespace petstore

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.