Cloud Architecture

GitOps with Argo CD: Managing Kubernetes Deployments

Master GitOps for Kubernetes with Argo CD. Learn to manage deployments, understand the pull-based model, use code examples, and best practices for robust CD.

Khader Vali September 19, 2026 14 min read

GitOps with Argo CD: Mastering Kubernetes Deployments

As a senior software engineer, I’ve navigated the ever-complex landscape of modern application deployment. Kubernetes, while incredibly powerful, introduces its own set of challenges, particularly when it comes to consistently deploying and managing applications across various environments. Manual deployments are error-prone, traditional CI/CD pipelines often struggle with drift, and maintaining a clear source of truth can become a nightmare. This is where GitOps, powered by tools like Argo CD, steps in as a game-changer.

In this comprehensive guide, we’ll dive deep into the world of GitOps, specifically focusing on how Argo CD enables a robust, auditable, and scalable continuous delivery workflow for your Kubernetes deployments. We’ll cover everything from the core principles of GitOps to practical setup, advanced configurations, and real-world scenarios. My goal is to equip you with the knowledge and examples needed to confidently implement GitOps in your own projects, bringing stability and efficiency to your Kubernetes operations.

The Challenge of Kubernetes Deployments and the Rise of GitOps

Kubernetes fundamentally changed how we deploy and manage applications. Its declarative nature, where you describe the desired state of your system using YAML manifests, is a massive leap forward. However, managing these manifests, ensuring consistency across environments (development, staging, production), handling rollbacks, and keeping track of who changed what and when, can quickly become overwhelming. Configuration drift – where the actual state of your cluster diverges from the intended state – is a common and insidious problem that can lead to unpredictable behavior and prolonged debugging sessions.

Traditional CI/CD pipelines often use a “push” model, where the CI system, after building artifacts, directly pushes changes to the Kubernetes cluster. While functional, this approach has drawbacks:

  • Security Concerns: The CI system needs direct access credentials to the Kubernetes API, widening the attack surface.
  • Lack of Auditability: It can be difficult to track changes and their origins if the CI system directly manipulates the cluster state without a clear, auditable source.
  • Configuration Drift: If manual changes are made to the cluster, the CI system might not be aware, leading to discrepancies.

Enter GitOps. Coined by Weaveworks, GitOps is an operational framework that takes DevOps best practices used for application code and applies them to infrastructure automation. At its core, GitOps means using Git as the single source of truth for your declarative infrastructure and applications. The entire state of your system, from application deployments to networking configurations and resource quotas, is described in Git. An automated agent then observes this Git repository and ensures that the live state of your cluster matches the desired state defined in Git.

Core Principles of GitOps

  1. Declarative Configuration: The entire system is described declaratively. Kubernetes’ own YAML manifests align perfectly with this.
  2. Git as the Single Source of Truth: All desired states of the system are stored in a Git repository. Any change to the system must originate from a Git commit.
  3. Automated Synchronization: An agent (like Argo CD) continuously observes the Git repository and the live state of the cluster, automatically applying changes to synchronize them.
  4. Pull Requests for Changes: All operational changes are made via Git pull requests, enabling version control, peer review, and audit trails.

GitOps with Argo CD: Managing Kubernetes Deployments
Generated Image

Benefits of Adopting GitOps

  • Increased Speed: Faster deployments and rollbacks as everything is automated and version-controlled.
  • Enhanced Reliability: The system is always reconciled to a known, desired state, reducing configuration drift and manual errors.
  • Improved Security: The “pull” model means the cluster agent pulls changes from Git, rather than an external system pushing them. This often reduces the need for external systems to have high-privilege access to the cluster.
  • Better Auditability and Compliance: Every change is a Git commit, providing a clear, immutable, and auditable history of all modifications. This is invaluable for compliance requirements.
  • Easier Rollbacks: Reverting to a previous stable state is as simple as reverting a Git commit.
  • Developer Experience: Developers can deploy applications using familiar Git workflows, reducing friction between development and operations teams.

Why GitOps is a Perfect Fit for Kubernetes

Kubernetes itself is a declarative system. You declare what you want (e.g., “I want 3 replicas of this Nginx image”), and Kubernetes’ control plane works to achieve and maintain that state. This inherent declarative nature makes Kubernetes an ideal candidate for GitOps. Instead of imperative scripts that tell Kubernetes *how* to do something, you simply define *what* the desired state is in Git.

Consider the typical challenges in a Kubernetes environment:

  • Managing Myriad YAML Files: A single application might require Deployment, Service, Ingress, ConfigMap, Secret, PersistentVolumeClaim, and more. Multiply that by several applications and environments, and you have a vast collection of YAML. GitOps centralizes this.
  • Ensuring Consistency: How do you guarantee that your staging environment exactly mirrors production’s configuration before a release? GitOps ensures that the Git repository is the single source of truth for both.
  • Disaster Recovery: If a cluster goes down, rebuilding it to a known state is straightforward when all configurations are in Git.
  • Collaboration: Team members can propose changes, review them, and approve them through standard Git pull request workflows, fostering collaboration and reducing errors.

GitOps streamlines these operations by treating your Kubernetes infrastructure and application configurations just like application code. This means applying all the mature development practices – version control, peer review, automated testing, and continuous integration – directly to your operational workflows.

Introducing Argo CD: The GitOps Continuous Delivery Tool

While GitOps is a methodology, you need tools to implement it. Among the leading choices, Argo CD stands out as a powerful, open-source, declarative GitOps continuous delivery tool for Kubernetes. Developed by Argoproj, Argo CD automates the deployment of applications to specified target environments. It continuously monitors your Git repositories for new commits and your Kubernetes clusters for configuration drift, ensuring that the live state always matches the desired state in Git.

Key Features of Argo CD

  • Automated Deployment and Synchronization: Automatically deploys applications and synchronizes their state with the Git repository.
  • Declarative Application Definition: Applications are defined declaratively as Kubernetes objects.
  • UI and CLI: Provides a rich web UI for real-time visibility into application health and sync status, as well as a powerful CLI for automation.
  • Multi-cluster and Multi-tenant Support: Manage applications across multiple Kubernetes clusters and environments.
  • Support for Configuration Management Tools: Natively integrates with Helm, Kustomize, Ksonnet, and plain YAML.
  • Health Checks: Built-in health checks for application resources.
  • Rollback and Rollforward: Easy rollbacks to any previous Git commit.
  • Access Control (RBAC): Granular role-based access control.
  • Webhooks: Integrates with Git providers (GitHub, GitLab, Bitbucket) for instant synchronization.

Architecture of Argo CD: A Pull-Based GitOps Model (Diagram in Words)

To truly understand how Argo CD works, let’s visualize its architecture and the flow of information. Imagine a central orchestrator, Argo CD, constantly observing two main entities:

  1. Your Git Repository: This is the “source of truth” – where all your Kubernetes desired state configurations (YAML files, Helm charts, Kustomize manifests) reside.
  2. Your Kubernetes Cluster(s): These are the target environments where your applications actually run.

Here’s the detailed flow:

  • The Git Repository (Source of Truth):

    • Developers commit changes (new features, bug fixes, configuration updates) to the Git repository, typically via Pull Requests which are reviewed and merged into a main branch (e.g., main or master).
    • This repository contains the *declarative desired state* of your applications and infrastructure.
  • Argo CD Components (running inside your Kubernetes cluster):

    • API Server:

      • Exposes the gRPC and REST APIs.
      • Provides the web UI and is used by the CLI.
      • Handles authentication and authorization.
    • Repo Server:

      • An internal service that maintains a local cache of Git repositories.
      • Responsible for fetching, caching, and processing Git repository files (e.g., rendering Helm charts, Kustomize manifests into plain Kubernetes YAML).
      • It acts as a secure bridge between the Application Controller and your Git provider, isolating Git access.
    • Application Controller:

      • This is the heart of Argo CD. It runs as a Kubernetes controller.
      • Continuously monitors the specified Git repositories (via the Repo Server) for changes.
      • It also continuously monitors the *actual live state* of the resources in your target Kubernetes cluster(s) by watching the Kubernetes API.
      • When a change is detected in Git, or on a defined sync interval, the Controller fetches the latest desired state from Git (rendered by the Repo Server).
      • It then compares this desired state from Git with the actual live state in the cluster.
      • If there’s a discrepancy (a “drift”), Argo CD marks the application as “OutOfSync”.
      • If auto-sync is enabled, or a manual sync is triggered, the Controller performs the necessary kubectl apply operations to reconcile the live state with the desired state.
    • UI (Web Interface):

      • Provides a visual representation of all deployed applications.
      • Shows the health status, sync status (Synced, OutOfSync, Progressing), and resource tree.
      • Allows users to manually synchronize applications, trigger rollbacks, view logs, and manage Argo CD configurations.
  • The Pull-Based Reconciliation Loop:

    1. Git Push: A developer merges changes to the main branch of the Git config repository.
    2. Argo CD Watches: The Application Controller, via the Repo Server, periodically polls the Git repository (or receives webhooks) for new commits.
    3. State Comparison: If new commits are found, the Controller compares the *desired state* (from Git, rendered by Repo Server) with the *live state* (observed in the Kubernetes cluster via its API).
    4. Drift Detection: If there’s a discrepancy (a “drift”), Argo CD marks the application as “OutOfSync”.
    5. Synchronization (Pull):
      • If auto-sync is enabled, Argo CD automatically kubectl applys the desired state from Git to the Kubernetes cluster, bringing the live state into alignment.
      • If manual sync is configured, an operator needs to trigger the sync via the UI or CLI.
    6. Status Reporting: Argo CD updates its UI and internal status, showing the application as “Synced” and healthy once the reconciliation is complete.

This pull-based model ensures that the Kubernetes cluster’s actual state is *always* reconciled with the declarative state defined in Git, without any external CI pipeline “pushing” changes directly. This forms a robust, auditable, and reliable continuous delivery pipeline.

Setting Up Argo CD: A Quick Start

Let’s get our hands dirty and set up Argo CD in a Kubernetes cluster. For this guide, I’ll assume you have a Kubernetes cluster (e.g., Minikube, kind, or a cloud provider’s managed Kubernetes) and kubectl configured.

1. Installation

Argo CD can be installed with a few kubectl apply commands. It creates its own namespace, argocd, and deploys all necessary components.

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

This command installs the core Argo CD components: API Server, Application Controller, Repo Server, and the UI. It might take a few moments for all pods to be ready.

kubectl get pods -n argocd

You should see pods like argocd-server, argocd-repo-server, argocd-application-controller, etc., running.

2. Accessing the Argo CD UI

The Argo CD API server is not exposed externally by default. The easiest way to access the UI locally is using kubectl port-forward:

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

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

3. Initial Login

The initial username is admin. The password is dynamically generated and stored in the argocd-initial-admin-secret Kubernetes secret. Retrieve it using:

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

Copy this password, log in to the UI, and then you can change the password via the UI or CLI if desired.

4. Installing the Argo CD CLI

The Argo CD CLI is a powerful tool for interacting with your Argo CD instance. Installation varies by OS:

macOS (Homebrew):

brew install argocd

Linux:

curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

Once installed, log in using the CLI:

argocd login localhost:8080 --username admin --password <your-initial-admin-password> --insecure --grpc-web

(--insecure and --grpc-web are needed if you are using port-forward without proper TLS setup).

The GitOps Workflow with Argo CD: Step-by-Step

Now that Argo CD is set up, let’s walk through a typical GitOps workflow, creating an application that Argo CD will manage.

1. Define Desired State in Git: Your Config Repository

The first step is to create a Git repository that will hold all your Kubernetes manifests. This is your “config repo.” For simplicity, let’s create a repository with a basic Nginx deployment and service.

Example repository structure:

my-k8s-apps/
├── dev/
│   └── my-app/
│       ├── deployment.yaml
│       └── service.yaml
└── prod/
    └── my-app/
        ├── deployment.yaml
        └── service.yaml

Let’s put our application manifests in my-k8s-apps/dev/my-app/:

my-k8s-apps/dev/my-app/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-app
  labels:
    app: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.6-alpine # Pinning to a specific version
        ports:
        - containerPort: 80

my-k8s-apps/dev/my-app/service.yaml:

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

Commit these files to a Git repository (e.g., on GitHub, GitLab, Bitbucket). Let’s assume the URL is https://github.com/your-org/my-k8s-apps.git and the branch is main.

2. Tell Argo CD About Your Application: The Application Resource

Argo CD manages applications using its own custom resource definition (CRD) called Application. This resource tells Argo CD where to find your manifests in Git and where to deploy them in Kubernetes.

You can create an Application via the UI, CLI, or by applying a YAML manifest to your Argo CD namespace.

Using the Argo CD CLI:

argocd app create my-nginx-dev \
  --repo https://github.com/your-org/my-k8s-apps.git \
  --path dev/my-app \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace default \
  --sync-policy automated --self-heal --prune

Let’s break down these arguments:

  • my-nginx-dev: The name of the Argo CD application.
  • --repo https://github.com/your-org/my-k8s-apps.git: The URL of your Git repository.
  • --path dev/my-app: The specific directory within the Git repository where the Kubernetes manifests are located.
  • --dest-server https://kubernetes.default.svc: The API server URL of the target Kubernetes cluster. https://kubernetes.default.svc refers to the cluster where Argo CD itself is running. For external clusters, you would first add them to Argo CD.
  • --dest-namespace default: The Kubernetes namespace where the application should be deployed.
  • --sync-policy automated: This is crucial for GitOps. It tells Argo CD to automatically synchronize the application if it detects a difference between Git and the live state.
  • --self-heal: If any resource managed by Argo CD is modified outside of Git (e.g., someone manually scales a deployment), Argo CD will automatically revert it to the desired state from Git.
  • --prune: Allows Argo CD to delete resources from the cluster that are no longer present in Git.

After running this command, navigate to the Argo CD UI. You should see my-nginx-dev application. Initially, it might be in an “OutOfSync” state and “Missing” (meaning the resources don’t exist in the cluster yet).

3. Argo CD Detects Differences and Synchronizes

Because we set --sync-policy automated, Argo CD will automatically detect that the desired state (in Git) does not match the live state (empty default namespace). It will then proceed to synchronize. You’ll see the application transition through “Progressing” to “Synced” and “Healthy” in the UI.

You can verify the deployment in your Kubernetes cluster:

kubectl get deploy,svc -n default

You should see my-nginx-app deployment with 2 replicas and my-nginx-service.

4. Making a Change and Observing Automatic Update

Now, let’s experience the power of GitOps. Imagine you need to scale your Nginx application to 3 replicas.

  1. Modify deployment.yaml in Git:

    Change the replicas count from 2 to 3 in my-k8s-apps/dev/my-app/deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-nginx-app
      labels:
        app: my-nginx
    spec:
      replicas: 3 # Changed from 2 to 3
      selector:
        matchLabels:
          app: my-nginx
      template:
        metadata:
          labels:
            app: my-nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.21.6-alpine
            ports:
            - containerPort: 80
            
  2. Commit and Push: Commit this change to your Git repository (e.g., git commit -m "Scale nginx to 3 replicas" && git push).
  3. Argo CD Reacts: Within a few seconds (or up to the sync interval, which is usually 3 minutes by default, but can be sped up with webhooks), Argo CD will detect the new commit.
  4. Synchronization:
    • The Argo CD UI will show the application as “OutOfSync”.
    • Since auto-sync is enabled, Argo CD will automatically apply the change to your Kubernetes cluster.
    • The application will go through “
Written by

Khader Vali

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

Share this article

Related Articles

Edge Computing Architecture Patterns & Use Cases Guide

Jun 16, 2026 · 17 min read

Building Scalable Data Pipelines with AWS Kinesis, Glue, and Redshift

Jul 03, 2026 · 16 min read

Cloud Cost Optimization: AWS vs Azure vs GCP Deep Dive

Aug 28, 2026 · 16 min read