ArgoCD: A DevOps Engineer's Best Friend - Real-World Guide

Hey folks! ๐ I'm Vikash Kumar, a seasoned DevOps Engineer navigating the thrilling landscapes of DevOps and Cloud โ๏ธ. My passion? Simplifying and automating processes to enhance our tech experiences. By day, I'm a Terraform wizard; by night, a Kubernetes aficionado crafting ingenious solutions with the latest DevOps methodologies ๐. From troubleshooting deployment snags to orchestrating seamless CI/CD pipelines, I've got your back. Fluent in scripts and infrastructure as code. With AWS โ๏ธ expertise, I'm your go-to guide in the cloud. And when it comes to monitoring and observability ๐, Prometheus and Grafana are my trusty allies. In the realm of source code management, I'm at ease with GitLab, Bitbucket, and Git. Eager to stay ahead of the curve ๐, I'm committed to exploring the ever-evolving domains of DevOps and Cloud. Let's connect and embark on this journey together! Drop me a line at thenameisvikash@gmail.com.
Hello, fellow Kubernetes enthusiasts! ๐
Let me tell you a story. A few months ago, our team was drowning in Kubernetes deployment headaches. Late nights, weekend emergencies, and the classic "but it worked in staging!" issues. Sound familiar? That's when we discovered ArgoCD, and honestly, it's been a game-changer for us.
Why We Fell in Love with ArgoCD
Before I walk you through the setup, let me share why we switched from our trusty (but showing its age) Jenkins setup to ArgoCD.
Picture this: It's 3 AM, and you get a call because someone manually updated a deployment in production (we've all been there, right?). With our old setup, we'd have to:
Figure out what changed
Update the Jenkins pipeline
Run the pipeline
Cross our fingers
Now with ArgoCD? It spots the difference automatically and brings the cluster back to the desired state. Sweet dreams! ๐ด
Real Talk: ArgoCD vs Traditional CI/CD
Let me break it down based on our experience:
| Feature | ArgoCD | Traditional CI/CD (like Jenkins) |
| Kubernetes-native | Built for K8s - it just "gets it" | Like using a sledgehammer to hang a picture |
| Configuration | Git is the single source of truth | "Where's the latest config?" - every team ever |
| State Management | Automatically fixes drift | "Hope no one changed anything in the cluster!" |
| Security | Smaller attack surface | Another set of credentials to manage |
| Learning Curve | Steep if you're new to K8s | Steep... period. |
Before You Start
Look, I'll be straight with you. You'll need:
A Kubernetes cluster (v1.22+) - I use minikube for testing, but any cluster works
kubectl configured - you know the drill
A load balancer - we use AWS ELB, but GCP or others work too
Nginx ingress controller - trust me, makes life easier
Coffee โ (optional but recommended)
The Manual Way (AKA "Understanding What the Script Does")
I always say, automate everything, but understand what you're automating. So let's do it manually first:
Create a Home for ArgoCD
kubectl create namespace argocdPro tip: Namespaces are like apartments in a building. Keep things organized!
Install the Core Stuff
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yamlThis is where the magic happens. It installs:
API Server (the brains)
Repository Server (the bookworm that reads your Git repos)
Application Controller (the worker bee)
Redis (the memory bank)
Check if Everything's Running
kubectl get pods -n argocdYou should see something like this:
NAME READY STATUS RESTARTS AGE argocd-application-controller-0 1/1 Running 0 2m argocd-dex-server-5859d9f46c-8lmww 1/1 Running 0 2m argocd-redis-5b6967fdfd-hr6qx 1/1 Running 0 2m argocd-repo-server-7c6cbc4648-jd2br 1/1 Running 0 2m argocd-server-544c4674b9-9nd6z 1/1 Running 0 2mIf something's not 1/1, grab that coffee - you might need it for troubleshooting.
Make It Accessible Now for the tricky part. We need to:
Make it work over HTTP (yes, we'll talk about HTTPS later)
Set up the path as /argo (trust me, helps with reverse proxies)
# First, let's make it okay with HTTP
kubectl patch deployment argocd-server \
-n argocd \
--type='json' \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--insecure"}]'
# Now, set up the root path
kubectl patch configmap argocd-cmd-params-cm \
-n argocd \
--type merge \
-p '{"data":{"server.rootpath":"/argo","server.insecure":"true"}}'
Set Up Ingress Create
argocd-ingress.yaml:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: argocd-ingress namespace: argocd annotations: nginx.ingress.kubernetes.io/backend-protocol: "HTTP" nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: ingressClassName: nginx rules: - http: paths: - path: /argo pathType: Prefix backend: service: name: argocd-server port: number: 80Apply it:
kubectl apply -f argocd-ingress.yamlGet the Secret Password
kubectl -n argocd get secret argocd-initial-admin-secret \ -o jsonpath="{.data.password}" | base64 -dWrite this down somewhere safe!
The "I Don't Have Time for Manual Steps" Way
Look, we're DevOps engineers. We automate. Here's a script that does all the above:
#!/bin/bash
# Set error handling
set -e
echo "๐ Starting ArgoCD deployment automation..."
# Function to check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Check prerequisites
if ! command_exists kubectl; then
echo "โ kubectl is not installed. Please install kubectl first."
exit 1
fi
# Check if namespace exists
if kubectl get namespace argocd >/dev/null 2>&1; then
echo "โ
ArgoCD namespace already exists"
else
echo "๐ Creating ArgoCD namespace..."
kubectl create namespace argocd
fi
echo "๐ฆ Installing ArgoCD..."
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
echo "โณ Waiting for ArgoCD pods to be ready..."
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s
echo "๐ง Patching ArgoCD server deployment to add '--insecure' flag..."
kubectl patch deployment argocd-server -n argocd --type='json' \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--insecure"}]'
echo "๐ Updating ArgoCD ConfigMap..."
kubectl patch configmap argocd-cmd-params-cm -n argocd --type merge \
-p '{"data":{"server.rootpath":"/argo","server.insecure":"true"}}'
echo "๐ Creating Ingress resource..."
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /argo
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80
EOF
echo "๐ Restarting ArgoCD server deployment..."
kubectl rollout restart deployment argocd-server -n argocd
echo "โณ Waiting for ArgoCD server to be ready (this may take a few minutes)..."
if kubectl rollout status deployment argocd-server -n argocd --timeout=300s; then
echo "โ
ArgoCD server deployment successfully restarted"
else
echo "โ ArgoCD server deployment failed to restart within the timeout period"
exit 1
fi
# Get initial admin password
echo "๐ Retrieving initial admin password..."
ARGO_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)
echo "โ
ArgoCD deployment completed!"
echo "๐ Installation Summary:"
echo "------------------------"
echo "Username: admin"
echo "Password: $ARGO_PASSWORD"
echo "URL: http://<your-ingress-ip>/argo"
echo "------------------------"
# Verify deployment
echo "๐ Deployment Status:"
echo "ArgoCD Pods:"
kubectl get pods -n argocd
echo "ArgoCD Service:"
kubectl get svc argocd-server -n argocd
echo "ArgoCD Ingress:"
kubectl get ingress argocd-ingress -n argocd
What the Script Does (The Cool Parts)
Error Handling: The
set -eat the top? That's like having a safety net. If anything fails, the script stops. No silent failures!Prerequisite Check: Ever had a colleague run a script without having the right tools? This prevents that headache.
Idempotency: You can run this script multiple times without breaking things. Trust me, this saves lives.

When Things Go Wrong (Because They Will)
1. The "My Pods Are Not Starting" Problem
If your pods are stuck in Pending:
kubectl get pods -n argocd
Usually, it's one of two things:
Not enough resources (we've all tried to run too much on minikube)
Node issues
Quick fixes:
# Check node resources
kubectl describe nodes | grep -A 5 "Allocated resources"
# Look for events
kubectl get events -n argocd --sort-by='.metadata.creationTimestamp'
2. The "I Can't Access the UI" Problem
First, check your ingress:
kubectl get ingress -n argocd
If that looks good, verify the service:
kubectl get svc -n argocd argocd-server
Still no luck? Check if the pods are actually receiving traffic:
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-server
3. The "Help, I Forgot My Password!" Problem
No worries, we've all been there:
kubectl -n argocd patch secret argocd-secret \
-p '{"data": {"admin.password": null, "admin.passwordMtime": null}}'
kubectl -n argocd rollout restart deploy argocd-server
This resets the password to the original one (which you can get from the initial secret).
Making It Production-Ready
Okay, now that it's working, let's make it bulletproof.
1. HTTPS (Because Security Matters)
# First, create a TLS secret
kubectl create secret tls argocd-tls \
--cert=/path/to/cert.crt \
--key=/path/to/key.key \
-n argocd
# Update the ingress
kubectl patch ingress argocd-ingress \
-n argocd \
--type='json' \
-p='[{"op": "add", "path": "/spec/tls", "value": [{"secretName": "argocd-tls"}]}]'
2. SSO (Because No One Likes Managing Multiple Logins)
Here's a GitHub example (we use this in our setup):
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
url: https://your-argocd-url
dex.config: |
connectors:
- type: github
id: github
name: GitHub
config:
clientID: your-client-id
clientSecret: your-client-secret
orgs:
- name: your-org-name
Real-World Tips from the Trenches
Start Small: Don't try to move everything to ArgoCD at once. We started with one non-critical service. It helped us learn.
Use the App of Apps Pattern: As you grow, managing multiple applications becomes challenging. Here's what we do:
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: root-app namespace: argocd spec: project: default source: repoURL: https://github.com/your-org/argocd-apps.git path: apps targetRevision: HEAD destination: server: https://kubernetes.default.svc namespace: argocdThis manages all our other apps. It's like Inception, but for Kubernetes!
Monitoring: Set up alerts for sync failures. Trust me, you want to know when ArgoCD can't reconcile state.
Wrapping Up
Look, moving to GitOps with ArgoCD isn't just about following steps in a guide. It's about changing how you think about deployments. It might feel weird at first - not directly applying changes to your cluster. But give it time. Start small, experiment, break things (in dev!), and gradually expand.
Remember, we're all on this journey together. If you hit any roadblocks, the ArgoCD community is incredibly helpful. And hey, feel free to reach out if you need help!
Now, go forth and GitOps! ๐
P.S. Keep an eye out for my next article on advanced ArgoCD patterns. We'll dive into some really cool stuff!



