| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- ipamd
- serviceaccount
- externaldns
- Node group
- CoreDNS
- eksctl
- eks upgrade
- EmptyDir
- gateway api
- aws vpc cni
- k8s scheduler
- 쿠버네티스 네트워크
- kubernetes networking
- hashicorp
- cni binary
- EKS
- auto mode
- Instance Store
- HostPath
- Terraform
- EKS vLLM
- EKS Architecture
- ClusterIP
- k8s authentication
- kube-proxy
- nodeport
- aws-node
- Fargate
- pv/pvc
- soci
- Today
- Total
ksc0204 님의 블로그
AEWS 4기 4주차(3) - EKS 인증/인가 실습, IRSA, Pod-identity 본문
before start..
주관적인 해석이 포함되어 있어 사실과 다르거나 오류가 있을 수 있으니 참고용으로만 읽어주시기 바랍니다.
환경 구성(개발 및 운영 네임스페이스 및 SA 구성)
# 네임스페이스(Namespace, NS) 생성 및 확인
kubectl create namespace dev-team
kubectl create ns infra-team
# 네임스페이스 확인
kubectl get ns
# 네임스페이스에 각각 서비스 어카운트 생성 : serviceaccounts 약자(=sa)
kubectl create sa dev-k8s -n dev-team
kubectl create sa infra-k8s -n infra-team
# 서비스 어카운트 정보 확인
kubectl get sa -n dev-team
kubectl get sa dev-k8s -n dev-team -o yaml
kubectl get sa -n infra-team
kubectl get sa infra-k8s -n infra-team -o yaml
(참고)Service Account 중 default는 네임스페이스를 생성하면 기본으로 생성됩니다.

각 네임스페이스 Pod 생성(SA를 곁들인..)
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: dev-kubectl
namespace: dev-team
spec:
serviceAccountName: dev-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: infra-kubectl
namespace: infra-team
spec:
serviceAccountName: infra-k8s
containers:
- name: kubectl-pod
image: bitnami/kubectl
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
kubectl get pod -A
# dev 확인
kubectl get pod -o dev-kubectl -n dev-team -o yaml
# infra 확인
kubectl get pod -o infra-kubectl -n infra-team -o yaml
# 파드에 기본 적용되는 서비스 어카운트(토큰) 정보 확인
kubectl exec -it dev-kubectl -n dev-team -- ls /run/secrets/kubernetes.io/serviceaccount
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/token
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt
# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
# 권한 테스트
k1 get pods # kubectl exec -it dev-kubectl -n dev-team -- kubectl get pods 와 동일한 실행 명령이다!
k1 run nginx --image nginx:1.20-alpine
k1 get pods -n kube-system
k2 get pods # kubectl exec -it infra-kubectl -n infra-team -- kubectl get pods 와 동일한 실행 명령이다!
k2 run nginx --image nginx:1.20-alpine
k2 get pods -n kube-system
# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
no



dev-kubectl Pod에 적용된 SA 정보 확인 시 ca.crt, namespace 정보, token 값을 확인할 수 있습니다.

Alias 설정 이후 dev-kubectl Pod에서 전체 Pod를 조회해보았지만 해당 SA에서 할당된 Role이 없기 때문에 조회가 되지 않습니다.

아래에서 api-resources 리스트를 확인하고 알맞은 권한을 할당할 수 있습니다.
kubectl api-resources
kubectl api-resources -o wide
# api-group으로 목록 조회
kubectl api-resources --api-group=""
kubectl api-resources --api-group="apps"
kubectl api-resources --api-group=metrics.k8s.io
kubectl api-resources --api-group=admissionregistration.k8s.io
kubectl api-resources --api-group=rbac.authorization.k8s.io
kubectl api-resources --api-group=apiextensions.k8s.io



Role 생성
# dev SA 매핑용 Role
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-dev-team
namespace: dev-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
# infra SA 매핑용 Role
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-infra-team
namespace: infra-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
# 롤 확인
kubectl get roles -n dev-team
kubectl get roles -n infra-team
kubectl get roles -n dev-team -o yaml
kubectl describe roles role-dev-team -n dev-team

RoleBinding(SA ↔ Role 연동)
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-dev-team
namespace: dev-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-dev-team
subjects:
- kind: ServiceAccount
name: dev-k8s
namespace: dev-team
EOF
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: roleB-infra-team
namespace: infra-team
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-infra-team
subjects:
- kind: ServiceAccount
name: infra-k8s
namespace: infra-team
EOF


Pod 생성 및 재조회 테스트
아래 이미지를 확인 시 dev-team 네임스페이스에 Pod는 정상적으로 조회되는 것을 확인할 수 있습니다.

다만, 아래 이미지에서 kube-system 네임스페이스 내에 리소스와 다른 노드 및 정보에 대해서는 인가된 SA가 아니기 때문에 조회가 되지 않는 것을 확인할 수 있습니다.

추가로, 노드 조회 시 debug 모드를 통해서 확인했을 때 403 Forbidden에 대한 응답 값을 보내주어 인가되지 않은 사용자라는걸 확인할 수 있습니다.

EKS Pod - IRSA(IAM Role Service Account)
EKS에서 Pod가 AWS 서비스를 사용하기 위해서 EKS 환경에서 파드(Pod)에 IRSA(IAM Roles for Service Accounts)를 할당하는 가장 핵심적인 이유는 AWS 리소스(S3, DynamoDB 등)에 접근하는 권한을 파드(Pod) 단위로 최소화하고 완벽하게 격리하기 위해서입니다. 이로 인해, 몇가지 모범 사례가 있습니다.
- 최소 권한 원칙
- 서비스 계정에 IAM 역할을 사용하는 기능을 활용하면 더 이상 노드의 Pod가 AWS API를 호출할 수 있도록 노드 IAM 역할에 확장 권한을 부여할 필요가 없습니다. IAM 권한을 서비스 계정으로 제한하면 해당 서비스 계정을 사용하는 Pod만 해당 권한에 접근할 수 있습니다. - 자격 증명 격리
- 컨테이너는 자신이 속한 서비스 계정과 연결된 IAM 역할에 대한 자격 증명만 가져올 수 있습니다. 컨테이너는 다른 파드에 속한 다른 컨테이너를 위한 자격 증명에는 절대 접근할 수 없습니다. - 감사 가능성
- AWS CloudTrail을 통해 액세스 및 이벤트 로깅이 가능하므로 사후 감사를 보장할 수 있습니다.
EKS IRSA 동작 과정

파드 생성 - 서비스어카운트 X
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test1
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
args: ['s3', 'ls']
restartPolicy: Never
automountServiceAccountToken: false
terminationGracePeriodSeconds: 0
EOF
서비스 어카운트 없이 S3 버킷을 조회하는 파드를 생성할 시 에러가 발생하는 것을 확인할 수 있습니다. (automountServiceAccountToken: false - 이 파드를 생성할 때 서비스 어카운트의 토큰을 자동으로 마운트 하지 않도록 설정 )

로그 확인 시 s3:ListAllMyBuckets에 대한 action 권한이 없는 것을 확인할 수 있습니다.

파드 생성 - 쿠버네티스 API 접근용 Service Account 첫번째 토큰 확인
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test2
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
- Kubernetes 1.12에서 ProjectedServiceAccountToken이라는새로운 기능이 도입되었습니다.
- 이 기능을 통해 Kubernetes의 TokenRequest API에서 발급된 OIDC JWT 토큰을 Pod에 프로젝션 볼륨으로 마운트할 수 있습니다.
- 관련 서비스 계정 토큰 볼륨 프로젝션 플래그는 EKS 클러스터에서 기본적으로 활성화되어 있습니다.
- 따라서 이전 이미지에서 언급된 JWT 토큰 대신 OIDC JWT 서비스 계정 토큰이 각 Pod에 프로젝션됩니다.

해당 Pod 내부에서도 확인할 수 있듯이 default 서비스 어카운트가 Pod에서 사용되고 있습니다.
kubectl get sa default
kubectl exec -it eks-iam-test2 -- ls -al /var/run/secrets/kubernetes.io/serviceaccount
kubectl exec -it eks-iam-test2 -- ls -al /var/run/secrets/kubernetes.io/serviceaccount/..data
kubectl exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ;echo
하지만, 파드 내부에서 s3 버킷 리스트를 조회하지만 여전히 권한이 없는 것을 확인할 수 있습니다.

현재, 사용중인 SA에 Token 값을 jwt.io URL에서 확인하여 주요 내용에 대해서 분석한 내용입니다.

[ 페이로드 주요 설정 확인 ]
| "aud": "https://kubernetes.default.svc | k8s api의 cluster ip 서비스 주소 도메인명 (API 서버에 접근은 가능하지만 이외 서비스는 불가능) |
| "exp": 1776057622 | 토큰 만료 시간 |
| "iat" : 1775971222 | 토큰 발급 시간 |
| "iss" : "https://oidc.eks.ap-northeast-2.amazonaws.com/id/159464F24B0A178FED9F6528990CB73A" | 토큰 발급자(OIDC 제공업체) |
| "warnafter" : 1775974829 | kubernetes 내부 로직에서 사용 - 이 시간 이후에는 토큰 갱신 권장 |
| "sub": "system.serviceaccount:default:default | 토큰의 소유자. default 네임스페이스의 default SA |
- 해당 defulat 서비스어카운트에서 발급 받은 OIDC 토큰을 기반으로 AWS API 인증에 사용할 수 있는 토큰 생성 가능
- AWS API에서 사용할 두번째 토큰을 Kubernetes Pod에 주입하는 추가 구성 요소가 필요합니다.
- K8s는 웹훅 유효성 검사 및 변경을 지원하고 AWS는 ID 웹훅을 제공한다.(해당 ID 웹훅은 EKS 클러스터에 사전 설치되어 있음)
- Pod 생성 API 호출을 수신하고 Pod에 추가 토큰을 주입할 수 있습니다. 이 웹훅은 자체 관리형 EKS에도 설치 가능
- SA 외에 추가로 발급되는 이 토큰을 통해 IRSA 기능을 사용할 수 잇습니다.
파드 생성 - IRSA 설정(aud : sts.amazonaws.com)
# 클러스터에 기존 IAM OIDC 공급자가 있는지 확인합니다. 클러스터의 OIDC 공급자 ID를 검색하여 변수에 저장합니다.
oidc_id=$(aws eks describe-cluster --name myeks --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
echo $oidc_id
# 클러스터 ID를 가진 IAM OIDC 공급자가 계정에 이미 있는지 확인합니다.
aws iam list-open-id-connect-providers | grep $oidc_id | cut -d "/" -f4
IDP=$(aws eks describe-cluster --name myeks --query cluster.identity.oidc.issuer --output text)
curl -s $IDP/.well-known/openid-configuration | jq -r '.'
curl -s $IDP/keys | jq -r '.'
curl -s https://oidc.eks.ap-northeast-2.amazonaws.com/id/D101CFA79EB3A774D39A52E2425B034F/.well-known/openid-configuration | jq .
# Discovery 엔드포인트 호출 (.well-known) : OIDC issuer 주소 뒤에 /.well-known/openid-configuration을 붙이면 됩
curl -s https://oidc.eks.ap-northeast-2.amazonaws.com/id/032357E88E266F4AE7C2E8CF6F5EFEB0/.well-known/openid-configuration | jq .
# JWKS(JSON Web Key Set) 호출 : 위에서 찾은 jwks_uri (보통 끝에 /keys가 붙음)로 다시 요청을 보냅니다.
## EKS가 발행한 JWT 토큰을 검증할 때 사용하는 공개키 세트
curl -s https://oidc.eks.ap-northeast-2.amazonaws.com/id/032357E88E266F4AE7C2E8CF6F5EFEB0/keys | jq .


위 과정이 중요한 이유
- AWS STS는 생성한 JWT 토큰의 서명이 유효한지 확인하기 위해 위 과정 처리
- Pod에서 보낸 JWT 토큰 수신
- issuer 확인 : 토큰 내부의 iss 필드를 보고 위 URL로 접속
- 공개키 획득 : /keys 경로에서 현재 유효한 공개키(JWKS)를 가져옴.
- 서명 검증 : 가져온 공개키와 토큰의 서명(Signature)을 대조하여 변조 여부 확인
OIDC 공급 확인

IAM Policy 생성
curl -o aws_lb_controller_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json
cat aws_lb_controller_policy.json | jq
# iam policy 생성
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://aws_lb_controller_policy.json
# 확인
ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy | jq

iamserviceacocunt 설정
CLUSTER_NAME=myeks
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller
eksctl create iamserviceaccount \
--cluster=$CLUSTER_NAME \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
--override-existing-serviceaccounts \
--approve
# 확인 : 아래 출력되는 Role ARN을 관리콘솔에서 확인!
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
# k8s 에 SA 확인
# Inspecting the newly created Kubernetes Service Account, we can see the role we want it to assume in our pod.
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml

AWS LBC 설치(helm)
# Helm Chart Repository 추가
helm repo add eks https://aws.github.io/eks-charts
helm repo update
# Helm Chart - AWS Load Balancer Controller 설치
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --version 3.1.0 \
--set clusterName=$CLUSTER_NAME \
--set serviceAccount.name=aws-load-balancer-controller \
--set serviceAccount.create=false \
--set enableCertManager=true
# 확인
helm list -n kube-system
kubectl get pod -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller
kubectl logs -n kube-system deployment/aws-load-balancer-controller -f
# 인증서 관련 정보 확인
## LBC는 단순히 AWS ALB/NLB를 만들기만 하는 것이 아니라, 사용자가 작성한 Ingress나 Service 설정이 올바른지 검토하고 수정하는 역할도 수행
## 이를 위해 API 서버는 LBC의 9443 포트로 HTTPS 요청을 보내는데, 이 통신을 위해 aws-load-balancer-tls 인증서가 필요함.
## 이때 해당 인증서의 만료 전 Cert-manager 이 자동 갱신 처리해줌
## 발급된 인증서 데이터를 aws-load-balancer-tls라는 이름의 Secret에 저장
kubectl get certificaterequests,issuers,certificates -n kube-system
kubectl get secret -n kube-system
kubectl get secret aws-load-balancer-tls -n kube-system -o yaml
# cert-manager 류의 인증서 자동 갱신 미사용 시?
## LBC의 웹훅 인증서는 보통 유효기간이 짧습니다. cert-manager가 없으면 인증서가 만료되는 순간 ,
# kubectl apply 명령이 모두 에러(Internal error: failed calling webhook...)가 나며 클러스터 관리가 불가능해집니다.
# AWS Load Balancer Controller 확인
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml
kubectl rolesum -n kube-system aws-load-balancer-controller
kubectl get deployment -n kube-system aws-load-balancer-controller
kubectl describe deploy -n kube-system aws-load-balancer-controller
kubectl describe deploy -n kube-system aws-load-balancer-controller | grep 'Service Account'

아래에서 aws-load-balancer-controller에 Mount된 볼륨을 확인 시 kubernetes 내부용도인 /var/run/secrets/kubernetes.io/serviceaccount와 aws sts와 통신하는 /var/run/secrets/eks.amazonaws.com/serviceaccount로 설정되어 있는 것을 확인할 수 있습니다.
kubectl get pod -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller -o yaml


WEBHOOKS - 갯수 : 해당 컨트롤러는 쿠버네티스와 AWS LB를 연결하기 위해 생각보다 많은 리소스에 대한 개입이 필요

LBC - kube-ops-view 설치
# kube-ops-view : NodePort 나 LoadBalancer Type 필요 없음!
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=ClusterIP --set env.TZ="Asia/Seoul" --namespace kube-system
# 확인
kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view
# 사용 리전의 인증서 ARN 변수 지정 : 정상 상태 확인(만료 상태면 에러 발생!)
CERT_ARN=$(aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text)
echo $CERT_ARN
# 자신의 공인 도메인 변수 지정
MyDomain=<자신의 공인 도메인>
echo $MyDomain
MyDomain=gasida.link
echo $MyDomain
# kubeopsview 용 Ingress 설정 : group 설정으로 1대의 ALB를 여러개의 ingress 에서 공용 사용
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/ssl-redirect: "443"
alb.ingress.kubernetes.io/success-codes: 200-399
alb.ingress.kubernetes.io/target-type: ip
labels:
app.kubernetes.io/name: kubeopsview
name: kubeopsview
namespace: kube-system
spec:
ingressClassName: alb
rules:
- host: kubeopsview.$MyDomain
http:
paths:
- backend:
service:
name: kube-ops-view
port:
number: 8080
path: /
pathType: Prefix
EOF
# service, ep, ingress 확인
kubectl get ingress,svc,ep -n kube-system
# Kube Ops View 접속 정보 확인
echo -e "Kube Ops View URL = https://kubeopsview.$MyDomain/#scale=1.5"
open "https://kubeopsview.$MyDomain/#scale=1.5" # macOS

S3 조회를 위한 Pod 생성 - IRSA 설정
iamserviceaccount 설정
eksctl create iamserviceaccount \
--name my-sa \
--namespace default \
--cluster $CLUSTER_NAME \
--approve \
--role-name eksctl-myeks-pod-irsa-s3-readonly-role \
--attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text)
# 확인 >> 웹 관리 콘솔에서 CloudFormation Stack >> IAM Role 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
kubectl get sa
kubectl describe sa my-sa
# my-sa 서비스어카운트를 곁들인 파드 3번 생성
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
# Pod Identity Webhook은 mutating webhook을 통해 아래 Env 내용과 1개의 볼륨을 추가함
kubectl get pod eks-iam-test3
kubectl get pod eks-iam-test3 -o yaml
kubectl exec -it eks-iam-test3 -- ls /var/run/secrets/eks.amazonaws.com/serviceaccount
token
kubectl exec -it eks-iam-test3 -- cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token ; echo
# 서비스 어카운트 두 번째 토큰 확인
SA_TOKEN=$(kubectl exec -it eks-iam-test3 -- cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token)
echo $SA_TOKEN
# 파드에서 aws cli 사용 확인
kubectl exec -it eks-iam-test3 -- aws sts get-caller-identity --query Arn
"arn:aws:sts::911283464785:assumed-role/eksctl-myeks-pod-irsa-s3-readonly-role/botocore-session-1775122119"
# 되는 것고 안되는 것은 왜그런가?
kubectl exec -it eks-iam-test3 -- aws s3 ls
kubectl exec -it eks-iam-test3 -- aws ec2 describe-instances --region ap-northeast-2
kubectl exec -it eks-iam-test3 -- aws ec2 describe-vpcs --region ap-northeast-2


eks-iam-test3 파드를 생성하고 난 다음 상세 확인 시 mount된 SA Token을 확인하였을 때, eks.amazonaws.com으로 마운트 된 것을 확인였고, 환경변수 또한 eks.amazonaws.com으로 설정되어 있습니다.



JWT 토큰 디코딩 확인 - aud : sts.amazonaws.com

Pod 내부에서 AWS 계정에 대한 S3 버킷이 조회되는 것을 확인할 수 있습니다.

다만, S3 버킷을 제외한 나머지 서비스들에 대한 action을 동작하려고 했을 때 권한이 없다는 에러가 발생하고 있습니다. 이것은 EKS에서 생성한 iamserviceaccount에 적용된 eksctl-myeks-pod-irsa-s3-readonly-role에 대한 역할에서 S3ReadOnlyAccess 권한만 주었기 때문인 점 참고부탁드립니다.


EKS - Pod Identity
EKS에서 Pod Identity를 사용할 경우 OIDC Provider가 필요하지 않다.(복잡한 인증 과정 불필요)
pod-identity-agent 설치 확인
# 확인
eksctl get addon --cluster $CLUSTER_NAME
kubectl -n kube-system get daemonset eks-pod-identity-agent
kubectl -n kube-system get pods -l app.kubernetes.io/name=eks-pod-identity-agent
kubectl get ds -n kube-system eks-pod-identity-agent -o yaml
# 네트워크 정보 확인 : SSM 을 통해 노드 접속 후 아래 확인
## EKS Pod Identity Agent uses the hostNetwork of the node and it uses port 80 and port 2703 on a link-local address on the node.
## This address is 169.254.170.23 for IPv4 and [fd00:ec2::23] for IPv6 clusters.
sudo ss -tnlp | grep eks-pod-identit
sudo ip -c route
sudo ip -c -br -4 addr
sudo ip -c addr



EKS - podidentityassociation 설정
eksctl create podidentityassociation \
--cluster $CLUSTER_NAME \
--namespace default \
--create-service-account \
--service-account-name s3-sa \
--role-name s3-eks-pod-identity-role \
--permission-policy-arns arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--region ap-northeast-2
# 확인
kubectl get sa
kubectl get sa s3-sa -oyaml
eksctl get podidentityassociation --cluster $CLUSTER_NAME
ASSOCIATION ARN NAMESPACE SERVICE ACCOUNT NAME IAM ROLE ARN
arn:aws:eks:ap-northeast-2:911283464785:podidentityassociation/myeks/a-blaanudo8dc1dbddw default s3-sa arn:aws:iam::911283464785:role/s3-eks-pod-identity-role
aws eks list-pod-identity-associations --cluster-name $CLUSTER_NAME | jq
# IAM Role 확인 : ABAC 지원을 위해 sts:Tagsession 추가
aws iam get-role --query 'Role.AssumeRolePolicyDocument' --role-name s3-eks-pod-identity-role | jq .


EKS - Pod 생성 ( Pod Identity )
# 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-pod-identity
spec:
serviceAccountName: s3-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
# 확인
## Amazon EKS가 EKS Pod Identity 연결이 있는 서비스 계정을 사용하는 새 Pod를 시작하면 EKS Pod Identity 웹훅이 실행됩니다
## 두 개의 환경 변수를 추가하여 pod 사양을 변경 합니다 : AWS_CONTAINER_CREDENTIALS_FULL_URI , AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE
kubectl get pod eks-pod-identity -o yaml
kubectl exec -it eks-pod-identity -- aws sts get-caller-identity --query Arn
kubectl exec -it eks-pod-identity -- aws s3 ls
kubectl exec -it eks-pod-identity -- env | grep AWS
# 토큰 정보 확인
kubectl exec -it eks-pod-identity -- ls /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/
kubectl exec -it eks-pod-identity -- cat /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token
Pod 내부에서 AWS STS서버로 통신되는 것을 확인할 수 있습니다.

S3 버킷 리스트 조회 및 파드 내 환경변수 조회(자격증명 파일이 API 서버에 등록되어 있는 것을 확인할 수 있습니다.)

JWT 토큰 디코딩 후 분석 시 pods.eks.amazonaws.com으로 통신되는 것을 알 수 있습니다.

'AWS 4기' 카테고리의 다른 글
| AEWS 4기 5주차(2) - 워커노드 kubelet,containerd 디버깅, Loadbalancer 트러블슈팅 (0) | 2026.04.18 |
|---|---|
| AEWS 4기 5주차(1) - EKS Debuggig(k8s debugging) (0) | 2026.04.18 |
| AEWS 4기 4주차(2) - EKS 인증/인가(kubectl 동작 방식) (0) | 2026.04.12 |
| AEWS 4기 4주차(1) - Kubernetes 인증/인가 (0) | 2026.04.11 |
| AEWS 4기 3주차(3) - EKS Scaling(Fargate) (0) | 2026.04.05 |