Skip to main content

Configure IAM Permissions for ACK Controllers

ACK controllers need AWS IAM permissions to manage resources. This guide shows you how to configure IAM permissions using either EKS Pod Identity (recommended for EKS 1.24+) or IRSA (traditional method).

Pod Identity Authentication Flow

Click to zoom • Pod Identity authentication flow

Choose Your Authentication Method​

What is Pod Identity?​

EKS Pod Identity is a feature that allows pods running in your EKS cluster to assume AWS IAM roles without requiring OIDC configuration. It simplifies the authentication flow by using the EKS Pod Identity Agent, which runs as a DaemonSet in your cluster and handles credential requests automatically.

How It Works​

  1. You create a Pod Identity Association that links:

    • An IAM role (with AWS service permissions)
    • A Kubernetes service account (used by the ACK controller)
    • A namespace (where the controller runs)
  2. When the ACK controller pod starts with this service account, the Pod Identity Agent automatically provides temporary AWS credentials

  3. The controller uses these credentials to manage AWS resources

Pod Identity Association​

A Pod Identity Association is an EKS resource that connects your controller's service account to an IAM role. Here's what it looks like:

apiVersion: eks.services.k8s.aws/v1alpha1
kind: PodIdentityAssociation
metadata:
name: ack-s3-controller-pod-identity
spec:
clusterName: my-cluster
namespace: ack-system
serviceAccount: ack-s3-controller
roleARN: arn:aws:iam::123456789012:role/ack-s3-controller

Key components:

  • clusterName: Your EKS cluster name
  • namespace: Where your ACK controller runs (typically ack-system)
  • serviceAccount: The service account used by the controller (auto-created during installation)
  • roleARN: The IAM role with permissions for the AWS service

You can create this using either:

  • AWS CLI: aws eks create-pod-identity-association
  • ACK EKS Controller: Create a PodIdentityAssociation CRD (shown above)

Example Configuration​

Here's a complete example for configuring the S3 controller with Pod Identity:

# Variables
export SERVICE=s3
export CLUSTER_NAME=my-cluster
export AWS_REGION=us-west-2
export ACK_SYSTEM_NAMESPACE=ack-system
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)

# Create Pod Identity Association
aws eks create-pod-identity-association \
--cluster-name $CLUSTER_NAME \
--namespace $ACK_SYSTEM_NAMESPACE \
--service-account ack-${SERVICE}-controller \
--role-arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/ack-${SERVICE}-controller \
--region $AWS_REGION

# Restart controller to pick up the association
kubectl rollout restart deployment -n $ACK_SYSTEM_NAMESPACE \
ack-${SERVICE}-controller

Or using the ACK EKS controller:

apiVersion: eks.services.k8s.aws/v1alpha1
kind: PodIdentityAssociation
metadata:
name: ack-s3-controller-pod-identity
spec:
clusterName: my-cluster
namespace: ack-system
serviceAccount: ack-s3-controller
roleARN: arn:aws:iam::123456789012:role/ack-s3-controller
Creating the IAM Role (expand for details)

Before creating the Pod Identity Association, you need an IAM role with the appropriate permissions.

Step 1: Create IAM Role with Pod Identity Trust Policy

export SERVICE=s3
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)

# Create IAM role with Pod Identity trust policy
aws iam create-role \
--role-name ack-${SERVICE}-controller \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "pods.eks.amazonaws.com"},
"Action": ["sts:AssumeRole", "sts:TagSession"]
}]
}'

Step 2: Attach AWS Service Permissions

# Get recommended policy for your service
export POLICY_ARN=$(curl -s https://raw.githubusercontent.com/aws-controllers-k8s/${SERVICE}-controller/main/config/iam/recommended-policy-arn)

# Attach the policy
aws iam attach-role-policy \
--role-name ack-${SERVICE}-controller \
--policy-arn $POLICY_ARN

Step 3: Attach Inline Policies (if needed)

Some controllers need additional inline policies (like iam:PassRole):

# Check if inline policy exists
curl -s https://raw.githubusercontent.com/aws-controllers-k8s/${SERVICE}-controller/main/config/iam/recommended-inline-policy > inline-policy.json

# If the file exists and has content, apply it
if [ -s inline-policy.json ]; then
aws iam put-role-policy \
--role-name ack-${SERVICE}-controller \
--policy-name ack-${SERVICE}-inline \
--policy-document file://inline-policy.json
fi

Verify​

Check that the Pod Identity Association was created:

aws eks list-pod-identity-associations \
--cluster-name $CLUSTER_NAME \
--region $AWS_REGION

# Check controller logs
kubectl logs -n $ACK_SYSTEM_NAMESPACE deployment/ack-${SERVICE}-controller

Each ACK controller repository contains recommended IAM policies:

# Policy ARN (AWS managed policy)
https://raw.githubusercontent.com/aws-controllers-k8s/${SERVICE}-controller/main/config/iam/recommended-policy-arn

# Inline policy (additional permissions)
https://raw.githubusercontent.com/aws-controllers-k8s/${SERVICE}-controller/main/config/iam/recommended-inline-policy

Examples:

  • S3: arn:aws:iam::aws:policy/AmazonS3FullAccess
  • DynamoDB: arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
  • RDS: arn:aws:iam::aws:policy/AmazonRDSFullAccess
Production use

For production, create custom policies with least-privilege permissions instead of using *FullAccess policies.

Next Steps​

Additional Resources​

Built with ♥ by AWS