이번 블로깅은 EKS의 IRSA에 대한 워크샵 실습을 정리하였습니다.
해당 워크샵을 사용하는 방법
워크샵 실습을 시작하기 앞서 이 워크샵을 사용하고 싶으신 분들을 위해 환경 세팅 가이드 하겠습니다.
https://www.eksworkshop.com/docs/introduction/setup/your-account/
In your AWS account | EKS Workshop
Provisioning this workshop environment in your AWS account will create resources and there will be cost associated with them. The cleanup section provides a guide to remove them, preventing further charges.
www.eksworkshop.com
이 워크샵은 누구나 환경을 세팅할 수 있도록 아주 잘 구성되어있습니다. 해당 링크로 들어간뒤 원하는 Region의 Launch 버튼을 누르면 CloudFormation으로 이동됩니다.

여기서 생성버튼을 눌러 실습환경을 만들면 됩니다. 인스턴스가 생성되는데 이게 실습 서버가 됩니다.
https://www.eksworkshop.com/docs/introduction/setup/your-account/using-eksctl
Using eksctl | EKS Workshop
This section outlines how to build a cluster for the lab exercises using the eksctl tool. This is the easiest way to get started, and is recommended for most learners.
www.eksworkshop.com
해당 실습서버에 eks 클러스터를 다음 명령어로 만들어줍니다.
export EKS_CLUSTER_NAME=eks-workshop
curl -fsSL https://raw.githubusercontent.com/aws-samples/eks-workshop-v2/stable/cluster/eksctl/cluster.yaml | \
envsubst | eksctl create cluster -f -
이제 워크샵 내용을 정리해보겠습니다.
IRSA에 대한 내용입니다.
https://www.eksworkshop.com/docs/security/iam-roles-for-service-accounts/
IAM Roles for Service Accounts | EKS Workshop
Manage AWS credentials for your applications running on Amazon Elastic Kubernetes Service with IAM Roles for Service Accounts.
www.eksworkshop.com
이 명령어를 통해서 실습 준비를 진행합니다.
prepare-environment security/irsa
IRSA란?
IAM Roles for Service Accounts(IRSA)는 Kubernetes 애플리케이션이 AWS 리소스에 접근하는 하나의 방식을 이야기합니다. 서비스를 운영하다보면 Kubernetes의 애플리케이션(일종의 pod)이 AWS의 리소스에 접근하는 경우가 많습니다. 특히 RDS와 같이 DB자원에 접근하거나 때로는 S3나 EFS와 같은 스토리지 혹은 Pod를 통해서 서버를 통제하는 등 다양한 일을 수행하는 경우가 생기게됩니다.
IRSA의 작동방식
IRSA는 기존의 EC2 인스턴스의 profile이 자격 증명을 제공하는 방식과 유사하게 애플리케이션(pod)에 자격증명을 부여하는 방식입니다. 이를 위해서 IAM Role을 Kubernetes의 Service Account와 연동하고 pod가 해당 Service Account를 사용하도록 적용합니다.
실습소개
이 실습을 통해서 왜 우리는 IRSA를 사용해야하는지 알아봅시다.
1. carts 서비스의 ConfigMap을 수정해, 실제 AWS DynamoDB테이블을 사용하도록 변경합니다.
carts-7c95cd549d-bp4nx라는 이름의 pod는 장바구니용 애플리케이션 입니다.
이 애플리케이션 pod는 carts-dynamodb-68bd8f6f6d-5zw6m라는 DynamoDB pod가 DB역할을 하고 있습니다.
kubectl -n carts get pod

컴포넌트를 확인해 봅니다. ENV를 통해 확인해보면 ENDPOINT가 http://carts-dynamodb:8000로 설정된 것을 확인할 수 있습니다.
kubectl -n carts exec deployment/carts -- env | grep CARTS_DYNAMODB_ENDPOINT

2. DynamoDB 연동하기
일단 carts의 configmap을 통해서 설정정보를 확인해보겠습니다.
kubectl -n carts get -o yaml cm carts

AWS ACCESS KEY와 SECRET KEY를 Configmap에 그대로 사용하고 있는데 이것은 보안적으로도 좋지않으며, 요구사항에 따라서 기존 pod에 있는 DynamoDB를 AWS의 DynamoDB 서비스로 이관하고자 합니다.
apiVersion: v1
data:
AWS_ACCESS_KEY_ID: key
AWS_SECRET_ACCESS_KEY: secret
CARTS_DYNAMODB_CREATETABLE: true
CARTS_DYNAMODB_ENDPOINT: http://carts-dynamodb:8000
CARTS_DYNAMODB_TABLENAME: Items
kind: ConfigMap
metadata:
name: carts
namespace: carts
따라서 다음과 같이 모든 내용을 제거하고 새로운 configmap을 설정합니다.
kubectl -n carts edit cm carts
apiVersion: v1
data:
CARTS_DYNAMODB_TABLENAME: eks-workshop-carts
kind: ConfigMap
metadata:
labels:
app: carts
name: carts
namespace: carts
ConfigMap 적용을 위해서 deployment를 재시작합니다.
kubectl rollout restart -n carts deployment/carts
상태를 확인해보면 계속해서 pod가 문제상태입니다.

Waiting for deployment "carts" rollout to finish: 1 old replicas are pending termination...
error: timed out waiting for the condition
이유가 뭘까요?
일단 DynamoDB 접근에 대한 인증정보를 모두 제거했기 때문에 권한이 없습니다. DynamoDB에 직접 접근하려면 IAM 권한이 필요한데 현재는 해당 pod는 접근권한이 없습니다.
3. Pod IAM 문제 이해하기
문제를 명확하게 확인하기 위해 pod 로그를 살펴봅시다.
LATEST_POD=$(kubectl get pods -n carts --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1:].metadata.name}')
kubectl logs -n carts -p $LATEST_POD
다음과 같이 DynamoDB에 대한 access가 없음을 확인할 수 있습니다.

***************************
APPLICATION FAILED TO START
***************************
Description:
An error occurred when accessing Amazon DynamoDB:
Cannot do operations on a non-existent table (Service: DynamoDb, Status Code: 400, Request ID: 6e5f1f88-cfdb-479b-a59e-f7c6e662fa6c)
Action:
Check that the DynamoDB table has been created and your IAM credentials are configured with the appropriate access.
기본적으로 Pod의 경우 직접적인 IAM 역할이나 정책이 연결되지 않을 경우 Pod가 실행 중인 EC2 인스턴스에 할당된 인스턴스 프로파일에 연결된 IAM 역할을 사용합니다. 따라서 EC2 워커노드에서는 DynamoDB에 대한 접근 허용이 없기 때문에 접근이 불가능합니다.
따라서 EC2의 Profile Role에 권한을 추가하거나 IRSA를 적용해야합니다. 그런데 EC2에 적용하는 순간 모든 pod가 DynamoDB에 접근 가능한 상태가 되어버립니다. 따라서 Pod에 제한적으로 주기 위해 IRSA를 적용해 봅시다.
4. IRSA 적용하기
이제 실제로 IRSA를 적용하겠습니다. IRSA를 적용하기에 앞서 OIDC 공급자 설정을 마쳐야합니다. 클러스터와 연결된 IAM OIDC Identity Provider가 필요합니다.
OIDC(OpenID Connect)는 아주 쉽게 말해 사용자 인증을 위한 표준 프로토콜입니다. OIDC는 일종의 디지털 신분증이고, 이를 통해 Pod는 AWS 자격증명을 직접 저장하지 않아도 AWS에 접근할 수 있도록 연결됩니다.
작동방식
- 쿠버네티스 Pod가 실행될 때 토큰을 부여받는다.
- Pod는 AWS 서비스를 사용하려고 할 때 이 토큰을 보여준다.
- AWS는 OIDC를 통해 이 토큰을 확인한다.
- Pod에 필요한 AWS 권한을 부여한다.
자세한 인증방식은 악분님이 너무 잘 정리해주셔서 추후에 더 익히고 싶다면 찾아가면 될듯하다.
참고 : https://malwareanalysis.tistory.com/724, https://akku-dev.tistory.com/199
다시 돌아 와서 EKS에서 OIDC와 잘 연결되어있는지 확인한다. 원래 기본적으로 EKS를 생성하면 OIDC가 같이 붙는다.
EKS OIDC 확인
aws iam list-open-id-connect-providers
aws eks describe-cluster --name ${EKS_CLUSTER_NAME} --query 'cluster.identity'

IAM 정책 확인
DynamoDB에 접근이 가능한 IAM Role / Policy를 생성한다. 생성했다면 만들어졌는지 확인하자.
aws iam get-policy-version \
--version-id v1 --policy-arn \
--query 'PolicyVersion.Document' \
arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${EKS_CLUSTER_NAME}-carts-dynamo | jq .

해당 역할 신뢰관계 확인
해당 역할이 OIDC를 신뢰관계로 가지고 있어야 접근할 수 있으므로 신뢰관계까지 확인한다.
aws iam get-role \
--query 'Role.AssumeRolePolicyDocument' \
--role-name ${EKS_CLUSTER_NAME}-carts-dynamo | jq .

Service Account 설정하기
이제 carts라는 이름의 Pod에 연결된 SA를 설정한다. SA에서는 annotation을 통해서 AWS의 역할과 연동합니다.
annotation에는 다음과 같은 양식으로 작성합니다.
Annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::1234567890:role/eks-workshop-carts-dynamo
다음 명령어를 통해서 sa에 annotation을 추가합니다.
kubectl edit sa -n carts carts
따라서 실제 다음과 같이 설정된다.
# echo $CARTS_IAM_ROLE
arn:aws:iam::160889332534:role/eks-workshop-carts-dynamo
# sa 설정
apiVersion: v1
kind: ServiceAccount
metadata:
name: carts
namespace: carts
annotations:
eks.amazonaws.com/role-arn: ${CARTS_IAM_ROLE}

변경사항을 적용하기 위해 deployment를 재시작합니다.
kubectl rollout restart -n carts deployment/carts
5. DynamoDB 접근 확인하기
이제 pod에서 실제 DynamoDB 접근이 가능한지 확인해봅시다.
LB_HOSTNAME=$(kubectl -n ui get service ui-nlb -o jsonpath='{.status.loadBalancer.ingress[*].hostname}{"\n"}')
echo "http://$LB_HOSTNAME"

쇼핑몰의 cart부분이 잘 작동되는것을 확인할 수 있습니다.
6. IRSA 동작확인
새로운 carts pod에서 환경 변수를 확인해봅시다.
kubectl -n carts exec deployment/carts -- env | grep AWS
확인해보면 다음과 같습니다. 이 환경 변수는 ConfigMap이나 Depolyment에서 설정한게 아니고 IRSA가 자동으로 설정한 것입니다.ㅣ 이를 통해 AWS SDK가 AWS STS 서비스에서 임시 자격 증명을 얻어 활동하게 됩니다.

AWS_STS_REGIONAL_ENDPOINTS=regional
AWS_DEFAULT_REGION=us-west-2
AWS_REGION=us-west-2
AWS_ROLE_ARN=arn:aws:iam::1234567890:role/eks-workshop-carts-dynamo
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
여기서 우리가 염두할 만한 것은
- AWS_REGION은 자동으로 EKS 클러스터와 동일하게 잡힙니다.
- AWS_STS_REGION_ENDPOINTS가 구성되어 us-east-1에 과도한 부담을 주지 않습니다.
- AWS_ROLE_ARN은 앞서 annotation정보와 동일하게 잡힙니다.
- AWS_WEB_IDENTITY_TOKEN_FILE을 받아 해당 위치에 저장합니다. 실제로 해당 위치에서 cat을 해보면 토큰정보가 보입니다.

이상으로 해당 워크샵을 통해 IRSA를 설정하는 실습을 진행해 보았습니다.
다음은 EKS Pod Identity를 활용해 IRSA와 무엇이 다른지 확인해봅시다.
https://devops-james.tistory.com/511
[EKS Workshop] EKS Pod Identity
EKS Pod Identity 개요EKS Pod Identity는 Amazon EC2 Instance Profile이 인스턴스에 자격 증명을 제공하는 방식과 유사하게 애플리케이션에 대한 자격 증명을 관리할 수 있는 기능을 제공합니다. AWS 자격 증명
devops-james.tistory.com