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.
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.gitinto 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
AppProjectCRD, 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.
<code>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
</code>After creating the project, define an
Applicationthat points to the Helm chart:
<code>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
</code>The application will initially be in
OutOfSyncbecause it has not been deployed yet.
Next, modify the original Tekton pipeline to remove the
deployand
rollbacktasks, 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.
<code># 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)
</code>The new
synctask logs into Argo CD and runs
argocd app syncfollowed by
argocd app waitto ensure the application reaches a healthy state.
<code>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
</code>To modify the Helm
values.yamlfile directly, we add a
change-manifeststask that clones the repo, updates
image.tagusing
yq, commits, and pushes the change.
<code>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
</code>Finally, create a secret for Argo CD login:
<code>apiVersion: v1
kind: Secret
metadata:
name: argocd-auth
type: Opaque
stringData:
username: admin
password: admin321
</code>Update the Tekton TriggerTemplate to launch the pipeline with the new parameters.
<code># 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
</code>Argo CD’s default health check for
Ingressresources may fail because the
status.loadBalancer.ingresslist is empty. To fix this, customize the health check using Lua in the
argocd-cmConfigMap:
<code># 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
</code>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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.