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.yaml GitLab 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
