GitOps Workflow with Argo CD and GitLab CI on Kubernetes
This article demonstrates a complete GitOps workflow on Kubernetes using Argo CD and GitLab CI, covering installation, configuration of Argo CD, GitLab project setup, Helm deployment, and a multi‑stage CI/CD pipeline that automatically builds, publishes Docker images, and synchronizes applications in dev and prod environments.
In the current cloud‑native landscape, GitOps is increasingly adopted as a continuous delivery model. This guide provides a hands‑on example that combines Argo CD and GitLab CI to implement a full GitOps workflow.
Introduction
The workflow consists of two core components: Argo CD , a declarative GitOps continuous delivery tool for Kubernetes, and GitLab CI , a lightweight CI/CD system tightly integrated with GitLab.
Argo CD Installation
Prerequisite: a reachable Kubernetes cluster. An ingress-nginx controller is installed to expose the Argo CD dashboard. The following commands install Argo CD via Helm:
$ kubectl create ns argocd $ helm repo add argo https://argoproj.github.io/argo-helm $ helm install argocd -n argocd argo/argo-cd --values values.yamlThe values.yaml used for the Helm install configures an Ingress with TLS termination:
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 installation, add an entry for argocd.k8s.local to /etc/hosts pointing to the Ingress node. The default admin password is the name of the Argo CD server pod, obtained with:
$ kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2GitLab Project Configuration
A simple Go web application (source: github.com/cnych/gitops-webapp-demo ) is used as the example. The project is hosted on a self‑installed GitLab instance reachable at git.k8s.local . Required CI/CD variables are added in GitLab Settings → CI/CD → Variables:
CI_REGISTRY – Docker registry URL (https://index.docker.io/v1/)
CI_REGISTRY_IMAGE – Image name (cnych/gitops-webapp)
CI_REGISTRY_USER – Docker Hub username (cnych)
CI_REGISTRY_PASSWORD – Docker Hub password
CI_PASSWORD – Git repository access password
CI_USERNAME – Git repository access username
Argo CD Configuration
Two Application CRDs are defined – one for the development environment 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: trueApplying the manifest creates the two applications:
$ kubectl apply -f gitops-demo-app.yaml
application.argoproj.io/web-app-dev created
application.argoproj.io/web-app-prod createdGitLab CI Pipeline
The pipeline is defined in .gitlab-ci.yml with four stages: build , publish , deploy-dev , and deploy-prod .
stages:
- build
- publish
- deploy-dev
- deploy-prodBuild stage compiles the Go binary inside a golang:1.13.1 image and stores the artifact.
build:
stage: build
image:
name: golang:1.13.1
script:
- go build -o main main.go
artifacts:
paths:
- main
variables:
CGO_ENABLED: 0Publish stage uses a Kaniko executor to build a Docker image and push it to the registry. It runs only on the master branch.
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:
- masterDeploy‑dev stage updates the deployment/dev kustomization with the new image tag, commits the change, and pushes it back to GitLab.
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:
- masterDeploy‑prod stage is similar but marked when: manual so production updates require a manual trigger.
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: manualUsage
Both dev and prod applications are exposed via Ingresses at http://webapp.dev.k8s.local/ and http://webapp.prod.k8s.local/ . Adding these hostnames to /etc/hosts allows local testing. After modifying the Go source (e.g., changing the welcome message) and pushing to master , the pipeline builds a new image, updates the kustomization files, and Argo CD automatically syncs the changes, resulting in the updated message being served.
Production deployments are triggered manually from the GitLab pipeline UI, after which Argo CD synchronizes the prod environment.
References
https://www.weave.works/technologies/gitops/
https://argoproj.github.io/argo-cd/
https://docs.gitlab.com/ee/ci/yaml/
https://medium.com/@andrew.kaczynski/gitops-in-kubernetes-argo-cd-and-gitlab-ci-cd-5828c8eb34d6
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.