EKS Pod Identity
比較 IRSA 與 EKS Pod Identity 的流程、Session Tags 與 ABAC 用法,並附 Terraform 設定範例。
除了 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)
- 你要先在 IAM 建一個 Role,Trust Policy 裡面要寫:
- 哪個 OIDC Provider (EKS cluster 的 issuer URL)。
- 哪個 Service Account (namespace + sa name)。
- Pod 啟動 → 透過 SA token + OIDC → AssumeRole → 拿到 credentials。
- 這導致每個 SA 要一個 Role,管理上很麻煩。
EKS Pod Identity 流程 (新的機制)
- 不用寫 OIDC trust policy:
- IAM Role 不用寫針對 OIDC 的
sts:AssumeRoleWithWebIdentitytrusted 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" ] } ] }
- IAM Role 不用寫針對 OIDC 的
- 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。
- Tags 包含:
- 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" } } } ] }
- 你可以用
步驟總覽(官方建議步驟)
- 安裝 EKS Pod Identity Agent(每個叢集一次;若用 EKS Auto Mode 已預裝可略過)。
- 建立 IAM Role(信任主體為
pods.eks.amazonaws.com,允許sts:AssumeRole與sts:TagSession)。 - 建立 Pod Identity Association(把 cluster / namespace / serviceAccount 映射到該 IAM Role)。
- 讓工作負載使用該 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 Namespaceservice_account→ 哪個 ServiceAccountrole_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 只是執行者。