如何排查 Amazon EKS 中的 OIDC 提供程序和 IRSA 问题?

上次更新日期:2021 年 11 月 15 日

我的 Pod 无法将 IAM 角色权限与Amazon Elastic Kubernetes Service (Amazon EKS) 账户令牌结合使用。

简短描述

要解决 Amazon EKS 中 OpenID Connect (OIDC) 提供程序和服务账户的 IAM 角色 (IRSA) 问题,请完成以下部分之一中的步骤:

  • 检查您的集群是否存在现有的 IAM OIDC 提供程序
  • 检查您的 IAM 角色是否附加了具有所需权限的必要 IAM 策略
  • 验证是否正确设置 IAM 角色信任关系
  • 核实是否创建了服务账户
  • 验证服务账户是否具有正确的 IAM 角色注释
  • 验证是否在 Pod 中正确指定了 serviceAccountName
  • 检查环境变量和权限
  • 验证应用程序使用受支持的 AWS 开发工具包
  • 检查 Pod 用户和组
  • 重新创建 Pod
  • 验证受众是否正确
  • 验证配置的指纹是否正确
  • 对于 AWS 中国区域,请检查 AWS_DEFAULT_REGION 环境变量

解决方法

检查您的集群是否存在现有的 IAM OIDC 提供程序

如果已存在提供程序,则会收到错误消息。

例如:

WebIdentityErr: failed to retrieve credentials\ncaused by: InvalidIdentityToken: No OpenIDConnect provider found in your account 
for https://oidc.eks.eu-west-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E\n\tstatus code: 400

1.    检查集群的 OIDC 提供程序 URL:

$ aws eks describe-cluster --name cluster_name --query "cluster.identity.oidc.issuer" --output text

示例输出:

https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E

2.    列出您账户中的 IAM OIDC 提供程序。将 EXAMPLED539D4633E53DE1B716D3041E(包括 <>)替换为从上一个命令返回的值:

aws iam list-open-id-connect-providers | grep EXAMPLED539D4633E53DE1B716D3041E

示例输出:

"Arn": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"

如果前面的命令返回输出,则表明您已有集群的提供程序。如果命令没有返回输出,则必须创建 IAM OIDC 提供程序。请参阅为集群创建 IAM OIDC 提供程序

检查您的 IAM 角色是否附加了具有所需权限的必要 IAM 策略

1.    打开 IAM console(IAM 控制台)。

2.    在导航窗格中,选择角色

3.    选择要验证的角色

4.    在权限选项卡下,验证此角色是否附加了所需的策略。

验证是否正确设置 IAM 角色信任关系

使用 AWS 管理控制台:

1.    打开 IAM console(IAM 控制台)。

2.    在导航窗格中,选择角色

3.    选择要检查的角色

4.    选择信任关系选项卡以验证策略的格式是否与以下 JSON 策略的格式一致:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:sub": "system:serviceaccount:SERVICE_ACCOUNT_NAMESPACE:SERVICE_ACCOUNT_NAME",
          "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}

使用 AWS CLI:

要验证信任关系,请使用您的角色名称运行以下命令:

$ aws iam get-role --role-name EKS-IRSA

注意:EKS-IRSA 替换为您的 IAM 角色名称。

在输出 JSON 中,查找 AssumeRolePolicyDocument 部分。

示例输出:

{
    "Role": {
        "Path": "/",
        "RoleName": "EKS-IRSA",
        "RoleId": "AROAQ55NEXAMPLELOEISVX",
        "Arn": "arn:aws:iam::ACCOUNT_ID:role/EKS-IRSA",
        "CreateDate": "2021-04-22T06:39:21+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"
                    },
                    "Action": "sts:AssumeRoleWithWebIdentity",
                    "Condition": {
                        "StringEquals": {
                            "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:aud": "sts.amazonaws.com",
                            "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:sub": "system:serviceaccount:SERVICE_ACCOUNT_NAMESPACE:SERVICE_ACCOUNT_NAME"
                        }
                    }
                }
            ]
        },
        "MaxSessionDuration": 3600,
        "RoleLastUsed": {
            "LastUsedDate": "2021-04-22T07:01:15+00:00",
            "Region": "AWS_REGION"
        }
    }
}

注意:检查您是否指定了正确的 AWS 区域、Kubernetes 服务账户名称和 Kubernetes 命名空间。

核实是否创建了服务账户

使用以下命令:

$ kubectl get sa -n YOUR_NAMESPACE

注意:YOUR_NAMESPACE 替换为您的 Kubernetes 命名空间。

示例输出:

NAME      SECRETS   AGE
default   1         28d
irsa      1         66m

如果您没有服务账户,请参阅为 Pod 配置服务账户(从 Kubernetes 网站)。

验证服务账户是否具有正确的 IAM 角色注释

使用以下命令:

$ kubectl describe sa irsa -n YOUR_NAMESPACE

注意:irsa 替换为您的 Kubernetes 服务账户名称。将 YOUR_NAMESPACE 替换为您的 Kubernetes 命名空间。

示例输出:

Name:                irsa
Namespace:           default
Labels:              none
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/IAM_ROLE_NAME
Image pull secrets:  none
Mountable secrets:   irsa-token-v5rtc
Tokens:              irsa-token-v5rtc
Events:              none

验证是否在 Pod 中正确指定了 serviceAccountName

使用以下命令:

$ kubectl get pod POD_NAME  -o yaml -n YOUR_NAMESPACE| grep -i serviceAccountName:

注意:POD_NAMEYOUR_NAMESPACE 替换为您的 Kubernetes Pod 和命名空间。

示例输出:

serviceAccountName: irsa

检查环境变量和权限

在 Pod 的环境变量中查找 AWS_ROLE_ARNAWS_WEB_IDENTITY_TOKEN_FILE

$ kubectl -n YOUR_NAMESPACE exec -it POD_NAME -- env | grep AWS

示例输出:

AWS_REGION=ap-southeast-2
AWS_ROLE_ARN=arn:aws:iam::111122223333:role/EKS-IRSA
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
AWS_DEFAULT_REGION=ap-southeast-2

验证应用程序使用受支持的 AWS 开发工具包

SDK 版本必须大于或等于以下值:

Java (Version 2) — 2.10.11
Java — 1.11.704
Go — 1.23.13
Python (Boto3) — 1.9.220
Python (botocore) — 1.12.200
AWS CLI — 1.16.232
Node — 3.15.0
Ruby — 2.11.345
C++ — 1.7.174
.NET — 3.3.659.1
PHP — 3.110.7

要查看支持的最新开发工具包版本,请参阅使用支持的 AWS 开发工具包

检查 Pod 用户和组

使用以下命令:

$ kubectl exec -it POD_NAME -- id
uid=0(root) gid=0(root) groups=0(root)

注意:默认情况下,只有以根身份运行的容器才具有读取 Web 身份令牌文件的适当文件系统权限。

如果您的容器没有以根身份运行,那么您可能会收到以下错误:

Error: PermissionError: [Errno 13] Permission denied: ‘/var/run/secrets/eks.amazonaws.com/serviceaccount/token

-或者-

WebIdentityErr: failed fetching WebIdentity token: \ncaused by: WebIdentityErr: unable to read file at /var/run/secrets/eks.amazonaws.com/serviceaccount/token\ncaused by: open /var/run/secrets/eks.amazonaws.com/serviceaccount/token: permission denied

要提供适当的文件系统权限,请确保您的容器以根身份运行。 对于 1.18 或更低版本的集群,请为清单中的容器提供以下安全环境:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: my-app
spec:
 template:
    metadata:
      labels:
        app: my-app
    spec:
      serviceAccountName: my-app
      containers:
      - name: my-app
        image: my-app:latest
      securityContext:
        fsGroup: 1337
...

注意:fsGroup ID 是任意值。您可以选择任何有效的组 ID。集群 1.19 或更高版本不需要上述安全环境设置。

重新创建 Pod

如果您在应用 IRSA 之前创建了 Pod,那么请重新创建 Pod。

示例命令:

$ kubectl rollout restart deploy nginx

示例输出:

deployment.apps/nginx restarted

对于守护进程集或有状态部署,可以使用以下命令:

$ kubectl rollout restart deploy DEPLOYMENT_NAME

如果仅创建了一个 Pod,那么必须删除该 Pod 并重新创建它。

用于删除的示例命令:

$ kubectl delete pod POD_NAME

用于重新创建的示例命令:

$ kubectl apply -f SPEC_FILE

注意:SPEC_FILE 替换为您的 Kubernetes 清单文件路径和文件名。

验证受众是否正确

如果您使用错误的受众创建了 OIDC 提供程序,则会收到以下错误:

Error - An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Incorrect token audience

检查您集群的 IAM 身份提供程序。您的 ClientIDListsts.amazonaws.com

$ aws iam get-open-id-connect-provider --open-id-connect-provider-arn arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E

示例输出:

{
    "Url": "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E",
    "ClientIDList": [
        "sts.amazonaws.com"
    ],
    "ThumbprintList": [
        "9e99a48a9960b14926bb7f3b02e22da2b0ab7280"
    ],
    "CreateDate": "2021-01-21T04:29:09.788000+00:00",
    "Tags": []
}

验证配置的指纹是否正确

如果在 IAM OIDC 中配置的指纹不正确,您可能会收到以下错误消息:

failed to retrieve credentials caused by: InvalidIdentityToken: OpenIDConnect provider's HTTPS certificate doesn't match configured thumbprint

要自动配置正确的指纹,请使用 eksctl 或 AWS 管理控制台创建 IAM 身份提供程序。有关获取指纹的其他方法,请参阅为 OpenID Connect 身份提供程序获取指纹

对于 AWS 中国区域,请检查 AWS_DEFAULT_REGION 环境变量

如果您将 IRSA 用于部署到 AWS 中国区域中集群的 Pod 或守护进程,请在 Pod 规范中设置 AWS_DEFAULT_REGION 环境变量。如果未执行此操作,Pod 或守护进程可能会收到以下错误:

An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid

使用以下示例将 AWS_DEFAULT_REGION 环境变量添加到 Pod 或守护进程规范中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      labels:
        app: my-app
    spec:
      serviceAccountName: my-app
      containers:
      - name: my-app
        image: my-app:latest
        env:
        - name: AWS_DEFAULT_REGION
          value: "AWS_REGION"
...

这篇文章对您有帮助吗?


您是否需要账单或技术支持?