Cloud Architecture

GitOps with ArgoCD: Managing Kubernetes Deployments

Master GitOps workflows for Kubernetes with ArgoCD. Learn its architecture, practical setup, and advanced strategies for declarative, automated deployments.

Khader Vali June 18, 2026 16 min read

GitOps with ArgoCD: Mastering Kubernetes Deployments

As a senior software engineer working with modern cloud-native architectures, you’re constantly seeking ways to streamline deployments, enhance reliability, and maintain a clear, auditable trail of changes. If you’re managing Kubernetes, you’ve likely grappled with the complexities of configuration drift, manual interventions, and the perennial “it worked on my machine” syndrome. Enter GitOps – a paradigm shift that brings the best practices of Git to infrastructure and application delivery, and ArgoCD – the leading tool that makes this vision a reality for Kubernetes.

In this comprehensive guide, we’ll dive deep into GitOps principles, explore how ArgoCD empowers a robust continuous delivery workflow for Kubernetes, and walk through practical examples to help you implement this powerful combination in your own projects. Whether you’re new to GitOps or looking to refine your existing strategies, you’ll find valuable insights here.

The Persistent Challenge of Kubernetes Deployments

Before we embrace the solution, let’s briefly acknowledge the pain points that GitOps and ArgoCD aim to resolve. Kubernetes, while incredibly powerful, introduces its own set of operational complexities:

  • Configuration Drift: Without a single source of truth, it’s easy for cluster configurations to diverge from their intended state. Manual changes, hotfixes, or ad-hoc adjustments can lead to inconsistencies across environments.
  • Lack of Visibility and Auditability: Pinpointing who changed what, when, and why, can be a nightmare in a highly dynamic Kubernetes environment. Traditional imperative scripts often lack this built-in history.
  • Manual Processes and Human Error: Relying on manual commands or complex scripts for deployments is slow, error-prone, and doesn’t scale.
  • Security Risks: Granting direct access to Kubernetes clusters for deployment purposes can increase the attack surface.
  • Slow Rollbacks: Reverting to a previous stable state can be a cumbersome process without proper version control and automation.

These challenges highlight the need for a more structured, automated, and auditable approach to managing Kubernetes resources. This is precisely where GitOps shines.

Understanding GitOps: The Single Source of Truth

At its core, GitOps is an operational framework that takes DevOps best practices used for application development and applies them to infrastructure automation. It’s about using Git as the single source of truth for your declarative infrastructure and applications.

The Four Pillars of GitOps

The GitOps model is built upon four fundamental principles:

  1. Declarative: All system configurations (infrastructure and applications) are described declaratively. This means you define the *desired state* of your system, rather than a sequence of commands to reach that state. Kubernetes’ YAML manifests are a perfect fit for this.
  2. Versioned and Immutable: The desired state is stored in Git, which provides version control, audit trails, and the ability to revert to any previous state. Every change is a commit, providing a complete history.
  3. Pulled Automatically: Instead of a traditional CI/CD pipeline *pushing* changes to the cluster, in GitOps, an automated agent within the cluster *pulls* changes from Git. This “pull request” model enhances security and stability.
  4. Continuously Reconciled: A software agent continuously observes the actual state of the system and compares it to the desired state defined in Git. If a divergence (drift) is detected, the agent automatically takes action to reconcile the actual state with the desired state.

Why Adopt GitOps? Benefits Galore!

Embracing GitOps offers a multitude of benefits that directly address the challenges mentioned earlier:

  • Enhanced Productivity: Automating deployments and rollbacks frees up engineering time, allowing teams to focus on feature development rather than operational overhead.
  • Faster Deployment and Recovery: Changes are applied automatically upon merging to the Git repository, and rollbacks are as simple as reverting a Git commit.
  • Increased Reliability and Stability: The continuous reconciliation process ensures your cluster always matches the desired state, minimizing configuration drift and unexpected behavior.
  • Improved Security: With a pull-based model, your CI system doesn’t need direct write access to your production clusters, reducing the blast radius of a compromised pipeline. All changes are reviewed through Git’s PR/MR process.
  • Clear Audit Trails: Every change to your infrastructure and applications is a Git commit, complete with author, timestamp, and commit message. This provides an unparalleled audit log.
  • Easier Compliance: The auditable history and declarative nature simplify demonstrating compliance requirements.
  • Consistency Across Environments: By applying the same GitOps principles and repositories across dev, staging, and production environments, you ensure consistency and reduce “works on my machine” issues.

GitOps vs. Traditional CI/CD: The Pull vs. Push Model

It’s important to understand how GitOps differs from a traditional CI/CD pipeline, particularly in its deployment phase:

  • Traditional CI/CD (Push Model):
    • The CI pipeline builds the application, runs tests.
    • The CD part of the pipeline then pushes the new image and possibly updates Kubernetes manifests directly to the cluster using tools like kubectl, Helm, or custom scripts.
    • Requires CI system to have elevated permissions to the target cluster.
    • State lives partly in the cluster, partly in CI logs, and partly in the CI pipeline definition.
  • GitOps (Pull Model):
    • The CI pipeline builds the application, runs tests, and then updates the desired state in a Git repository (e.g., changes an image tag in a Kubernetes manifest).
    • A GitOps operator (like ArgoCD) running *inside* the Kubernetes cluster continuously observes this Git repository.
    • When a change is detected, the operator pulls the new desired state from Git and applies it to the cluster.
    • The cluster’s actual state is continuously reconciled against the state in Git.
    • The source of truth is Git, not the cluster or the CI pipeline.

The pull model significantly improves security by limiting the necessary permissions of your CI system and centralizing control in Git.

<

GitOps with ArgoCD: Managing Kubernetes Deployments
Generated Image

>

Introducing ArgoCD: The GitOps Powerhouse for Kubernetes

Now that we have a solid understanding of GitOps, let’s turn our attention to ArgoCD. ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes. It automates the deployment of applications to specified Kubernetes clusters directly from Git repositories. Part of the broader Argo project, ArgoCD is purpose-built to implement the GitOps pull model efficiently and effectively.

Key Features of ArgoCD

ArgoCD comes packed with features that make it an ideal choice for GitOps:

  • Automated Synchronization: ArgoCD continuously monitors your Git repositories for changes to application manifests and automatically synchronizes them with your clusters.
  • Configuration Drift Detection: It constantly compares the live state of your applications in the cluster with the desired state in Git. If a difference is detected, it flags the application as “OutOfSync” and can be configured to automatically reconcile.
  • Rollback and Roll-forward: Because Git is the source of truth, rolling back to a previous stable version is as simple as reverting a Git commit and letting ArgoCD sync.
  • Web UI and CLI: ArgoCD provides a rich web UI for visualizing applications, their health, and deployment status, along with a powerful CLI for automation.
  • Support for Various Manifest Formats: It natively supports Kustomize, Helm charts, plain YAML, and any custom configuration management tools.
  • Multi-cluster and Multi-tenant Support: Manage applications across multiple Kubernetes clusters from a single ArgoCD instance.
  • PreSync, Sync, PostSync Hooks: Define actions to run before, during, or after a sync operation for complex deployment strategies (e.g., database migrations, smoke tests).
  • Application Health Monitoring: Monitors the health of deployed applications and shows their status in the UI.
  • RBAC (Role-Based Access Control): Granular control over who can access and manage applications within ArgoCD.
  • Notifications: Integrate with Slack, Email, and other communication channels for deployment events.

ArgoCD’s Core Components

ArgoCD consists of several components working in concert within your Kubernetes cluster:

  1. API Server: Exposes the gRPC and REST APIs, which are used by the web UI and CLI. It’s responsible for application management, authentication, and RBAC.
  2. Controller: The heart of ArgoCD. It continuously monitors running applications, compares the live state with the desired state in Git, and performs sync operations.
  3. Repo Server: An internal service that maintains a local cache of Git repositories and renders Kubernetes manifests (e.g., expands Helm charts, applies Kustomize overlays).
  4. ApplicationSet Controller (Optional but Recommended): Extends ArgoCD to manage applications across multiple clusters or to deploy many applications from a single template, using generators (Git, Cluster, List, etc.).
  5. Dex (Optional): An identity service that integrates with various identity providers (LDAP, SAML, OIDC, GitHub, etc.) for authentication.

Architecting a GitOps Workflow with ArgoCD

Let’s visualize a typical GitOps workflow leveraging ArgoCD. This architecture centers around two primary Git repositories, a common and recommended pattern known as the “Dual Repository Model.”

The Dual Repository Model (Recommended Architecture)

This model separates application source code from Kubernetes manifests, offering cleaner separation of concerns and improved security.

Repository 1: Application Source Code Repository (app-repo)

  • Contains the application’s source code (e.g., Python, Node.js, Java).
  • Includes the Dockerfile for building the application image.
  • Defines the CI pipeline (e.g., GitHub Actions, GitLab CI, Jenkinsfile) for building, testing, and pushing Docker images to a container registry.

Repository 2: GitOps Configuration Repository (gitops-repo)

  • This is your “source of truth” for Kubernetes deployments.
  • Contains all Kubernetes manifests (Deployment, Service, Ingress, ConfigMaps, Secrets, etc.) for your applications, potentially organized with Helm charts or Kustomize.
  • Also contains ArgoCD Application Custom Resource Definitions (CRDs) that tell ArgoCD where to find the application manifests within this repository and where to deploy them.

Workflow Diagram (in words):

Let’s trace the journey of a code change through this GitOps pipeline:

  1. Developer Commits Code: A developer makes a change to the application’s source code in app-repo (e.g., adds a new feature, fixes a bug). They commit and push this change to a feature branch.
  2. Pull Request & Code Review: The developer opens a pull request, which triggers automated tests (unit, integration). Code review ensures quality and adherence to standards.
  3. Merge to Main & CI Trigger: Once approved, the changes are merged into the main branch of app-repo. This merge triggers the CI pipeline.
  4. Build & Publish Image: The CI pipeline (e.g., GitHub Actions) builds a new Docker image from the updated source code, runs image-specific tests, and pushes the new image (with a unique tag, often derived from the Git commit SHA or a semantic version) to a container registry (e.g., Docker Hub, ECR, GCR).
  5. Update GitOps Repository: Crucially, the CI pipeline then updates the Kubernetes manifest in the gitops-repo. It typically modifies the image tag in the relevant Deployment YAML file to point to the newly built image. This change is committed and pushed to the main branch of gitops-repo. This step is often automated using tools like kustomize edit set image or Helm’s --set functionality if a Helm chart is used.
  6. ArgoCD Detects Change: ArgoCD, running inside your Kubernetes cluster, continuously polls the main branch of gitops-repo. It detects the new commit containing the updated image tag.
  7. ArgoCD Syncs: ArgoCD identifies that the desired state in Git (the new image tag) differs from the live state in the cluster. It then pulls the updated manifest from Git and applies it to the Kubernetes API server.
  8. Kubernetes Reconciles: Kubernetes, in turn, detects the change in the Deployment object (e.g., a new image tag) and initiates a rolling update to deploy new pods running the updated application version.
  9. ArgoCD Monitors & Reports: ArgoCD continuously monitors the health of the deployed application, showing its status and any discrepancies (OutOfSync, Degraded) in its UI.

This flow ensures that every change to your application and infrastructure goes through Git, is version-controlled, auditable, and automatically deployed by ArgoCD.

<

GitOps with ArgoCD: Managing Kubernetes Deployments
Generated Image

>

Setting Up ArgoCD: A Quick Start

Before we dive into a practical example, let’s cover the basic installation of ArgoCD. You’ll need a running Kubernetes cluster and kubectl configured to access it.

Installation

The simplest way to install ArgoCD is by applying its manifest:

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

This command installs all necessary ArgoCD components into the argocd namespace.

Accessing the ArgoCD UI

By default, the ArgoCD API server is not exposed externally. For initial access, you can use port-forwarding:

kubectl port-forward svc/argocd-server -n argocd 8080:443

Now, navigate to https://localhost:8080 in your browser. You’ll likely encounter a certificate warning, which you can safely bypass for local testing.

To get the initial admin password:

kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 -d

Use admin as the username and the retrieved password to log in.

Initial Configuration: Registering a Git Repository

Before ArgoCD can sync applications, it needs to know about your Git repository. You can add it via the UI or CLI. Let’s use the CLI for now:

argocd repo add https://github.com/your-org/your-gitops-repo.git --username YOUR_GIT_USERNAME --password YOUR_GIT_PAT

Replace your-org/your-gitops-repo.git with your actual GitOps repository URL and provide appropriate credentials (a Personal Access Token is recommended for security).

GitOps in Action: A Practical Walkthrough with ArgoCD

Let’s walk through deploying a simple Nginx application using GitOps with ArgoCD. We’ll simulate the dual repository model.

Step 1: The Application (Conceptual app-repo)

For this example, let’s imagine our app-repo has a Dockerfile that builds a simple Nginx image. Our CI pipeline would build this image and push it to a registry. For simplicity, we’ll just use a public Nginx image for now, but in a real scenario, your CI would update the image tag.

Step 2: The GitOps Configuration Repository (gitops-repo)

Create a new Git repository (e.g., my-nginx-gitops). Inside it, create a directory structure like this:

my-nginx-gitops/
├── apps/
│   └── nginx/
│       ├── kustomization.yaml
│       ├── deployment.yaml
│       └── service.yaml
└── argocd/
    └── nginx-app.yaml

apps/nginx/deployment.yaml

This defines our Nginx deployment. Notice the image tag, which our CI pipeline would update.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2 # Initial replicas
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.23.4 # This is the image tag our CI updates
        ports:
        - containerPort: 80

apps/nginx/service.yaml

A simple ClusterIP service to expose Nginx within the cluster.

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

apps/nginx/kustomization.yaml (Optional, but good practice for organization)

If you’re using Kustomize (highly recommended for managing variations), this file ties your manifests together.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

Step 3: ArgoCD Application Definition (argocd/nginx-app.yaml)

This YAML file defines an ArgoCD Application custom resource. This tells ArgoCD where to find the Kubernetes manifests in your GitOps repository and where to deploy them in your cluster.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-nginx-app
  namespace: argocd # ArgoCD applications usually live in the argocd namespace
spec:
  project: default # Use the default project
  source:
    repoURL: https://github.com/your-org/my-nginx-gitops.git # Replace with your repo URL
    targetRevision: HEAD # Track the latest commit on the main branch
    path: apps/nginx # Path to the Kubernetes manifests within the repo
  destination:
    server: https://kubernetes.default.svc # Deploy to the local cluster
    namespace: default # Target namespace for deployment
  syncPolicy:
    automated:
      prune: true # Delete resources that are no longer in Git
      selfHeal: true # Automatically sync if drift is detected
    syncOptions:
    - CreateNamespace=true # Create the target namespace if it doesn't exist

Commit and push all these files to your my-nginx-gitops repository.

Step 4: Deploying the ArgoCD Application

Now, apply the ArgoCD Application definition to your cluster. ArgoCD will pick it up.

kubectl apply -n argocd -f argocd/nginx-app.yaml

Once applied, log in to the ArgoCD UI (https://localhost:8080 via port-forward) or use the CLI:

argocd app list
argocd app get my-nginx-app
argocd app sync my-nginx-app

You should see my-nginx-app appear in the UI. Initially, it might be “OutOfSync” if you applied the application definition before ArgoCD detected the repo. Click “Sync” or wait for the automated sync. ArgoCD will then pull the manifests from your GitOps repo and deploy the Nginx deployment and service to your default namespace.

After a successful sync, the application status should be “Synced” and “Healthy”. You can then verify the deployment in your Kubernetes cluster:

kubectl get deploy -n default
kubectl get svc -n default

Step 5: Making a Change and Observing GitOps in Action

This is where the magic of GitOps becomes evident. Let’s scale our Nginx deployment.

  1. Edit deployment.yaml: In your my-nginx-gitops repository, open apps/nginx/deployment.yaml and change the replicas count from 2 to 4.
  2. ...
    spec:
      replicas: 4 # Changed from 2 to 4
      selector:
        matchLabels:
          app: nginx
    ...
    
  3. Commit and Push: Commit this change with a meaningful message (e.g., “Scale Nginx to 4 replicas”) and push it to your GitOps repository’s main branch.
  4. ArgoCD Auto-Sync: Within seconds (or based on your ArgoCD’s refresh interval), ArgoCD will detect this change in the Git repository. The my-nginx-app in the ArgoCD UI will briefly show “OutOfSync” and then transition back to “Synced” as ArgoCD automatically applies the updated deployment manifest to your cluster.
  5. Verify Scale: Check your Kubernetes cluster:
  6. kubectl get deploy nginx-deployment -n default
    # Output should show 4/4 replicas
    

You’ve just performed a GitOps-driven update! The entire process was driven by a Git commit, completely automated by ArgoCD, and left a clear audit trail in your Git history.

Step 6: Simulating a Rollback

What if the change caused an issue? Rolling back is equally simple:

  1. Revert the Git Commit: In your GitOps repository, revert the commit where you changed the replica count back to 2. Push this revert commit to main.
  2. ArgoCD Reconciles: ArgoCD will again detect the change in Git and automatically apply the older, stable state (replicas=2) to your cluster.
  3. Verify Rollback: Observe your deployment scaling down.

This demonstrates the power of Git as the single source of truth for reliable and fast rollbacks.

Advanced GitOps with ArgoCD

ArgoCD’s capabilities extend far beyond simple YAML deployments. Let’s explore some advanced features crucial for real-world scenarios.

Managing Configuration with Kustomize and Helm

Most complex applications require more than plain YAML. ArgoCD natively supports popular templating and packaging tools:

  • Kustomize: Ideal for managing variations of your Kubernetes manifests across different environments (e.g., dev, staging, prod) without modifying the original base files. ArgoCD understands kustomization.yaml files and applies the overlays.
  • Helm: A package manager for Kubernetes. Helm charts provide templating, dependency management, and release management. ArgoCD can deploy applications directly from Helm charts, either from a Git repository or a Helm chart repository. You specify chart name, version, and values.

Example: Using Helm in ArgoCD Application Definition

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-helm-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://charts.helm.sh/stable # Or your Git repo containing a Helm chart
    targetRevision: 1.2.3 # Chart version
    chart: nginx # Chart name
    helm:
      valueFiles:
      - values-prod.yaml # If in Git repo
      values: | # Or inline values
        replicaCount: 3
        service:
          type: LoadBalancer
  destination:
    server: https://kubernetes.default.svc
    namespace: my-helm-app-prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Automating Multi-Cluster Deployments with ApplicationSets

If you manage multiple Kubernetes clusters (e.g., separate clusters for dev, staging, prod, or regional clusters), manually creating ArgoCD Application resources for each cluster can be tedious. The ApplicationSet controller solves this.

An ApplicationSet resource can generate multiple ArgoCD Application resources automatically based on various “generators”:

  • Git Generator:
Written by

Khader Vali

Senior Software Engineer specializing in cloud architecture, real-time systems, and enterprise-scale applications.

Share this article

Related Articles

Building Centralized Component Libraries in Monorepos

Oct 18, 2024 · 2 min read

Kubernetes Production Patterns for Real-Time Applications

Sep 28, 2024 · 2 min read

Implementing LLM Integration Patterns in Production Systems

Sep 02, 2024 · 1 min read