Skip to main content

Command Palette

Search for a command to run...

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

Published
โ€ข8 min read
ArgoCD: A DevOps Engineer's Best Friend - Real-World Guide
V

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:

  1. Figure out what changed

  2. Update the Jenkins pipeline

  3. Run the pipeline

  4. 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:

FeatureArgoCDTraditional CI/CD (like Jenkins)
Kubernetes-nativeBuilt for K8s - it just "gets it"Like using a sledgehammer to hang a picture
ConfigurationGit is the single source of truth"Where's the latest config?" - every team ever
State ManagementAutomatically fixes drift"Hope no one changed anything in the cluster!"
SecuritySmaller attack surfaceAnother set of credentials to manage
Learning CurveSteep if you're new to K8sSteep... 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:

  1. Create a Home for ArgoCD

     kubectl create namespace argocd
    

    Pro tip: Namespaces are like apartments in a building. Keep things organized!

  2. Install the Core Stuff

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

    This 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)

  3. Check if Everything's Running

     kubectl get pods -n argocd
    

    You 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          2m
    

    If something's not 1/1, grab that coffee - you might need it for troubleshooting.

  4. 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"}}'
  1. 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: 80
    

    Apply it:

     kubectl apply -f argocd-ingress.yaml
    
  2. Get the Secret Password

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

    Write 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)

  1. Error Handling: The set -e at the top? That's like having a safety net. If anything fails, the script stops. No silent failures!

  2. Prerequisite Check: Ever had a colleague run a script without having the right tools? This prevents that headache.

  3. 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

  1. Start Small: Don't try to move everything to ArgoCD at once. We started with one non-critical service. It helped us learn.

  2. 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: argocd
    

    This manages all our other apps. It's like Inception, but for Kubernetes!

  3. 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!


More from this blog

Devops

48 posts