ArgoCD Setup Guide for AWS

Complete guide for setting up ArgoCD on AWS EKS

This guide provides detailed instructions for setting up ArgoCD on Amazon EKS, including AWS-specific configurations and integrations.

Video Tutorial

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

View Source Code

Prerequisites

  • AWS CLI installed and configured
  • kubectl configured for EKS
  • eksctl installed
  • Helm (optional)
  • AWS IAM permissions

EKS Cluster Setup

1. Create EKS Cluster

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: argocd-cluster
  region: us-west-2
nodeGroups:
  - name: ng-1
    instanceType: m5.large
    desiredCapacity: 3
    volumeSize: 80
    iam:
      withAddonPolicies:
        autoScaler: true
        albIngress: true
        cloudWatch: true

2. Install AWS Load Balancer Controller

This guide manages the cluster with ArgoCD, not Flux, so install the controller directly with Helm rather than a flux.toolkit.fluxcd.io HelmRelease (a separate GitOps tool/CRD this cluster doesn’t have):

apiVersion: v1
kind: ServiceAccount
metadata:
  name: aws-load-balancer-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/aws-load-balancer-controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  --namespace kube-system \
  --set clusterName=argocd-cluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  --version 1.4.1

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. AWS ALB Configuration

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/backend-protocol: HTTPS
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:region:account-id:certificate/certificate-id
spec:
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              number: 443

AWS IAM Integration

1. IRSA Setup

apiVersion: v1
kind: ServiceAccount
metadata:
  name: argocd-application-controller
  namespace: argocd
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/argocd-application-controller
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: argocd-server
  namespace: argocd
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/argocd-server

2. IAM Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "eks:DescribeCluster",
                "eks:ListClusters",
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:eks:*:*:cluster/*",
                "arn:aws:s3:::argocd-artifacts/*"
            ]
        }
    ]
}

AWS Secrets Management

1. AWS Secrets Manager Integration

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secrets
  namespace: argocd
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-west-2
      auth:
        jwt:
          serviceAccountRef:
            name: argocd-server

2. External Secrets Configuration

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: argocd-secrets
  namespace: argocd
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets
    kind: SecretStore
  target:
    name: argocd-secret
  data:
  - secretKey: admin.password
    remoteRef:
      key: argocd/admin-password
  - secretKey: server.secretkey
    remoteRef:
      key: argocd/server-secretkey

AWS S3 Integration

1. Backup Configuration

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 S3:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: argocd-backup
  namespace: argocd
spec:
  schedule: "0 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: argocd-backup # IRSA-bound to an S3-writer role
          containers:
          - name: argocd-backup
            # custom image bundling both the argocd CLI and the aws 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
              aws s3 cp /tmp/backup.yaml "s3://argocd-backup/$(date +%Y-%m-%d).yaml"
          restartPolicy: OnFailure

2. S3 IAM Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::argocd-backup",
                "arn:aws:s3:::argocd-backup/*"
            ]
        }
    ]
}

Monitoring Integration

1. CloudWatch Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  aws.cloudwatch.enabled: "true"
  aws.cloudwatch.region: "us-west-2"
  aws.cloudwatch.logGroup: "argocd"

2. CloudWatch Metrics

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: 30s
    metricRelabelings:
    - sourceLabels: [__name__]
      regex: 'argocd_.*'
      action: keep

Auto Scaling Configuration

1. HPA Setup

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

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-autoscaler
  namespace: kube-system
spec:
  template:
    spec:
      containers:
      - name: cluster-autoscaler
        image: registry.k8s.io/autoscaling/cluster-autoscaler:v1.22.2 # k8s.gcr.io was frozen in 2023
        command:
        - ./cluster-autoscaler
        - --v=4
        - --stderrthreshold=info
        - --cloud-provider=aws
        - --skip-nodes-with-local-storage=false
        - --nodes=2:10:eks-ng-1

Best Practices Checklist

  1. Use IRSA for AWS authentication
  2. Configure ALB for ingress
  3. Setup backup to S3
  4. Enable CloudWatch monitoring
  5. Configure auto scaling
  6. Implement secrets management
  7. Enable encryption
  8. Regular backups
  9. Monitor costs
  10. Security compliance

Cost Optimization

1. Instance Selection

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: argocd-cluster
nodeGroups:
  - name: ng-1
    instanceTypes: ["t3.large", "t3a.large"]
    desiredCapacity: 3
    spotInstances: true
    spotAllocationStrategy: capacity-optimized

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

Conclusion

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

Additional Resources