饮墨

子安饮墨馀三斗,留与卿儿作赋来

EKS Pod Identity 实战:告别 IRSA,更优雅地管理 Pod AWS 权限

痛点

在 EKS 集群中,Pod 访问 AWS 资源(S3、DynamoDB、SQS 等)需要 IAM 权限。长期以来,IRSA(IAM Roles for Service Accounts) 是标准方案,但随着集群规模增长,IRSA 的痛点越来越明显:

  1. OIDC Provider 管理复杂 — 每个集群需要配置 OIDC Provider,跨账户场景下信任关系配置繁琐
  2. IAM Role Trust Policy 膨胀 — 每个 Role 的信任策略必须精确匹配 OIDC issuer URL + namespace + SA name,维护成本高
  3. Role 数量爆炸 — 多集群共享同一 Role 需要在 Trust Policy 中逐个添加 OIDC Provider ARN,条目越来越多
  4. 排障困难 — Token 挂载、Webhook 注入、STS AssumeRoleWithWebIdentity 链路长,出问题定位耗时

AWS 在 2023 年底推出 EKS Pod Identity,从根本上简化了这个流程。经过一年多的生产验证,它已经足够成熟,是时候迁移了。

方案:EKS Pod Identity 核心原理

EKS Pod Identity 采用完全不同的架构:

对比项 IRSA EKS Pod Identity
认证机制 OIDC + STS AssumeRoleWithWebIdentity EKS Auth API + Pod Identity Agent
集群配置 需创建 OIDC Provider 无需额外配置
IAM Trust Policy 必须包含 OIDC issuer URL 统一信任 pods.eks.amazonaws.com
跨集群复用 每个集群需修改 Trust Policy 同一 Role 直接关联多个集群
Token 来源 Projected Service Account Token EKS Pod Identity Agent 注入
权限粒度 Namespace + ServiceAccount Namespace + ServiceAccount

核心改进:IAM Role 的信任关系不再绑定具体集群的 OIDC URL,而是统一信任 EKS Pod Identity 服务。权限绑定通过 EKS API 的 Pod Identity Association 资源完成,与 IAM Role 本身解耦。

实操步骤

Step 1:安装 EKS Pod Identity Agent Addon

# 确认集群版本 >= 1.24
aws eks describe-cluster --name my-cluster \
  --query 'cluster.version' --output text

# 安装 Pod Identity Agent addon
aws eks create-addon \
  --cluster-name my-cluster \
  --addon-name eks-pod-identity-agent \
  --addon-version v1.3.4-eksbuild.1

# 验证 DaemonSet 运行正常
kubectl get ds eks-pod-identity-agent -n kube-system
# 所有节点都应该有一个 Running 的 Pod

Agent 以 DaemonSet 形式运行,监听节点的 169.254.170.23:80169.254.170.23:2703,拦截 Pod 的凭证请求并返回临时 credentials。

Step 2:创建 IAM Role(信任 Pod Identity 服务)

# 创建信任策略文件
cat > trust-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "pods.eks.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"
      ]
    }
  ]
}
EOF

# 创建 Role
aws iam create-role \
  --role-name my-app-s3-reader \
  --assume-role-policy-document file://trust-policy.json

# 附加业务权限(示例:S3只读)
aws iam attach-role-policy \
  --role-name my-app-s3-reader \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

注意 Trust Policy 的简洁程度 — 不再有冗长的 OIDC issuer URL 和 Condition 块。同一个 Role 可以被任意数量的集群关联,无需修改信任策略。

Step 3:创建 Pod Identity Association

# 确保目标 namespace 和 ServiceAccount 已存在
kubectl create sa my-app-sa -n production

# 创建关联:将 Role 绑定到特定集群的 namespace/sa
aws eks create-pod-identity-association \
  --cluster-name my-cluster \
  --namespace production \
  --service-account my-app-sa \
  --role-arn arn:aws:iam::111122223333:role/my-app-s3-reader

# 验证关联
aws eks list-pod-identity-associations \
  --cluster-name my-cluster \
  --namespace production

Step 4:部署应用并验证

# deployment.yaml
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  # 关联到此 SA
      containers:
      - name: app
        image: amazon/aws-cli:latest
        command: ["sleep", "infinity"]
kubectl apply -f deployment.yaml

# 进入 Pod 验证权限
kubectl exec -it deploy/my-app -n production -- aws sts get-caller-identity
# 应显示 assumed-role/my-app-s3-reader/...

kubectl exec -it deploy/my-app -n production -- aws s3 ls
# 能正常列出 bucket

从 IRSA 迁移的注意事项

迁移是平滑的,两种机制可以共存:

# 1. 先创建 Pod Identity Association(不影响现有 IRSA)
# 2. Pod Identity 优先级高于 IRSA,重启 Pod 后自动使用新机制
# 3. 确认新机制工作后,清理旧的 IRSA 注解和 OIDC Provider

# 清理 SA 上的 IRSA 注解
kubectl annotate sa my-app-sa -n production \
  eks.amazonaws.com/role-arn-

# 验证迁移后凭证来源
kubectl exec deploy/my-app -n production -- env | grep AWS
# 不再有 AWS_WEB_IDENTITY_TOKEN_FILE 和 AWS_ROLE_ARN
# 改为通过 Pod Identity Agent 获取凭证

避坑指南

1. 节点需要网络可达 EKS Auth API

Pod Identity Agent 需要与 EKS 控制平面通信。如果节点在私有子网且没有 NAT Gateway 或 VPC Endpoint,Agent 无法获取凭证。解决方案:

# 确保节点安全组允许出站 443 到 EKS API
# 或者创建 VPC Endpoint
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-xxx \
  --service-name com.amazonaws.us-east-1.eks-auth \
  --vpc-endpoint-type Interface \
  --subnet-ids subnet-xxx

2. Fargate 暂不支持

截至目前,EKS Pod Identity 仅支持 EC2 节点(包括 Managed Node Group 和 Self-Managed)。Fargate Profile 上的 Pod 仍需使用 IRSA。

3. 同一 SA 不能关联多个 Role

一个 namespace/serviceAccount 组合只能关联一个 IAM Role。如果 Pod 需要多个服务的权限,应将权限合并到一个 Role,或拆分为多个 ServiceAccount。

4. Session Tags 的妙用

Pod Identity 自动给 STS Session 打上 Tags(kubernetes-namespacekubernetes-service-accounteks-cluster-name 等),可以在 IAM Policy 中用 Condition 做更细粒度的控制:

{
  "Condition": {
    "StringEquals": {
      "aws:PrincipalTag/kubernetes-namespace": "production"
    }
  }
}

总结

EKS Pod Identity 是 IRSA 的下一代替代方案,核心优势:

  • 配置简单 — Trust Policy 不再绑定集群 OIDC URL,一个 Role 多集群复用无需改动
  • 管理解耦 — 权限关联通过 EKS API 管理,IAM 和 K8s 配置分离
  • 可观测性好 — Session Tags 自动注入,CloudTrail 中能直接看到是哪个集群、哪个 namespace 的 Pod 发起的请求
  • 迁移平滑 — 与 IRSA 共存,逐步切换无需停服

推荐策略: 新集群直接使用 Pod Identity,存量集群制定迁移计划逐步切换。对于仍在 Fargate 上运行的工作负载,暂时保留 IRSA。目标是消除所有 OIDC Provider 依赖,统一权限管理模型。

您还没有登录,请登录后发表评论。