Skip to main content

Overview

Argo CD manages external Kubernetes clusters by storing their credentials in Secrets with the label argocd.argoproj.io/secret-type: cluster. This guide covers declarative cluster configuration, authentication methods, and EKS-specific setup.

Cluster Secret Structure

Cluster credentials are stored in Secrets with the following required fields:
name
string
required
Cluster display name in Argo CD
server
string
required
Cluster API server URL
config
JSON
required
JSON configuration containing authentication and TLS settings
namespaces
string
Comma-separated list of accessible namespaces. Setting this will cause cluster-level resources to be ignored unless clusterResources is true.
clusterResources
boolean
Whether Argo CD can manage cluster-level resources. Only applies when namespaces is set.
project
string
Designate this as a project-scoped cluster

Basic Cluster Configuration

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

Authentication Methods

Bearer Token Authentication

config: |
  {
    "bearerToken": "<authentication token>",
    "tlsClientConfig": {
      "insecure": false,
      "caData": "<base64 encoded certificate>"
    }
  }

Basic Authentication

config: |
  {
    "username": "admin",
    "password": "<password>",
    "tlsClientConfig": {
      "insecure": false,
      "caData": "<base64 encoded certificate>"
    }
  }

AWS IAM Authentication

For AWS EKS clusters:
config: |
  {
    "awsAuthConfig": {
      "clusterName": "my-eks-cluster-name",
      "roleARN": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>"
    },
    "tlsClientConfig": {
      "insecure": false,
      "caData": "<base64 encoded certificate>"
    }
  }

Exec Provider Configuration

Use external commands to supply credentials:
config: |
  {
    "execProviderConfig": {
      "command": "argocd-k8s-auth",
      "args": ["aws", "--cluster-name", "my-eks-cluster"],
      "apiVersion": "client.authentication.k8s.io/v1beta1",
      "env": {
        "AWS_REGION": "us-east-1",
        "AWS_ACCESS_KEY_ID": "<access-key>",
        "AWS_SECRET_ACCESS_KEY": "<secret-key>"
      }
    },
    "tlsClientConfig": {
      "insecure": false,
      "caData": "<base64 encoded certificate>"
    }
  }
Commands specified in execProviderConfig must be available in the Argo CD image. See BYOI (Build Your Own Image) for details.

Namespace-Scoped Clusters

Restrict cluster access to specific namespaces:
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster
  server: https://mycluster.example.com
  namespaces: "dev,staging,prod"
  clusterResources: "false"
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }
When namespaces is set, Argo CD performs a separate list/watch operation for each namespace. Increase ARGOCD_K8S_CLIENT_MAX_IDLE_CONNECTIONS if needed.

Skipping Cluster Reconciliation

Prevent the application controller from reconciling apps on a cluster:
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
  annotations:
    argocd.argoproj.io/skip-reconcile: "true"
type: Opaque
stringData:
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }
To annotate an existing cluster:
kubectl -n argocd annotate secret mycluster-secret argocd.argoproj.io/skip-reconcile=true
To resume reconciliation:
kubectl -n argocd annotate secret mycluster-secret argocd.argoproj.io/skip-reconcile-

EKS Clusters with IRSA

Configure EKS clusters using IAM Roles for Service Accounts:
apiVersion: v1
kind: Secret
metadata:
  name: eks-cluster-secret
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: "eks-cluster-name-for-argo"
  server: "https://xxxyyyzzz.xyz.us-east-1.eks.amazonaws.com"
  config: |
    {
      "awsAuthConfig": {
        "clusterName": "my-eks-cluster-name",
        "roleARN": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>"
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

Service Account Annotations

Annotate the Argo CD service accounts with the management role:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: argocd-application-controller
  namespace: argocd
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ARGO_CD_MANAGEMENT_IAM_ROLE_NAME>"
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: argocd-server
  namespace: argocd
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ARGO_CD_MANAGEMENT_IAM_ROLE_NAME>"
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: argocd-applicationset-controller
  namespace: argocd
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ARGO_CD_MANAGEMENT_IAM_ROLE_NAME>"

Config Field Reference

The config field accepts a JSON object with the following structure:
{
  "username": "string",
  "password": "string",
  "bearerToken": "string",
  "awsAuthConfig": {
    "clusterName": "string",
    "roleARN": "string",
    "profile": "string"
  },
  "execProviderConfig": {
    "command": "string",
    "args": ["string"],
    "env": {"key": "value"},
    "apiVersion": "string",
    "installHint": "string"
  },
  "proxyUrl": "string",
  "tlsClientConfig": {
    "caData": "string",
    "certData": "string",
    "insecure": "boolean",
    "keyData": "string",
    "serverName": "string"
  },
  "disableCompression": "boolean"
}

CLI Management

Adding a Cluster

argocd cluster add context-name
List available contexts:
kubectl config get-contexts

Removing a Cluster

argocd cluster rm context-name
The in-cluster cluster cannot be removed via CLI. To disable it, set cluster.inClusterEnabled: "false" in the argocd-cm ConfigMap.

Best Practices

Use IRSA for EKS

Leverage IAM Roles for Service Accounts for secure, credential-free authentication to EKS clusters.

Namespace Restrictions

Use namespace scoping to limit cluster access and improve security.

TLS Verification

Always set insecure: false and provide caData for production clusters.

Skip Reconciliation

Use the skip-reconcile annotation for maintenance windows or debugging.