Implementing GitOps with Argo CD and Azure DevOps: A Step-by-Step Tutorial

Quick answer
Learn how to bridge the gap between Azure DevOps and Kubernetes with Argo CD. A complete guide to setting up a production-ready GitOps pipeline.
- The Architecture
- Step 1: Preparing Azure DevOps
- Step 2: Setting up Argo CD
- Step 3: The CI Pipeline (Azure Pipelines)
- Step 4: Configuring the Argo CD Application
10 min read · DevOps & Platform
GitOps manages Kubernetes clusters by treating infrastructure as code and making Git the single source of truth. While many tutorials focus on GitHub Actions or GitLab, many enterprises rely on Azure DevOps.
In this tutorial, we'll walk through setting up a robust GitOps workflow using Azure Repos, Azure Pipelines, and Argo CD. (Still deciding on a GitOps controller? See our Argo CD vs Flux CD comparison first — everything below assumes Argo CD.)
The Architecture
Our pipeline will follow the standard GitOps separation of concerns:
- Application Repo: Contains the source code and a Dockerfile.
- Manifest Repo: Contains Kubernetes manifests (Helm charts or Kustomize).
- Azure Pipelines: Handles CI (building and pushing images).
- Argo CD: Handles CD (synchronizing the Manifest Repo to the cluster).
Step 1: Preparing Azure DevOps
1.1 Create the Repositories
Create two repositories in your Azure DevOps project: my-app and my-app-gitops.
1.2 Create a Personal Access Token (PAT)
Argo CD needs a PAT to read the my-app-gitops repository. Ensure it has "Code: Read" permissions.
Step 2: Setting up Argo CD
Assuming you have Argo CD installed in your cluster, add your Azure Repo:
argocd repo add https://dev.azure.com/your-org/your-project/_git/my-app-gitops \
--username internal-bot \
--password <YOUR-PAT>Step 3: The CI Pipeline (Azure Pipelines)
Your CI pipeline in my-app should do two things: build the image and update the tag in the GitOps repo.
1# azure-pipelines.yml snippet
2steps:
3- task: Docker@2
4 inputs:
5 command: buildAndPush
6 repository: my-app
7 tags: $(Build.BuildId)
8
9- script: |
10 git config --global user.email "[email protected]"
11 git config --global user.name "Azure Pipeline"
12 git clone https://$(PAT)@dev.azure.com/org/proj/_git/my-app-gitops
13 cd my-app-gitops
14 sed -i "s/tag: .*/tag: $(Build.BuildId)/" values.yaml
15 git add .
16 git commit -m "Update image tag to $(Build.BuildId)"
17 git push
18 displayName: 'Update GitOps Manifest'Step 4: Configuring the Argo CD Application
Create the Application resource in Kubernetes (or via the Argo UI):
1apiVersion: argoproj.io/v1alpha1
2kind: Application
3metadata:
4 name: my-app
5 namespace: argocd
6spec:
7 project: default
8 source:
9 repoURL: 'https://dev.azure.com/your-org/your-project/_git/my-app-gitops'
10 targetRevision: HEAD
11 path: charts/my-app
12 destination:
13 server: 'https://kubernetes.default.svc'
14 namespace: prod
15 syncPolicy:
16 automated:
17 prune: true
18 selfHeal: trueWhy This Works
By using this setup, you gain:
- Auditability: Every change to production is recorded in Git.
- Rollbacks: Want to revert? Just
git revertthe last commit in the GitOps repo. - Security: The CI system doesn't need
cluster-adminaccess. It only needs to push to Git.
Always use a separate bot account for the PAT used by Argo CD and the Pipeline to ensure the principle of least privilege.
Conclusion
Integrating Argo CD with Azure DevOps provides a powerful, enterprise-grade GitOps experience. It bridges the gap between Microsoft's ecosystem and the cloud-native world of Kubernetes.
Struggling with complex CI/CD migrations? Coding Protocols can help you design and implement production-ready GitOps workflows tailored to your stack.
Frequently Asked Questions
Can Argo CD work with Azure DevOps?
Yes, cleanly. Azure Repos hosts the manifest repository, Azure Pipelines handles CI (build, test, push the image, bump the manifest), and Argo CD watches the repo and pulls changes into the cluster. Argo CD authenticates to Azure Repos with a PAT or SSH key — the cluster never needs push access to your pipeline.
Why separate CI from CD in GitOps?
Because the pull model keeps cluster credentials inside the cluster. The pipeline never holds kubeconfigs; it only writes to Git. You get an auditable history of every deployment (it's just commits), trivial rollbacks (revert the commit), and drift detection — the cluster state converges to Git instead of drifting from your last push.
Should I use one Argo CD Application or the app-of-apps pattern?
Start with one Application per service while you have few services. Graduate to app-of-apps (a root Application that manages child Applications) when onboarding a new service starts feeling like ceremony — it turns adding a service into adding one file in Git. See app-of-apps vs ApplicationSet for how that decision plays out at larger scale.
Official References
- Argo CD declarative setup — the Application and AppProject spec
- Argo CD sync options — prune, self-heal and sync-wave behaviour
Was this article helpful?
Be the first to rate this article
Related Topics
Found this useful? Share it.


