> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/continuous-delivery/use-gitops/gitops-entities/clusters/create-cluster-with-iam.md).

# Create a GitOps cluster with IAM role

Create a Harness GitOps cluster in Amazon EKS and deploy applications to it using an IAM role.

This topic shows how to create a Harness GitOps cluster in Amazon EKS and deploy applications to the cluster using an Identity and Access Management (IAM) role. IAM roles are sets of permissions that you assign to AWS services or resources, rather than to individual users.

The walkthrough covers Harness GitOps Agent setup in a multi-cluster AWS environment and how the Agent assumes an IAM role to deploy applications to those clusters.

{% hint style="info" %}
**EKS Agent requirement**

GitOps clusters with IAM roles can be created only for a GitOps Agent installed in Amazon EKS.
{% endhint %}

***

## What you will learn from this topic

* How to [create a management cluster](#create-a-management-cluster) that hosts the Harness GitOps Agent
* How to create an IAM role (`role/ArgoCD`) that the GitOps Agent assumes first
* How to [create a testing cluster](#create-a-testing-cluster) where you deploy a guestbook sample application
* How to create an IAM role (`role/Deployer`) with permissions to deploy applications in your testing cluster
* How to [register the testing cluster with Harness](#register-the-testing-cluster-with-harness) and [deploy applications](#deploy-applications-to-your-cluster)

![Architecture for GitOps management and testing clusters with IAM roles](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-c84519790078ac0c75aaf6b0494c7d94d07ee72e%2Fcreate-cluster-iam-86.png?alt=media)

***

## Before you begin

Complete the following prerequisites before you start:

* **AWS account**: An AWS account ready to receive new VPCs with EKS clusters.
* **AWS CLI**: Go to [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) to install and configure it for your account.
* **eksctl**: Go to [eksctl](https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html#installing-eksctl) to install it on your machine.
* **kubectl**: Go to [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to install it on your machine.
* **GitOps Agent**: A Harness GitOps Agent installed in an EKS cluster. Go to [Install a Harness GitOps Agent](/continuous-delivery/use-gitops/gitops-entities/agents/install-a-harness-git-ops-agent.md) to set one up.
* **Harness permissions**: Permission to create and manage GitOps clusters and applications in your project. Go to [RBAC in Harness](https://developer.harness.io/docs/platform/role-based-access-control/rbac-in-harness) to configure roles.

***

## Create a management cluster

Create two clusters in a single AWS account. The configuration also works with cross-account and multi-cluster setups when you set the proper trust relations between the IAM roles.

### Provision the management cluster

Use the following command to provision the management cluster with an OpenID Connect (OIDC) provider:

```bash
eksctl create cluster --name management --with-oidc
```

The command can take 10 to 20 minutes. It creates a management cluster and the resources it needs, such as a VPC, security groups, and an EC2 node group.

The AWS authenticator packaged with the Harness GitOps Agent uses the OIDC provider to acquire a token. With that token, the Agent can assume the IAM role `role/ArgoCD` that you create in the next step.

### Create an IAM role for your GitOps Agent

Perform the following steps to create the Argo CD IAM role and attach an assume-role policy:

1. Set the management cluster `AWS_ACCOUNT_ID` and `OIDC_PROVIDER` as environment variables:

```bash
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)

OIDC_PROVIDER=$(aws eks describe-cluster --name management --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
```

2. Create a `trust.json` file with the variables you set in the previous step. Reference the namespace where you deploy your GitOps Agent so that cluster roles can assume the IAM role you create next:

```bash
read -r -d '' TRUST_RELATIONSHIP <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "${OIDC_PROVIDER}:sub": "system:serviceaccount:iam:*"
        }
      }
    }
  ]
}
EOF

echo "${TRUST_RELATIONSHIP}" > trust.json && cat trust.json
```

Confirm that `trust.json` includes the correct `AWS_ACCOUNT_ID` and `OIDC_PROVIDER`, then create the role:

```bash
aws iam create-role --role-name ArgoCD --assume-role-policy-document file://trust.json --description "IAM Role to be used by Harness GitOps Agent to gain AWS access"
```

3. Create an inline policy that lets the IAM role assume other roles so the GitOps Agent can assume the Deployer role you create later. You could use the Argo CD role directly; a separate Deployer role for the testing cluster is recommended because it is more flexible and secure.

```bash
read -r -d '' POLICY <<EOF
 {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AssumeRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "*"
        }
    ]
}
EOF

echo "${POLICY}" > policy.json && cat policy.json

aws iam put-role-policy --role-name ArgoCD --policy-name AssumeRole --policy-document file://policy.json
```

Use the AWS web console to check the role you created. The Kubernetes service accounts that the Agent uses in the management cluster assume the IAM role through the OIDC provider.

### Set up Harness GitOps Agent

Create a namespace for the Harness GitOps Agent in the management cluster:

```bash
kubectl create namespace iam
```

Go to [Install a Harness GitOps Agent](/continuous-delivery/use-gitops/gitops-entities/agents/install-a-harness-git-ops-agent.md) to install and configure your GitOps Agent in that namespace.

### Patch the GitOps Agent

Perform the following steps to annotate service accounts and set `fsGroup` so the Agent can assume the IAM role:

1. Annotate the Kubernetes service accounts the Agent uses with the ARN of the role:

```bash
kubectl -n iam patch serviceaccount argocd-application-controller --type=json \
-p="[{\"op\": \"add\", \"path\": \"/metadata/annotations/eks.amazonaws.com~1role-arn\", \"value\": \"arn:aws:iam::${AWS_ACCOUNT_ID}:role/ArgoCD\"}]"

kubectl -n iam patch serviceaccount gitops-agent --type=json \
-p="[{\"op\": \"add\", \"path\": \"/metadata/annotations/eks.amazonaws.com~1role-arn\", \"value\": \"arn:aws:iam::${AWS_ACCOUNT_ID}:role/ArgoCD\"}]"
```

The annotations must show the correct ARN of the Argo CD role; otherwise the Agent does not know which IAM role to assume.

2. Verify that the service accounts changed correctly:

```bash
kubectl -n iam describe serviceaccount gitops-agent

kubectl -n iam describe serviceaccount argocd-application-controller
```

3. Patch the deployments to set `securityContext/fsGroup` to `999` so the Docker image user can use the IAM authenticator. The IAM authenticator tries to mount a secret on `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`. If the correct `fsGroup` (`999` corresponds to the Argo CD user) is not set, the mount fails.

```bash
kubectl -n iam patch deployment gitops-agent --type=json  \
-p='[{"op": "add", "path": "/spec/template/spec/securityContext/fsGroup", "value": 999}]'

kubectl -n iam patch statefulset argocd-application-controller --type=json \
-p='[{"op": "add", "path": "/spec/template/spec/securityContext/fsGroup", "value": 999}]'
```

After you patch the Deployment and StatefulSet, the `application-controller` and `gitops-agent` pods restart. Ensure that the GitOps Agent is healthy and connected in Harness before you continue.

***

## Create a testing cluster

You now have a working management cluster with a GitOps Agent installed. Next, set up a testing cluster to which you can deploy.

### Provision the testing cluster

Enter the following command to provision the testing cluster:

```bash
eksctl create cluster --name testing
```

You do not need an OIDC provider for the testing cluster. You do need an IAM role to deploy applications in this cluster.

### Create an IAM role to deploy applications

Perform the following steps to create the Deployer role and map it to the testing cluster:

1. Create a trust relationship for the Argo CD role so it can assume the Deployer role.

{% hint style="info" %}
**Multi-account setup**

In a multi-account setup, you can change the trust relationship to reference the Argo CD role in the account that holds the management cluster, and place the Deployer role in the same account as the testing cluster.
{% endhint %}

```bash
read -r -d '' TRUST_TESTING <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::${AWS_ACCOUNT_ID}:role/ArgoCD"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
EOF

echo "${TRUST_TESTING}" > trust-testing.json && cat trust-testing.json
```

2. Verify that the `AWS_ACCOUNT_ID` for the Argo CD role is correct, then create the role and map it to the testing cluster:

```bash
aws iam create-role --role-name Deployer --assume-role-policy-document file://trust-testing.json --description "IAM Role to be used by AWS to Deploy in the testing cluster"

eksctl create iamidentitymapping --cluster testing  --arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/Deployer --group system:masters --username deployer
```

***

## Register the testing cluster with Harness

Perform the following steps to register the testing cluster in Harness so you can create and deploy applications:

{% stepper %}
{% step %}

### Open the New Cluster dialog

In Harness, select **Deployments** -> **GitOps**. Select **Settings** in the top right corner, then select **Clusters** -> **New Cluster**.
{% endstep %}

{% step %}

### Name the cluster and select the Agent

Enter a name for the cluster. Select the GitOps Agent, then select **Continue**.
{% endstep %}

{% step %}

### Enter cluster details

In **Details**, configure the following fields:

* **Master URL**: The HTTP endpoint of the Kubernetes API of the server. Obtain this from your EKS cluster endpoint in the AWS console or with `aws eks describe-cluster`.
* **Authentication**: Select **IRSA** (IAM Roles for Service Accounts).
* **Role ARN**: The role your GitOps Agent must assume to deploy to this cluster (the Deployer role ARN).
* **Certificate Authority Data**: The corresponding public certificate of the Kubernetes API.

![New Cluster dialog with IRSA authentication and Role ARN fields](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-ff39059d7c44306523aaf10607f4b6c4f5d808d1%2Fcreate-cluster-iam-87.png?alt=media)
{% endstep %}
{% endstepper %}

You have created a cluster in Harness. The connection status can show as `unknown` until the Agent successfully connects and syncs.

***

## Deploy applications to your cluster

Go to [Add a Harness GitOps application](/continuous-delivery/use-gitops/get-started/harness-cd-git-ops-quickstart.md#step-4-add-a-harness-gitops-application) to deploy applications to your cluster through Harness. After you add an application that targets this cluster, sync it and confirm resources appear in the testing cluster.

***

## Troubleshooting

Use the following entries when Agent patching, IAM assume-role, or cluster registration fails.

<details>

<summary>GitOps Agent unhealthy or disconnected after patch</summary>

Confirm the `gitops-agent` and `argocd-application-controller` pods restarted cleanly in the `iam` namespace. Describe the service accounts and verify the `eks.amazonaws.com/role-arn` annotation matches `arn:aws:iam::ACCOUNT_ID:role/ArgoCD`. Confirm `securityContext.fsGroup` is `999` on the Deployment and StatefulSet. In Harness, open the Agent and verify status is healthy and connected before you register the testing cluster.

</details>

<details>

<summary>Agent cannot assume the Deployer role</summary>

Verify the Argo CD role has the AssumeRole inline policy and that the Deployer role trust policy principal is `arn:aws:iam::ACCOUNT_ID:role/ArgoCD`. In multi-account setups, confirm the trust relationship references the management-account Argo CD role. Check CloudTrail or pod logs for `AccessDenied` on `sts:AssumeRole`.

</details>

<details>

<summary>Cluster connection status stays unknown</summary>

Confirm **Master URL**, **Certificate Authority Data**, and **Role ARN** match the testing cluster and Deployer role. Ensure the Agent is in the management cluster and healthy. Retry registration after correcting IRSA fields; status can remain `unknown` until the first successful connection attempt.

</details>

***

## Next steps

* [Manage GitOps applications](/continuous-delivery/use-gitops/application/manage-gitops-applications.md): Create and sync applications to your new cluster.
* [Add a Harness GitOps application](/continuous-delivery/use-gitops/get-started/harness-cd-git-ops-quickstart.md): Follow the quickstart to deploy your first application end to end.
* [GitOps basics](/continuous-delivery/use-gitops/get-started/harness-git-ops-basics.md): Review the core GitOps concepts used in this setup.

{% @harness-feedback/feedback %}
