IRSA (IAM Roles for Service Accounts) is the recommended way to provide AWS credentials to Karpenter Optimizer when running on Amazon EKS. This eliminates the need to manage AWS access keys and follows AWS security best practices.
While the AWS Pricing API uses a public endpoint that doesn’t require authentication, using IRSA provides:
eksctl or aws CLI installedCreate an IAM policy that grants access to the AWS Pricing API:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"pricing:GetProducts",
"pricing:DescribeServices"
],
"Resource": "*"
}
]
}
Save this as karpenter-optimizer-policy.json and create the policy:
aws iam create-policy \
--policy-name KarpenterOptimizerPolicy \
--policy-document file://karpenter-optimizer-policy.json
Note the policy ARN (e.g., arn:aws:iam::ACCOUNT_ID:policy/KarpenterOptimizerPolicy).
Create an IAM role with a trust policy that allows your EKS service account to assume it.
aws eks describe-cluster --name YOUR_CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text
Create trust-policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/OIDC_PROVIDER_ID"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"OIDC_PROVIDER_ID:sub": "system:serviceaccount:NAMESPACE:SERVICE_ACCOUNT_NAME",
"OIDC_PROVIDER_ID:aud": "sts.amazonaws.com"
}
}
}
]
}
Replace:
ACCOUNT_ID: Your AWS account IDOIDC_PROVIDER_ID: Your OIDC provider ID (from step above, e.g., oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E)NAMESPACE: Kubernetes namespace (e.g., karpenter-optimizer)SERVICE_ACCOUNT_NAME: Service account name (e.g., karpenter-optimizer)aws iam create-role \
--role-name karpenter-optimizer-role \
--assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy \
--role-name karpenter-optimizer-role \
--policy-arn arn:aws:iam::ACCOUNT_ID:policy/KarpenterOptimizerPolicy
Note the role ARN (e.g., arn:aws:iam::ACCOUNT_ID:role/karpenter-optimizer-role).
Update your values.yaml to use IRSA:
serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/karpenter-optimizer-role
config:
aws:
region: "us-east-1"
Or install with --set:
helm install karpenter-optimizer ./charts/karpenter-optimizer \
--namespace karpenter-optimizer \
--create-namespace \
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::ACCOUNT_ID:role/karpenter-optimizer-role \
--set config.aws.region=us-east-1
After deploying, verify the pod has the AWS credentials:
# Check the pod is running
kubectl get pods -n karpenter-optimizer
# Check environment variables (should include AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE)
kubectl exec -n karpenter-optimizer deployment/karpenter-optimizer -- env | grep AWS
# Test AWS API access
kubectl exec -n karpenter-optimizer deployment/karpenter-optimizer -- \
aws pricing get-products --service-code AmazonEC2 --region us-east-1
If you’re using eksctl, you can create the IAM role and service account in one command:
eksctl create iamserviceaccount \
--name karpenter-optimizer \
--namespace karpenter-optimizer \
--cluster YOUR_CLUSTER_NAME \
--attach-policy-arn arn:aws:iam::ACCOUNT_ID:policy/KarpenterOptimizerPolicy \
--approve \
--override-existing-serviceaccounts
Then update your Helm values:
serviceAccount:
create: false # eksctl already created it
name: karpenter-optimizer
aws eks describe-cluster --name YOUR_CLUSTER_NAME --query "cluster.identity.oidc.issuer"
aws iam get-role --role-name karpenter-optimizer-role --query "Role.AssumeRolePolicyDocument"
kubectl get serviceaccount -n karpenter-optimizer karpenter-optimizer -o yaml
kubectl logs -n karpenter-optimizer deployment/karpenter-optimizer
aws iam list-attached-role-policies --role-name karpenter-optimizer-role
kubectl exec -n karpenter-optimizer deployment/karpenter-optimizer -- \
aws sts get-caller-identity