

 **帮助改进此页面** 

要帮助改进本用户指南，请选择位于每个页面右侧窗格中的**在 GitHub 上编辑此页面**链接。

# 服务账户的 IAM 角色
<a name="iam-roles-for-service-accounts"></a>

**提示**  
 [注册参加](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el)即将举办的 Amazon EKS 讲习会。

容器组（pod）的容器中的应用程序可以使用 AWS SDK 或 AWS CLI 以向使用 AWS Identity and Access Management（IAM）权限的 AWS 服务 发出 API 请求。应用程序必须通过 AWS 凭证签署 AWS API 请求。**服务账户的 IAM 角色（IRSA）**可用于管理供应用程序使用的凭证，这与 Amazon EC2 实例配置文件为 Amazon EC2 实例提供凭证的方式类似。您可以将 IAM 角色与 Kubernetes 服务账户关联并配置容器组（pod）来使用服务账户，而不是创建 AWS 凭证并将其分配到容器或使用 Amazon EC2 实例的角色。您不能将服务账户的 IAM 角色用于 [AWS Outposts 上的 Amazon EKS 本地集群](eks-outposts-local-cluster-overview.md)。

服务账户的 IAM 角色提供下列优势：
+  **最低权限** – 您可以将 IAM 权限范围限定到服务账户，并且只有使用该服务账户的容器组（pod）可以访问这些权限。此功能还消除了对 `kiam` 或 `kube2iam` 等第三方解决方案的需求。
+  **凭证隔离**：当对 [Amazon EC2 实例元数据服务（IMDS）](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)的访问受到限制时，容器组的容器只能检索与该容器所使用服务账户关联的 IAM 角色的凭证。容器永远无法访问其他容器组（pod）中其他容器所使用的凭证。如果 IMDS 不受限制，则容器组的容器还可以访问 [Amazon EKS 节点 IAM 角色](create-node-role.md)，并且容器可能能够访问同一节点上其他容器组 IAM 角色的凭证。有关更多信息，请参阅[限制对分配给 Worker 节点的实例配置文件的访问](https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html#_identities_and_credentials_for_eks_pods_recommendations)。

**注意**  
配置为 `hostNetwork: true` 的容器组将始终具有 IMDS 访问权限，但 AWS SDK 和 CLI 在启用后将使用 IRSA 凭证。
+  **可审核性** – 可通过 AWS CloudTrail 进行访问和事件日志记录以帮助确保可追溯性审核。

**重要**  
容器并非安全边界，使用服务账户的 IAM 角色也不会改变这一点。分配给同一个节点的容器组将共享一个内核，并可能共享其他资源，具体视您的容器组配置而定。虽然在不同节点上运行的容器组将在计算层被隔离，但有些节点应用程序在 Kubernetes API 中拥有超出单个实例范围的额外权限。一些示例包括 `kubelet`、`kube-proxy`、CSI 存储驱动程序或您自己的 Kubernetes 应用程序。

通过完成下列步骤为服务账户启用 IAM 角色：

1.  [为集群创建 IAM OIDC 提供者](enable-iam-roles-for-service-accounts.md) – 您只需为集群完成一次此操作。
**注意**  
如果启用了 EKS VPC 端点，则无法从该 VPC 内部访问 EKS OIDC 服务端点。因此，您在 VPC 中使用 `eksctl` 创建 OIDC 提供者等操作将不起作用，并且在尝试请求 `https://oidc.eks.region.amazonaws.com` 时将导致超时。错误消息示例如下：  

   ```
   server cant find oidc.eks.region.amazonaws.com: NXDOMAIN
   ```
要完成此步骤，您可以在 VPC 外部运行该命令，例如在 AWS CloudShell 中或在连接到互联网的计算机上。您也可在 VPC 中创建水平分割条件解析器（例如 Route 53 Resolver），以便为 OIDC 发布者 URL 使用不同的解析器，而不对其使用 VPC DNS。有关 CoreDNS 中条件转发的示例，请参阅 GitHub 上的 [Amazon EKS feature request](https://github.com/aws/containers-roadmap/issues/2038)。

1.  [将 IAM 角色分配给 Kubernetes 服务账户](associate-service-account-role.md) – 针对您希望应用程序拥有的每组唯一权限完成此步骤。

1.  [将容器组（pod）配置为使用 Kubernetes 服务账户](pod-configuration.md) – 为需要访问 AWS 服务的每个 容器组（pod）完成此过程。

1.  [将 IRSA 与 AWS SDK 结合使用](iam-roles-for-service-accounts-minimum-sdk.md) – 确认工作负载使用支持版本的 AWS SDK，并且工作负载使用默认凭证链。

## IAM、Kubernetes 和 OpenID Connect（OIDC）背景信息
<a name="irsa-oidc-background"></a>

2014 年，AWS Identity and Access Management 使用 OpenID Connect（OIDC）增加了对联合身份验证的支持。此功能允许您通过支持的身份提供商对 AWS API 调用进行身份验证，并获得有效的 OIDC JSON Web 令牌 (JWT)。您可以将此令牌传递到 AWS STS `AssumeRoleWithWebIdentity` API 操作并接收 IAM 临时角色凭证。您可以使用这些凭证与任意 AWS 服务交互，包括 Amazon S3 和 DynamoDB。

每个 JWT 令牌均由签名密钥对签名。密钥由 Amazon EKS 管理的 OIDC 提供者提供，私钥每 7 天轮换一次。Amazon EKS 会保留公钥直至其过期。如果您连接外部 OIDC 客户端，请注意您需要在公钥过期之前刷新签名密钥。了解如何[获取签名密钥以验证 OIDC 令牌](irsa-fetch-keys.md)。

Kubernetes 长期以来将服务账户用作其内部身份系统。Pod 可以使用自动装载的令牌（这是非 OIDC JWT，只有 Kubernetes API 服务器可以验证）进行 Kubernetes API 服务器的身份验证。这些旧服务账户令牌不会过期，轮换签名密钥是一个困难的过程。在 Kubernetes `1.12` 版本中，添加了对新 `ProjectedServiceAccountToken` 功能的支持。此功能是 OIDC JSON Web 令牌，包含了服务账户身份，且支持可配置的受众。

Amazon EKS 为包含 `ProjectedServiceAccountToken` JSON Web 令牌的签名密钥的每个集群托管公有 OIDC 发现端点，这样 IAM 等外部系统就可以验证和接收 Kubernetes 颁发的 OIDC 令牌。

# 为集群创建 IAM OIDC 提供商
<a name="enable-iam-roles-for-service-accounts"></a>

您的集群具有与其关联的 [OpenID Connect](https://openid.net/connect/)（OIDC）发布者 URL。要将 AWS Identity and Access Management（IAM）角色用于服务账户，您集群的 OIDC 发布者 URL 必须存在 IAM OIDC 提供者。

## 先决条件
<a name="_prerequisites"></a>
+ 现有 Amazon EKS 集群。要部署一个角色，请参阅[开始使用 Amazon EKS](getting-started.md)。
+ 在您的设备或 AWS CloudShell 上安装和配置 AWS 命令行界面（AWS CLI）的版本 `2.12.3` 或更高版本，或版本 `1.27.160` 或更高版本。要查看当前版本，请使用 `aws --version | cut -d / -f2 | cut -d ' ' -f1`。`yum`、`apt-get` 或适用于 macOS 的 Homebrew 等软件包管理器通常比 AWS CLI 的最新版本落后几个版本。要安装最新版本，请参阅《AWS 命令行界面用户指南》**中的[安装](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)和[使用 aws configure 快速配置](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。AWS CloudShell 中安装的 AWS CLI 版本也可能比最新版本落后几个版本。要对其进行更新，请参阅《AWS CloudShell 用户指南》**中的[将 AWS CLI 安装到您的主目录](https://docs.aws.amazon.com/cloudshell/latest/userguide/vm-specs.html#install-cli-software)。
+ 您的设备或 AWS CloudShell 上安装了 `kubectl` 命令行工具。该版本可以与集群的 Kubernetes 版本相同，或者最多早于或晚于该版本一个次要版本。例如，如果您的集群版本为 `1.29`，则可以将 `kubectl` 的 `1.28`、`1.29` 或 `1.30` 版本与之配合使用。要安装或升级 `kubectl`，请参阅 [设置 `kubectl` 和 `eksctl`](install-kubectl.md)。
+ 包含集群配置的现有 `kubectl` `config` 文件。要创建 `kubectl` `config` 文件，请参阅 [通过创建 kubeconfig 文件将 kubectl 连接到 EKS 集群](create-kubeconfig.md)。

您可以使用 `eksctl` 或 AWS 管理控制台为集群创建 IAM OIDC 提供者。

## 创建 OIDC 提供者（eksctl）
<a name="_create_oidc_provider_eksctl"></a>

1. 您的设备或 AWS CloudShell 上安装 `0.215.0` 版或更高版本的 `eksctl` 命令行工具。要安装或更新 `eksctl`，请参阅 `eksctl` 文档中的 [Installation](https://eksctl.io/installation)。

1. 确定集群的 OIDC 发布者 ID。

   检索集群的 OIDC 发布者 ID 并将其存储在变量中。将 `<my-cluster>` 替换为您自己的值。

   ```
   cluster_name=<my-cluster>
   oidc_id=$(aws eks describe-cluster --name $cluster_name --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
   echo $oidc_id
   ```

1. 确定账户中是否已存在具有集群发布者 ID 的 IAM OIDC 提供者。

   ```
   aws iam list-open-id-connect-providers | grep $oidc_id | cut -d "/" -f4
   ```

   如果返回了输出，则表示集群已经有 IAM OIDC 提供者，您可以跳过下一步。如果没有返回输出，则您必须为集群创建 IAM OIDC 提供者。

1. 使用以下命令为您的集群创建 IAM OIDC 身份提供商。

   ```
   eksctl utils associate-iam-oidc-provider --cluster $cluster_name --approve
   ```
**注意**  
如果启用了 EKS VPC 端点，则无法从该 VPC 内部访问 EKS OIDC 服务端点。因此，您在 VPC 中使用 `eksctl` 创建 OIDC 提供者等操作将不起作用，并将导致超时。错误消息示例如下：  

   ```
   ** server cant find oidc.eks.<region-code>.amazonaws.com: NXDOMAIN
   ```

   要完成此步骤，您可以在 VPC 外部运行该命令，例如在 AWS CloudShell 中或在连接到互联网的计算机上。您也可在 VPC 中创建水平分割条件解析器（例如 Route 53 Resolver），以便为 OIDC 发布者 URL 使用不同的解析器，而不对其使用 VPC DNS。有关 CoreDNS 中条件转发的示例，请参阅 GitHub 上的 [Amazon EKS feature request](https://github.com/aws/containers-roadmap/issues/2038)。

## 创建 OIDC 提供者（AWS 控制台）
<a name="create_oidc_provider_shared_aws_console"></a>

1. 打开 [Amazon EKS 控制台](https://console.aws.amazon.com/eks/home#/clusters)。

1. 在左侧窗格中，选择 **Clusters**（集群），然后在 **Clusters**（集群）页面上选择集群的名称。

1. 在 **Overview**（概述）选项卡上的 **Details**（详细信息）部分中，记下 **OpenID Connect provider URL**（OpenID Connect 提供商 URL）的值。

1. 通过 https://console.aws.amazon.com/iam/ 打开 IAM 控制台。

1. 请在左侧导航窗格中，选择 **Access management**（访问管理）下方的 **Identity Providers**（标识提供程序）。如果列出的 **Provider（提供商）**与集群的 URL 匹配，那么您的集群已经有了提供商。如果未列出与集群 URL 匹配的提供者，则必须创建一个提提供者。

1. 要创建提供商，请选择 **Add Provider**（添加提供商）。

1. 对于**提供者类型**，选择 **OpenID Connect**。

1. 对于**提供者 URL**，输入集群的 OIDC 提供者 URL。

1. 对于**受众**,，输入 `sts.amazonaws.com`。

1. （可选）添加任何标签，例如用于标识哪个集群用于该提供商的标签。

1. 选择**添加提供程序**。

下一步: [为 Kubernetes 服务账户分配 IAM 角色](associate-service-account-role.md) 

# 为 Kubernetes 服务账户分配 IAM 角色
<a name="associate-service-account-role"></a>

本主题介绍如何配置 Kubernetes 服务账户，以担任 AWS Identity and Access Management（IAM）角色。然后，配置为使用服务账户的任何容器组（pod）都可以访问该角色有权访问的任何 AWS 服务。

## 先决条件
<a name="_prerequisites"></a>
+ 现有集群。如果您没有，可以按照[开始使用 Amazon EKS](getting-started.md) 中的指南之一创建一个。
+ 您的集群的现有 IAM OpenID Connect (OIDC) 提供商。要了解您是否已拥有一个（IAM）角色或如何创建一个（IAM）角色，请参阅 [为集群创建 IAM OIDC 提供商](enable-iam-roles-for-service-accounts.md)。
+ 在您的设备或 AWS CloudShell 上安装和配置 AWS 命令行界面（AWS CLI）的版本 `2.12.3` 或更高版本，或版本 `1.27.160` 或更高版本。要查看当前版本，请使用 `aws --version | cut -d / -f2 | cut -d ' ' -f1`。`yum`、`apt-get` 或适用于 macOS 的 Homebrew 等软件包管理器通常比 AWS CLI 的最新版本落后几个版本。要安装最新版本，请参阅《AWS 命令行界面用户指南》**中的[安装](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)和[使用 aws configure 快速配置](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。AWS CloudShell 中安装的 AWS CLI 版本也可能比最新版本落后几个版本。要对其进行更新，请参阅《AWS CloudShell 用户指南》**中的[将 AWS CLI 安装到您的主目录](https://docs.aws.amazon.com/cloudshell/latest/userguide/vm-specs.html#install-cli-software)。
+ 您的设备或 AWS CloudShell 上安装了 `kubectl` 命令行工具。该版本可以与集群的 Kubernetes 版本相同，或者最多早于或晚于该版本一个次要版本。例如，如果您的集群版本为 `1.29`，则可以将 `kubectl` 的 `1.28`、`1.29` 或 `1.30` 版本与之配合使用。要安装或升级 `kubectl`，请参阅 [设置 `kubectl` 和 `eksctl`](install-kubectl.md)。
+ 包含集群配置的现有 `kubectl` `config` 文件。要创建 `kubectl` `config` 文件，请参阅 [通过创建 kubeconfig 文件将 kubectl 连接到 EKS 集群](create-kubeconfig.md)。

## 步骤 1：创建 IAM 策略
<a name="irsa-associate-role-procedure"></a>

要将现有 IAM 策略关联到您的 IAM 角色，请跳至下一步。

1. 创建一个 IAM 策略。您可以创建自己的策略，也可以复制已授予您部分所需权限的 AWS 托管策略，并根据您的特定要求对其进行自定义。有关更多信息，请参阅《IAM 用户指南》**中的[创建 IAM 策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html)。

1. 创建一个文件，其中包含您希望容器组（pod）访问的 AWS 服务所需的权限。有关所有 AWS 服务的所有操作的列表，请参阅[服务授权参考](https://docs.aws.amazon.com/service-authorization/latest/reference/)。

   您可以运行以下命令创建一个示例策略文件，以实现对 Amazon S3 存储桶的只读访问权限。您可以选择将配置信息或引导脚本存储在此存储桶中，并且容器组（pod）中的容器可以从存储桶读取文件并将其加载到应用程序中。如果您要创建此示例策略，请将以下内容复制到您的设备。将 *my-pod-secrets-bucket* 替换为您的存储桶名称并运行该命令。

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "s3:GetObject",
               "Resource": "arn:aws:s3:::my-pod-secrets-bucket"
           }
       ]
   }
   ```

1. 创建 IAM 策略。

   ```
   aws iam create-policy --policy-name my-policy --policy-document file://my-policy.json
   ```

## 步骤 2：创建和关联 IAM 角色
<a name="_step_2_create_and_associate_iam_role"></a>

创建 IAM 角色并将其与 Kubernetes 服务账户关联。您可以使用 `eksctl` 或 AWS CLI。

### 创建和关联角色（eksctl）
<a name="_create_and_associate_role_eksctl"></a>

此 `eksctl` 命令会在指定的命名空间中创建一个 Kubernetes 服务账户，创建具有指定名称的 IAM 角色（如果其不存在），将现有的 IAM 策略 ARN 附加到该角色，并使用 IAM 角色 ARN 为该服务账户添加注释。请务必使用您的具体值替换此命令中的示例占位符值。要安装或更新 `eksctl`，请参阅 `eksctl` 文档中的 [Installation](https://eksctl.io/installation)。

```
eksctl create iamserviceaccount --name my-service-account --namespace default --cluster my-cluster --role-name my-role \
    --attach-policy-arn arn:aws:iam::111122223333:policy/my-policy --approve
```

**重要**  
如果角色或服务账户已经存在，则之前的命令可能会失败。在这些情况下，`eksctl` 提供不同的选项供您使用。有关更多信息，请运行 `eksctl create iamserviceaccount --help`。

### 创建和关联角色（AWS CLI）
<a name="create_and_associate_role_shared_aws_cli"></a>

如果您有要担任 IAM 角色的现有 Kubernetes 服务账户，则可跳过此步骤。

1. 创建一个 Kubernetes 服务账户。将以下内容复制到您的设备。将 *my-service-account* 替换为所需的名称，如有必要，将 *default* 替换为其他命名空间。如更改 *default*，则命名空间必须已经存在。

   ```
   cat >my-service-account.yaml <<EOF
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: my-service-account
     namespace: default
   EOF
   kubectl apply -f my-service-account.yaml
   ```

1. 使用以下命令将 AWS 账户 ID 设置为环境变量。

   ```
   account_id=$(aws sts get-caller-identity --query "Account" --output text)
   ```

1. 使用以下命令将集群的 OIDC 身份提供者设置为环境变量。将 *my-cluster* 替换为您的集群的名称。

   ```
   oidc_provider=$(aws eks describe-cluster --name my-cluster --region $AWS_REGION --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
   ```

1. 为服务账户的命名空间和名称设置变量。将 *my-service-account* 替换为要担任角色的 Kubernetes 服务账户。将 *default* 替换为服务账户的命名空间。

   ```
   export namespace=default
   export service_account=my-service-account
   ```

1. 运行以下命令为 IAM 角色创建信任策略文件。若要允许命名空间内的所有服务账户使用该角色，请将以下内容复制到您的设备。将 *StringEquals* 替换为 `StringLike`，并将 *\$1service\$1account* 替换为 `*`。您可在 `StringEquals` 和 `StringLike` 条件中添加多个条目，以允许多个服务账户或命名空间分派角色。要允许其它 AWS 账户中的角色（而不是您的集群所在账户中的角色）分派该角色户，请参阅[使用 IRSA 对另一个账户进行身份验证](cross-account-access.md)获取更多信息。

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Federated": "arn:aws:iam::123456789012:oidc-provider/$oidc_provider"
         },
         "Action": "sts:AssumeRoleWithWebIdentity",
         "Condition": {
           "StringEquals": {
             "$oidc_provider:aud": "sts.amazonaws.com",
             "$oidc_provider:sub": "system:serviceaccount:$namespace:$service_account"
           }
         }
       }
     ]
   }
   ```

1. 创建角色。将 *my-role* 替换为您的 IAM 角色的名称，并将 *my-role-description* 替换为您的角色的描述。

   ```
   aws iam create-role --role-name my-role --assume-role-policy-document file://trust-relationship.json --description "my-role-description"
   ```

1. 将 IAM 策略附加到您的角色。将 *my-role* 替换为您的 IAM 角色的名称，并将 *my-policy* 替换为您创建的现有策略的名称。

   ```
   aws iam attach-role-policy --role-name my-role --policy-arn=arn:aws:iam::$account_id:policy/my-policy
   ```

1. 请使用要让服务账户分派的 IAM 角色的 Amazon 资源名称（ARN）注释您的服务账户。将 *my-role* 替换为您的现有 IAM 角色的名称。假设您在上一步中允许其它 AWS 账户中的角色（而不是您的集群所在账户中的角色）分派该角色户。那么，请确保指定其它账户中的 AWS 账户和角色。有关更多信息，请参阅[使用 IRSA 对另一个账户进行身份验证](cross-account-access.md)。

   ```
   kubectl annotate serviceaccount -n $namespace $service_account eks.amazonaws.com/role-arn=arn:aws:iam::$account_id:role/my-role
   ```

1. （可选）[为服务账户配置 AWS Security Token Service 端点](configure-sts-endpoint.md)。AWS 建议使用区域级 AWS STS 端点而不是全局端点。这可以减少延迟，提供内置冗余并提高会话令牌的有效性。

## 步骤 3：确认配置
<a name="irsa-confirm-role-configuration"></a>

1. 确认 IAM 角色的信任策略配置正确。

   ```
   aws iam get-role --role-name my-role --query Role.AssumeRolePolicyDocument
   ```

   示例输出如下。

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": {
                   "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
               },
               "Action": "sts:AssumeRoleWithWebIdentity",
               "Condition": {
                   "StringEquals": {
                       "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:default:my-service-account",
                       "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
                   }
               }
           }
       ]
   }
   ```

1. 确认您在上一步中附加到角色的策略已附加到该角色。

   ```
   aws iam list-attached-role-policies --role-name my-role --query "AttachedPolicies[].PolicyArn" --output text
   ```

   示例输出如下。

   ```
                  arn:aws:iam::111122223333:policy/my-policy
   ```

1. 设置一个变量以存储要使用策略的 Amazon 资源名称（ARN）。将 *my-policy* 替换为要确认其权限的策略的名称。

   ```
   export policy_arn=arn:aws:iam::111122223333:policy/my-policy
   ```

1. 查看该策略的默认版本。

   ```
   aws iam get-policy --policy-arn $policy_arn
   ```

   示例输出如下。

   ```
   {
       "Policy": {
           "PolicyName": "my-policy",
           "PolicyId": "EXAMPLEBIOWGLDEXAMPLE",
           "Arn": "arn:aws:iam::111122223333:policy/my-policy",
           "Path": "/",
           "DefaultVersionId": "v1",
           [...]
       }
   }
   ```

1. 查看策略内容以确保该策略包含容器组（pod）所需的所有权限。如有必要，将以下命令中的 *1* 替换为上一个输出中返回的版本。

   ```
   aws iam get-policy-version --policy-arn $policy_arn --version-id v1
   ```

   示例输出如下。

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "s3:GetObject",
               "Resource": "arn:aws:s3:::my-pod-secrets-bucket"
           }
       ]
   }
   ```

   如果您在上一步中创建了示例策略，则您的输出与示例相同。如果您创建了其他策略，则与*示例*内容不同。

1. 确认已使用角色为 Kubernetes 服务账户添加注释。

   ```
   kubectl describe serviceaccount my-service-account -n default
   ```

   示例输出如下。

   ```
   Name:                my-service-account
   Namespace:           default
   Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role
   Image pull secrets:  <none>
   Mountable secrets:   my-service-account-token-qqjfl
   Tokens:              my-service-account-token-qqjfl
   [...]
   ```

## 后续步骤
<a name="_next_steps"></a>
+  [配置容器组（pod）使用 Kubernetes 服务账户](pod-configuration.md) 

# 配置容器组（pod）使用 Kubernetes 服务账户
<a name="pod-configuration"></a>

如果容器组（pod）需要访问 AWS 服务，则必须配置它来使用 Kubernetes 服务账户。服务账户必须关联到有权访问 AWS 服务的 AWS Identity and Access Management（IAM）角色。
+ 现有集群。如果还没有，可以使用[开始使用 Amazon EKS](getting-started.md) 中的指南之一创建一个。
+ 您的集群的现有 IAM OpenID Connect (OIDC) 提供商。要了解您是否已拥有一个（IAM）角色或如何创建一个（IAM）角色，请参阅 [为集群创建 IAM OIDC 提供商](enable-iam-roles-for-service-accounts.md)。
+ 与 IAM 角色关联的现有 Kubernetes 服务账户。必须使用 IAM 角色的 Amazon 资源名称（ARN）注释服务账户。该角色必须具有关联的 IAM 策略，其中包含您希望容器组（pod）必须具有的权限，以便使用 AWS 服务。有关如何创建和配置服务账户和角色的更多信息，请参阅 [为 Kubernetes 服务账户分配 IAM 角色](associate-service-account-role.md)。
+ 在您的设备或 AWS CloudShell 上安装和配置 AWS 命令行界面（AWS CLI）的版本 `2.12.3` 或更高版本，或版本 `1.27.160` 或更高版本。要查看当前版本，请使用 `aws --version | cut -d / -f2 | cut -d ' ' -f1`。`yum`、`apt-get` 或适用于 macOS 的 Homebrew 等软件包管理器通常比 AWS CLI 的最新版本落后几个版本。要安装最新版本，请参阅《AWS 命令行界面用户指南》**中的[安装](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)和[使用 aws configure 快速配置](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。AWS CloudShell 中安装的 AWS CLI 版本也可能比最新版本落后几个版本。要对其进行更新，请参阅《AWS CloudShell 用户指南》**中的[将 AWS CLI 安装到您的主目录](https://docs.aws.amazon.com/cloudshell/latest/userguide/vm-specs.html#install-cli-software)。
+ 您的设备或 AWS CloudShell 上安装了 `kubectl` 命令行工具。该版本可以与集群的 Kubernetes 版本相同，或者最多早于或晚于该版本一个次要版本。例如，如果您的集群版本为 `1.29`，则可以将 `kubectl` 的 `1.28`、`1.29` 或 `1.30` 版本与之配合使用。要安装或升级 `kubectl`，请参阅 [设置 `kubectl` 和 `eksctl`](install-kubectl.md)。
+ 包含集群配置的现有 `kubectl` `config` 文件。要创建 `kubectl` `config` 文件，请参阅 [通过创建 kubeconfig 文件将 kubectl 连接到 EKS 集群](create-kubeconfig.md)。

  1. 使用以下命令创建部署清单，您可以使用该部署清单部署容器组（pod）来确认配置。将示例值替换为您自己的值。

     ```
     cat >my-deployment.yaml <<EOF
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: my-app
     spec:
       selector:
         matchLabels:
           app: my-app
       template:
         metadata:
           labels:
             app: my-app
         spec:
           serviceAccountName: my-service-account
           containers:
           - name: my-app
             image: public.ecr.aws/nginx/nginx:X.XX
     EOF
     ```

  1. 将清单部署到集群。

     ```
     kubectl apply -f my-deployment.yaml
     ```

  1. 确认容器组（pod）具有所需的环境变量。

     1. 按上一步部署后，查看部署的容器组（pod）。

        ```
        kubectl get pods | grep my-app
        ```

        示例输出如下。

        ```
        my-app-6f4dfff6cb-76cv9   1/1     Running   0          3m28s
        ```

     1. 查看容器组（pod）使用的 IAM 角色的 ARN。

        ```
        kubectl describe pod my-app-6f4dfff6cb-76cv9 | grep AWS_ROLE_ARN:
        ```

        示例输出如下。

        ```
        AWS_ROLE_ARN:                 arn:aws:iam::111122223333:role/my-role
        ```

        角色 ARN 必须与您用于注释现有服务账户的角色 ARN 匹配。有注释服务账户的更多信息，请参阅 [为 Kubernetes 服务账户分配 IAM 角色](associate-service-account-role.md)。

     1. 确认容器组（pod）有 Web 身份令牌文件挂载。

        ```
        kubectl describe pod my-app-6f4dfff6cb-76cv9 | grep AWS_WEB_IDENTITY_TOKEN_FILE:
        ```

        示例输出如下。

        ```
        AWS_WEB_IDENTITY_TOKEN_FILE:  /var/run/secrets/eks.amazonaws.com/serviceaccount/token
        ```

        `kubelet` 代表容器组（pod）请求并存储令牌。默认情况下，如果令牌早于其总生存时间的 80%，或者令牌大于 24 小时，则 `kubelet` 会刷新令牌。您可以使用容器组（pod）规范中的设置修改任何账户（默认服务账户除外）的到期期限。有关更多信息，请参阅 Kubernetes 文档中的[服务账户令牌卷预测](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection)。

        集群上的 [Amazon EKS 容器组身份 Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook#amazon-eks-pod-identity-webhook) 监控使用具有以下注释的服务账户：

        ```
        eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role
        ```

        Webhook 将之前的环境变量应用于这些容器组（pod）。您的集群无需使用 Webhook 来配置环境变量和令牌文件挂载。您可以手动配置容器组（pod）来包含这些环境变量。[AWS 开发工具包支持的版本](iam-roles-for-service-accounts-minimum-sdk.md)首先在凭证链提供商中查找这些环境变量。角色凭证用于满足这些标准的容器组（pod）。

  1. 确认您的容器组（pod）可以使用您在附加到角色的 IAM 策略中分配的权限与 AWS 服务进行交互。
**注意**  
当容器组（pod）使用来自与服务账户关联的 IAM 角色的 AWS 凭证时，该容器组（pod）中的 AWS CLI 或其他 SDK 包仅使用该角色提供的凭证。如果您不限制对提供给 [Amazon EKS 节点 IAM 角色](create-node-role.md)的凭证的访问，容器组（pod）仍然可以访问这些凭证。有关更多信息，请参阅[限制对分配给 Worker 节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

     如果您的容器组（pod）无法按预期与服务进行交互，请完成以下步骤，确认所有配置都正确。

     1. 确认您的容器组（pod）使用支持通过 OpenID Connect Web 身份令牌文件担任 IAM 角色的 AWS SDK 版本。有关更多信息，请参阅 [将 IRSA 与 AWS SDK 结合使用](iam-roles-for-service-accounts-minimum-sdk.md)。

     1. 确认部署正在使用服务账户。

        ```
        kubectl describe deployment my-app | grep "Service Account"
        ```

        示例输出如下。

        ```
        Service Account:  my-service-account
        ```

     1. 如果您的容器组（pod）仍然无法访问服务，请查看[为 Kubernetes 服务账户分配 IAM 角色](associate-service-account-role.md#irsa-confirm-role-configuration)中描述的[步骤](associate-service-account-role.md)，确认角色和服务账户的配置都正确。

# 为服务账户配置 AWS Security Token Service 端点
<a name="configure-sts-endpoint"></a>

如果将 Kubernetes 服务账户与[服务账户的 IAM 角色](iam-roles-for-service-accounts.md)结合使用，则可配置服务账户使用的 AWS Security Token Service 端点类型。

 AWS 建议使用区域 AWS STS 端点而不是全局端点。这可以减少延迟，提供内置冗余并提高会话令牌的有效性。AWS Security Token Service 必须在容器组（pod）运行的 AWS 区域处于活动状态。此外，您的应用程序必须内置冗余功能，以便在该 AWS 区域的服务出现故障时选择其它 AWS 区域。有关更多信息，请参阅《IAM 用户指南》中的[在 AWS 区域中管理 AWS STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)。
+ 现有集群。如果还没有，可以使用 [开始使用 Amazon EKS](getting-started.md) 中的指南之一创建一个。
+ 集群的现有 IAM OIDC 提供商。有关更多信息，请参阅 [为集群创建 IAM OIDC 提供商](enable-iam-roles-for-service-accounts.md)。
+ 现有的 Kubernetes 服务账户配置为与[适用于服务账户的 Amazon EKS IAM](iam-roles-for-service-accounts.md) 功能结合使用。

以下示例全部使用 [Amazon VPC CNI 插件](cni-iam-role.md)所使用的 aws-node Kubernetes 服务账户。可将*示例值*替换为您自己的服务账户、容器组（pod）、命名空间和其他资源。

1. 选择一个使用要更改其端点的服务账户的容器组（pod）。确定容器组（pod）在其中运行的 AWS 区域。将 *aws-node-6mfgv* 替换为容器组（pod）的名称，并将 *kube-system* 替换为容器组（pod）的命名空间。

   ```
   kubectl describe pod aws-node-6mfgv -n kube-system |grep Node:
   ```

   示例输出如下。

   ```
   ip-192-168-79-166.us-west-2/192.168.79.166
   ```

   在之前的输出中，容器组（pod）在 us-west-2 AWS 区域中的节点上运行。

1. 确定容器组（pod）的服务账户使用的端点类型。

   ```
   kubectl describe pod aws-node-6mfgv -n kube-system |grep AWS_STS_REGIONAL_ENDPOINTS
   ```

   示例输出如下。

   ```
   AWS_STS_REGIONAL_ENDPOINTS: regional
   ```

   如果当前端点是全局端点，则输出中将返回 `global`。如果没有返回输出，则默认端点类型正在使用中且尚未被覆盖。

1. 如果您的集群或平台版本与表中列出的版本相同或晚于该版本，则可以使用以下命令之一将服务账户使用的端点类型从默认类型更改为其他类型。将 *aws-node* 替换为您的服务账户的名称，并将 *kube-system* 替换为您的服务账户的命名空间。
   + 如果您的默认或当前端点类型为全局端点类型，并且您想将其更改为区域性端点：

     ```
     kubectl annotate serviceaccount -n kube-system aws-node eks.amazonaws.com/sts-regional-endpoints=true
     ```

     如果您使用[服务账户的 IAM 角色](iam-roles-for-service-accounts.md)，在容器组（pod）的容器中运行的应用程序中生成预签名 S3 URL，则区域端点的 URL 格式与以下示例类似：

     ```
     https://bucket.s3.us-west-2.amazonaws.com/path?...&X-Amz-Credential=your-access-key-id/date/us-west-2/s3/aws4_request&...
     ```
   + 如果您的默认或当前端点类型为区域性端点类型，并且您想将其更改为全局性端点：

     ```
     kubectl annotate serviceaccount -n kube-system aws-node eks.amazonaws.com/sts-regional-endpoints=false
     ```

     如果您的应用程序明确向 AWS STS 全局端点提出请求，且您不会覆盖在 Amazon EKS 集群中使用区域端点的默认行为，则请求将失败，并出现错误。有关更多信息，请参阅 [容器组（pod）容器收到以下错误：`An error occurred (SignatureDoesNotMatch) when calling the GetCallerIdentity operation: Credential should be scoped to a valid region`](security-iam-troubleshoot.md#security-iam-troubleshoot-wrong-sts-endpoint)。

     如果您使用[服务账户的 IAM 角色](iam-roles-for-service-accounts.md)，在容器组（pod）的容器中运行的应用程序中生成预签名 S3 URL，则全局端点的 URL 格式与以下示例类似：

     ```
     https://bucket.s3.amazonaws.com/path?...&X-Amz-Credential=your-access-key-id/date/us-west-2/s3/aws4_request&...
     ```

   如果您的自动化需要特定格式的预签名 URL，或者如果您的应用程序或使用预签名 URL 的下游依赖关系对目标 AWS 区域有期望，则进行必要的更改以使用适当的 AWS STS 端点。

1. 删除并重新创建任何与服务账户关联的现有容器组（pod），以应用凭证环境变量。变更 Webhook 不会将其应用到已经在运行的容器组（pod）。您可以将 *Pods*、*kube-system* 和 *-l k8s-app=aws-node* 替换为设置注释的容器组（pod）信息。

   ```
   kubectl delete Pods -n kube-system -l k8s-app=aws-node
   ```

1. 确认容器组（pod）已全部重新启动。

   ```
   kubectl get Pods -n kube-system -l k8s-app=aws-node
   ```

1. 查看其中一个容器组（pod）的环境变量。验证 `AWS_STS_REGIONAL_ENDPOINTS` 值是您在上一步中将其设置的值。

   ```
   kubectl describe pod aws-node-kzbtr -n kube-system |grep AWS_STS_REGIONAL_ENDPOINTS
   ```

   示例输出如下。

   ```
   AWS_STS_REGIONAL_ENDPOINTS=regional
   ```

# 使用 IRSA 对另一个账户进行身份验证
<a name="cross-account-access"></a>

您可以通过从其它账户的集群创建身份提供者或者使用链接的 `AssumeRole` 操作，配置跨账户 IAM 权限。在以下示例中，*账户 A* 拥有一个支持服务账户的 IAM 角色的 Amazon EKS 集群。在该集群上运行的容器组（pod）需要承担来自*账户 B* 的 IAM 权限。
+  **选项 1** 更简单，但需要账户 B 为账户 A 的集群创建和管理 OIDC 身份提供程序。
+  **选项 2 将** OIDC 管理保留在账户 A 中，但需要通过两次 `AssumeRole` 调用进行角色链式操作。

## 从其它账户的集群创建身份提供程序
<a name="_option_1_create_an_identity_provider_from_another_accounts_cluster"></a>

在此示例中，账户 A 从其集群向账户 B 提供 OpenID Connect（OIDC）颁发者 URL。账户 B 遵循[为集群创建 IAM OIDC 提供者](enable-iam-roles-for-service-accounts.md)和[为 Kubernetes 服务账户分配 IAM 角色](associate-service-account-role.md)中的说明，使用来自账户 A 集群的 OIDC 发布者 URL。然后，集群管理员注释账户 A 的集群中的服务账户以使用来自账户 B 的角色（*444455556666*）。

```
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::444455556666:role/account-b-role
```

## 选项 2：使用链式 `AssumeRole` 操作
<a name="_option_2_use_chained_assumerole_operations"></a>

在此方案中，每个账户创建一个 IAM 角色。账户 B 的角色信任账户 A，账户 A 的角色使用 OIDC 联合身份验证从集群获取凭证。然后，容器组（pod）使用 AWS CLI 配置文件将这两个角色链接在一起。

### 步骤 1：在账户 B 中创建目标角色
<a name="_step_1_create_the_target_role_in_account_b"></a>

账户 B（*444455556666*）创建一个 IAM 角色，该角色具有账户 A 集群中容器组（pod）所需的权限。账户 B 将所需权限策略附加到此角色，然后添加以下信任策略。

 **账户 B 角色的信任策略**–该策略允许账户 A 的特定 IRSA 角色承担此角色。

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
```

**重要**  
为遵循最低权限原则，请将 `Principal` ARN 替换为账户 A 中的特定角色 ARN，而不是使用账户根（`arn:aws:iam::111122223333:root`）。使用账户根将允许账户 A 中的*任何* IAM 主体承担此角色。

### 步骤 2：在账户 A 中创建 IRSA 角色
<a name="_step_2_create_the_irsa_role_in_account_a"></a>

账户 A （*111122223333*）创建具有信任策略的角色，该策略从使用集群的 OIDC 颁发者地址创建的身份提供者处获取凭证。

 **账户 A 角色的信任策略（OIDC 联合联合身份验证）**–该策略允许 EKS 集群的 OIDC 提供程序为此角色颁发凭证。

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
```

**重要**  
为遵循最低权限原则，请为 `sub` 声明添加 `StringEquals` 条件，以将此角色限定给特定的 Kubernetes 服务账户。在没有 `sub` 条件的情况下，集群中的任何服务账号都可以担任此角色。`sub` 值的格式为 `system:serviceaccount:NAMESPACE:SERVICE_ACCOUNT_NAME `。例如，要将范围限定为 `default` 命名空间中名为 `my-service-account` 的服务账户：  

```
"oidc.eks.region-code.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:default:my-service-account"
```

### 步骤 3：将 AssumeRole 权限附加到账户 A 的角色
<a name="_step_3_attach_the_assumerole_permission_to_account_as_role"></a>

账户 A 将为步骤 2 中创建的角色附加一个权限策略。该策略允许该角色承担账户 B 的角色。

 **账户 A 角色的权限策略**–该策略授予对账户 B 目标角色的 `sts:AssumeRole` 权限。

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::444455556666:role/account-b-role"
        }
    ]
}
```

### 步骤 4：配置容器组（pod）以链式使用角色
<a name="_step_4_configure_the_pod_to_chain_roles"></a>

容器组（pod）的应用程序代码使用两个配置文件担任账户 B 的角色：`account_b_role` 和 `account_a_role`。`account_b_role` 配置文件使用 `account_a_role` 配置文件作为其源。对于 AWS CLI，`~/.aws/config` 文件类似于以下内容。

```
[profile account_b_role]
source_profile = account_a_role
role_arn=arn:aws:iam::444455556666:role/account-b-role

[profile account_a_role]
web_identity_token_file = /var/run/secrets/eks.amazonaws.com/serviceaccount/token
role_arn=arn:aws:iam::111122223333:role/account-a-role
```

要为其它 AWS SDK 指定链接的配置文件，请参考所使用 SDK 的文档。有关更多信息，请参阅[用于在 AWS 上进行构建的工具](https://aws.amazon.com/developer/tools/)。

# 将 IRSA 与 AWS SDK 结合使用
<a name="iam-roles-for-service-accounts-minimum-sdk"></a>

**使用凭证**  
要使用服务账户的 IAM 角色（IRSA）凭证，代码可以使用任何 AWS SDK 为具有 SDK 的 AWS 服务创建客户端。默认情况下，SDK 会在一系列位置中搜索要使用的 AWS Identity and Access Management 凭证。如果您在创建客户端或者初始化 SDK 时未指定凭证提供程序，则将使用服务账户凭证的 IAM 角色。

由于服务账户的 IAM 角色已添加为默认凭证链中的一个步骤，因此该操作可行。如果您的工作负载当前使用凭证链中较早的证书，则即使您为同一工作负载的服务账户配置了 IAM 角色，这些凭证也将继续使用。

SDK 使用 `AssumeRoleWithWebIdentity` 操作自动将服务账户 OIDC 令牌交换为 AWS Security Token Service 中的临时凭证。Amazon EKS 和此 SDK 操作会在临时凭证到期前进行续订，从而继续轮换临时凭证。

在使用[服务账户的 IAM 角色](iam-roles-for-service-accounts.md)时，容器组（pod）中的容器必须使用支持通过 OpenID Connect Web 身份令牌文件担任 IAM 角色的 AWS SDK 版本。请确保为您的 AWS SDK 使用以下版本或更高版本：
+ Java（版本 2）– [2.10.11](https://github.com/aws/aws-sdk-java-v2/releases/tag/2.10.11) 
+ Java – [1.12.782](https://github.com/aws/aws-sdk-java/releases/tag/1.12.782) 
+  AWS SDK for Go v1 – [1.23.13](https://github.com/aws/aws-sdk-go/releases/tag/v1.23.13) 
+  AWS SDK for Go v2 – 所有版本均支持
+ Python (Boto3) – [1.9.220](https://github.com/boto/boto3/releases/tag/1.9.220) 
+ Python (botocore) – [1.12.200](https://github.com/boto/botocore/releases/tag/1.12.200) 
+  AWS CLI – [1.16.232](https://github.com/aws/aws-cli/releases/tag/1.16.232) 
+ 节点：[2.525.0](https://github.com/aws/aws-sdk-js/releases/tag/v2.525.0) 和 [3.27.0](https://github.com/aws/aws-sdk-js-v3/releases/tag/v3.27.0) 
+ Ruby – [3.58.0](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-core/CHANGELOG.md#3580-2019-07-01) 
+ C\$1\$1 – [1.7.174](https://github.com/aws/aws-sdk-cpp/releases/tag/1.7.174) 
+ .NET：[3.3.659.1](https://github.com/aws/aws-sdk-net/releases/tag/3.3.659.1)，您必须还包括 `AWSSDK.SecurityToken`。
+ PHP – [3.110.7](https://github.com/aws/aws-sdk-php/releases/tag/3.110.7) 

许多流行的 Kubernetes 附加组件（例如 [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)、[使用 AWS 负载均衡器控制器的路由互联网流量](aws-load-balancer-controller.md)和[适用于 Kubernetes 的 Amazon VPC CNI 插件](cni-iam-role.md)）支持服务账户的 IAM 角色。

为了确保您使用的是受支持的 SDK，请在构建容器时按照[用于在 AWS 上进行构建的工具](https://aws.amazon.com/tools/)中针对您的首选 SDK 的安装说明操作。

## 注意事项
<a name="_considerations"></a>

### Java
<a name="_java"></a>

使用 Java 时，*必须*在类路径中包括 `sts` 模块。有关更多信息，请参阅 Java SDK 文档中的 [WebIdentityTokenFileCredentialsProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/WebIdentityTokenFileCredentialsProvider.html)。

# 获取签名密钥以验证 OIDC 令牌
<a name="irsa-fetch-keys"></a>

Kubernetes 向每个 Kubernetes 服务账户发放一个 `ProjectedServiceAccountToken`。此令牌是一个 OIDC 令牌，更是一种 JSON Web 令牌（JWT）。Amazon EKS 为包含令牌的签名密钥的每个集群托管公有 OIDC 端点，这样外部系统就可以验证。

您需要获取 OIDC 公有签名密钥 [又称 JSON Web 密钥集（简称 JWKS）] 才能验证 `ProjectedServiceAccountToken`。在应用程序中使用这些密钥来验证令牌。例如，您可以使用 [PyJWT Python 库](https://pyjwt.readthedocs.io/en/latest/)来验证使用这些密钥的令牌。有关 `ProjectedServiceAccountToken` 的更多信息，请参阅 [IAM、Kubernetes 和 OpenID Connect（OIDC）背景信息](iam-roles-for-service-accounts.md#irsa-oidc-background)。

## 先决条件
<a name="_prerequisites"></a>
+ 适用于集群的现有 AWS Identity and Access Management（IAM）OpenID Connect（OIDC）提供者。要确定您是否已经拥有一个或是否要创建一个，请参阅[为集群创建 IAM OIDC 提供商](enable-iam-roles-for-service-accounts.md)。
+  **AWS CLI** – 与 AWS 服务（包括 Amazon EKS）结合使用的命令行工具。有关更多信息，请参阅《AWS 命令行界面用户指南》中的[安装](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)。在安装 AWS CLI 后，建议您还要对其进行配置。有关更多信息，请参阅《AWS 命令行界面用户指南》中的[使用 aws configure 快速配置](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。

## 过程
<a name="_procedure"></a>

1. 使用 AWS CLI 检索适用于 Amazon EKS 集群的 OIDC URL。

   ```
   $ aws eks describe-cluster --name my-cluster --query 'cluster.identity.oidc.issuer'
   "https://oidc.eks.us-west-2.amazonaws.com/id/8EBDXXXX00BAE"
   ```

1. 使用 curl 或类似工具检索公有签名密钥。结果是 [JSON Web 密钥集（JWKS）](https://www.rfc-editor.org/rfc/rfc7517#section-5)。
**重要**  
Amazon EKS 会限制对 OIDC 端点的调用。您应该缓存公共签名密钥。请遵守响应中包含的 `cache-control` 标题。
**重要**  
Amazon EKS 每七天轮换一次 OIDC 签名密钥。

   ```
   $ curl https://oidc.eks.us-west-2.amazonaws.com/id/8EBDXXXX00BAE/keys
   {"keys":[{"kty":"RSA","kid":"2284XXXX4a40","use":"sig","alg":"RS256","n":"wklbXXXXMVfQ","e":"AQAB"}]}
   ```