Back to GitOps: ArgoCD, Flux
Q1Question 1 of 3

What GitOps is and why it is better than manual kubectl apply

Key Concepts
  • GitOps declares the desired state of infrastructure and applications in a Git repository that serves as the single source of truth.
  • An in-cluster operator (ArgoCD or Flux) continuously watches the repo and reconciles the live cluster to match the declared state.
  • Every change is a Git commit with an author, timestamp, and reviewed PR, giving a complete, tamper-evident audit trail essential for banking.
  • Self-healing means the operator detects manual drift on the cluster and automatically reverts it back to the Git-declared state.
  • Rollback is trivial and safe: revert the Git commit and the operator syncs the cluster to the previous good state.
  • Engineers change the system through Git, not direct cluster access, shrinking the blast radius and centralizing control.

Definition

GitOps makes Git the single source of truth and lets an in-cluster operator continuously sync the cluster to match it, giving auditable, repeatable, self-healing deployments that manual `kubectl apply` cannot.
  • GitOps model – The desired state of infrastructure and applications is declared in a Git repository as Kubernetes YAML, Helm charts, or Kustomize overlays.
  • GitOps operator – An in-cluster controller (ArgoCD or Flux) continuously watches the repo, compares declared state to live state, and reconciles any difference.
  • Auditable – Every change is a Git commit with an author, timestamp, message, and reviewed PR, giving a tamper-evident audit trail.
  • Repeatable – The same commit recreates the same environment, so disaster recovery is as simple as pointing the operator at the same repo.
  • Self-healing – The operator detects manual drift and reverts the cluster to the declared state automatically.
  • Safe rollback – Reverting a Git commit causes the operator to sync the cluster back to the previous good state.

Imagine the National Bank of India keeps one official, version-controlled rulebook describing exactly how every branch should be set up. Instead of a manager walking into each branch and changing things by hand (and nobody knowing who changed what), the bank employs a diligent inspector who constantly compares each branch to the official rulebook and quietly fixes anything that does not match. To change a branch, you edit the rulebook through a reviewed approval process, and the inspector rolls the change out everywhere. Every edit is signed and dated, so there is a perfect audit trail.

Understanding the Concepts

What is GitOps?

In GitOps, the desired state lives as declarative manifests in Git: Kubernetes YAML, Helm charts, or Kustomize overlays describing exactly what should run, how many replicas, which image tags, and which config. Nothing is changed by hand on the cluster. To deploy, you open a pull request that edits those files; after review and merge, a GitOps operator running inside the cluster detects the change and applies it.

YAML
# Git repository structure for National Bank of India
# gitops-repo/banking-api/
#   deployment.yaml
#   service.yaml
#   configmap.yaml
#   kustomization.yaml

# deployment.yaml (the source of truth)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: banking-api
  namespace: banking
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: banking-api
          image: registry.nationalbank.in/banking-api:v5.2
          ports:
            - containerPort: 8080

How does a GitOps operator work?

The operator (ArgoCD or Flux) runs inside the cluster. It periodically polls or receives a webhook from the Git repository, renders the manifests, and compares the rendered desired state to the live cluster state. This process is called reconciliation. When it detects a difference, it applies the manifests to bring the cluster into line.

BASH
# ArgoCD Application definition
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: banking-api
  namespace: argocd
spec:
  source:
    repoURL: https://git.nationalbank.in/gitops-repo.git
    path: banking-api
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: banking
  syncPolicy:
    automated:
      prune: true      # delete resources removed from Git
      selfHeal: true   # revert manual drift
TEXT
# ArgoCD status:
# Application: banking-api
# Sync Status: Synced
# Health: Healthy
# Last Sync: 2024-01-15 10:30 (commit abc1234)

Why is GitOps better than manual kubectl apply? (comparison table)

| Aspect | Manual kubectl apply | GitOps (ArgoCD/Flux) |
|---|---|---|
| Audit trail | No durable record of who applied what | Every change is a Git commit with author and PR |
| Repeatability | Depends on what commands someone ran | Same commit recreates the same environment |
| Drift detection | None: cluster silently diverges | Operator continuously detects and reverts drift |
| Rollback | Remember and re-apply old manifests by hand | Revert the Git commit; operator syncs automatically |
| Access control | Engineers need broad cluster credentials | Engineers change Git; operator holds cluster access |
| Consistency | Each person may apply different versions | Single source of truth for all environments |

BASH
# Manual kubectl apply (no audit, no drift detection)
kubectl apply -f deployment.yaml
# Who ran this? When? From which version? No record.
# If someone edits the deployment manually later, nobody notices.

# GitOps: change via Git PR
git checkout -b update-banking-api
# Edit deployment.yaml: change image tag to v5.3
git commit -m "Bump banking-api to v5.3 for fee-fix"
git push origin update-banking-api
# Create PR -> review -> merge
# ArgoCD detects the commit and syncs the cluster automatically.
# Full audit trail: who, when, what, why (PR description).

How does self-healing work?

With selfHeal: true, the operator continuously compares live state to Git. If someone manually edits a resource (for example, scaling down a Deployment), the operator detects the drift and reverts the cluster back to the declared state.

BASH
# Someone manually scales down the banking-api
kubectl scale deployment banking-api --replicas=1 -n banking
# The cluster now has 1 replica, but Git says 3.

# Within seconds, ArgoCD detects the drift:
# "banking-api is OutOfSync: replicas changed from 3 to 1"
# With selfHeal enabled, it automatically applies the Git state:
# replicas restored to 3.

# Without GitOps, the scale-down stays, nobody notices,
# and the service runs at reduced capacity until a customer complains.

How does rollback work in GitOps?

Rolling back is just reverting the Git commit. The operator sees the repo change and syncs the cluster to the previous good state.

BASH
# Rollback: revert the last commit in Git
git revert HEAD
git push origin main
# ArgoCD detects the revert, syncs the cluster back to v5.2
# The banking-api is back to the previous image tag.
# No manual kubectl commands needed.

What is the pull-based model vs push-based?

GitOps is pull-based: the in-cluster operator reaches outward to read Git. Traditional CI/CD is push-based: an external CI server (Jenkins) pushes changes into the cluster with credentials. Pull-based is more secure because deploy credentials stay inside the cluster and the cluster API is not exposed to external systems.

TEXT
# Push-based (traditional):
# Jenkins (outside) --[kubeconfig]--> Cluster
# Credentials live outside the cluster. Risky.

# Pull-based (GitOps):
# Cluster (ArgoCD inside) --[read]--> Git repo
# Credentials stay inside the cluster. Secure.
BASH
# CI still builds and tests (push to registry + update Git)
# Jenkins/GitHub Actions:
# 1. Build image: docker build -t banking-api:v5.3 .
# 2. Push to registry: docker push registry.nationalbank.in/banking-api:v5.3
# 3. Update Git: sed -i 's/v5.2/v5.3/' deployment.yaml && git commit && git push
# ArgoCD handles the actual deployment by pulling from Git.

What are common mistakes with GitOps?

BASH
# WRONG: Making manual changes directly on the cluster
kubectl edit deployment banking-api -n banking
# This creates drift that the operator will revert (with selfHeal)
# or that goes unnoticed (without selfHeal).

# CORRECT: All changes go through Git
# Edit the YAML in the repo, create a PR, merge after review.
# The operator applies the change. No manual kubectl edits.
BASH
# WRONG: Storing secrets in plaintext in the Git repo
# database-password: mySecretPassword123
# Anyone with repo access can read the secret.

# CORRECT: Use sealed secrets, SOPS, or external secrets
# Encrypt secrets before committing to Git.
# ArgoCD decrypts them at sync time using a cluster-side key.

What should a senior engineer know?

GitOps separates CI from CD: CI builds, tests, and updates the image tag in Git; the GitOps operator handles deployment. This does not eliminate Jenkins but repositions it to build and test. ArgoCD supports app-of-apps patterns for managing many applications declaratively, sync waves and hooks for ordering, and progressive delivery through Argo Rollouts for canary and blue-green strategies.

Visual Overview

DIAGRAM
GitOps Flow
============

  Developer (Rajesh)
       │
       ▼
  ┌──────────────┐    PR + Review    ┌──────────────┐
  │  Edit YAML   │ ─────────────────> │  Git Repo    │
  │  in branch   │                    │  (source of  │
  └──────────────┘                    │   truth)     │
                                      └──────┬───────┘
                                             │ webhook / poll
                                             ▼
                                      ┌──────────────┐
                                      │  ArgoCD      │
                                      │  (in-cluster │
                                      │   operator)  │
                                      └──────┬───────┘
                                             │ compare & sync
                                             ▼
                                      ┌──────────────┐
                                      │  Kubernetes  │
                                      │  Cluster     │
                                      │  (live state │
                                      │   matches    │
                                      │   Git)       │
                                      └──────────────┘

  Drift detected? ──> selfHeal reverts to Git state
  Rollback needed? ──> git revert + operator syncs

Key Takeaway

GitOps is an operational model where the desired state of infrastructure and applications is declared in a Git repository as the single source of truth, and an in-cluster operator like ArgoCD or Flux continuously watches that repository and reconciles the live cluster to match it. Nothing is changed on the cluster by hand; to deploy, you open a pull request, and after review and merge the operator detects the change and applies it. Because every change is a Git commit, the whole system becomes auditable, repeatable, and self-healing.

It is better than manual kubectl apply on every axis that matters in banking. On auditability, every change has an author, timestamp, and reviewed PR. On repeatability, the same commit recreates the same environment for disaster recovery. On self-healing, the operator detects manual drift and reverts it automatically, so the cluster never silently diverges. On rollback, reverting a Git commit causes the operator to sync the cluster back to the previous good state, which is far safer than remembering and re-applying old manifests by hand. At the National Bank of India, moving the transfer service to GitOps with ArgoCD meant that when someone scaled the service down by hand, the operator restored the declared replica count on its own.

Remember one sentence: GitOps turns deployment from a series of imperative, unlogged commands into a reviewed, reproducible, continuously-enforced declaration where Git is the single source of truth.

---

Share
Use ← → arrow keys to navigate