IRSA 실습
IRSA
IRSA는 쿠버네티스의 서비스 어카운트(Service Account, SA)와 AWS IAM 역할(Role)을 연결하는 방법이다. 기본적으로 쿠버네티스의 파드는 AWS 리소스(S3, DynamoDB 등)에 직접 접근할 수 없으며, AWS의 보안 정책에 따라 IAM 권한을 부여해야 한다.
기존에는 EC2 인스턴스에 IAM Role을 붙이는 방식을 사용했지만 이는 세분화된 권한 관리를 어렵게 만든다.
IRSA를 사용하면 파드 단위로 IAM 권한을 부여할 수 있어 보안성과 유연성이 증가한다.
- 불필요한 권한을 줄일 수 있음 → 특정 Pod에만 필요한 AWS 리소스 접근 권한을 부여 가능
- 멀티테넌시 환경에서 보안 강화 → 동일한 클러스터 내에서도 애플리케이션(파드)별로 다른 IAM 정책을 적용 가능
- IAM 정책 적용이 파드 수준으로 내려감 → 개발자가 직접 관리 가능
sa
eksctl create iamserviceaccount \
--name my-sa \
--namespace default \
--cluster $CLUSTER_NAME \
--approve \
--attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text)
kubectl describe sa my-sa
Name: my-sa
Namespace: default
Labels: app.kubernetes.io/managed-by=eksctl
Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::~:role/eksctl-myeks-addon-iamserviceaccount-default--Role1-3OtbVkhc7PHP
Image pull secrets: <none>
Mountable secrets: <none>
Tokens: <none>
Events: <none>
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test3
spec:
serviceAccountName: my-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
kubectl get pod eks-iam-test3 -o yaml
...
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-dccvr
readOnly: true
- mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
name: aws-iam-token
readOnly: true
...
volumes:
- name: aws-iam-token
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: sts.amazonaws.com
expirationSeconds: 86400
path: token
kubectl describe pod eks-iam-test3
...
Environment:
AWS_STS_REGIONAL_ENDPOINTS: regional
AWS_DEFAULT_REGION: ap-northeast-2
AWS_REGION: ap-northeast-2
AWS_ROLE_ARN: arn:aws:iam::~:role/eksctl-myeks-addon-iamserviceaccount-default--Role1-3OtbVkhc7PHP
AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
Mounts:
/var/run/secrets/eks.amazonaws.com/serviceaccount from aws-iam-token (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-dccvr (ro)
kubectl exec -it eks-iam-test3 -- aws sts get-caller-identity --query Arn
"arn:aws:sts::~~:assumed-role/eksctl-myeks-addon-iamserviceaccount-default--Role1-3OtbVkhc7PHP/botocore-session-1742074654"
eks-iam-test3 파드는 my-service-account라는 서비스 어카운트를 사용하고 있고 AWS IAM Role과 연결되어 있다.
파드가 실행되면 AWS IAM STS(Security Token Service)에서 토큰을 받아서 IAM Role을 Assume할 수 있고 이 과정을 통해 파드는 IAM Role의 권한을 사용하여 AWS 리소스에 접근할 수 있다.
IAM 인증 토큰 설정과 Mutating Webhook 확인
kubectl get pod eks-iam-test3 -o json | jq -r '.spec.containers | .[].volumeMounts'
[
{
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
"name": "kube-api-access-dccvr",
"readOnly": true
},
{
"mountPath": "/var/run/secrets/eks.amazonaws.com/serviceaccount",
"name": "aws-iam-token",
"readOnly": true
}
]
kube-api-access-dccvr:
- 쿠버네티스 기본 서비스 어카운트(SA) 토큰을 저장하는 디렉토리(/var/run/secrets/kubernetes.io/serviceaccount)
- 파드가 쿠버네티스 API 서버와 통신하는 데 사용된다.
aws-iam-token:
- IRSA를 통해 AWS STS 토큰을 저장하는 디렉토리(/var/run/secrets/eks.amazonaws.com/serviceaccount)
- 이 토큰을 사용하여 IAM Role을 Assume하여 AWS 리소스에 접근 가능하다.
kubectl get pod eks-iam-test3 -o json | jq -r '.spec.volumes[] | select(.name=="aws-iam-token")'
{
"name": "aws-iam-token",
"projected": {
"defaultMode": 420,
"sources": [
{
"serviceAccountToken": {
"audience": "sts.amazonaws.com",
"expirationSeconds": 86400,
"path": "token"
}
}
]
}
}
IAM STS 토큰 설정
- audience: “sts.amazonaws.com” → AWS STS(Security Token Service)에서 사용할 IAM 인증 토큰
- expirationSeconds: 86400 → 토큰 만료 시간(24시간)
- path: “token” → Pod 내부에서 /var/run/secrets/eks.amazonaws.com/serviceaccount/token 경로에 토큰이 저장된다.
kubectl get MutatingWebhookConfiguration
NAME WEBHOOKS AGE
pod-identity-webhook 1 6h37m
vpc-resource-mutating-webhook 1 6h37m
쿠버네티스에서 파드가 생성될 때 자동으로 특정 설정을 추가할 수 있도록 하는 웹훅이다.
만약 파드 생성 요청이 들어오면 Mutating Webhook이 이를 가로채서 볼륨 마운트, 환경 변수 추가와 같은 추가 설정을 적용한다.
파드에 IAM 롤 설정 확인
kubectl get pod eks-iam-test3 -o json | jq -r '.spec.containers | .[].env'
[
{
"name": "AWS_STS_REGIONAL_ENDPOINTS",
"value": "regional"
},
{
"name": "AWS_DEFAULT_REGION",
"value": "ap-northeast-2"
},
{
"name": "AWS_REGION",
"value": "ap-northeast-2"
},
{
"name": "AWS_ROLE_ARN",
"value": "arn:aws:iam::~~:role/eksctl-myeks-addon-iamserviceaccount-default--Role1-3OtbVkhc7PHP"
},
{
"name": "AWS_WEB_IDENTITY_TOKEN_FILE",
"value": "/var/run/secrets/eks.amazonaws.com/serviceaccount/token"
}
]
- IAM Role (AWS_ROLE_ARN)이 할당되어 있다.
- STS 토큰 파일 (AWS_WEB_IDENTITY_TOKEN_FILE)이 /var/run/secrets/eks.amazonaws.com/serviceaccount/token에 존재한다.
- 파드 내부에서 STS 토큰을 이용하여 AWS IAM Role을 Assume할 수 있음
파드 내부 STS 인증 토큰 확인
IAM_TOKEN=$(kubectl exec -it eks-iam-test3 -- cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token)
echo $IAM_TOKEN
파드 내부에서 이 토큰을 AWS STS에 제출하여 해당 IAM Role로 AWS API를 호출할 수 있다.
OIDC 설정 정보 확인
curl -s $IDP/.well-known/openid-configuration | jq -r '.'
{
"issuer": "https://oidc.eks.ap-northeast-2.amazonaws.com/id/XXXXXXXXX",
"jwks_uri": "https://oidc.eks.ap-northeast-2.amazonaws.com/id/XXXXXXXXX/keys",
"authorization_endpoint": "urn:kubernetes:programmatic_authorization",
"response_types_supported": [
"id_token"
],
"subject_types_supported": [
"public"
],
"claims_supported": [
"sub",
"iss"
],
"id_token_signing_alg_values_supported": [
"RS256"
]
}
EKS는 OIDC를 지원하며 OIDC 기반 인증을 통해 AWS IAM 역할을 파드에 부여할 수 있다.
JWKS URL을 통해 공개 키를 제공하며 AWS STS는 이를 사용하여 OIDC 토큰의 유효성을 검증하는데, 이 정보를 기반으로 EKS의 IRSA 가 동작하여 파드가 AWS 리소스에 접근할 수 있도록 한다.
리소스 삭제
kubectl delete pod eks-iam-test3
pod "eks-iam-test3" deleted
eksctl delete iamserviceaccount --cluster $CLUSTER_NAME --name my-sa --namespace default
2025-03-16 06:48:14 [ℹ] 1 iamserviceaccount (default/my-sa) was included (based on the include/exclude rules)
2025-03-16 06:48:14 [ℹ] 1 task: {
2 sequential sub-tasks: {
delete IAM role for serviceaccount "default/my-sa" [async],
delete serviceaccount "default/my-sa",
} }2025-03-16 06:48:15 [ℹ] will delete stack "eksctl-myeks-addon-iamserviceaccount-default-my-sa"
2025-03-16 06:48:15 [ℹ] deleted serviceaccount "default/my-sa"