GitOps Workflows with ArgoCD

Comprehensive guide for implementing GitOps workflows using ArgoCD

This guide covers implementing GitOps workflows using ArgoCD, including repository structure, CI/CD integration, and best practices.

Architecture Overview

GitOps Workflow with ArgoCD

The architecture diagram above shows:

  • Development: Backend (Python), Frontend (React), and Services (Spring Boot)
  • Version Control: Application and Configuration repositories in GitHub
  • Continuous Integration: Jenkins for building and testing applications
  • GitOps Engine: ArgoCD with its core components (Repo Server, App Controller, API Server, Dex SSO)
  • Kubernetes Production: Control plane, workloads (Deployments, StatefulSets, Pods), networking, and storage
  • Monitoring & Observability: Prometheus, Grafana, and CloudWatch integration

The workflow follows these steps:

  1. Developers commit code to the Application Repository
  2. Jenkins builds, tests, and creates container images
  3. Updated manifests are committed to the Config Repository
  4. ArgoCD detects changes and synchronizes the cluster state
  5. Applications are deployed to Kubernetes with proper networking and storage
  6. Monitoring tools collect metrics and logs for observability

Video Tutorial

Learn more about GitOps workflows with ArgoCD in this comprehensive video tutorial:

View Source Code

GitOps Repository Structure

1. Monorepo Structure

.
├── apps/
│   ├── app1/
│   │   ├── base/
│   │   │   ├── deployment.yaml
│   │   │   ├── service.yaml
│   │   │   └── kustomization.yaml
│   │   └── overlays/
│   │       ├── dev/
│   │       ├── staging/
│   │       └── prod/
│   └── app2/
│       ├── base/
│       └── overlays/
├── infrastructure/
│   ├── monitoring/
│   ├── logging/
│   └── security/
└── platform/
    ├── namespaces/
    ├── rbac/
    └── quotas/

2. Multi-repo Structure

app-repo/
├── src/
├── tests/
└── kubernetes/
    ├── base/
    └── overlays/

config-repo/
├── apps/
├── infrastructure/
└── platform/

CI/CD Integration

1. GitHub Actions Integration

name: CI
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Build and Test
      run: |
        make test
        make build
        
    - name: Update Kubernetes manifests
      run: |
        cd kubernetes/overlays/dev
        kustomize edit set image app=${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
        
    - name: Commit changes
      run: |
        git config --local user.email "action@github.com"
        git config --local user.name "GitHub Action"
        git commit -am "Update image tag to ${{ github.sha }}"
        git push

2. GitLab CI Integration

stages:
  - test
  - build
  - deploy

test:
  stage: test
  script:
    - make test

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

deploy:
  stage: deploy
  script:
    - cd kubernetes/overlays/dev
    - kustomize edit set image app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - git commit -am "Update image tag"
    - git push origin main

Environment Management

1. Application Sets

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: env-apps
spec:
  generators:
  - matrix:
      generators:
      - list:
          elements:
          - env: dev
          - env: staging
          - env: prod
      - git:
          repoURL: https://github.com/org/apps.git
          revision: HEAD
          directories:
          - path: apps/*
  template:
    metadata:
      name: '{{path.basename}}-{{env}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/org/apps.git
        targetRevision: HEAD
        path: '{{path}}/overlays/{{env}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}-{{env}}'

2. Environment-specific Configurations

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: dev-
namespace: dev
patchesStrategicMerge:
- deployment-patch.yaml
configMapGenerator:
- name: app-config
  files:
  - config.yaml

Promotion Workflows

1. Manual Promotion

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: promotion-app
spec:
  source:
    repoURL: https://github.com/org/app.git
    targetRevision: v1.0.0
    path: kubernetes/overlays/staging
  destination:
    server: https://kubernetes.default.svc
    namespace: staging
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

2. Automated Promotion

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: promotion-apps
spec:
  generators:
  - git:
      repoURL: https://github.com/org/app.git
      revision: HEAD
      directories:
      - path: releases/*
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      source:
        repoURL: https://github.com/org/app.git
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}'

Pull Request Workflows

1. Preview Environments

{{ }} templating only resolves inside an ApplicationSet’s template: block, not in a plain Application manifest - preview-per-PR environments need the pullRequest generator:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: pr-preview
  namespace: argocd
spec:
  generators:
  - pullRequest:
      github:
        owner: org
        repo: app
      requeueAfterSeconds: 60
  template:
    metadata:
      name: 'pr-{{number}}-preview'
      finalizers:
      - resources-finalizer.argocd.argoproj.io
    spec:
      project: default
      source:
        repoURL: https://github.com/org/app.git
        targetRevision: '{{head_sha}}'
        path: kubernetes/overlays/preview
      destination:
        server: https://kubernetes.default.svc
        namespace: 'pr-{{number}}'

2. Automated Testing

apiVersion: batch/v1
kind: Job
metadata:
  name: pr-test
  annotations:
    argocd.argoproj.io/hook: Sync
spec:
  template:
    spec:
      containers:
      - name: test
        image: test-runner:latest
        command: ["./run-tests.sh"]
      restartPolicy: Never

Drift Detection and Reconciliation

1. Drift Detection

resource.compareoptions only accepts a small set of global comparison flags (like ignoreAggregatedRoles) - per-resource ignoreDifferences rules are a separate argocd-cm key, resource.customizations.ignoreDifferences.<group>_<kind>:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.compareoptions: |
    ignoreAggregatedRoles: true
  resource.customizations.ignoreDifferences.apps_Deployment: |
    jsonPointers:
    - /spec/replicas

2. Auto-healing Configuration

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: self-healing-app
spec:
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

Version Control Strategies

1. Git Tags

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: versioned-app
spec:
  source:
    repoURL: https://github.com/org/app.git
    targetRevision: v1.0.0
    path: kubernetes

2. Release Branches

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: release-apps
spec:
  generators:
  - git:
      repoURL: https://github.com/org/app.git
      revision: HEAD
      branches:
      - release-*
  template:
    metadata:
      name: '{{branch}}-app'
    spec:
      source:
        repoURL: https://github.com/org/app.git
        targetRevision: '{{branch}}'
        path: kubernetes

Best Practices Checklist

  1. Use declarative configurations
  2. Implement environment parity
  3. Automate promotions
  4. Enable drift detection
  5. Configure auto-healing
  6. Implement PR workflows
  7. Version control strategy
  8. Security controls
  9. Monitoring
  10. Documentation

Security Considerations

1. Repository Security

apiVersion: v1
kind: Secret
metadata:
  name: repo-creds
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/org/app.git
  password: <token>
  username: git

2. RBAC Controls

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.csv: |
    p, role:developer, applications, sync, */*, allow
    p, role:developer, applications, get, */*, allow
    g, org:developers, role:developer

Conclusion

Implementing GitOps workflows with ArgoCD provides a robust and secure way to manage Kubernetes deployments. Regular reviews and updates of workflows ensure optimal operation.

Additional Resources