Kubernetes Deployments with Argo CD and GitOps
Argo CD is an open-source, declarative Continuous Delivery (CD) tool built specifically for Kubernetes. It follows the GitOps methodology, using Git repositories as the single source of truth for application configurations and deployment definitions.
Rather than relying on external pipelines to continuously push changes into Kubernetes clusters, Argo CD operates from within the Kubernetes environment, monitors the desired application state stored in Git, and ensures that the actual cluster state remains aligned with it.
This approach makes application deployments more predictable, auditable, consistent, and easier to manage.
How Argo CD works
When an application is registered with Argo CD, we specify:
- The Git repository containing the Kubernetes configuration.
- The Git branch, tag, or commit to monitor.
- The directory containing the Kubernetes manifests.
- The destination Kubernetes cluster.
- The namespace where the application should be deployed.
- The synchronisation policy.
Argo CD continuously compares the desired state defined in Git with the actual state of the Kubernetes cluster. It identifies differences between the two states and reports whether the application is synchronised.

1. Install Argo CD
Argo CD runs inside the Kubernetes cluster and uses its own namespace to manage its components.
1
2
3
4
5
# create a namespace
kubectl create namespace argocd
# install argocd
kubectl apply -n argocd --server-side --force-conflicts -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
The installation creates several Kubernetes components, including:
- Argo CD API Server
- Application Controller
- Repository Server
- ApplicationSet Controller
- Redis
- Dex Server
- Notifications Controller
Check running Pods
Once the installation is complete, let’s verify whether all the Argo CD components are running.
1
2
3
4
5
6
7
8
9
10
11
# check running pods
kubectl get pods -n argocd -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
argocd-application-controller-0 1/1 Running 0 25h 10.244.2.5 minikube-m03 <none> <none>
argocd-applicationset-controller-86bcdc46cf-cbzcl 1/1 Running 0 25h 10.244.2.3 minikube-m03 <none> <none>
argocd-dex-server-7f65987db5-2tx5r 1/1 Running 2 (25h ago) 25h 10.244.1.5 minikube-m02 <none> <none>
argocd-notifications-controller-6885f68ddd-zlxv6 1/1 Running 0 25h 10.244.2.2 minikube-m03 <none> <none>
argocd-redis-7d5d5cb5b6-8b8qv 1/1 Running 0 25h 10.244.2.4 minikube-m03 <none> <none>
argocd-repo-server-7f4759f94-tr8vq 1/1 Running 0 25h 10.244.1.3 minikube-m02 <none> <none>
argocd-server-777cfb8fc4-rwwm2 1/1 Running 0 25h 10.244.1.4 minikube-m02 <none> <none>
Check running Services
The argocd-server service is particularly important because it exposes the Argo CD API Server.
By default, it is configured as a ClusterIP service, which means it is accessible from within the Kubernetes cluster.
1
2
3
4
5
6
7
8
9
10
11
12
# check running services
kubectl get service -n argocd -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
argocd-applicationset-controller ClusterIP 10.106.232.180 <none> 7000/TCP,8080/TCP 25h app.kubernetes.io/name=argocd-applicationset-controller
argocd-dex-server ClusterIP 10.96.235.26 <none> 5556/TCP,5557/TCP,5558/TCP 25h app.kubernetes.io/name=argocd-dex-server
argocd-metrics ClusterIP 10.100.49.150 <none> 8082/TCP 25h app.kubernetes.io/name=argocd-application-controller
argocd-notifications-controller-metrics ClusterIP 10.110.102.37 <none> 9001/TCP 25h app.kubernetes.io/name=argocd-notifications-controller
argocd-redis ClusterIP 10.98.220.159 <none> 6379/TCP 25h app.kubernetes.io/name=argocd-redis
argocd-repo-server ClusterIP 10.99.203.169 <none> 8081/TCP,8084/TCP 25h app.kubernetes.io/name=argocd-repo-server
argocd-server ClusterIP 10.105.146.106 <none> 80/TCP,443/TCP 25h app.kubernetes.io/name=argocd-server
argocd-server-metrics ClusterIP 10.108.157.188 <none> 8083/TCP 25h app.kubernetes.io/name=argocd-server
Accessing the Argo CD Dashboard
Since we are using Minikube, we can access the Argo CD dashboard using Kubernetes port forwarding.
1
2
3
4
5
# port forward command
kubectl port-forward -n argocd svc/argocd-server 8181:80
Forwarding from 127.0.0.1:8181 -> 8080
Forwarding from [::1]:8181 -> 8080
Access ArgoCD UI
1
https://localhost:8181/

Retrieving the Initial Admin Password
Argo CD creates an initial user admin and stores the password in a Kubernetes Secret named argocd-initial-admin-secret.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# extract the password and decode the base64 string.
kubectl -n argocd get secret argocd-initial-admin-secret -o json
{
"apiVersion": "v1",
"data": {
"password": "SHIzUDE3Tkd0Vy1sb0Z6ZA=="
},
"kind": "Secret",
"metadata": {
"creationTimestamp": "2026-10-31T07:48:01Z",
"name": "argocd-initial-admin-secret",
"namespace": "argocd",
"resourceVersion": "148687",
"uid": "ced77344-5754-40d4-a0bd-fb3831f4e597"
},
"type": "Opaque"
}
ArgoCD dashboard UI

2. Create an Argo CD Application (Argo CD Application Manifest).
Argo CD uses a Kubernetes Custom Resource Definition (CRD) called Application to define an application deployment. It’s a declarative resource that tells Argo CD where to retrieve Kubernetes manifests and where to deploy them.
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
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: python-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/pratyush1806/kubernetes-argocd.git
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: python-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Explaination
kind: Application: This identifies the resource as an Argo CD Application.project: default: Argo CD Projects provide logical grouping and access control for applications.source: This section tells Argo CD where to retrieve the Kubernetes deployment configuration. There are three important properties -repoURL: The Git repository containing the Kubernetes manifests.targetRevision: The Git branch, tag, or commit Argo CD should monitor. In this case, it is the main branch.path: The directory inside the repository containing the Kubernetes configuration files.
destination: This specifies where the application should be deployed.server: server property identifies the destination Kubernetes API Server.- The address
https://kubernetes.default.svcrefers to the Kubernetes API Server accessible from within the cluster. This is commonly used when Argo CD deploys applications to the same cluster where it is installed.
prune: Pruning ensures that resources removed from the Git repository are also removed from the Kubernetes cluster during synchronisation.selfHeal: Self-healing allows Argo CD to automatically correct configuration drift.CreateNamespace: This option tells Argo CD to create the destination namespace automatically if it does not already exist.
3. Deploying the Argo CD Application
1
2
3
kubectl apply -f argocd-app.yaml
application.argoproj.io/python-app created
At this point, Argo CD will start processing the Application resource.
It will:
- Connect to the configured Git repository.
- Retrieve the main branch.
- Locate the k8s directory.
- Read and generate the Kubernetes manifests.
- Compare the desired configuration with the cluster state.
- Create the necessary Kubernetes resources.
Since we enabled automated synchronisation, Argo CD will automatically apply the deployment configuration.
4. Verifying the Application Deployment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl get all -n python-app -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/python-app-77dcf86589-dczff 1/1 Running 0 15m 10.244.2.9 minikube-m03 <none> <none>
pod/python-app-77dcf86589-h9r2d 1/1 Running 0 15m 10.244.1.9 minikube-m02 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/python-app-service NodePort 10.105.1.195 <none> 8000:30675/TCP 31m app=python-app
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/python-app 2/2 2 2 31m python-app prat1980/python-app:v1 app=python-app
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/python-app-77dcf86589 2 2 2 15m python-app prat1980/python-app:v1 app=python-app,pod-template-hash=77dcf86589
The output indicates that:
- Two application Pods have been created.
- Both Pods are running.
- The Deployment has two desired replicas.
- Both replicas are available.
- A NodePort Service has been created to expose the application.
Verifying the Application in Argo CD
1
http://localhost:8181/applications

1
https://localhost:8181/applications/argocd/python-app

We are able to see:
- The Application resource.
- The Deployment.
- The ReplicaSet.
- The running Pods.
- The Service.
5. Accessing the Python Application
The application is exposed through a Kubernetes NodePort Service. We can access it locally using port forwarding.
1
2
3
4
kubectl port-forward svc/python-app-service 8000:8000 -n python-app
Forwarding from 127.0.0.1:8000 -> 8000
Forwarding from [::1]:8000 -> 8000
Accessing the Python Application through browser
1
http://localhost:8000

6. Understanding Automated Synchronisation Through GitOps
Te real value of GitOps becomes apparent when we start making changes to the application configuration.
Scenario 1: Updating the Application Configuration
We modify the Kubernetes Deployment manifest in the Git repository:
1
2
spec:
replicas: 3
After committing and pushing the changes, Argo CD detects the updated configuration. Since automated synchronisation is enabled, Argo CD applies the new configuration to the Kubernetes cluster. Kubernetes then creates the additional Pod.
Scenario 2: Manual Changes to Kubernetes Resources
Imagine someone manually scales the Deployment to five replicas:
1
2
3
kubectl scale deployment python-app \
--replicas=5 \
-n python-app
The live Kubernetes configuration now differs from the desired configuration in Git. Because selfHeal is enabled, Argo CD detects the drift and restores the replica count to the value defined in the Git repository.
Scenario 3: Removing Resources from Git
Suppose we delete a Kubernetes Service manifest from the Git repository. Because prune is enabled, Argo CD removes the corresponding Service from the Kubernetes cluster during synchronisation. This prevents obsolete resources from accumulating in the cluster.
Argo CD simplifies Kubernetes application delivery by introducing a declarative, GitOps-based deployment model.
Instead of relying on deployment pipelines to push configuration changes directly into Kubernetes, Argo CD continuously monitors Git repositories and reconciles the cluster with the desired application state.