CloudNet@ Team Study/EKS Workshop 4th Cohort

Setting up EKS credentials for DevOps Engineers

"Everything about infra" 2026. 4. 10. 03:15
포스팅은 CloudNet@팀 서종호(Gasida)님이 진행하시는
AWS EKS Workshop Study 내용을 참고하여 작성합니다.

 

안녕하세요!

오늘은 신입 DevOps 엔지니어를 위하여

eks 자격 증명 설정에 대한 실습을 진행할 예정입니다.

 

전에 작성하였던 "EKS Identity and Access Management" 글 내용이

이어서 진행되므로, 참고 바랍니다.

 

 

 

01. 사전 준비 내용

📌 testuser 사용자 생성

# 1. testuser 생성
aws iam create-user --user-name testuser
{
    "User": {
        "Path": "/",
        "UserName": "testuser",
        "UserId": "AIDARLPFODNRYW7DMK3DN",
        "Arn": "arn:aws:iam::093359840099:user/testuser",
        "CreateDate": "2026-04-09T15:45:29+00:00"
    }
}

# 2. 액세스 키 발급 (결과에서 AccessKeyId, SecretAccessKey 꼭 저장해둬)
aws iam create-access-key --user-name testuser
{
    "AccessKey": {
        "UserName": "testuser",
        "AccessKeyId": "AKIARLPFODNR3RUKN5HT",
        "Status": "Active",
        "SecretAccessKey": "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",
        "CreateDate": "2026-04-09T15:46:09+00:00"
    }
}

# 3. AdministratorAccess 정책 부여
aws iam attach-user-policy \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
  --user-name testuser

# 4. 현재 내가 누구인지 확인 (admin 계정인지 체크)
aws sts get-caller-identity --query Arn

실습을 위해 testuser를 생성하여 access-key를 발급받는 과정입니다.

실제로 이 access key가 유출되면 권한을 탈취당하여 피해를 입으시니, 잘 보관해두시길 권고드립니다.

 

📌 aws-cli 컨테이너 실행 후 aws iam 자격증명 설정 및 확인

profile 방식으로 로컬 관리자를 격리시키는 방법도 있으나, 해당 실습은 컨테이너로 실행하겠습니다.

먼저 아래 컨테이너를 실행하기 전에 docker에 로그인이 되어 있어야 하므로, 참고 바랍니다.

# aws-cli 컨테이너 실행
docker run -it --name aws-cli --entrypoint /bin/sh amazon/aws-cli
-------------------------------------------------
# testuser 자격증명 설정
aws configure
AWS Access Key ID [None]: AKIARLPFODNR3RUKN5HT
AWS Secret Access Key [None]: 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
Default region name [None]: ap-northeast-2

# get-caller-identity 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::911283464785:user/testuser"

# aws cli 명령 시도
aws s3 ls

아래와 같이 aws-cli에 대한 이미지를 다운받고, 컨테이너 안으로 진입에 성공하였습니다.

처음 s3 정보를 받아오지 못했는데, 자격 증명을 등록하고 다시 s3 정보를 확인하니 에러가 뜨지 않았습니다.

 

📌 testuser kubeconfig 생성 및 kubectl 사용 확인

컨테이너 안에 그대로 진입되어 있는 상태에서 kubeconfig를 생성해줍니다.

CLUSTER_NAME=myeks
aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias testuser
Added new context testuser to /root/.kube/config

# kubeconfig 확인
cat ~/.kube/config

그럼 클러스터의 context 정보와 testuser의 client 정보가 출력이 될 것입니다.

 

📌 kubectl 설치

컨테이너 안에서 kubectl 명령이 가능하도록 아래와 같이 설치해줍니다.

# kubectl 설치
# https://docs.aws.amazon.com/eks/latest/userguide/install-kubectl.html
curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.35.2/2026-02-27/bin/linux/arm64/kubectl  # macOS

install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

kubectl version --client=true

버전 확인이 되었다면 성공입니다 !

 

📌 rbac-tool 설치

# rbac-tool 설치 : https://github.com/alcideio/rbac-tool
yum install tar gzip -y
curl https://raw.githubusercontent.com/alcideio/rbac-tool/master/download.sh | bash

# Shows the subject for the current context with which one authenticates with the cluster
./bin/rbac-tool whoami
Error: Failed to create kubernetes client - the server has asked for the client to provide credentials

클러스터 리소스를 조회해주는 도구입니다.

즉 IAM ARN이 K8S에서 어떤 username/group으로 매핑됐는지 확인하는 도구에요

실습을 용이하게 하기 위해 설치 진행해줍시다!


 

02. kubectl 명령 사용 확인 - 인증

이제 kubeconfig 설정도 마쳤고, kubectl 도구도 설치를 하였으니 node 정보를 출력해볼까요?

kubectl get node -v6

디버깅 레벨을 높여서 출력을 해보겠습니다.

현재 노드 정보를 출력하였는데 오류가 발생하였습니다. 원인이 뭘까요?

status="401 Unauthorized"
message: "the server has asked for the client to provide credentials"

kubectl이 재시도를 반복하여도 여전히 401 에러가 발생하고 있는 상황입니다.

 

해당 로그들을 분석하면 아래와 같습니다:

  1. testuser가 kubectl get node 실행
  2. kubeconfig의 exec plugin이 aws eks get-token 호출
  3. STS presigned URL 기반 토큰 생성
  4. API Server에 Bearer Token + 요청 전달
  5. API Server → aws-iam-authenticator에 TokenReview 요청
  6. aws-iam-authenticator → STS GetCallerIdentity 호출
  7. STS가 응답: { "Arn": "arn:aws:iam::093359840099:user/testuser" }
  8. aws-iam-authenticator가 이 ARN을 Access Entry에서 찾음 → 없음
  9. API Server에 "모르는 사용자" 반환
  10. 401 Unauthorized

여기서 핵심은? 토큰 자체는 유효합니다. 즉, STS도 testuser가 맞다고 확인 응답을 해줬지만

클러스터가 testuser를 모르기 때문에 401 에러가 반환이 된겁니다.

 

정리를 해보자면?

IAM Identity (testuser) ✅ 확인됨
      ↓
Access Entry            ❌ 없음  ← 여기서 막힘
      ↓
K8S username/group      ❌ 매핑 불가
      ↓
RBAC                    ❌ 도달 못함

인증 실패는 아니고, IAM 레벨에서는 확인이 되었지만 K8S 레벨에서는 매핑이 없어서 막힌 것 입니다.

즉, "AWS는 알지만 K8S는 모르는 상태" 입니다.

 

이게 EKS 인증의 특이점입니다. 일반 K8S였으면 kubeconfig에 인증서 넣으면 끝인데,

EKS는 IAM → K8S 매핑이 반드시 필요해요. Access Entry 또는 aws-auth가 그 역할을 하는 것 입니다.

 


 

03. EKS API를 통한 Access 설정

testuser에 AmazonEKSAdminPolicy 정책 부여로 EKS 관리자 수준 권한 설정하는 것이 목표입니다.

aws-auth 보다, 최근 표준인 Access Entry를 통해 진행하도록 하겠습니다.

 

1) access entry 생성

# testuser 의 access entry 생성
export CLUSTER_NAME=myeks
export ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)

aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser
aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq -r .accessEntries[]

아래와 같이 access entry가 생성이 되었습니다.

현재 'kubernetesGroups' 필드가 비어있는데 K8S RBAC group 매핑이 아직 없다는 뜻이고,

아직 Policy를 연동 안해서 정상입니다. 아래에서 진행할게요 !

 

2) AmazonEKSAdminPolicy 연동

aws eks associate-access-policy --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSAdminPolicy --access-scope type=cluster

이 행위가 "testuser가 myeks 클러스터 전체에서 Admin 권한"을 가지게 하도록 설정하는 행위에요.

아까 access entry를 생성한 것과 비교를 해보자면:

create-access-entry 했을 때:
→ "testuser라는 사람이 클러스터에 존재한다" 등록만 한 것
→ 아직 아무 권한 없음

associate-access-policy 한 지금:
→ "testuser에게 Admin 권한을 부여한다" 연결된 것
→ 이제 실제로 뭔가 할 수 있음

 

그래서 실제로 aws-iam-authenticator에서 STS에서 응답받은 ARN을 실제로 찾을 수 있게 설정하였고,

K8S username/group을 맵핑할 수 있게 되서 API Server에 testuser를 반환해줄 수 있게 되었습니다.

IAM Identity (testuser)
      ↓
Access Entry             ← create-access-entry로 등록
      ↓
K8S username/group 확정
      ↓
RBAC 인가                ← AmazonEKSAdminPolicy가 여기서 권한 부여
      ↓
클러스터 접근 허용

 

3) 확인

aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser | jq
aws eks describe-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser | jq

현재 testuser가 AmazonEKSAdminPolicy 연동된 것을 확인하실 수 있습니다.

이제 K8S에서 username: "arn:aws:iam::093359840099:user/testuser" 이 ARN을 인식할 수 있습니다 !

 


 

04. kubectl 명령 최종 사용 확인 - 인가

다시 kubectl get node 명령을 해보면 아래와 같이 출력이 조금 다르게 나오네요.

처음 kubectl 명령을 입력하였을 때는 401 에러로, 인증 관련된 부분의 이슈였습니다.

하지만 지금은 403 포비든 에러가 발생하고 있네요.

 

해당 로그를 분석해보면 아래와 같습니다:

  1. testuser가 kubectl get node 실행
  2. STS presigned URL 토큰 생성
  3. API Server에 토큰 전달
  4. API Server → aws-iam-authenticator에 TokenReview 요청
  5. aws-iam-authenticator → STS GetCallerIdentity 호출
  6. STS 응답: "이 ARN은 testuser 맞아"
  7. aws-iam-authenticator → Access Entry에서 ARN 검색
  8. 찾음! username: "arn:aws:iam::...user/testuser" → 인증 완료
  9. RBAC에서 인가(AuthZ) 체크
  10. "이 username이 nodes를 list할 수 있어?" → AmazonEKSAdminPolicy에 nodes 권한 없음
  11. 403 Forbidden Error 반환

즉, 인증은 완료 되었지만 해당 testuser가 node를 list할 수 있는 권한이 있는지 없는지

체크가 되지 않으므로 'kubectl get nodes' 명령에 실패하였음을 알 수 있습니다.

 

그런데 왜 node를 조회할 땐 403 Error였는데 Pods 조회는 가능할까요?

해당 권한을 살펴보면 apps, autoscaling, batch, authorization.k8s.io 그룹의 리소스들이 있는데

node에 대한 리소스가 없습니다. 즉, 위 RBAC에 명시된 리소스와 권한만 사용이 가능하죠.

 

AWS가 이 표대로 ClusterRole을 미리 만들어 놓은 것이 AmazonEKSAdminPolicy 인거에요.

rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch"]

예시로 위와 같이 들 수 있고, 저희가 직접 AmazonEKSAdminPolicy를 가져다 쓰므로 RBAC를 짤 필요X

 

그렇다면 EKS에서 제공하는 관리형 정책이 아닌, 직접 커스터마이징 해서 RBAC를 사용해볼까요?

 


 

05. RBAC 커스터마이징 후 적용

현재 Access Entry에 AmazonEKSAdminPolicy 관리형 정책이 적용이 되어 있어서,

삭제 후에 커스터마이징 한 RBAC 정책을 적용해보도록 하겠습니다.

 

📌  testuser에 Access Entry 제거

컨테이너 환경에서 testuser에 대한 기존 access entry를 제거해줍시다.

aws eks delete-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser
aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq -r .accessEntries[]

 

ClusterRole & ClusterRoleBinding 생성

이 RBAC를 생성하려면 관리자 권한이 필요하므로, 컨테이너 환경에서 나와서 로컬(관리자 권한)에서 진행.

 

1) ClusterRole 생성

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-viewer-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["list", "get", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-admin-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["*"]
EOF

kubectl get clusterrole | grep ^pod

pod-viewer-role라는 이름으로 pod에 대한 읽기 전용 role을 생성하고,

pod-admin-role라는 이름으로 pod에 대한 모든 작업을 허용해주는 role을 생성하였습니다.

이렇게 clusterrole을 생성하였으면, 그룹별로 바인딩을 시켜줘서 나중에 testuser를 이 그룹에 추가하면 돼요.

 

2) ClusterRoleBinding 생성

kubectl create clusterrolebinding viewer-role-binding --clusterrole=pod-viewer-role --group=pod-viewer
kubectl create clusterrolebinding admin-role-binding  --clusterrole=pod-admin-role  --group=pod-admin
kubectl get clusterrolebinding | grep -E 'admin-role|viewer-role'

아까 설치한 rbac-tool로 RBAC 권한을 쉽게 확인하실 수 있습니다.

직관적으로 롤, 바인딩, 그룹별로 권한을 쉽게 파악할 수 있으나 각 컬럼의 의미는 아래를 참고해주세요.

G = get
L = list
W = watch
C = create
U = update
P = patch
D = delete
DC = deletecollection

 

Access Entry 설정 : pod-viewer Group

다시 컨테이너에 접근하시어 access entry를 설정해줍시다.

docker run -it --name aws-cli --entrypoint /bin/sh amazon/aws-cli

* 혹시 컨테이너 접근이 안되셨다면 docker 프로세스를 확인하시어 start 시켜주시면 될 것 같습니다.

더보기

아마 컨테이너를 재시작했으므로 환경변수가 날라갔을 것입니다.

사전 준비 챕터에서 진행하였던 환경변수 셋팅을 다시 해주시면 될 것 같습니다.

 

CLUSTER_NAME=myeks

export ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)

 

1) Access Entry 설정 (pod-viewer 그룹으로 바인딩)

aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser --kubernetes-group pod-viewer

첫번째 Access Entry를 생성했을 때와 다르게 kubernetesGroups 필드가 "pod-viewer"로 되어있네요.

아까 만든 ClusterRoleBinding이 여기서 연결되는 것입니다 !

 

2) Access Entry 확인

아까와 달라진 점은 아래와 같습니다.

방식 1 (아까):
associatedAccessPolicies: [AmazonEKSAdminPolicy]
kubernetesGroups: []
→ AWS가 권한 관리

방식 2 (지금):
associatedAccessPolicies: []
kubernetesGroups: ["pod-viewer"]
→ K8S RBAC이 권한 관리

즉, AWS 관리형 정책을 사용하지 않고 커스텀 RBAC 그룹인 "pod-viewer" 연결을 확인할 수 있습니다.

 

3) kubectl 사용 확인

ClusterRole을 생성할 당시, pod에 대한 list, get, watch 권한만 부여하였습니다.

 

그래서 node를 조회하는 명령은 실패하고, pod를 조회하는 명령은 성공했네요.

추가적으로 delete 권한은 없으므로 pod를 delete하는 명령에 대해 "no" 출력을 확인할 수 있습니다.

 

Access Entry 업데이트 : pod-admin Group

이번에는 pod-admin Group으로 업데이트 하여 다시 kubectl 명령을 사용해보도록 하겠습니다.

 

1) Access Entry 업데이트 (pod-admin 그룹으로 바인딩)

aws eks update-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/testuser --kubernetes-group pod-admin | jq -r .accessEntry

아래와 같이 kubernetesGroups가 "pod-admin"으로 업데이트된 것을 확인하실 수 있습니다.

 

2) kubectl 명령 사용 확인

pod-viewer 그룹과 다르게 pod를 create, delete 할 수 있습니다.

 

이렇게 "Access Entry의 kubernetesGroups만 바꿨는데 pods에 대한 권한 수준이 달라지네요"

이게 그룹 기반 RBAC의 핵심이고, Access Entry에서 그룹만 바꾸면 권한이 자동으로 부여됩니다.

 


 

06. AWS Access Key → Role 기반 인증 전환 테스트

지금까지는 사실 Access Key로 자격증명을 받아와서 테스트를 진행하였습니다.

Access Key는 만료 기간이 따로 없고 장기 자격 증명 방식이므로, 보안에 취약합니다.

 

Role 기반 인증 방식으로 전환하게 된다면, 아래와 같은 기대효과를 볼 수 있습니다.

Access Key 방식:
- 키가 유출되면 영구적으로 위험
- 주기적으로 직접 교체해야 함
- 어디에 저장됐는지 추적 어려움

Role 기반:
- STS가 임시 토큰 발급 (기본 1시간)
- 만료되면 자동으로 무효화
- 재발급할 때마다 새 토큰
- 최소 권한 원칙 적용 쉬움

그렇다면 Role 기반 인증 방식으로 전환하기 위해서 아래의 단계를 진행해주세요!

 

Step1. IAM Role 생성

testuser가 AssumeRole 할 수 있는 Role 생성할 것입니다 (로컬 환경에서 진행)

cat <<EOF > trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::${ACCOUNT_ID}:user/testuser"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

aws iam create-role \
  --role-name eks-testuser-role \
  --assume-role-policy-document file://trust-policy.json

# 확인
aws iam get-role --role-name eks-testuser-role | jq .Role.Arn

"testuser가 이 Role을 Assume할 수 있다" 는 신뢰 정책을 만든 행위 입니다.

지금은 아무 권한이 없는 빈 IAM Role 이고, Access Entry에 Role을 등록해야합니다.

 

Step2. Access Entry에 Role ARN 등록

Access Entry를 생성해줍시다.

aws eks create-access-entry \
  --cluster-name myeks \
  --principal-arn arn:aws:iam::093359840099:role/eks-testuser-role \
  --kubernetes-group pod-viewer

그러면 아래와 같이 "pod-viewer"가 Role을 Assume하여 사용하게 됩니다.

여기서 username 필드에 {{SessionName}} 부분이 핵심인데요,

IAM User  → username이 고정됨
IAM Role  → AssumeRole할 때마다 SessionName이 달라짐
           → 누가 언제 Assume했는지 추적 가능
           → CloudTrail에서 세션별로 감사 가능

IAM User로 Access Entry를 구성하는 것 보다 Role을 Assume 하여 구성하면 위와 같은 장점이 있습니다.

 

Step3. 컨테이너에서 Role Assume

docker container가 아마도 종료가 되어있을 텐데, 다시 시작하시어 접근하시면 됩니다.

 

접근하셨으면 이제 Role을 Assume 해볼까요?

aws sts assume-role \
  --role-arn arn:aws:iam::093359840099:role/eks-testuser-role \
  --role-session-name testuser-session

어슘을 한다면 아래와 같이 또 임시 자격증명 키를 발급해줍니다.

STS가 AccessKeyId, SecretAccessKey, SessionToken 이렇게 총 3개를 임시 발급 해주네요.

default로 한시간 후에 만료가 되는 임시 자격 증명입니다.

 

📌  환경 변수 방식으로 자격 증명 설정

'aws configure'로 자격 증명을 설정하게 되면 SESSION_TOKEN을 설정하지 못합니다.

export AWS_ACCESS_KEY_ID=ASIARLPF0DNRWQWL6GFK
export AWS_SECRET_ACCESS_KEY=lTPt8DoyJ+MwSb2AtHLswLSK7eevXvD8pNMpu0Jo
export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjEFIaDmFwLW5vcnRoZWFzdC0yIkYwRAIgM7DEkoGYTclhv...(전체)

# 확인
aws sts get-caller-identity

자격 증명 설정이 완료되면 아래와 같이 testuser-session으로 ARN이 작성됩니다.

지금 컨테이너는 Role로 Assume된 상태라 EKS API 권한이 없으니까 로컬 터미널에서

eks-testuser-role Access Entry를 확인해줍시다.

 

Step4. Access Entry & RBAC 확인

role이 testuser-session으로 연결된 것을 확인할 수 있습니다.

Access Entry username 템플릿:
assumed-role/eks-testuser-role/{{SessionName}}
                                ↓
실제 접속 시:
assumed-role/eks-testuser-role/testuser-session

그리고 저희가 아까 생성한 "pod-viewer"의 RBAC를 가지고 있는 것도 확인하였습니다.

 

이제, pod-viewer 권한으로 써 create와 delete가 가능한지 볼까요?

create 권한이 없으므로, 403 포비든 에러가 발생한 것을 확인하실 수 있습니다 (인가에서 거절됌)

 

다시한번 짚고 넘어가자면, Access Entry를 생성 후 바인딩 시에

Access Entry 생성 시:
--kubernetes-group pod-viewer
    ↓
ClusterRoleBinding (viewer-role-binding)
    ↓
ClusterRole (pod-viewer-role)
    ↓
verbs: ["list", "get", "watch"] 만 허용
    ↓
create, delete → 403

이 과정을 거치고 현재 role group이 "pod-viewer-role"이므로 권한 부족으로 인해 Error !

 

Role Assume 방식의 한계

현재 방식대로 Role Assume 방식으로 권한을 붙혀서 사용하게 된다면,

1시간이 지나면 토큰이 만료되어서 아무 작업도 할 수 없게 됩니다.

 

그래서 나온게 IRSA (IAM Roles for Service Accounts) 입니다.

Pods(SA) 단위로 권한을 부여하고 각 Pod마다 다른 IAM Role을 Assume 하게 합니다.

 

IRSA 토큰 자동 로테이션 흐름은 아래와 같이 동작합니다.

Pod 기동
    ↓
kubelet이 Projected Volume에
IRSA용 토큰 자동 마운트
    ↓
토큰 만료 전 (80% 시점)
kubelet이 자동으로 새 토큰 발급
    ↓
Pod 재시작 없이 투명하게 교체

 


 

긴 글 읽어주셔서 감사합니다.

 

다음으로 다뤄볼 주제는 IRSA와 Pod Identity에 대해 다뤄볼 예정입니다.

(방금 위에서 말씀드렸던 자격 증명 자동 주입 + Pod 최소 단위 권한 적용)이 목표입니다 !