From Jenkins to ArgoCD: Real Migration Lessons Nobody Writes About

💡 Introduction

When teams talk about migrating from Jenkins to ArgoCD, they often discuss the tools, not the transformation. You’ll find plenty of “how to install” guides — but almost no one writes about what really happens when you shift from pipelines to GitOps.

In this blog, I’ll share real migration lessons learned during a multi-cluster move from Jenkins-based CD pipelines to GitOps with ArgoCD — lessons that include YAML comparisons, mindset changes, and the unexpected issues that never make it to documentation.

Because the truth is simple:

GitOps isn’t about tools — it’s about a mindset shift from execution to declaration.


🧩 Why We Moved: From Imperative Pipelines to Declarative State

Our Jenkins setup worked — it built, tested, deployed. But at scale, we faced:

  • Environment drift — dev and prod rarely looked identical.
  • 🔍 Visibility gaps — Jenkins UI didn’t tell us what the cluster actually ran.
  • ⚠️ RBAC sprawl — pipelines had over-permissive service accounts.
  • 🌀 Manual gates — too many approvals delayed releases.

We needed a source of truth for deployments — something that could detect drift, self-heal, and show what was really running.

That’s where ArgoCD and GitOps entered the picture.


🗺️ Migration Roadmap

We didn’t just “switch tools.” We migrated mindsets.
Here’s the phased roadmap we used — practical and repeatable.

PhaseDescriptionKey Focus
Phase 0: AssessmentInventory all Jenkins jobs, environments, and dependencies.Identify what stays in CI vs moves to CD.
Phase 1: PilotSet up ArgoCD for a non-critical app. Keep Jenkins for builds.Validate GitOps flow.
Phase 2: ExpansionGradually migrate staging and prod apps. Add ApplicationSets.Multi-cluster, RBAC design.
Phase 3: GovernanceCreate ArgoCD Projects, enforce sync policies.Standardization, observability.
Phase 4: CultureTrain teams, measure drift, celebrate automation.Shift from “click deploy” → “merge manifest.”

📊 Featured Image:
Include the previously generated visual roadmap + YAML comparison as the header image.


⚙️ YAML Comparison: Jenkinsfile vs ArgoCD Application

The biggest mental shift?
You move from defining steps to defining state.

🧱 Jenkins Declarative Pipeline

pipeline {
  agent any
  environment {
    IMAGE = "myapp:${env.BUILD_NUMBER}"
    REGISTRY = "registry.mycorp.com/myapp"
  }
  stages {
    stage('Checkout') {
      steps {
        git url: 'https://git.mycorp.com/myapp.git', branch: 'main'
      }
    }
    stage('Build & Push') {
      steps {
        sh "docker build -t ${REGISTRY}:${BUILD_NUMBER} ."
        sh "docker push ${REGISTRY}:${BUILD_NUMBER}"
      }
    }
    stage('Deploy to Dev') {
      steps {
        sh "kubectl set image deployment/myapp myapp=${REGISTRY}:${BUILD_NUMBER} -n dev"
      }
    }
  }
}

🧭 ArgoCD Application YAML

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: myapp-project
  source:
    repoURL: 'https://git.mycorp.com/myapp.git'
    targetRevision: main
    path: deployments/overlays/dev
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: dev
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

🔍 Key Takeaways

JenkinsArgoCD
Defines how to build & deployDefines what to deploy
Uses shell commands (kubectl)Uses Git repo + reconciliation
Imperative flowDeclarative state
Manual approvalsGit-based promotions
CI + CD tightly coupledCI (build) and CD (deploy) separated

🧨 Common Issues (and How We Fixed Them)

1. Environment Drift

  • Issue: Teams still used kubectl patch manually.
  • Fix: Enabled selfHeal: true in ArgoCD, restricted direct cluster edits, enforced Git PRs for changes.

2. RBAC Mismatches

  • Issue: Jenkins service accounts had broad cluster access.
  • Fix: Created ArgoCD Projects with role-based sync and namespace boundaries.

3. Visibility Gaps

  • Issue: Teams couldn’t see full flow from build → deploy → cluster.
  • Fix: Built dashboards combining Jenkins (build), ArgoCD (sync), and Prometheus (health).

4. Legacy Logic

  • Issue: Complex Groovy scripts in Jenkins didn’t translate easily.
  • Fix: Extracted business logic into CI, converted deployment logic into Helm/Kustomize overlays.

5. Cultural Resistance

  • Issue: Developers were comfortable “clicking deploy.”
  • Fix: Held GitOps workshops. Showed how a merge auto-deploys. Metrics spoke louder than words.

🧠 Lessons Nobody Writes About

  1. Drift is cultural, not technical — unless you restrict manual edits, GitOps won’t save you.
  2. RBAC matters more than you think — ArgoCD will happily deploy everywhere if misconfigured.
  3. Visibility ≠ simplicity — You’ll need to stitch Jenkins, ArgoCD, and cluster metrics for a full picture.
  4. CI/CD separation is liberating — Jenkins focuses on building. ArgoCD focuses on syncing.
  5. GitOps is a mindset — It’s about declaring desired state, not scripting actions.

🧭 The Mindset Shift: From Execution → Declaration

Old World: “Run Jenkins job, deploy manually.”

New World: “Merge to main, ArgoCD syncs automatically.”

Once teams internalize this, magic happens:

  • Fewer production surprises
  • Transparent audit trails
  • Predictable, repeatable deployments

You stop chasing what happened and start trusting what’s declared.


🚀 Final Thoughts

Migrating from Jenkins to ArgoCD isn’t just a tool swap — it’s an organizational evolution.

Start small, migrate gradually, and make Git the single source of truth.
Let Jenkins handle what it’s best at — building and testing, while ArgoCD ensures your clusters reflect your code.

Once that shift clicks, you’ll realize why the best DevOps transformations aren’t about pipelines — they’re about people, processes, and declaration.

Leave a Comment