大数跨境
0
0

在 AWS EKS 中使用 aws_iam_openid_connect_provider 解决身份认证问题

在 AWS EKS 中使用 aws_iam_openid_connect_provider 解决身份认证问题 运维开发与AI实战
2025-03-18
2
导读:aws_iam_openid_connect_provider 是 EKS 中实现 IRSA 的关键组件,连接了 Kubernetes 服务账户和 AWS IAM 角色。

在 Amazon Elastic Kubernetes Service (EKS) 中部署应用程序时,经常会遇到需要与 AWS 服务交互的场景,例如使用 Amazon EBS CSI 驱动动态创建存储卷。然而,当集群配置不当或缺少关键组件时,可能会遇到类似“缺少 OpenID Connect (OIDC) 提供程序”的错误。本文以一个真实的案例为背景,深入讲解 AWS 的 aws_iam_openid_connect_provider 资源的作用、配置方法及其在 EKS 生态中的重要性。


案例背景

我在为一个生产环境部署 Apache RocketMQ 集群到 EKS 上,使用 Terraform 管理基础设施。RocketMQ 的 Broker 需要持久化存储,因此我们配置了一个 StatefulSet,通过 volumeClaimTemplates 请求 EBS 卷。然而,在运行 kubectl apply 后,pod创建遇到了以下错误:

failed to provision volume with StorageClass "gp2": rpc error: code = Internal desc = Could not create volume "pvc-34f31fa2-a30e-4e2d-ba4e-c787d39791f6": could not create volume in EC2: operation error EC2: CreateVolume, get identity: get credentials: failed to refresh cached credentials, failed to retrieve credentials, operation error STS: AssumeRoleWithWebIdentity, exceeded maximum number of attempts, 3, https response error StatusCode: 400, RequestID: cc63c0cd-155b-4053-ad62-b48c51906bc7, InvalidIdentityToken: No OpenIDConnect provider found in your account for https://oidc.eks.ap-southeast-1.amazonaws.com/id/8DE440F2238C6B959FB7C65EA52AF80B

检查后发现:

  • 集群名称:prod,区域:ap-southeast-1,OIDC issuer URL:https://oidc.eks.ap-southeast-1.amazonaws.com/id/8DE440F2238C6B959FB7C65EA52AF80B
  • AWS IAM 中没有对应的 OIDC 提供程序(aws iam list-open-id-connect-providers 返回空)。
  • EBS CSI 驱动的 ServiceAccount ebs-csi-controller-sa 已绑定 IAM 角色 eks-ebs-csi-driver,但无法获取凭证。

问题根源在于:EKS 集群缺少 OIDC 提供程序,导致 EBS CSI 驱动无法通过 IAM Roles for Service Accounts (IRSA) 机制认证到 AWS。


什么是 aws_iam_openid_connect_provider

aws_iam_openid_connect_provider 是 AWS IAM 中的一种资源,用于在 AWS 账户中注册一个外部身份提供者(Identity Provider, IdP),支持 OpenID Connect 协议。在 EKS 中,它的作用是将 Kubernetes 集群的 OIDC 身份提供程序与 AWS IAM 集成,从而允许 Kubernetes 服务账户通过 IRSA 扮演 IAM 角色,获取 AWS API 的临时凭证。

工作原理

  1. EKS 集群的 OIDC Issuer

    • 每个 EKS 集群在创建时都会生成一个唯一的 OIDC issuer URL(例如 https://oidc.eks.ap-southeast-1.amazonaws.com/id/8DE440F2238C6B959FB7C65EA52AF80B)。
    • 这个 URL 指向集群的 OIDC 端点,负责为服务账户生成 JWT(JSON Web Token)。
  2. 注册到 AWS IAM

    • 通过 aws_iam_openid_connect_provider,你将这个 OIDC issuer 注册到 AWS 账户中,成为一个受信任的身份提供者。
    • AWS STS(Security Token Service)会验证 JWT 是否由该 OIDC 提供程序签发。
  3. IAM 角色绑定

    • 创建一个 IAM 角色(如 eks-ebs-csi-driver),并在信任关系中指定 OIDC 提供程序和特定的服务账户(例如 system:serviceaccount:kube-system:ebs-csi-controller-sa)。
    • 当服务账户所在的 Pod 发起请求时,AWS STS 会根据 JWT 颁发临时凭证。
  4. 权限执行

    • Pod 使用这些凭证调用 AWS API,例如创建 EBS 卷。

为什么需要它?

在案例中,EBS CSI 驱动需要调用 ec2:CreateVolume API 来动态创建存储卷。由于 Terraform 创建的 prod 集群未配置 OIDC 提供程序,STS 无法验证服务账户的身份,导致认证失败。


在 Terraform 中配置 aws_iam_openid_connect_provider

由于我的集群是通过 Terraform 创建的,我们可以通过 Terraform 添加 OIDC 提供程序并修复问题。以下是具体步骤和代码。

1. 获取 EKS 集群的 OIDC Issuer

使用 data 源引用现有集群:

data "aws_eks_cluster" "prod" {
  name = "prod"
}

output "oidc_issuer_url" {
  value = data.aws_eks_cluster.prod.identity[0].oidc[0].issuer
}

运行后,oidc_issuer_url 应输出 https://oidc.eks.ap-southeast-1.amazonaws.com/id/8DE440F2238C6B959FB7C65EA52AF80B

2. 创建 OIDC 提供程序

使用 aws_iam_openid_connect_provider 资源:

resource "aws_iam_openid_connect_provider" "eks_oidc" {
  url = data.aws_eks_cluster.prod.identity[0].oidc[0].issuer

  client_id_list = [
    "sts.amazonaws.com"
  ]

  thumbprint_list = [
    "9e99a48a9960b14926bb7f3b02e22da2b0ab7280"
  ]
}
  • url
    :EKS 集群的 OIDC issuer URL。
  • client_id_list
    :指定允许的客户端 ID,sts.amazonaws.com 是 AWS STS 的标准值。
  • thumbprint_list
    :OIDC 服务器证书的根 CA 指纹,用于验证签名。9e99... 是 AWS 的默认值,通常无需更改。

3. 配置 IAM 角色

为 EBS CSI 驱动创建或更新 IAM 角色,确保信任关系指向 OIDC 提供程序:

resource "aws_iam_role" "ebs_csi_driver" {
  name = "eks-ebs-csi-driver"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Federated = aws_iam_openid_connect_provider.eks_oidc.arn
        }
        Action = "sts:AssumeRoleWithWebIdentity"
        Condition = {
          StringEquals = {
            "${data.aws_eks_cluster.prod.identity[0].oidc[0].issuer}:sub" = "system:serviceaccount:kube-system:ebs-csi-controller-sa"
          }
        }
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "ebs_csi_driver_policy" {
  role       = aws_iam_role.ebs_csi_driver.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy"
}

4. 应用并验证

运行以下命令:

terraform plan -out=ftplan
terraform apply "ftplan"

完成后,检查 OIDC 提供程序:

aws --profile prod iam list-open-id-connect-providers

应返回 arn:aws:iam::140023393377:oidc-provider/oidc.eks.ap-southeast-1.amazonaws.com/id/8DE440F2238C6B959FB7C65EA52AF80B

5. 更新 Kubernetes ServiceAccount

确保 EBS CSI 的服务账户绑定到新角色:

kubectl annotate sa ebs-csi-controller-sa -n kube-system eks.amazonaws.com/role-arn=arn:aws:iam::140023393377:role/eks-ebs-csi-driver --overwrite

修复案例中的问题

配置好 OIDC 提供程序后,重试 RocketMQ 部署:

  1. 删除失败的 PVC:
    kubectl delete pvc -n rocketmq -l app=rocketmq-broker
  2. 重启 EBS CSI 控制器:
    kubectl delete pod -n kube-system -l app=ebs-csi-controller
  3. 重新应用:
    kubectl apply -f rocketmq-broker.yaml
  4. 验证:
    kubectl get pvc -n rocketmq
    kubectl get pods -n rocketmq

如果配置正确,PVC 会成功绑定到 EBS 卷,RocketMQ 的 Broker Pod 将正常运行。


为什么 Terraform 创建的集群缺少 OIDC?

在 Terraform 中,EKS 集群默认不会自动创建 OIDC 提供程序,除非你在 aws_eks_cluster 资源创建时显式配置关联的 aws_iam_openid_connect_provider。例如:

resource "aws_eks_cluster" "example" {
  name     = "example-cluster"
  role_arn = aws_iam_role.cluster.arn
  vpc_config { ... }
}

resource "aws_iam_openid_connect_provider" "example" {
  url = aws_eks_cluster.example.identity[0].oidc[0].issuer
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"]
}

在我的案例中,Terraform 配置可能只创建了集群(aws_eks_cluster),但未添加 OIDC 提供程序,导致后续 IRSA 功能失效。


替代方案:AWS Web 安装 EBS CSI

如果不想手动配置 Terraform,可以通过 AWS 管理控制台安装 EBS CSI 插件:

  • 进入 EKS 集群的 Add-ons 页面。
  • 添加 Amazon EBS CSI Driver,AWS 会自动创建 OIDC 提供程序和 IAM 角色。

这种方式更简单,但如果我们需要基础设施即代码(IaC)管理,Terraform 是更好的选择。


总结

aws_iam_openid_connect_provider 是 EKS 中实现 IRSA 的关键组件,连接了 Kubernetes 服务账户和 AWS IAM 角色。在案例中,由于缺少 OIDC 提供程序,EBS CSI 驱动无法认证,导致 RocketMQ 部署失败。通过 Terraform 配置 OIDC,可以快速修复问题,并为未来的 AWS 服务集成奠定基础。

无论是手动配置还是通过 AWS Web 安装,理解 OIDC 在 EKS 中的作用,能帮助我们更好地管理云原生工作负载,避免类似的认证难题。

【声明】内容源于网络
0
0
运维开发与AI实战
DevSecOps工程师,分享AI, Web3, Claude code开发的经验与心得。希望能帮大家解决技术难题,提升开发效率!自身从与大家的沟通中获得进步,欢迎留言交流,一起成长!
内容 2386
粉丝 0
运维开发与AI实战 DevSecOps工程师,分享AI, Web3, Claude code开发的经验与心得。希望能帮大家解决技术难题,提升开发效率!自身从与大家的沟通中获得进步,欢迎留言交流,一起成长!
总阅读3.4k
粉丝0
内容2.4k