AWS

EKS Pod Identity vs IRSA: 파드에 IAM 권한을 주는 두 가지 방식

Somaz 2026. 6. 30. 00:00
728x90
반응형

Overview

EKS 위에서 돌아가는 파드는 결국 AWS 리소스를 건드린다. S3에서 파일을 읽고, Secrets Manager에서 시크릿을 꺼내고, DynamoDB에 쓰는 식이다. 문제는 어떻게 그 권한을 안전하게 주느냐다.

 

액세스 키를 매니페스트에 박아 넣는 건 답이 아니다. AWS가 내놓은 정답은 두 가지다 — IRSA(IAM Roles for Service Accounts)Pod Identity.

 

둘 다 목표는 같다. 파드에 장기 자격증명 없이, 짧게 살았다 사라지는 임시 자격증명을 쥐어주는 것이다. 하지만 그 목표에 도달하는 방식은 근본부터 다르다.

  • IRSA(2019) 는 OIDC 페더레이션에 기댄다. 클러스터마다 OIDC 프로바이더를 세우고, 서비스 어카운트에 역할 ARN을 어노테이션으로 붙인 뒤, IAM 역할의 trust policy가 그 클러스터의 OIDC issuer와 서비스 어카운트를 검증하는 구조다.
  • Pod Identity(2023, re:Invent) 는 에이전트 기반이다. 클러스터 안에서 도는 에이전트와 EKS Auth API가 매핑을 대신 처리하고, IAM 역할의 trust policy는 정적 principal 하나로 끝난다. OIDC 프로바이더도, 어노테이션도 없다.

 

이 글에서는 두 방식이 토큰을 받아오는 흐름이 어떻게 다른지, 설정은 얼마나 차이 나는지, 그리고 2026년 기준으로 어느 쪽을 골라야 하는지를 정리한다.

 

결론부터 말하면, 새로 생성하는 클러스터라면 대체로 Pod Identity가 낫다. 다만 IRSA가 여전히 유일한 방법인 경우도 분명히 있다.

 

 

 

 

 

 


 

 

한눈에 보는 두 가지 흐름

핵심은 "파드가 임시 자격증명을 어디에 요청하고, AWS가 무엇을 보고 신뢰하는가"다. 두 흐름을 나란히 보면 차이가 분명하다.

IRSA  —  sts:AssumeRoleWithWebIdentity (OIDC 페더레이션)

  Pod ──(projected SA token, JWT)──▶  AWS STS
   │      env: AWS_WEB_IDENTITY_TOKEN_FILE        │
   │                                              │ 클러스터 OIDC issuer로
   │                                              │ 토큰 서명 검증
   │                                              ▼
   │                                   trust policy 확인:
   │                                   - issuer == 이 클러스터의 OIDC
   │                                   - sub    == system:serviceaccount:<ns>:<sa>
   │                                   - aud    == sts.amazonaws.com
   │                                              │
   ◀──────────── 임시 자격증명 ──────────────────────┘


Pod Identity  —  EKS Auth API: AssumeRoleForPodIdentity (에이전트 기반)

  Pod ──▶  Pod Identity Agent  (DaemonSet, 169.254.170.23)
   │      env: AWS_CONTAINER_CREDENTIALS_FULL_URI       │
   │                                                    ▼
   │                                EKS Auth API (AssumeRoleForPodIdentity)
   │                                - 연결(association) 조회: <ns>/<sa> -> role
   │                                - principal: pods.eks.amazonaws.com
   │                                - sts:AssumeRole + 세션 태그 주입
   │                                                    │
   ◀──────────── 임시 자격증명 (자동 로테이션) ────────────────┘

 

 

IRSA는 파드가 직접 STS에 가서 "내 OIDC 토큰을 줄 테니 이 역할을 달라"고 한다. 그래서 클러스터의 OIDC issuer가 trust policy에 명시되어야 한다.

 

Pod Identity는 파드가 노드 위의 에이전트에게만 말을 걸고, 실제 신뢰 검증은 EKS Auth API가 처리한다. 그래서 trust policy에는 클러스터 고유 정보가 들어가지 않는다. 이 한 가지 차이가 뒤따르는 거의 모든 차이를 만든다.

 

 

 

 

 

 

 

IRSA가 동작하는 방식

IRSA는 클러스터마다 OIDC 프로바이더를 IAM에 등록하는 데서 시작한다. 이게 "이 EKS 클러스터가 서명한 토큰을 믿겠다"는 선언이다. 그다음 IAM 역할을 만들고, 그 역할의 trust policy에 클러스터의 OIDC issuer URL과 서비스 어카운트를 못박는다.

{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:default:my-app",
      "oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
    }
  }
}

 

 

여기서 Federated principal과 sub 조건에 클러스터별 OIDC issuer ID가 통째로 박혀 있는 점을 보자.

 

이게 IRSA의 가장 큰 운영 부담의 뿌리다. 클러스터가 다르면 issuer ID도 다르므로, 같은 역할을 두 클러스터에서 쓰려면 trust policy에 두 issuer를 모두 나열해야 한다. 클러스터를 새로 만들 때마다 역할의 trust policy를 손봐야 한다는 뜻이다.

 

마지막으로 서비스 어카운트에 어노테이션을 단다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  namespace: default
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-app

 

파드가 이 서비스 어카운트로 뜨면, EKS가 projected service account 토큰(JWT)을 볼륨으로 마운트하고 `AWS_WEB_IDENTITY_TOKEN_FILE` 환경변수를 주입한다.

 

AWS SDK는 이 토큰을 들고 STS의 `AssumeRoleWithWebIdentity` 를 호출해 임시 자격증명을 받아온다. 정리하면 IRSA가 굴러가려면 세 가지가 손발을 맞춰야 한다 — OIDC 프로바이더, IAM 역할의 trust policy, 서비스 어카운트 어노테이션. 한쪽을 바꾸면 다른 쪽도 따라 바뀌어야 하고, 어디 하나가 어긋나면 AccessDenied가 난다.

 

IRSA의 강점도 분명하다. EKS 클라우드뿐 아니라 EKS Anywhere, ROSA, EC2 위의 self-managed 쿠버네티스까지 어디서나 쓸 수 있다. OIDC라는 표준에 기대기 때문이다. 이 호환성은 뒤에서 다시 짚는다.

 

 

 

 

 

 

Pod Identity가 동작하는 방식

Pod Identity는 출발점이 다르다. OIDC 프로바이더를 등록하는 대신, 클러스터에 EKS Pod Identity Agent 애드온을 설치한다. 이 에이전트는 노드마다 DaemonSet으로 떠서, 파드의 자격증명 요청을 받아 EKS Auth API에 중개한다.

 

 

IAM 역할의 trust policy는 이렇게까지 단순해진다.

{
  "Effect": "Allow",
  "Principal": { "Service": "pods.eks.amazonaws.com" },
  "Action": ["sts:AssumeRole", "sts:TagSession"]
}

`pods.eks.amazonaws.com` 라는 정적 서비스 principal 하나가 전부다. OIDC issuer URL이 어디에도 없다. 그래서 이 역할은 클러스터를 가리지 않고 그대로 재사용된다. 새 클러스터를 만들어도 trust policy는 손댈 필요가 없다.

 

역할과 서비스 어카운트를 잇는 건 어노테이션이 아니라 연결(Pod Identity Association)이다. EKS API로 한 번 만들어두면 끝이다.

resource "aws_eks_pod_identity_association" "my_app" {
  cluster_name    = module.eks.cluster_name
  namespace       = "default"
  service_account = "my-app"
  role_arn        = aws_iam_role.my_app.arn
}

 

 

서비스 어카운트 매니페스트에는 아무 어노테이션도 붙지 않는다. 매핑이 클러스터(쿠버네티스 매니페스트)가 아니라 AWS 쪽(연결 리소스)에 살기 때문이다. 이게 IRSA에서 늘 따라다니던 "매니페스트와 IAM이 서로를 알아야 하는" 결합을 끊어준다.

 

파드가 뜨면 에이전트가 AWS_CONTAINER_CREDENTIALS_FULL_URI 환경변수를 주입하고(링크-로컬 주소 169.254.170.23을 가리킨다), SDK는 그 엔드포인트에서 자격증명을 받는다. 내부적으로 EKS Auth API의 AssumeRoleForPodIdentity가 연결을 조회해 역할을 assume하고, 임시 자격증명을 돌려준다. 자격증명은 자동으로 로테이션된다.

 

여기서 Pod Identity만의 장점이 하나 더 있다. 세션 태그(session tags)다.

 

역할을 assume할 때 EKS가 클러스터 ARN, 네임스페이스, 서비스 어카운트 이름 같은 정보를 세션 태그로 자동으로 붙여준다. 이걸 IAM 정책에서 `${aws:PrincipalTag/kubernetes-namespace}` 같은 형태로 받아 쓰면, 태그 기반 접근 제어(ABAC)가 가능하다. 역할 하나에 정책 하나를 붙여두고, 네임스페이스별로 접근 범위를 가르는 식이다. IRSA에는 없던 기능이다.

 

 

 

 

 

핵심 차이 비교

지금까지의 내용을 표로 추리면 다음과 같다.

항목 IRSA Pod Identity
등장 2019 2023 (re:Invent)
신뢰 메커니즘 OIDC 페더레이션 EKS 서비스 principal + Auth API
STS 호출 AssumeRoleWithWebIdentity AssumeRoleForPodIdentity (+ AssumeRole)
클러스터별 사전 설정 OIDC 프로바이더 등록 필요 에이전트 애드온만 설치
trust policy 내용 클러스터 OIDC issuer + sub 고정 정적 principal 하나
SA 어노테이션 role-arn 필요 불필요
매핑 위치 쿠버네티스 매니페스트 AWS 연결 리소스
역할 재사용 클러스터마다 trust 추가 그대로 재사용
세션 태그 / ABAC 미지원 지원 (전이적 태그)
크로스 계정 수동 role chaining targetRoleArn 한 줄 (2025.06)
동작 환경 EKS, EKS Anywhere, ROSA, self-managed EKS(클라우드) 전용
Fargate 지원 에이전트가 DaemonSet이라 제약

 

표에서 가장 중요한 줄은 trust policy 내용역할 재사용이다.

 

IRSA의 복잡성은 대부분 "클러스터 고유의 OIDC issuer가 신뢰 관계에 박힌다"는 한 가지 사실에서 파생된다. Pod Identity는 그걸 정적 principal로 치환하면서 연쇄적으로 따라오던 부담을 함께 걷어낸다.

 

 

 

 

 

 

 


 

 

 

 

설정으로 보는 차이

같은 일(파드 하나에 S3 접근 역할 주기)을 두 방식으로 짜면 코드량 차이가 확연하다.

 

 

IRSA — 세가지 설정이 필요하다.

# 1) 클러스터 OIDC 프로바이더 생성
module "eks" {
  # ...
  enable_irsa = true   # OIDC 프로바이더를 만들어준다
}

# 2) OIDC에 묶인 trust policy를 가진 역할
module "irsa_role" {
  source    = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
  role_name = "my-app"
  oidc_providers = {
    main = {
      provider_arn               = module.eks.oidc_provider_arn
      namespace_service_accounts = ["default:my-app"]
    }
  }
}

# 3) 서비스 어카운트에 어노테이션
#    serviceAccount.annotations:
#      eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-app

 

 

Pod Identity — 두가지 설정 이면 끝난다.

# 1) 정적 EKS principal을 신뢰하는 역할
data "aws_iam_policy_document" "trust" {
  statement {
    principals {
      type        = "Service"
      identifiers = ["pods.eks.amazonaws.com"]
    }
    actions = ["sts:AssumeRole", "sts:TagSession"]
  }
}

# 2) 연결 (OIDC 없음, 어노테이션 없음)
resource "aws_eks_pod_identity_association" "my_app" {
  cluster_name    = module.eks.cluster_name
  namespace       = "default"
  service_account = "my-app"
  role_arn        = aws_iam_role.my_app.arn
}
  • OIDC 프로바이더가 사라지고, 서비스 어카운트 매니페스트를 건드릴 필요도 없어진다. 클러스터를 하나 더 띄워도 1번 역할은 그대로 두고 2번 연결만 새로 만들면 된다.

 

 

특정 클러스터로만 역할 사용을 제한하고 싶다면, trust policy에 조건을 한 줄 더한다.

{
  "Effect": "Allow",
  "Principal": { "Service": "pods.eks.amazonaws.com" },
  "Action": ["sts:AssumeRole", "sts:TagSession"],
  "Condition": {
    "ArnEquals": {
      "aws:SourceArn": "arn:aws:eks:eu-central-1:111122223333:cluster/prod-myapp-v1"
    }
  }
}

 

 

 

 

크로스 계정: Pod Identity가 좁혔던 차이

초기 Pod Identity의 약점 중 하나가 크로스 계정 접근이었다. 다른 계정의 S3 버킷을 읽으려면 직접 role chaining을 손으로 엮어야 했다. 이 차이는 2025년 6월 에 수정됫다.

 

연결을 만들 때 소스 역할과 타깃 역할(targetRoleArn)을 함께 지정하면, EKS가 role chaining을 뒤에서 알아서 처리해 크로스 계정 임시 자격증명을 내려준다. 애플리케이션 코드는 한 줄도 바꿀 필요가 없다.

resource "aws_eks_pod_identity_association" "cross_account" {
  cluster_name         = module.eks.cluster_name
  namespace            = "default"
  service_account      = "my-app"
  role_arn             = aws_iam_role.source.arn              # 클러스터와 같은 계정
  target_role_arn      = "arn:aws:iam::222233334444:role/s3-access"  # 리소스가 있는 계정
  disable_session_tags = false
}
  • 타깃 역할 쪽 trust policy가 소스 역할의 assume를 허용하도록 엮어두면 된다.
  • 세션 태그는 전이적(transitive)이라, 소스에서 붙은 태그가 크로스 계정 정책까지 그대로 따라가 ABAC를 이어서 쓸 수 있다.
  • (패킹된 정책이 한도를 넘어 `PackedPolicyTooLarge` 가 뜨면 `disable_session_tags = true` 로 태그를 끌 수 있다.)

 

 

 

언제 무엇을 쓸까

새로 생성하는 EKS 클라우드 클러스터라면 Pod Identity를 기본값으로 두는 게 합리적이다. 설정이 가볍고, 역할을 재사용할 수 있고, ABAC와 크로스 계정까지 깔끔하게 풀린다.

 

내가 Karpenter를 구성할 때 Pod Identity를 택한 것도 같은 이유였다 — OIDC 프로바이더도, trust policy의 issuer 고정도, SA 어노테이션도 없이 역할 하나를 여러 클러스터에서 돌려쓸 수 있어서다.

 

다만 IRSA가 여전히 유일하거나 더 나은 답인 자리가 있다.

  • EKS 클라우드가 아닌 환경. EKS Anywhere, ROSA, EC2 위의 self-managed 쿠버네티스에서는 Pod Identity를 못 쓴다. IRSA만 동작한다.
  • Fargate 워크로드. Pod Identity 에이전트는 노드 DaemonSet으로 도는데, Fargate에는 그 노드가 없다. Fargate 파드에는 IRSA를 쓴다.
  • 아직 Pod Identity를 못 받는 도구. 오래된 AWS SDK나 일부 서드파티 컴포넌트는 컨테이너 자격증명 방식을 모를 수 있다. 이럴 땐 IRSA가 안전하다.
  • 이미 IRSA로 잘 돌고 있고 옮길 이득이 적을 때. 멀쩡히 도는 걸 굳이 갈아엎을 이유는 없다.

 

두 방식은 공존할 수 있다. 같은 클러스터에서 어떤 워크로드는 Pod Identity로, 어떤 워크로드는 IRSA로 돌려도 된다. 한 파드에 둘 다 설정돼 있으면 SDK의 자격증명 탐색 순서상 Pod Identity가 먼저 잡힌다. 그래서 마이그레이션도 한 번에 다 갈아치울 필요 없이, 워크로드 단위로 연결을 만들어 하나씩 넘기면 된다.

 

 

 

 

 

 

 

운영 메모

Pod Identity로 넘어갈 때 실무에서 챙기는 것들이다.

  • 에이전트 애드온부터 깐다. `eks-pod-identity-agent` 를 클러스터 애드온으로 설치해야 한다. 이게 없으면 연결을 아무리 만들어도 파드가 자격증명을 못 받는다.
  • EKS 애드온도 Pod Identity를 받는다. 예전엔 VPC CNI, EBS CSI 같은 코어 애드온에 IRSA 역할을 일일이 붙여야 했는데, 이제 애드온 자체가 Pod Identity로 권한을 받을 수 있어 OIDC 의존이 더 줄어든다.
  • 디버깅 포인트가 줄어든다. IRSA에서 `AccessDenied` 를 디버깅 할 땐 토큰 projection → OIDC 검증 → trust policy 조건 → STS 응답까지 여러 층을 봐야 했다. Pod Identity는 연결이 맞는지, 에이전트가 떠 있는지 정도로 표면이 단순해진다.
  • 연결 조회. `aws eks list-pod-identity-associations --cluster-name <name>` 으로 어떤 네임스페이스/서비스 어카운트가 어떤 역할에 묶였는지 한눈에 확인할 수 있다.

 

 

 

 

 


 

 

 

 

마무리

두 방식을 같이 써오며 정리한 결론이다.

  • 목표는 같고 메커니즘이 다르다. 둘 다 파드에 장기 키 없이 임시 자격증명을 준다. IRSA는 OIDC 페더레이션, Pod Identity는 에이전트 + EKS Auth API.
  • 복잡성의 뿌리는 OIDC issuer다. IRSA의 운영 부담 대부분은 "클러스터 고유 issuer가 trust policy에 명시된다"는 한 가지에서 나온다. Pod Identity는 이를 정적 principal로 바꿔 따라오던 부담을 함께 걷어낸다.
  • 새 EKS 클라우드 클러스터는 Pod Identity가 기본값. 설정이 가볍고, 역할을 재사용할 수 있고, 세션 태그 기반 ABAC와 (2025년 6월부터) 크로스 계정까지 깔끔하다.
  • IRSA는 아직 죽지 않았다. EKS Anywhere/ROSA/self-managed, Fargate, 오래된 SDK 환경에서는 IRSA가 여전히 정답이다.
  • 공존과 점진적 이전이 된다. 한 클러스터에 둘을 섞을 수 있고, 충돌 시 Pod Identity가 우선한다. 워크로드 단위로 천천히 옮기면 된다.

 

 

 

 

 

 

 

 

 

 


Reference

 

 

 

 

 

Somaz | DevOps Engineer | Kubernetes & Cloud Infrastructure Specialist

728x90
반응형