EKS Pod Identity

比較 IRSA 與 EKS Pod Identity 的流程、Session Tags 與 ABAC 用法,並附 Terraform 設定範例。

發佈 ~3 分鐘 #EKS

除了 IRSA 以外,最近 EKS release 一種新的 pod 授權方式,叫做 EKS Pod Identity。根據文件,EKS Pod Identity 會讓 role 身上帶有特定的 session tags,像是 ns/cluster name 等標記;然後 agent 會根據 role 身上的 tag 判斷 SA 可以 assume 哪個 role,在根據這個 role 身上有的 policy 決定可以去碰哪些資源。基本上算是 ABAC 概念的實作。

傳統 IRSA 流程 (需要 OIDC trust policy)

  1. 你要先在 IAM 建一個 Role,Trust Policy 裡面要寫:
    • 哪個 OIDC Provider (EKS cluster 的 issuer URL)。
    • 哪個 Service Account (namespace + sa name)。
  2. Pod 啟動 → 透過 SA token + OIDC → AssumeRole → 拿到 credentials。
  3. 這導致每個 SA 要一個 Role,管理上很麻煩。

EKS Pod Identity 流程 (新的機制)

  1. 不用寫 OIDC trust policy:
    • IAM Role 不用寫針對 OIDC 的 sts:AssumeRoleWithWebIdentity trusted policy
    • 改成讓 pods.eks.amazonaws.com 當成信任主體,並允許 sts:AssumeRole 與 sts:TagSession。
    • Trusted policy 範例
      {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Sid": "EKSPodIdentityTrust",
            "Effect": "Allow",
            "Principal": {
              "Service": "pods.eks.amazonaws.com"
            },
            "Action": [
              "sts:AssumeRole",
              "sts:TagSession"
            ]
          }
        ]
      }
  2. EKS Pod Identity Agent(跑在 DaemonSet)會:
    • 監聽 Pod 的 Service Account。
    • 幫 Pod 對應到某個 IAM Role。
    • 發給 Pod 帶有 Session Tags 的臨時 IAM credential。
      • Tags 包含:eks:cluster-name, eks:namespace, eks:service-account-name。
  3. IAM Policy 判斷階段:
    • 你可以用 Condition 搭配這些 Tags 做細緻控管。
    • 例如:同一個 Role 給不同 SA 用,但限制「只有在 ns=prod 時能存取某個 S3 bucket」。
    • Role policy 範例
      {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Sid": "ListAndReadProdBucket",
            "Effect": "Allow",
            "Action": [
              "s3:ListBucket",
              "s3:GetObject"
            ],
            "Resource": [
              "arn:aws:s3:::my-app-prod-bucket",
              "arn:aws:s3:::my-app-prod-bucket/*"
            ],
            "Condition": {
              "StringEquals": {
                "aws:PrincipalTag/eks-cluster-name": "my-eks-cluster",
                "aws:PrincipalTag/kubernetes-namespace": "prod"
              }
            }
          }
        ]
      }

步驟總覽(官方建議步驟)

  1. 安裝 EKS Pod Identity Agent(每個叢集一次;若用 EKS Auto Mode 已預裝可略過)。
  2. 建立 IAM Role(信任主體為 pods.eks.amazonaws.com,允許 sts:AssumeRole 與 sts:TagSession)。
  3. 建立 Pod Identity Association(把 cluster / namespace / serviceAccount 映射到該 IAM Role)。
  4. 讓工作負載使用該 ServiceAccount,並確認使用支援的 AWS SDK 預設認證鏈。 AWS 文件+3AWS 文件+3AWS 文件+3

實務細節與重點

  • Agent 以位址 169.254.170.23(IPv4)與 [fd00:ec2::23](IPv6)提供憑證服務;若停用 IPv6,Agent 可能起不來。 [reference]
  • 限制與支援度:每個叢集最多 5,000 個 Association;僅支援 EC2 Linux 節點(不支援 Fargate、Windows nodes/pods)。 [reference]
  • Session Tags / ABAC:EKS 會在 AssumeRole 時自動附加 eks-cluster-name / kubernetes-namespace / service-account-name 等 Session Tags,可在 IAM Policy/資源政策用 aws:PrincipalTag/* 做條件判斷,實作 ABAC。 [reference]

Apply in Terraform

############################################################
# 1) EKS 叢集(terraform-aws-modules/eks/aws)
############################################################
module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 21.0"

  name                = var.cluster_name
  kubernetes_version  = "1.32"                # 依實際需求
  vpc_id              = var.vpc_id
  subnet_ids          = var.private_subnet_ids

  # 直接用 module 管理 Add-ons
  addons = {
    vpc-cni = {
      # CNI 推薦在建 compute 之前就裝好
      before_compute = true
    }
    eks-pod-identity-agent = {
      before_compute = true
    }
    kube-proxy = {}
    coredns    = {}
  }
}

############################################################
# 2) IAM Role for VPC CNI (aws-node)
#    - Principal: pods.eks.amazonaws.com
#    - Actions: sts:AssumeRole, sts:TagSession
#    - Attach: AmazonEKS_CNI_Policy
############################################################
data "aws_iam_policy_document" "cni_trust" {
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["pods.eks.amazonaws.com"]
    }
    actions = [
      "sts:AssumeRole",
      "sts:TagSession"
    ]
  }
}

resource "aws_iam_role" "cni_role" {
  name               = "${var.cluster_name}-cni-pod-identity"
  assume_role_policy = data.aws_iam_policy_document.cni_trust.json
}

# 附上 AWS 受管的 CNI 權限政策
data "aws_iam_policy" "amazon_eks_cni_policy" {
  arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
}

resource "aws_iam_role_policy_attachment" "cni_attach" {
  role       = aws_iam_role.cni_role.name
  policy_arn = data.aws_iam_policy.amazon_eks_cni_policy.arn
}

############################################################
# 3) 建立 Pod Identity Association
#    對象:kube-system / aws-node (VPC CNI DaemonSet 的 SA)
############################################################
resource "aws_eks_pod_identity_association" "cni" {
  cluster_name    = module.eks.cluster_name
  namespace       = "kube-system"
  service_account = "aws-node"
  role_arn        = aws_iam_role.cni_role.arn
}

############################################################
# 4) (可選)輸出
############################################################
output "cni_role_arn" {
  value = aws_iam_role.cni_role.arn
}
output "cni_pod_identity_association_id" {
  value = aws_eks_pod_identity_association.cni.id
}

Resource aws_eks_pod_identity_association 具體行為

📌 簡單來說就是在 control plane 紀錄 SA ↔ Role 的 mapping

  • 控制面 (EKS API)
    • 這個 Terraform resource 會透過 EKS API 建立一個 Pod Identity Association 物件。
    • 這個 Association 其實存在於 EKS 的 control plane,不是 IAM 本身的資源。
    • 也就是說,它不是在 IAM 裡新增什麼「實體資源」,而是由 EKS 儲存一個「規則 (mapping)」。
  • 內容物 (Association 規則)
    • 包含以下幾個欄位:
      • cluster_name → 哪個叢集
      • namespace → 哪個 K8s Namespace
      • service_account → 哪個 ServiceAccount
      • role_arn → 綁定的 IAM Role
      • (optional) external_id → 跨帳號時要用的 External ID
    • 換句話說,它就是「一個 mapping:<cluster/ns/sa> → <IAM Role>」。
  • EKS Pod Identity Agent 的角色
    • Pod Identity Agent 會定期呼叫 control plane 的 Pod Identity API,拿到所有已建立的 Association。
    • 當有 Pod 用到對應的 ServiceAccount 時,Agent 會幫它向 STS 要臨時憑證(AssumeRole + TagSession),並把憑證注入 Pod。
    • 所以 Association 資訊本身存在 EKS,Agent 只是執行者。

Reference