Comprehensive ArgoCD Setup Guide for Kubernetes

This comprehensive guide provides detailed, step-by-step instructions for deploying and configuring ArgoCD in your Kubernetes cluster. It covers installation, initial setup, and best practices, including declarative application definitions, enabling automated sync, configuring SSO, setting up RBAC, enabling monitoring, configuring notifications, performing regular backups, setting resource limits, ensuring high availability, and implementing security hardening to maintain a robust, scalable, and secure GitOps workflow.

ArgoCD Terraform Deployment

Prerequisites

  • Kubernetes cluster (v1.19+)
  • kubectl CLI tool installed
  • Helm (optional)
  • Access to a Git repository
  • Basic understanding of Kubernetes and GitOps

Step 1: Install ArgoCD

1.1 Create Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: argocd

1.2 Install ArgoCD Core Components

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

1.3 Verify Installation

kubectl get pods -n argocd

Expected output:

NAME                                  READY   STATUS    RESTARTS   AGE
argocd-application-controller-0       1/1     Running   0          2m
argocd-dex-server-5dd657bd9-xm6x4    1/1     Running   0          2m
argocd-redis-759b6bc7f4-r2qzb        1/1     Running   0          2m
argocd-repo-server-7c475dcc7-nf85p   1/1     Running   0          2m
argocd-server-544c4c6b5-p4h9r        1/1     Running   0          2m

Step 2: Access ArgoCD UI

2.1 Get Initial Admin Password

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

2.2 Access the UI

Option 1: Port Forwarding

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

Option 2: LoadBalancer Service

apiVersion: v1
kind: Service
metadata:
  name: argocd-server
  namespace: argocd
spec:
  type: LoadBalancer
  ports:
    - port: 443
      targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-server

Step 3: Configure SSO (Optional)

3.1 Setup Dex Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  url: https://argocd.example.com
  dex.config: |
    connectors:
      - type: github
        id: github
        name: GitHub
        config:
          clientID: your-client-id
          clientSecret: your-client-secret
          orgs:
          - name: your-github-org

3.2 Configure RBAC

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly
  policy.csv: |
    p, role:org-admin, applications, *, */*, allow
    p, role:org-admin, clusters, get, *, allow
    g, your-github-org:team-name, role:org-admin

Step 4: Setup Your First Application

4.1 Create Application Manifest

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: guestbook
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

4.2 Apply the Application

kubectl apply -f application.yaml

Step 5: Configure High Availability

5.1 HA Manifest

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: argocd-application-controller
  namespace: argocd # ✅ Added namespace
spec:
  serviceName: "argocd-application-controller" # ✅ Required field
  selector: # ✅ Required field
    matchLabels:
      app: argocd-application-controller
  replicas: 3
  template:
    metadata:
      labels:
        app: argocd-application-controller
    spec:
      containers:
        - name: argocd-application-controller
          args:
            - --status-processors=20
            - --operation-processors=10

If you can afford downtime or the StatefulSet doesn’t have critical persistent data:

kubectl delete sts argocd-application-controller -n argocd
kubectl apply -f application-controller.yaml
This option may result in data loss if the StatefulSet has critical persistent data.
Note: Deleting a StatefulSet does not delete associated PVCs unless explicitly specified.

If you want to delete the PVCs too:

kubectl delete pvc -l app=argocd-application-controller -n argocd
kubectl apply -f application-controller.yaml

5.2.2 Option 2: Modify Allowed Fields (No Downtime)

If you only need to change replicas, template, updateStrategy, or minReadySeconds, use kubectl patch instead of applying a new manifest.

kubectl patch statefulset argocd-application-controller -n argocd --type='strategic' -p '{"spec":{"replicas":5}}'

5.2 Resource Requirements

apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-server
spec:
  template:
    spec:
      containers:
        - name: argocd-server
          resources:
            requests:
              cpu: 500m
              memory: 512Mi
            limits:
              cpu: 1000m
              memory: 1024Mi

Step 6: Setup Monitoring

6.1 ServiceMonitor Configuration

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: argocd
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-server # ✅ Match this with the actual service labels
  namespaceSelector:
    matchNames:
      - argocd # ✅ Ensure Prometheus can scrape from this namespace
  endpoints:
    - port: metrics # ✅ Ensure the service has this port name
      interval: 30s # Optional: Set a scrape interval
      path: /metrics # Optional: Define the metrics path (default is usually `/metrics`)
Make sure to replace `argocd-server` with the actual name of the ArgoCD server service.
Check that the ArgoCD Service exposing metrics has the correct labels and port:

6.2 Grafana Dashboard

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-grafana-dashboard
  namespace: monitoring
data:
  argocd-dashboard.json: |
    {
      "title": "ArgoCD Dashboard",
      "panels": [
        {
          "title": "Sync Status",
          "type": "graph"
        },
        {
          "title": "Application Health",
          "type": "graph"
        }
      ]
    }

Step 7: Configure Notifications

7.1 Setup Notification Controller

apiVersion: v1
kind: Secret
metadata:
  name: argocd-notifications-secret
  namespace: argocd
stringData:
  slack-token: "xoxb-your-token"
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  trigger.on-sync-status-changed: |
    - when: app.status.sync.status == 'Synced'
      send: [app-sync-succeeded]
    - when: app.status.sync.status == 'OutOfSync'
      send: [app-out-of-sync]

Step 8: Backup Configuration

8.1 Backup CronJob

apiVersion: batch/v1
kind: CronJob
metadata:
  name: argocd-backup
  namespace: argocd
spec:
  schedule: "0 0 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: argocd-backup
              image: bitnami/kubectl
              command:
                - /bin/sh
                - -c
                - |
                  kubectl get applications.argoproj.io -n argocd -o yaml > /backup/applications.yaml
                  kubectl get appprojects.argoproj.io -n argocd -o yaml > /backup/projects.yaml

Best Practices Checklist

  1. ✅ Use declarative application definitions
  2. ✅ Enable automated sync
  3. ✅ Configure SSO
  4. ✅ Setup RBAC
  5. ✅ Enable monitoring
  6. ✅ Configure notifications
  7. ✅ Regular backups
  8. ✅ Resource limits
  9. ✅ High availability
  10. ✅ Security hardening

Security Considerations

1. TLS Configuration

apiVersion: v1
kind: Secret
metadata:
  name: argocd-secret
  namespace: argocd
type: Opaque
data:
  tls.crt: <base64-encoded-certificate>
  tls.key: <base64-encoded-key>

2. Network Policies

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: argocd-server-network-policy
  namespace: argocd
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: argocd-server
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - protocol: TCP
          port: 8080

Troubleshooting Guide

Common Issues and Solutions

  1. Application Not Syncing

    • Check application logs
    • Verify Git credentials
    • Check network connectivity
  2. UI Not Accessible

    • Verify service status
    • Check ingress configuration
    • Validate TLS certificates
  3. Authentication Issues

    • Verify SSO configuration
    • Check RBAC settings
    • Validate user permissions

Conclusion

Following this guide will help you set up a production-ready ArgoCD installation. Remember to regularly update ArgoCD and follow security best practices.

Additional Resources