🎯 Problem Statement

Traditional deployment approaches often suffer from:

  • Manual deployments leading to human errors
  • Configuration drift between environments
  • Lack of audit trail for changes
  • Slow rollback processes during incidents
  • No single source of truth for cluster state

πŸ’‘ Solution Overview

I implemented a GitOps-based continuous deployment pipeline using ArgoCD that treats Git as the single source of truth for declarative infrastructure and application definitions.

πŸ—οΈ Architecture

β”Œβ”‚β””β”Œβ”‚β”‚β”‚β””β”Œβ”‚β”‚β”‚β”‚β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€G(---────ASR──iC────poe──tIBTP────pup──Hueu────lro──uPiss────ics──bilth───│▼─cei─││▼─pdβ”€β”Œβ”‚β”‚β”‚β”‚β”‚β””β”€β”€β”€at──AeI──────tCo──clm──────ior──tiaβ”€β”€β”Œβ”‚β”‚β””β”€β”€β”€β”€ody──ing───N─────ne──oee───a───────n)───m───────s───De──────────esβ”€β”€β”€β”€β”β”‚β”‚β”‚β”˜β”β”‚β”‚β”‚β”‚β”‚β”˜β”€β”€vp─────────a─────────c────────K─e────────uβ”β”‚β”‚β”˜β”€β”€β”€β–Ίβ–Ίβ”€β”€b──Dβ”€β”Œβ”‚β”‚β”‚β””β”Œβ”‚β”‚β”‚β”‚β”Όβ”‚β””β”€eβ”Œβ”‚β”‚β””β”€β”€e───────r─N───v───────n─Sa───e────(--─-──e─tm───l──C(──C───t─ae───o──oK──DSH─R──e─gs───p──n8──Aye─o──s─ip───e──fs──rPna─l───na───r──i──glcl─l──C─gc─────gY─││▼─oat─b─│▼─l─e───W──A──Cth─a──uβ”β”‚β”‚β”˜β”€β”€o──RM──Df─c──s──r──eL──oC─k──tβ”Œβ”‚β”‚β””β”€β”€k──p)──rh───e─N───f──o──me───r─a───l────)c────Pm───o────k────re───w────────osβ”€β”€β”€β”€β”β”‚β”‚β”‚β”˜β”β”‚β”‚β”‚β”‚β”Όβ”‚β”˜β”€β”€dp───────a───────c───────eβ”€β”€β”€β”€β”€β”€β”β”‚β”‚β”˜β”€β”€β”€β”€β”€β”€β”€β”€β”Œβ”‚β”‚β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€CR(───││││────oeAβ”€β”€β”β”‚β”˜β”€β”€β”€ngC─────tiR─────as/β”€β”‚β”‚β”‚β”‚β”‚β”˜β”€β”€β”€itG─▲││───nrC────eyR────r)β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”˜β”β”‚β”‚β”‚β”˜β”‚

πŸ› οΈ Technologies Used

CategoryTechnology
GitOps PlatformArgoCD 2.8+
CI PlatformGitHub Actions
Container RegistryAzure Container Registry
KubernetesAKS / GKE
Secrets ManagementSealed Secrets / External Secrets
NotificationsSlack, Microsoft Teams
MetricsPrometheus + ArgoCD Metrics

πŸ“ Repository Structure

#aβ”œβ”œβ”œβ”‚β”‚β””#gβ”œβ”‚β”‚β”‚β”‚β”‚β”‚β”‚β”‚β”‚β”œβ”‚β”‚β”‚β”‚β”‚β”‚β””p────i───Ap────Gt───p-ioprsD.β””Rtpaβ”œβ”‚β”‚β”‚β”‚β””aβ”œβ”‚β”‚β”‚β””iβ”œβ”œβ””lerog─EOsp──r──n───ipcci─Ap-p──g──f───coktDsrsoraehwβ””Me/bβ”œβ”œβ”œβ””β”œβ”œβ””caβ”œβ”œβ””pβ””acimtruo─ECpa────v───dp───r─senoifbr─.oos────e───/p───o─trgnoi/kmn/erljrtrinlfcdf/dsikldspiaaaemu-eteliieenuaetrcpppcycmsoRo.gprgsyvaoapppt-tasrewyulvrtsgdt---spun-ipsaroieoi/idsp/rranno/maycsmnoetroegggsltmesignvaoj/ei/iie..z/s.gderntonyyayi.c/xontaatanyt/r.mmimga.yRyllol.myeanylapm.amolymlsalimtlory

πŸ”„ GitOps Workflow

CI Pipeline (GitHub Actions)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
name: CI Pipeline

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

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      
      - name: Build and test
        run: |
          docker build -t app:${{ github.sha }} .
          docker run app:${{ github.sha }} npm test
      
      - name: Push to ACR
        uses: azure/docker-login@v1
        with:
          login-server: ${{ secrets.ACR_LOGIN_SERVER }}
          username: ${{ secrets.ACR_USERNAME }}
          password: ${{ secrets.ACR_PASSWORD }}
      
      - run: |
          docker tag app:${{ github.sha }} ${{ secrets.ACR_LOGIN_SERVER }}/app:${{ github.sha }}
          docker push ${{ secrets.ACR_LOGIN_SERVER }}/app:${{ github.sha }}

  update-manifests:
    needs: build-and-push
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          repository: org/gitops-repo
          token: ${{ secrets.GH_PAT }}
      
      - name: Update image tag
        run: |
          cd apps/overlays/dev
          kustomize edit set image app=${{ secrets.ACR_LOGIN_SERVER }}/app:${{ github.sha }}
      
      - name: Commit and push
        run: |
          git config user.name "github-actions"
          git config user.email "github-actions@github.com"
          git add .
          git commit -m "Update dev image to ${{ github.sha }}"
          git push

ArgoCD Application Definition

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-dev
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/org/gitops-repo.git
    targetRevision: HEAD
    path: apps/overlays/dev
  destination:
    server: https://kubernetes.default.svc
    namespace: dev
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        maxDuration: 3m0s
        factor: 2

πŸ” Security Implementation

  • RBAC - Role-based access control for ArgoCD users
  • SSO Integration - Azure AD / GitHub OAuth
  • Sealed Secrets - Encrypted secrets in Git
  • Network Policies - ArgoCD namespace isolation
  • Audit Logging - Complete audit trail of all changes

πŸ“Š Results & Metrics

MetricBeforeAfter
Deployment FrequencyWeeklyMultiple per day
Lead Time for Changes2-3 days< 1 hour
Mean Time to Recovery4 hours< 15 minutes
Change Failure Rate15%< 2%

πŸ”‘ Key Learnings

  1. Separation of Concerns - Keeping app code and configuration in separate repos provides clear boundaries
  2. Progressive Delivery - Promoting changes through environments (dev β†’ staging β†’ prod) catches issues early
  3. Self-Healing - ArgoCD’s self-heal feature ensures the cluster always matches the desired state
  4. Observability - ArgoCD’s built-in dashboard provides excellent visibility into deployment status

πŸ”— Resources


Interested in implementing GitOps? Let’s discuss!