Go SDK使用AWS Web Identity Token认证调用EC2返回空排查
问题根因
- 所有错误返回被完全丢弃:从session初始化、凭证获取到EC2接口调用的所有错误都被你用
_忽略了。接口调用失败时返回的result会为空,你看不到具体报错(可能是区域不匹配、权限失败、网络不通、端点配置错误等任意原因),根本无法定位问题。 - 服务客户端配置不统一:你先创建了无任何自定义配置的空session,用这个空session初始化STS客户端,后续才给EC2客户端单独传入region和凭证配置,很容易出现配置冲突——比如STS客户端未使用正确的区域端点、空session默认加载的代理/超时/元数据检测配置和EC2客户端预期配置不符。
- 冗余的手动凭证配置:容器场景下的Web Identity认证(包括EKS IRSA、ECS任务身份等),AWS Go SDK v1的默认凭证链已经原生支持,只要环境变量存在
AWS_WEB_IDENTITY_TOKEN_FILE、AWS_ROLE_ARN、AWS_REGION,SDK会自动读取token、代入角色,不需要手动创建WebIdentityRoleProvider,手动实现反而容易出现参数错误。 - 硬编码区域可能和资源实际区域不符:你硬编码了
us-east-1作为区域,如果目标EC2实例实际在其他区域,跨区调用自然查不到对应资源;你测试CLI时大概率用了实例实际所在的区域配置,所以能查询成功。
正确实现方式
优先使用SDK默认凭证链,全链路处理错误,统一所有服务客户端的配置:
package main import ( "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" ) func main() { // 初始化session时直接加载默认配置链(自动识别WebIdentity凭证、区域、代理等配置) sess, err := session.NewSessionWithOptions(session.Options{ SharedConfigState: session.SharedConfigEnable, // 自动加载环境变量、共享配置文件的配置 }) if err != nil { panic(fmt.Sprintf("初始化session失败: %v", err)) } nodeID := "i-00843f27cfeb0beff" svc := ec2.New(sess) request := &ec2.DescribeInstancesInput{ InstanceIds: []*string{aws.String(nodeID)}, } result, err := svc.DescribeInstances(request) if err != nil { panic(fmt.Sprintf("查询EC2实例失败: %v", err)) } fmt.Printf("查询结果: %v\n", result) }
如果你确实需要手动指定token路径、角色ARN,不依赖环境变量,参考如下写法,保证STS和EC2客户端使用统一配置:
package main import ( "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials/stscreds" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" ) func main() { // 初始化基础session,统一指定区域 sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-east-1"), // 这里替换为你EC2实例实际所在的区域 }) if err != nil { panic(fmt.Sprintf("初始化session失败: %v", err)) } roleARN := "arn:aws:iam::1234567:role/s2-p0o5-csi-drivers-ebs-cloud-credentials" // 用统一配置的session创建WebIdentity凭证提供者 creds := stscreds.NewWebIdentityCredentials(sess, roleARN, "gosession", "/build/token") // 给EC2客户端传入统一配置+自定义凭证 svc := ec2.New(sess, &aws.Config{ Credentials: creds, }) nodeID := "i-00843f27cfeb0beff" request := &ec2.DescribeInstancesInput{ InstanceIds: []*string{aws.String(nodeID)}, } result, err := svc.DescribeInstances(request) if err != nil { panic(fmt.Sprintf("查询EC2实例失败: %v", err)) } fmt.Printf("查询结果: %v\n", result) }
额外排查点
如果替换代码后仍有问题,按以下顺序排查:
- 确认硬编码的区域和目标EC2实例实际所在区域一致
- 确认容器内可以正常访问EC2、STS的服务端点(无网络策略拦截、代理配置正确)
- 打印接口返回的错误信息,根据错误码定向排查(比如
UnauthorizedOperation是角色权限不足,InvalidInstanceID.NotFound是实例ID/区域错误)
内容的提问来源于stack exchange,提问作者Sasi
相关产品推荐
相关产品推荐

