ebs-csi-controller Pod 가 1/6 상태로 CrashLoopBackOff 를 반복하고 ebs-plugin 로그에 AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity 가 찍힌다. eksctl create iamserviceaccount --override-existing-serviceaccounts 를 실행해도 다음처럼 아무 작업도 하지 않는다.
1 existing iamserviceaccount(s) (kube-system/ebs-csi-controller-sa) will be excluded
1 iamserviceaccount ... was excluded (based on the include/exclude rules)
no tasks
원인은 IAM Role AmazonEKS_EBS_CSI_DriverRole 의 Trust Policy 가 현재 클러스터의 OIDC provider 와 맞지 않는 상태에서 eksctl 이 "SA 가 이미 있다" 는 이유로 건너뛰어 Role 과 ServiceAccount 가 따로 놀았기 때문이다.
kubectl logs -n kube-system -l app=ebs-csi-controller -c ebs-plugin --tail=50
kubectl get sa ebs-csi-controller-sa -n kube-system -o yaml | grep role-arn
OIDC_ISSUER=$(aws eks describe-cluster --name <cluster> --region ap-northeast-2 \
--query "cluster.identity.oidc.issuer" --output text)
aws iam get-role --role-name AmazonEKS_EBS_CSI_DriverRole --query "Role.AssumeRolePolicyDocument"
Trust Policy 의 Federated ARN 끝(oidc.eks.ap-northeast-2.amazonaws.com/id/XXXX) 이 OIDC_ISSUER 와 같아야 하고, Condition.StringEquals 에 다음이 있어야 한다.
"<OIDC_ID>:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa",
"<OIDC_ID>:aud": "sts.amazonaws.com"
다른 클러스터에서 쓰던 Role 을 재사용하면 OIDC 경로가 달라 토큰 교환이 실패한다.
eksctl delete iamserviceaccount --name ebs-csi-controller-sa --namespace kube-system \
--cluster <cluster> --region ap-northeast-2
kubectl delete sa ebs-csi-controller-sa -n kube-system --ignore-not-found
# 실패 · 롤백된 CloudFormation 스택과 잔재 Role 정리
STACK=eksctl-<cluster>-addon-iamserviceaccount-kube-system-ebs-csi-controller-sa
aws cloudformation describe-stacks --region ap-northeast-2 --stack-name $STACK --query "Stacks[0].StackStatus" --output text
aws cloudformation delete-stack --region ap-northeast-2 --stack-name $STACK
aws cloudformation wait stack-delete-complete --region ap-northeast-2 --stack-name $STACK
aws iam list-attached-role-policies --role-name AmazonEKS_EBS_CSI_DriverRole --query "AttachedPolicies[].PolicyArn" --output text \
| xargs -n1 -I{} aws iam detach-role-policy --role-name AmazonEKS_EBS_CSI_DriverRole --policy-arn {}
aws iam delete-role --role-name AmazonEKS_EBS_CSI_DriverRole
eksctl utils associate-iam-oidc-provider --cluster <cluster> --region ap-northeast-2 --approve
eksctl create iamserviceaccount --name ebs-csi-controller-sa --namespace kube-system \
--cluster <cluster> --region ap-northeast-2 \
--role-name AmazonEKS_EBS_CSI_DriverRole \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy --approve
kubectl rollout restart deployment ebs-csi-controller -n kube-system
kubectl rollout status deployment ebs-csi-controller -n kube-system --timeout=180s
kubectl get pods -n kube-system -l app=ebs-csi-controller # 6/6 Running
eksctl delete 를 연속으로 두 번 실행하면 이전 스택 삭제와 새 스택 생성이 충돌해 "waiting for CloudFormation stack" 에서 멈출 수 있다. 스택 상태가 DELETE_IN_PROGRESS 면 끝날 때까지 기다린다. 가장 흔한 CREATE_FAILED 사유는 같은 이름의 IAM Role 이 이미 있는 경우다.
Pod 의 env 에 aws-secret Secret 의 AWS_ACCESS_KEY_ID 가 Optional 로 걸려 있는데 그 Secret 에 무효한 키가 들어 있으면 SDK 자격증명 체인에서 IRSA 보다 먼저 잡힌다. kubectl get secret aws-secret -n kube-system 으로 존재 여부를 본다.
Add-on 으로 관리한다면 Role ARN 을 Add-on 에 묶어 두어야 업그레이드로 SA 가 재생성돼도 annotation 이 유지된다.
ROLE_ARN=$(aws iam get-role --role-name AmazonEKS_EBS_CSI_DriverRole --query 'Role.Arn' --output text)
aws eks update-addon --cluster-name <cluster> --region ap-northeast-2 \
--addon-name aws-ebs-csi-driver --service-account-role-arn "$ROLE_ARN"
기본 StorageClass 가 없으면 gp3 를 default 로 만든다.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp3
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: gp3
encrypted: "true"