无法通过AWS EKS服务账号访问S3 Bucket问题求助
问题:EKS Pod绑定IAM角色后无法加载AWS凭证访问S3
背景
Java Spring Boot项目原本通过硬编码AK/SK可正常列出S3 Bucket,为遵循最佳实践,改用EKS服务账号绑定IAM角色的方式,但配置后出现凭证加载失败的错误。
已完成配置
- 创建包含S3权限的IAM策略
my-policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:Get*", "s3:List*", "s3:Describe*", "s3-object-lambda:Get*", "s3-object-lambda:List*" ], "Resource": "*" } ] }
- 通过CLI完成策略创建与服务账号绑定:
aws iam create-policy --policy-name my-policy --policy-document file://my-policy.json eksctl create iamserviceaccount --name my-service-account --namespace kube-system --cluster my-cluster --role-name my-role \ --attach-policy-arn arn:aws:iam::111122223333:policy/my-policy --approve
- 确认服务账号已关联IAM角色:
kubectl describe serviceaccount my-service-account -n kube-system
输出显示eks.amazonaws.com/role-arn注解配置正确。
修改后的代码
@GetMapping("service2/getListOfS3Buckets") public String getListOfS3Buckets() { AmazonS3 s3Client = AmazonS3ClientBuilder .standard() .withRegion(awsRegion) .withCredentials(DefaultAWSCredentialsProviderChain.getInstance()) .build(); List<Bucket> buckets = s3Client.listBuckets(); StringBuilder response = new StringBuilder("List of S3 Buckets:\n"); for (Bucket bucket : buckets) { response.append(bucket.getName()).append("\n"); } return response.toString(); }
错误信息
Request processing failed: com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS credentials from Java system properties (aws.accessKeyId and aws.secretKey), WebIdentityTokenCredentialsProvider: To use assume role profiles the aws-java-sdk-sts module must be on the class path., com.amazonaws.auth.profile.ProfileCredentialsProvider@59639381: profile file cannot be null, com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@39201cc7: Failed to connect to service endpoint:]
解决步骤
1. 确认Pod关联了目标服务账号
检查Deployment/StatefulSet配置,确保指定了正确的服务账号:
apiVersion: apps/v1 kind: Deployment metadata: name: your-app-deployment spec: template: spec: serviceAccountName: my-service-account # 与创建的服务账号名称一致 containers: - name: your-app-container image: your-app-image:tag
执行kubectl describe pod <your-pod-name> -n kube-system,验证ServiceAccount字段值为my-service-account。
2. 添加AWS STS依赖
错误提示WebIdentityTokenCredentialsProvider需要aws-java-sdk-sts模块,在项目中添加依赖:
Maven(pom.xml)
<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-sts</artifactId> <version>你的AWS SDK版本号</version> <!-- 与其他AWS SDK版本保持一致 --> </dependency>
Gradle(build.gradle)
implementation 'com.amazonaws:aws-java-sdk-sts:你的AWS SDK版本号'
3. 验证IAM角色信任关系
进入AWS控制台的IAM角色页面,检查my-role的信任策略,确保允许目标服务账号扮演该角色,示例信任策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.<region>.amazonaws.com/id/<OIDC_ID>" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.<region>.amazonaws.com/id/<OIDC_ID>:sub": "system:serviceaccount:kube-system:my-service-account" } } } ] }
注:使用eksctl创建的角色会自动配置此策略,若手动修改过需重新确认。
4. 简化客户端构建(可选)
EKS环境中,SDK可自动发现WebIdentity凭证,可省略显式指定凭证提供者:
AmazonS3 s3Client = AmazonS3ClientBuilder .standard() .withRegion(awsRegion) .build();
5. 检查Pod网络连通性
错误中提到Failed to connect to service endpoint,需确保Pod能访问AWS STS服务(sts.<region>.amazonaws.com)。若集群配置了网络策略,需允许出站访问该端点。
验证方式
部署修改后的应用后,执行以下命令测试:
kubectl exec -it <your-pod-name> -n kube-system -- curl http://localhost:<port>/service2/getListOfS3Buckets
若返回S3 Bucket列表,说明配置成功。
内容的提问来源于stack exchange,提问作者Nasil Kp
相关产品推荐
相关产品推荐

