[AWS] EKS IRSA - Pod별 AWS 권한 분리하기

growing·2025년 8월 3일

AWS

목록 보기
6/10

왜 IRSA?

기존 방식의 문제점

EKS의 Pod는 기본적으로 EC2 노드의 IAM Role을 그대로 상속받음. 모든 Pod가 동일한 권한을 공유하므로 세밀한 권한 제어가 불가능

[EC2 Node IAM Role]
     │
 ┌───▼────┐
 │ Pod A  │  → S3, DynamoDB 모두 접근 가능 (과도한 권한)
 │ Pod B  │  → 실제로는 S3만 필요한데 불필요한 권한까지 보유
 └────────┘

보안 문제:

  • 최소 권한 원칙 위반
  • Pod 하나 해킹당하면 노드 전체 권한 노출
  • 권한 변경 시 노드 재시작 필요

IRSA란?

IAM Roles for Service Accounts의 약자. Pod 단위로 AWS IAM 권한을 세밀하게 부여할 수 있는 EKS의 공식 메커니즘

Pod → ServiceAccount → IAM Role → AWS 리소스 접근

동작 방식:
1. Kubernetes ServiceAccount에 IAM Role ARN 부여
2. Pod가 해당 ServiceAccount 사용
3. AWS STS가 임시 자격증명 발급
4. Pod가 IAM Role의 권한으로 AWS 리소스 접근


구성 요소

1. OIDC Provider

EKS 클러스터가 발급한 ServiceAccount 토큰(JWT)을 AWS가 검증할 수 있도록 하는 연결 고리

resource "aws_iam_openid_connect_provider" "eks" {
  url             = aws_eks_cluster.this.identity[0].oidc[0].issuer
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.eks.certificates[0].sha1_fingerprint]
}

EKS가 발급한 토큰이 유효한지 AWS가 확인


2. IAM Role with Trust Policy

Pod가 assume할 수 있는 IAM Role을 생성. Trust Policy에서 특정 ServiceAccount만 Role을 사용할 수 있도록 제한

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/EXAMPLE"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.ap-northeast-2.amazonaws.com/id/EXAMPLE:sub": "system:serviceaccount:my-namespace:my-sa",
          "oidc.eks.ap-northeast-2.amazonaws.com/id/EXAMPLE:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
  • sub: 특정 namespace의 특정 ServiceAccount만 허용
  • aud: STS 서비스만 토큰 사용 가능

3. IAM Policy

실제 AWS 리소스 접근 권한을 정의하는 정책

resource "aws_iam_role_policy_attachment" "s3_read" {
  role       = aws_iam_role.irsa_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}

또는 커스텀 정책:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}

4. Kubernetes ServiceAccount

IAM Role ARN을 annotation으로 지정한 ServiceAccount 생성

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: production
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-irsa-role

5. Pod에 ServiceAccount 연결

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
spec:
  template:
    spec:
      serviceAccountName: my-app-sa
      containers:
      - name: app
        image: my-app:latest
        env:
        - name: AWS_REGION
          value: ap-northeast-2

Pod 생성 시 자동으로 다음 환경변수들이 주입됨:

AWS_ROLE_ARN
AWS_WEB_IDENTITY_TOKEN_FILE
AWS_STS_REGIONAL_ENDPOINTS

전체 동작 흐름

1. EKS 클러스터 생성 시 OIDC Provider URL 자동 생성

2. AWS IAM에 OIDC Provider 등록

3. IAM Role 생성
   - Trust Policy에 OIDC Provider와 ServiceAccount 조건 명시
   - 필요한 AWS 권한 정책 연결

4. Kubernetes ServiceAccount 생성
   - IAM Role ARN을 annotation으로 추가

5. Pod에 ServiceAccount 지정

6. Pod 실행 시:
   - Kubernetes가 ServiceAccount 토큰 발급
   - AWS SDK가 토큰으로 STS AssumeRoleWithWebIdentity 호출
   - 임시 자격증명 받아서 AWS 리소스 접근

실제 구성 예시

Terraform으로 IRSA 구성

# OIDC Provider
data "tls_certificate" "eks" {
  url = aws_eks_cluster.main.identity[0].oidc[0].issuer
}

resource "aws_iam_openid_connect_provider" "eks" {
  url             = aws_eks_cluster.main.identity[0].oidc[0].issuer
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.eks.certificates[0].sha1_fingerprint]
}

# IAM Role
resource "aws_iam_role" "app_irsa" {
  name = "my-app-irsa-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Federated = aws_iam_openid_connect_provider.eks.arn
      }
      Action = "sts:AssumeRoleWithWebIdentity"
      Condition = {
        StringEquals = {
          "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:sub" = "system:serviceaccount:production:my-app-sa"
          "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:aud" = "sts.amazonaws.com"
        }
      }
    }]
  })
}

# IAM Policy 연결
resource "aws_iam_role_policy_attachment" "app_s3" {
  role       = aws_iam_role.app_irsa.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}

Kubernetes 리소스

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: production
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-irsa-role

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      serviceAccountName: my-app-sa
      containers:
      - name: app
        image: my-app:latest
        ports:
        - containerPort: 8080

IRSA의 장점

구분기존 방식 (EC2 Role)IRSA
권한 범위노드 내 모든 Pod 동일Pod별 독립적 권한
보안 수준낮음 (권한 과다 부여)높음 (최소 권한 원칙)
권한 변경노드 재시작 필요즉시 반영
권한 추적어려움CloudTrail에서 Pod별 추적 가능
profile
Hello, World!

0개의 댓글