GitOps Workflow Example with Argo CD, GitLab CI, and Kubernetes
This article provides a step‑by‑step guide to implementing a GitOps workflow on a Kubernetes cluster using Argo CD and GitLab CI, covering Argo CD installation, Helm deployment, application configuration, CI/CD pipeline definition, and deployment to dev and prod environments.
GitOps is a declarative continuous‑delivery approach that stores the desired state of a Kubernetes cluster in a Git repository. This guide demonstrates a complete GitOps workflow using Argo CD as the delivery engine and GitLab CI for building and publishing container images.
Argo CD installation : After ensuring a reachable Kubernetes cluster, install the ingress-nginx controller, then add the Argo CD Helm chart and install it with a custom values.yaml that enables an NGINX ingress.
kubectl create ns argocd helm repo add argo https://argoproj.github.io/argo-helm helm install argocd -n argocd argo/argo-cd --values values.yaml server:
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
hosts:
- argocd.k8s.localAfter the Helm release is ready, verify the pods are running and retrieve the initial admin password:
kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2GitLab project configuration : Create a GitLab repository for a simple Go web application, then define CI/CD variables (e.g., CI_REGISTRY , CI_REGISTRY_IMAGE , CI_REGISTRY_USER , CI_REGISTRY_PASSWORD , CI_USERNAME , CI_PASSWORD ) in the project settings.
Argo CD application manifests : Two Application CRDs are created—one for the development namespace and one for production. They point to the Git repository and the respective deployment/dev or deployment/prod directories.
# gitops-demo-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-dev
namespace: argocd
spec:
project: default
source:
repoURL: http://git.k8s.local/course/gitops-webapp.git
targetRevision: HEAD
path: deployment/dev
destination:
server: https://kubernetes.default.svc
namespace: dev
syncPolicy:
automated:
prune: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-prod
namespace: argocd
spec:
project: default
source:
repoURL: http://git.k8s.local/course/gitops-webapp.git
targetRevision: HEAD
path: deployment/prod
destination:
server: https://kubernetes.default.svc
namespace: prod
syncPolicy:
automated:
prune: trueApply the manifests:
kubectl apply -f gitops-demo-app.yamlGitLab CI pipeline : The .gitlab-ci.yml defines four stages— build , publish , deploy-dev , and deploy-prod . The build stage compiles the Go binary, the publish stage builds a Docker image with Kaniko and pushes it to the registry, and the deploy stages update the Kustomize manifests and push the changes back to Git.
stages:
- build
- publish
- deploy-dev
- deploy-prod
build:
stage: build
image:
name: golang:1.13.1
script:
- go build -o main main.go
artifacts:
paths:
- main
variables:
CGO_ENABLED: 0
publish:
stage: publish
image:
name: cnych/kaniko-executor:v0.22.0
entrypoint: [""]
script:
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile ./Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
dependencies:
- build
only:
- master
deploy-dev:
stage: deploy-dev
image: cnych/kustomize:v1.0
before_script:
- git remote set-url origin http://$CI_USERNAME:[email protected]/course/gitops-webapp.git
- git config --global user.email "[email protected]"
- git config --global user.name "GitLab CI/CD"
script:
- git checkout -B master
- cd deployment/dev
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- git commit -am '[skip ci] DEV image update'
- git push origin master
only:
- master
deploy-prod:
stage: deploy-prod
image: cnych/kustomize:v1.0
before_script:
- git remote set-url origin http://$CI_USERNAME:[email protected]/course/gitops-webapp.git
- git config --global user.email "[email protected]"
- git config --global user.name "GitLab CI/CD"
script:
- git checkout -B master
- git pull origin master
- cd deployment/prod
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- git commit -am '[skip ci] PROD image update'
- git push origin master
only:
- master
when: manualWhen a developer pushes changes to the master branch, the pipeline builds a new image, updates the Kustomize manifests, and Argo CD automatically syncs the changes to the dev namespace. A manual trigger can promote the same image to the prod namespace.
Both environments are exposed via Ingress; adding the hostnames to /etc/hosts allows local browsers to reach http://webapp.dev.k8s.local/ and http://webapp.prod.k8s.local/ . Updating the source code (e.g., changing the welcome message) and committing triggers the pipeline, resulting in a live update of the running application.
References: Weaveworks GitOps overview, Argo CD documentation, GitLab CI/CD YAML reference, a medium article on GitOps with Argo CD, and the demo repository https://github.com/cnych/gitops-webapp-demo .
DevOps Cloud Academy
Exploring industry DevOps practices and technical expertise.
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.