Cloud Native 17 min read

Transform Tekton CI/CD into a GitOps Workflow with Argo CD

This guide shows how to refactor a Tekton CI/CD pipeline by extracting Helm chart templates into a separate repository, configuring Argo CD to manage the deployment stage, and adding Tekton tasks that update Helm values, sync the application, and handle health checks, achieving a full GitOps workflow on Kubernetes.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Transform Tekton CI/CD into a GitOps Workflow with Argo CD

Previously we used Tekton to implement the CI/CD pipeline, but the CD stage was performed within Tekton tasks. Now we redesign the pipeline to use GitOps, delegating the CD part to Argo CD.

First, extract the Helm Chart templates from the project http://git.k8s.local/course/devops-demo.git into a dedicated repository http://git.k8s.local/course/devops-demo-deploy. This repository will contain only the Helm chart used for application deployment, making it easier to integrate with Argo CD.

Add the new repository to Argo CD, then create a new Application. First, define an AppProject CRD, which groups applications logically and includes the following key fields: sourceRepos: repositories from which the applications can fetch manifests. destinations: target clusters and namespaces for deployment. roles: role definitions for resource access within the project.

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: demo
  namespace: argocd
spec:
  destinations:
  - namespace: '*'
    server: https://kubernetes.default.svc
  sourceRepos:
  - http://git.k8s.local/course/devops-demo-deploy.git

After creating the project, define an Application that points to the Helm chart:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: devops-demo
  namespace: argocd
spec:
  destination:
    namespace: default
    server: 'https://kubernetes.default.svc'
  project: demo
  source:
    path: helm
    repoURL: 'http://git.k8s.local/course/devops-demo-deploy.git'
    targetRevision: HEAD
    helm:
      parameters:
      - name: replicaCount
        value: '2'
      valueFiles:
      - my-values.yaml

The application will initially be in OutOfSync because it has not been deployed yet.

Next, modify the original Tekton pipeline to remove the deploy and rollback tasks, since deployment will now be handled by Argo CD. After the Docker image is built and pushed, a new task updates the Helm values file and triggers Argo CD synchronization.

# pipeline.yaml (excerpt)
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: pipeline
spec:
  workspaces:
  - name: go-repo-pvc
  params:
  - name: git_url
  - name: git_infra_url
  - name: revision
    type: string
    default: "master"
  - name: image
  - name: image_tag
  - name: registry_url
    type: string
    default: "harbor.k8s.local"
  - name: registry_mirror
    type: string
    default: "https://ot2k4d59.mirror.aliyuncs.com/"
  - name: git_manifest_dir
    default: "helm"
  - name: argocd_url
  - name: argocd_secret
  - name: app_name
  - name: app_revision
    type: string
    default: "HEAD"
  tasks:
  - name: clone
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: go-repo-pvc
    params:
    - name: url
      value: $(params.git_url)
    - name: revision
      value: $(params.revision)
  - name: test
    taskRef:
      name: test
  - name: build
    taskRef:
      name: build
    runAfter:
    - test
    - clone
    workspaces:
    - name: go-repo
      workspace: go-repo-pvc
  - name: docker
    taskRef:
      name: docker
    runAfter:
    - build
    workspaces:
    - name: go-repo
      workspace: go-repo-pvc
    params:
    - name: image
      value: $(params.image):$(params.image_tag)
    - name: registry_url
      value: $(params.registry_url)
    - name: registry_mirror
      value: $(params.registry_mirror)
  - name: manifests
    taskRef:
      name: change-manifests
    runAfter:
    - docker
    params:
    - name: git_url
      value: $(params.git_infra_url)
    - name: git_manifest_dir
      value: $(params.git_manifest_dir)
    - name: image_tag
      value: $(params.image_tag)
  - name: sync
    taskRef:
      name: sync
    runAfter:
    - manifests
    params:
    - name: argocd_url
      value: $(params.argocd_url)
    - name: argocd_secret
      value: $(params.argocd_secret)
    - name: app_name
      value: $(params.app_name)
    - name: app_revision
      value: $(params.app_revision)

The new sync task logs into Argo CD and runs argocd app sync followed by argocd app wait to ensure the application reaches a healthy state.

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: sync
spec:
  volumes:
  - name: argocd-secret
    secret:
      secretName: $(inputs.params.argocd_secret)
  params:
  - name: argocd_url
    description: "The URL of the ArgoCD server"
  - name: argocd_secret
    description: "Secret containing username and password for Argo CD"
  - name: commit_id
    description: "The commit ID to update"
  - name: app_name
    description: "The name of the Argo CD application"
  - name: app_revision
    default: "HEAD"
    description: "Revision of the application"
  steps:
  - name: deploy
    image: argoproj/argocd
    volumeMounts:
    - name: argocd-secret
      mountPath: /var/secret
    command:
    - sh
    args:
    - -ce
    - |
      set -e
      echo "update commit id"
      argocd login --insecure $(params.argocd_url) --username $(/bin/cat /var/secret/username) --password $(/bin/cat /var/secret/password)
      argocd app sync $(params.app_name) --revision $(params.app_revision)
      argocd app wait $(params.app_name) --health

To modify the Helm values.yaml file directly, we add a change-manifests task that clones the repo, updates image.tag using yq, commits, and pushes the change.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: change-manifests
spec:
  params:
  - name: git_url
    description: Git repository containing manifest files to update
  - name: git_email
    default: [email protected]
  - name: git_name
    default: Tekton Pipeline
  - name: git_manifest_dir
    description: Manifests files directory
  - name: tool_image
    default: cnych/helm-kubectl-curl-git-jq-yq
  - name: image_tag
    description: Deploy docker image tag
  steps:
  - name: git-push
    image: $(params.tool_image)
    env:
    - name: GIT_USERNAME
      valueFrom:
        secretKeyRef:
          name: gitlab-auth
          key: username
          optional: true
    - name: GIT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: gitlab-auth
          key: password
          optional: true
    command: ["/bin/bash"]
    args:
    - -c
    - |
      set -eu
      git config --global user.email "$(params.git_email)"
      git config --global user.name "$(params.git_name)"
      git clone --branch master --depth 1 http://${GIT_USERNAME}:${GIT_PASSWORD}@$(params.git_url) repo
      cd "repo/$(params.git_manifest_dir)"
      yq w --inplace my-values.yaml 'image.tag' "$(params.image_tag)"
      if ! git diff-index --quiet HEAD --; then
        git add .
        git commit -m "helm values updated by tekton pipeline in change-manifests task"
        git push
      else
        echo "no changes, git repository is up to date"
      fi

Finally, create a secret for Argo CD login:

apiVersion: v1
kind: Secret
metadata:
  name: argocd-auth
type: Opaque
stringData:
  username: admin
  password: admin321

Update the Tekton TriggerTemplate to launch the pipeline with the new parameters.

# gitlab-template.yaml
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: gitlab-template
spec:
  params:
  - name: gitrevision
  - name: gitrepositoryurl
  resourcetemplates:
  - apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: gitlab-run-
    spec:
      serviceAccountName: tekton-build-sa
      pipelineRef:
        name: pipeline
      workspaces:
      - name: go-repo-pvc
        persistentVolumeClaim:
          claimName: go-repo-pvc
      params:
      - name: git_url
        value: $(tt.params.gitrepositoryurl)
      - name: git_infra_url
        value: git.k8s.local/course/devops-demo-deploy.git
      - name: image
        value: "harbor.k8s.local/course/devops-demo"
      - name: image_tag
        value: "$(tt.params.gitrevision)"
      - name: argocd_url
        value: argocd.k8s.local
      - name: argocd_secret
        value: argocd-auth
      - name: app_name
        value: devops-demo

Argo CD’s default health check for Ingress resources may fail because the status.loadBalancer.ingress list is empty. To fix this, customize the health check using Lua in the argocd-cm ConfigMap:

# Edit ConfigMap argocd-cm
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.customizations: |
    extensions/Ingress:
      health.lua: |
        hs = {}
        hs.status = "Healthy"
        return hs

After applying the customization, the application shows a healthy status in the Argo CD UI. Rollbacks can be performed directly from the UI using the "HISTORY AND ROLLBACK" feature.

The final pipeline run can be inspected with tkn pr describe, showing all tasks, parameters, and workspaces.

Overall, this workflow demonstrates how to combine Tekton and Argo CD to achieve a streamlined GitOps CI/CD pipeline on Kubernetes.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KubernetesGitOpsCI/CDhelmArgo CDtekton
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.