ArgoCD Setup Guide for Microsoft Azure

Complete guide for setting up ArgoCD on Azure Kubernetes Service (AKS)

This guide provides detailed instructions for setting up ArgoCD on Azure Kubernetes Service (AKS), including Azure-specific configurations and integrations.

Video Tutorial

Learn more about setting up ArgoCD on Azure in this comprehensive video tutorial:

View Source Code

Prerequisites

  • Azure CLI installed and configured
  • kubectl configured for AKS
  • Azure subscription with required permissions
  • Helm (optional)

AKS Cluster Setup

1. Create AKS Cluster

az group create --name argocd-rg --location eastus

az aks create \
  --resource-group argocd-rg \
  --name argocd-cluster \
  --node-count 3 \
  --enable-managed-identity \
  --enable-addons monitoring \
  --enable-msi-auth-for-monitoring \
  --generate-ssh-keys \
  --node-vm-size Standard_DS3_v2 \
  --network-plugin azure \
  --network-policy azure

2. Configure Azure CNI

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

ArgoCD Installation

1. Install ArgoCD

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

2. Configure Application Gateway

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/ssl-redirect: "true"
    appgw.ingress.kubernetes.io/backend-protocol: "https"
    appgw.ingress.kubernetes.io/backend-hostname: "argocd.example.com"
spec:
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              number: 443
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-secret-tls

Azure AD Integration

1. Azure AD Application Registration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  url: https://argocd.example.com
  dex.config: |
    connectors:
      - type: microsoft
        id: azure-ad
        name: Azure AD
        config:
          clientID: $AZURE_AD_CLIENT_ID
          clientSecret: $AZURE_AD_CLIENT_SECRET
          tenant: $AZURE_AD_TENANT_ID
          redirectURI: https://argocd.example.com/api/dex/callback

2. RBAC Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.csv: |
    p, role:org-admin, applications, *, */*, allow
    p, role:org-admin, clusters, get, *, allow
    g, "azure-ad:ArgoCD Admins", role:org-admin

Azure Key Vault Integration

1. Key Vault Setup

aad-pod-identity (the aadpodidentity.k8s.io CRDs used below) was deprecated by Microsoft and archived in September 2023. The supported replacement is Azure AD Workload Identity, which uses OIDC federation instead of a pod-identity webhook - no usePodIdentity parameter or AzureIdentity/AzureIdentityBinding CRDs required:

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: azure-kvname
  namespace: argocd
spec:
  provider: azure
  parameters:
    clientID: CLIENT_ID
    keyvaultName: argocd-keyvault
    objects: |
      array:
        - |
          objectName: argocd-admin-password
          objectType: secret
        - |
          objectName: argocd-server-secret
          objectType: secret
    tenantId: TENANT_ID

2. Workload Identity Configuration

apiVersion: v1
kind: ServiceAccount
metadata:
  name: argocd-workload-identity
  namespace: argocd
  annotations:
    azure.workload.identity/client-id: CLIENT_ID
  labels:
    azure.workload.identity/use: "true"

Azure Storage Integration

1. Azure Blob Storage Configuration

apiVersion: v1
kind: Secret
metadata:
  name: azure-storage-secret
  namespace: argocd
type: Opaque
stringData:
  azure-storage-account-name: argocdstorageaccount
  azure-storage-account-key: STORAGE_ACCOUNT_KEY

argocd-cm has no backup.destination/backup.schedule keys - ArgoCD has no built-in scheduled backup feature. Back up on a schedule with a CronJob running argocd admin export (restored with the matching argocd admin import) and upload the result to Blob Storage:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: argocd-backup
  namespace: argocd
spec:
  schedule: "0 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: argocd-workload-identity
          containers:
          - name: argocd-backup
            # custom image bundling both the argocd CLI and the az CLI -
            # no single official image ships both
            image: your-registry/argocd-backup-tools:latest
            command:
            - /bin/sh
            - -c
            - |
              argocd admin export -n argocd > /tmp/backup.yaml
              az storage blob upload \
                --account-name argocdstorageaccount \
                --container-name argocd-backup \
                --name "$(date +%Y-%m-%d).yaml" \
                --file /tmp/backup.yaml
          restartPolicy: OnFailure

2. Storage Class Configuration

# kubernetes.io/azure-disk is the deprecated in-tree provisioner; AKS now
# uses the Azure Disk CSI driver, whose StorageClass parameter is skuName
# (not the in-tree storageaccounttype).
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: argocd-azure-disk
provisioner: disk.csi.azure.com
parameters:
  skuName: Premium_LRS
  kind: Managed
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer

Azure Monitor Integration

1. Container Insights Setup

apiVersion: v1
kind: ConfigMap
metadata:
  name: container-azm-ms-agentconfig
  namespace: kube-system
data:
  schema-version: v1
  config-version: v1
  log-data-collection-settings: |-
    [log_collection_settings]
       [log_collection_settings.stdout]
          enabled = true
          exclude_namespaces = ["kube-system"]
       [log_collection_settings.stderr]
          enabled = true
          exclude_namespaces = ["kube-system"]

2. Custom Metrics

AzureMetricConfiguration is not a real Kubernetes/Azure CRD. Azure Monitor’s managed Prometheus add-on scrapes the standard Prometheus Operator ServiceMonitor/PodMonitor CRDs, so expose ArgoCD’s metrics the same way as any other Prometheus target:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: argocd
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
  endpoints:
  - port: metrics
    interval: 1m
    scrapeTimeout: 30s

Auto Scaling Configuration

1. Horizontal Pod Autoscaling

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: argocd-server
  namespace: argocd
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: argocd-server
  minReplicas: 2
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80

2. Cluster Autoscaler

ClusterAutoscaler is not a real Kubernetes CRD - AKS’s managed autoscaler is enabled and tuned through the az aks CLI (or ARM/Bicep), not an in-cluster custom resource:

az aks nodepool update \
  --resource-group argocd-rg \
  --cluster-name argocd-cluster \
  --name ng-1 \
  --enable-cluster-autoscaler \
  --min-count 2 \
  --max-count 10

az aks update \
  --resource-group argocd-rg \
  --name argocd-cluster \
  --cluster-autoscaler-profile scale-down-delay-after-add=10m,scan-interval=10s

Best Practices Checklist

  1. Enable Azure AD integration
  2. Configure Application Gateway
  3. Setup Azure Key Vault
  4. Enable Azure Monitor
  5. Configure auto scaling
  6. Implement backup strategy
  7. Enable encryption
  8. Regular monitoring
  9. Cost management
  10. Security compliance

Cost Optimization

1. Node Pool Configuration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-server
  namespace: argocd
spec:
  template:
    spec:
      nodeSelector:
        agentpool: spotpool
      tolerations:
      - key: "kubernetes.azure.com/scalesetpriority"
        operator: "Equal"
        value: "spot"
        effect: "NoSchedule"

2. Resource Limits

apiVersion: v1
kind: LimitRange
metadata:
  name: argocd-limits
  namespace: argocd
spec:
  limits:
  - default:
      cpu: 500m
      memory: 512Mi
    defaultRequest:
      cpu: 200m
      memory: 256Mi
    type: Container

Security Hardening

1. Network Security Groups

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

2. Pod Security Context

apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-server
spec:
  template:
    spec:
      securityContext:
        runAsUser: 999
        runAsGroup: 999
        fsGroup: 999

Conclusion

This guide provides a comprehensive setup for running ArgoCD on AKS. Regular monitoring and updates are essential for optimal performance.

Additional Resources