痛点
在 EKS 集群中,Pod 访问 AWS 资源(S3、DynamoDB、SQS 等)需要 IAM 权限。长期以来,IRSA(IAM Roles for Service Accounts) 是标准方案,但随着集群规模增长,IRSA 的痛点越来越明显:
- OIDC Provider 管理复杂 — 每个集群需要配置 OIDC Provider,跨账户场景下信任关系配置繁琐
- IAM Role Trust Policy 膨胀 — 每个 Role 的信任策略必须精确匹配 OIDC issuer URL + namespace + SA name,维护成本高
- Role 数量爆炸 — 多集群共享同一 Role 需要在 Trust Policy 中逐个添加 OIDC Provider ARN,条目越来越多
- 排障困难 — 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:80 和 169.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-namespace、kubernetes-service-account、eks-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 依赖,统一权限管理模型。