如何在EKS Pod中以环境变量形式获取AWS角色密钥?
首先纠正你的思路:不要从节点实例元数据获取凭证,这会让Pod继承节点的IAM角色权限,违反最小权限原则,EKS官方推荐的是使用**IAM Roles for Service Accounts(IRSA)**为Pod分配专属IAM角色,这也是最安全合规的方式。
你看不到环境变量里的凭证,是因为IRSA默认不会将凭证注入为环境变量——AWS SDK会自动通过容器内的服务账户token获取临时凭证,无需手动处理。下面是具体实现步骤和注意事项:
一、确认IRSA基础配置是否正确
先排查核心配置是否到位,这是凭证能正常生效的前提:
- EKS集群已配置OIDC身份提供商:运行
aws eks describe-cluster --name <cluster-name> --query "cluster.identity.oidc.issuer",能返回OIDC issuer URL即为已配置。 - IAM角色信任策略正确:角色的信任策略必须允许对应的EKS OIDC提供商和目标服务账户(ServiceAccount)扮演该角色,示例策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<account-id>:oidc-provider/<oidc-issuer-host>" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "<oidc-issuer-host>:sub": "system:serviceaccount:<namespace>:<serviceaccount-name>" } } } ] } - ServiceAccount关联IAM角色:在ServiceAccount的annotations中添加目标角色ARN:
apiVersion: v1 kind: ServiceAccount metadata: name: <sa-name> namespace: <namespace> annotations: eks.amazonaws.com/role-arn: arn:aws:iam::<account-id>:role/<role-name> - Pod指定该ServiceAccount:在Pod的spec中设置
serviceAccountName字段:spec: serviceAccountName: <sa-name> containers: - name: your-app image: your-app-image
二、让应用自动获取凭证(最佳实践)
只要你的应用使用AWS SDK v1.11.53+或v2.x,SDK会自动从容器内的路径/var/run/secrets/eks.amazonaws.com/serviceaccount/token读取服务账户token,然后调用STS服务获取临时凭证,整个过程无需手动配置环境变量或凭证文件。
如果应用无法自动识别,可以手动设置以下环境变量引导SDK:
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token AWS_ROLE_ARN=arn:aws:iam::<account-id>:role/<role-name>
这些变量可直接在Pod的env字段中定义,部分EKS版本也支持自动注入。
三、强制将凭证注入为环境变量(仅兼容旧应用场景)
如果你的应用必须通过AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN这三个环境变量获取凭证,可以通过initContainer或sidecar容器来获取临时凭证并注入:
使用initContainer的示例配置
apiVersion: v1 kind: Pod metadata: name: app-with-creds spec: serviceAccountName: <sa-name> initContainers: - name: fetch-creds image: amazon/aws-cli:latest command: - sh - -c - | # 读取IRSA提供的token和角色ARN TOKEN=$(cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token) ROLE_ARN=$(cat /var/run/secrets/eks.amazonaws.com/serviceaccount/role-arn) # 调用STS获取临时凭证 CREDS=$(aws sts assume-role-with-web-identity --role-arn $ROLE_ARN --role-session-name pod-session --web-identity-token "$TOKEN") # 将凭证写入共享volume的脚本文件 echo "export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r '.Credentials.AccessKeyId')" > /creds/setup.sh echo "export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r '.Credentials.SecretAccessKey')" >> /creds/setup.sh echo "export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r '.Credentials.SessionToken')" >> /creds/setup.sh volumeMounts: - name: creds-volume mountPath: /creds - name: aws-token mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount containers: - name: app-container image: your-app-image command: - sh - -c - | # 加载凭证环境变量后启动应用 source /creds/setup.sh exec your-app-command volumeMounts: - name: creds-volume mountPath: /creds volumes: - name: creds-volume emptyDir: {} - name: aws-token projected: sources: - serviceAccountToken: path: token expirationSeconds: 86400 audience: sts.amazonaws.com
注意:临时凭证默认有效期为1小时,这种方式需要手动处理凭证刷新(比如用sidecar定时更新),安全性和可靠性远不如SDK自动处理,仅在无法使用AWS SDK的场景下使用。
内容的提问来源于stack exchange,提问作者Anton Kim

