AWS Controller for Kubernetes(ACK) Getting started
Modern kubernetes application often require additional infrastructure like Database
, storage bucket
etc. Often these resources are provisioned by Platform team and developments teams to coordinate infrastructure creation before deploying application. Tools like Crossplane and Kubernetes Resource Orchestrator aim to make it possible to manage it via Kubernetes object. KRO
does this by using providers, and for AWS it is `AWS Controller for Kubernetes aka ACK.
AWS Controllers for Kubernetes (ACK) lets you define and use AWS service resources directly from Kubernetes. ACK can be used directly on EKS/Kubernetes instances or along with other tools like KRO.
In this example, I will demonstrate how to install ACK controllers with IAM PodIdentity instead of IAM RSA
Step 1. Provision EKS-Auto mode and EKS with Pod identity enabled
To follow along you will need an EKS cluster with PodIdentity enables as I am using Pod Identity instead of IAM-RSA
. Source Code in terraform is available in my Gitrepo https://github.com/vettom/aws-eks-terraform/eks-auto-ACK.
Step 2. Create IAM role with POD-ID for IAM-Chart
Each ACK service controller is packaged into a separate container image that is published in a public repository corresponding to an individual ACK service controller. Container images for ACK service controllers can be found in the ACK registry within the Amazon ECR Public Gallery that contains images as well Helm
chart for the controller.
In this example, I am starting with IAM-CHART
and it requires an IAM policy attachment with necessary permission to create IAM roles. Here is a sample policy with Pod identity configuration using terraform.
ack-role-iam-podid.tf
data "aws_iam_policy_document" "pod_id_assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}
actions = [
"sts:AssumeRole",
"sts:TagSession"
]
}
}
resource "aws_iam_role" "ack-iam-controller" {
name = "ack-iam-controller"
assume_role_policy = data.aws_iam_policy_document.pod_id_assume_role.json
}
resource "aws_iam_policy" "ack-iam-controller" {
name = "ack-iam-controller-policy"
description = "Policy for ACK IAM Controller"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowRoleCreation",
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:TagRole",
"iam:PassRole",
"iam:UpdateAssumeRolePolicy",
"iam:GetRole",
"iam:ListRolePolicies",
"iam:PutRolePolicy",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:ListRoles",
"iam:ListRoleTags",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:ListPolicies",
"iam:GetPolicy",
"iam:GetPolicyVersion"
],
"Resource": "*"
},
{
"Sid": "DenyAdministratorAccessAttachment",
"Effect": "Deny",
"Action": ["iam:AttachRolePolicy", "iam:DetachRolePolicy" ],
"Resource": "arn:aws:iam::aws:policy/AdministratorAccess"
}
]
})
}
resource "aws_iam_role_policy_attachment" "ack-iam-controller" {
role = aws_iam_role.ack-iam-controller.name
policy_arn = aws_iam_policy.ack-iam-controller.arn
}
resource "aws_eks_pod_identity_association" "ack-iam-controller" {
cluster_name = module.eks.cluster_name
namespace = "ack-system"
service_account = "ack-iam-controller"
role_arn = aws_iam_role.ack-iam-controller.arn
}
Step 3. Provision IAM controller chart
IAM-Chart requires aws.region
to be set.
export SERVICE=iam
export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/${SERVICE}-controller/releases/latest | jq -r '.tag_name | ltrimstr("v")')
export ACK_SYSTEM_NAMESPACE=ack-system
export AWS_REGION=eu-west-1
aws ecr-public get-login-password --region us-east-1 | helm registry login --username AWS --password-stdin public.ecr.aws
helm install --create-namespace -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller \
oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart --version=$RELEASE_VERSION --set=aws.region=$AWS_REGION
Step 4. Create sample IAM role
Create example-role
and validate role is created in AWS.
apiVersion: iam.services.k8s.aws/v1alpha1
kind: Role
metadata:
name: example-role
spec:
name: example-role
assumeRolePolicyDocument: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": [
"sts:AssumeRole",
"sts:TagSession"
]
}
]
}
description: "Example role created by ACK"
maxSessionDuration: 3600
policies:
- arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
Step 5. Provisioning Additional controllers
Once IAM controller is installed, you can provision additional controller direct from K8s using ACK
Here is example of S3 controller - Define IAM role with IAM-RSA role for S3 controller - Install S3 controller chart
Create IAM Pod ID role for S3 controller
ack-s3-iam-rsa.yaml
apiVersion: iam.services.k8s.aws/v1alpha1
kind: Role
metadata:
name: ack-s3-controller
spec:
name: ack-s3-controller
assumeRolePolicyDocument: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS-Account-id>:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/87AD44391B740265AE0AB65382E8D918"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.eu-west-1.amazonaws.com/id/87AD44391B740265AE0AB65382E8D918:sub": "system:serviceaccount:ack-system:ack-s3-controller"
}
}
}
]
}
description: "S3 role created by ACK"
maxSessionDuration: 3600
policies:
- "arn:aws:iam::aws:policy/AmazonS3FullAccess"
Install S3 controller
export SERVICE=s3
export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/${SERVICE}-controller/releases/latest | jq -r '.tag_name | ltrimstr("v")')
export ACK_SYSTEM_NAMESPACE=ack-system
export AWS_REGION=eu-west-1
aws ecr-public get-login-password --region us-east-1 | helm registry login --username AWS --password-stdin public.ecr.aws
helm install --create-namespace -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller \
oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart --version=$RELEASE_VERSION --set=aws.region=$AWS_REGION
Provision Sample bucket
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
name: example-ack-bucket-sample
spec:
name: example-ack-bucket-051020251400
versioning:
status: Enabled
tagging:
tagSet:
- key: environment
value: dev
- key: owner
value: "Denny Vettom"
Step 6. Provision sample app with S3 access
Scenario: Deploy app that require access to S3 bucket. Configure bucket and IAM-RSA permissions using ACK
- Create necessary access policy using ACK
- Create Role with IAM-RSA and attach policy
- Deploy app with configured SA and validate
ack-demo-iam-rsa.yaml
apiVersion: iam.services.k8s.aws/v1alpha1
kind: Policy
metadata:
name: demo-app-bucket-access-policy
spec:
name: demo-app-bucket-access-policy
description: "Allows ACK EKS Controller to manage Pod Identity Associations"
policyDocument: |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [ "s3:GetObject", "s3:ListBucket", "s3:PutObject"],
"Resource": [ "arn:aws:s3:::eks-auto-demo-bucket-102025", "arn:aws:s3:::eks-auto-demo-bucket-102025/*"]
}
]
}
---
apiVersion: iam.services.k8s.aws/v1alpha1
kind: Role
metadata:
name: ack-demo-app-role
spec:
name: ack-demo-app-role
assumeRolePolicyDocument: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS-Account-id>:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/87AD44391B740265AE0AB65382E8D918"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.eu-west-1.amazonaws.com/id/87AD44391B740265AE0AB65382E8D918:sub": "system:serviceaccount:default:ack-demo-app-sa"
}
}
}
]
}
description: "Example role created by ACK"
maxSessionDuration: 3600
policies:
- arn:aws:iam::<AWS-Account-id>:policy/demo-app-bucket-access-policy
Apply the configuration and verify. kubectl apply -f ack-demo-iam-rsa.yaml
Deploy Demo app
This is a pod with AWS CLI installed. No credentials configured, it will use authentication provided by IAM-RSA
deploy-ack-demo-app.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: ack-demo-app-sa
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: ack-demo-app
name: ack-demo-app
spec:
replicas: 1
selector:
matchLabels:
app: ack-demo-app
strategy: {}
template:
metadata:
labels:
app: ack-demo-app
spec:
serviceAccountName: ack-demo-app-sa
containers:
- image: dennysv/dvawscli
name: dvawscli
resources: {}
Verify bucket access
SSH on to the pod
$ aws s3 ls eks-auto-demo-bucket-102025/
$ aws s3 cp /etc/os-release s3://eks-auto-demo-bucket-102025/
$ aws s3 ls eks-auto-demo-bucket-102025/
$ aws s3 crm os-release s3://eks-auto-demo-bucket-102025/os-release
You have successfully configured ACK and deployed sample App making use of ACK.