

 **帮助改进此页面** 

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

# 使用自行管理型节点来自行维护节点
<a name="worker"></a>

一个集群包含一个或多个在其上调度了容器组（pod）的 Amazon EC2 节点。Amazon EKS 节点在 AWS 账户中运行并通过集群 API 服务器端点连接到集群的控制层面。您需要根据 Amazon EC2 价格收取费用。有关更多信息，请参阅 [Amazon EC2 定价](https://aws.amazon.com/ec2/pricing/)。

一个集群可以包含多个节点组。每个节点组都包含在 [Amazon EC2 Auto Scaling 组](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html)中部署的一个或多个节点。组内节点的实例类型可能会有所不同，例如[将基于属性的实例类型选择](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-fleet-attribute-based-instance-type-selection.html)与 [Karpenter](https://karpenter.sh/) 结合使用时。节点组中的所有实例都必须使用 [Amazon EKS 节点 IAM 角色](create-node-role.md)。

Amazon EKS 提供一个专用亚马逊机器映像（AMI），称为 Amazon EKS 优化版 AMI。AMI 配置为与 Amazon EKS 配合使用。其组件包括 `containerd`、`kubelet` 和 AWS IAM 身份验证器。此 AMI 还包含专用[引导脚本](https://github.com/awslabs/amazon-eks-ami/blob/main/templates/al2/runtime/bootstrap.sh)，从而允许它自动发现并连接到您的集群控制面板。

如果使用 CIDR 块限制对集群的公有端点的访问，建议您还启用私有端点访问。目的是为了让节点可以与集群通信。在未启用私有终端节点的情况下，您指定用于公有访问的 CIDR 块必须包含来自 VPC 的出口源。有关更多信息，请参阅 [集群 API 服务器端点](cluster-endpoint.md)。

要向您的 Amazon EKS 集群添加自行管理的节点，请参阅以下主题。如果手动启动自主管理型节点，则向每个节点添加以下标签，同时确保 `<cluster-name>` 与集群匹配。有关更多信息，请参阅[为单个资源添加和删除标签](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#adding-or-deleting-tags)。如果按照下面指南中的步骤操作，则会将您所需的标签自动添加到节点。


| 键 | 值 | 
| --- | --- | 
|   `kubernetes.io/cluster/<cluster-name>`   |   `owned`   | 

**重要**  
Amazon EC2 实例元数据服务（IMDS）中的标签与 EKS 节点不兼容。启用实例元数据标签后，将禁止在标签值中使用正斜杠（“/”）。不执行此限制可能会导致实例启动失败，尤其是在使用 Karpenter 或 Cluster Autoscaler 等节点管理工具时，因为这些服务能否正常运行取决于标签是否包含正斜杠。

有关节点的更多信息（从一般 Kubernetes 角度看），请参阅 Kubernetes 文档中的[节点](https://kubernetes.io/docs/concepts/architecture/nodes/)。

**Topics**
+ [创建自行管理的 Amazon Linux 节点](launch-workers.md)
+ [创建自主管理型 Bottlerocket 节点](launch-node-bottlerocket.md)
+ [创建自主管理型 Microsoft Windows 节点](launch-windows-workers.md)
+ [创建自主管理型 Ubuntu Linux 节点](launch-node-ubuntu.md)
+ [更新集群的自行管理型节点](update-workers.md)

# 创建自行管理的 Amazon Linux 节点
<a name="launch-workers"></a>

本主题介绍如何启动向 Amazon EKS 集群注册的 Linux 节点的自动扩缩组。在这些节点加入集群后，您可以向其部署 Kubernetes 应用程序。您可以使用 `eksctl` 或 AWS 管理控制台 启动自行管理的 Amazon Linux 节点。如果您需要在 AWS Outposts 上启动节点，请参阅 [在 AWS Outpost 上创建 Amazon Linux 节点](eks-outposts-self-managed-nodes.md)。
+ 现有 Amazon EKS 集群。要部署一个角色，请参阅[创建一个 Amazon EKS 集群。](create-cluster.md)。如果您在启用了 AWS Outposts、AWS Wavelength 或 AWS 本地区域的 AWS 区域中拥有子网，则这些子网不得在您创建集群时就已传入。
+ 供节点使用的现有 IAM 角色。要创建该文件，请参阅 [Amazon EKS 节点 IAM 角色](create-node-role.md)。如果此角色没有 VPC CNI 的任一策略，则需要为 VPC CNI Pod 使用随后的单独角色。
+ （可选，但推荐）适用于 Kubernetes 附加组件的 Amazon VPC CNI 插件已配置自己的 IAM 角色，并附加了必要的 IAM 策略。有关更多信息，请参阅 [配置 Amazon VPC CNI 插件以使用 IRSA](cni-iam-role.md)。
+ 熟悉[选择最优的 Amazon EC2 节点实例类型](choosing-instance-type.md)中列出的注意事项。根据您选择的实例类型，您的集群和 VPC 可能还有其他先决条件。

您可以使用以下任一选项来启动自行管理的 Linux 节点：
+  [`eksctl`](#eksctl_create_managed_amazon_linux) 
+  [AWS 管理控制台](#console_create_managed_amazon_linux) 

## `eksctl`
<a name="eksctl_create_managed_amazon_linux"></a>

 **使用 `eksctl` 启动自主管理型 Linux 节点** 

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

1. （可选）如果 **AmazonEKS\$1CNI\$1Policy** 托管的 IAM 策略附加到 [Amazon EKS 节点 IAM 角色](create-node-role.md)，我们建议将其分配给您与 Kubernetes `aws-node` 服务账户关联的 IAM 角色。有关更多信息，请参阅 [配置 Amazon VPC CNI 插件以使用 IRSA](cni-iam-role.md)。

1. 以下命令在现有集群中创建节点组。将 *al-nodes* 替换为您的节点组名称。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。将 *my-cluster* 替换为您的集群的名称。名称只能包含字母数字字符（区分大小写）和连字符。该名称必须以字母数字字符开头，且不得超过 100 个字符。对于您在其中创建集群的 AWS 区域和 AWS 账户，该名称必须在其内具有唯一性。将其余的 *example value* 替换为您自己的值。预设情况下，将使用与控制层面相同的 Kubernetes 版本创建节点。

   在为 `--node-type` 选择值之前，请查看[选择最优的 Amazon EC2 节点实例类型](choosing-instance-type.md)。

   将 *my-key* 替换为您的 Amazon EC2 密钥对或公有密钥的名称。此密钥用于在节点启动后通过 SSH 进入节点。如果还没有 Amazon EC2 密钥对，可以在 AWS 管理控制台 中创建一个。有关更多信息，请参阅*《Amazon EC2 用户指南》*中的 [Amazon EC2 密钥对](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)。

   使用以下命令创建您的节点组。
**重要**  
如果要将节点组部署到 AWS Outposts、Wavelength 或本地区域子网，还有其它注意事项：  
创建集群时，不得传入子网。
您必须使用配置文件创建节点组，指定子网和 ` [volumeType](https://eksctl.io/usage/schema/#nodeGroups-volumeType): gp2`。有关更多信息，请参阅 `eksctl` 文档中的[从配置文件创建节点组](https://eksctl.io/usage/nodegroups/#creating-a-nodegroup-from-a-config-file)和 [Config 文件架构](https://eksctl.io/usage/schema/)。

   ```
   eksctl create nodegroup \
     --cluster my-cluster \
     --name al-nodes \
     --node-type t3.medium \
     --nodes 3 \
     --nodes-min 1 \
     --nodes-max 4 \
     --ssh-access \
     --managed=false \
     --ssh-public-key my-key
   ```

   部署符合以下条件的节点组：
   + 可以将明显高出默认配置数量的 IP 地址分配给容器组（pod），请参阅[为带前缀的 Amazon EKS 节点分配更多 IP 地址](cni-increase-ip-addresses.md)。
   + 可以将 `IPv4` 地址分配给来自与实例不同的 CIDR 块的容器组（pod），请参阅[使用自定义网络在备用子网中部署容器组（pod）](cni-custom-network.md)。
   + 可以将 `IPv6` 地址分配给容器组（pod）和服务，请参阅[了解如何将 IPv6 地址分配给集群、容器组（pod）和服务](cni-ipv6.md)。
   + 没有出站互联网访问权限，请参阅[部署具有有限互联网访问权限的私有集群](private-clusters.md)。

     要查看所有可用选项和默认设置的完整列表，请输入以下命令。

     ```
     eksctl create nodegroup --help
     ```

     如果节点无法加入集群，则请参阅故障排除一章中的 [节点未能加入集群](troubleshooting.md#worker-node-fail)。

     示例输出如下。创建节点时会输出几行。输出的最后几行类似于以下示例行。

     ```
     [✔]  created 1 nodegroup(s) in cluster "my-cluster"
     ```

1. （可选）部署[示例应用程序](sample-deployment.md)以测试集群和 Linux 节点。

1. 如果满足以下条件，我们建议阻止容器组（pod）访问 IMDS：
   + 您计划将 IAM 角色分配给所有 Kubernetes 服务账户，以便容器组（pod）仅具有其所需的最低权限。
   + 集群中没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 Amazon EC2 实例元数据服务（IMDS）。

   有关更多信息，请参阅[限制对分配给 Worker 节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

## AWS 管理控制台
<a name="console_create_managed_amazon_linux"></a>

 **第 1 步：使用 AWS 管理控制台 启动自主管理型 Linux 节点** 

1. 下载最新版本的 AWS CloudFormation 模板。

   ```
   curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2025-11-26/amazon-eks-nodegroup.yaml
   ```

1. 等待集群状态显示为 `ACTIVE`。如果在集群处于活动状态之前启动节点，则节点将无法向集群注册，您必须重新启动节点。

1. 打开 [AWS CloudFormation 控制台](https://console.aws.amazon.com/cloudformation/)。

1. 选择 **Create stack（创建堆栈）**，然后选择 **With new resources (standard)（使用新资源（标准））**。

1. 对于 **Specify template（指定模板）**，选择 **Upload a template file（上传模板文件）**，然后选择**Choose file（选择文件） **。

1. 选择您下载的 `amazon-eks-nodegroup.yaml` 文件。

1. 选择**下一步**。

1. 在 **Specify stack details**（指定堆栈详细信息）页面上，相应填写以下参数，然后选择 **Next**（下一步）：
   +  **堆栈名称**：为 AWS CloudFormation 堆栈选择堆栈名称。例如，您可以将其称为 *my-cluster-nodes*。名称只能包含字母数字字符（区分大小写）和连字符。该名称必须以字母数字字符开头，且不得超过 100 个字符。对于您在其中创建集群的 AWS 区域和 AWS 账户，该名称必须在其内具有唯一性。
   +  **ClusterName**：输入您在创建 Amazon EKS 集群时使用的名称。此名称必须与集群名称完全匹配，否则您的节点无法加入该集群。
   +  **ClusterControlPlaneSecurityGroup**：从您在创建 [VPC](creating-a-vpc.md) 时生成的 AWS CloudFormation 输出中，选择 **SecurityGroups** 值。

     以下步骤显示了检索适用组的一种操作。

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

     1. 选择集群的名称。

     1. 选择 **Networking**（联网）选项卡。

     1. 从 **ClusterControlPlaneSecurityGroup** 下拉列表中选择时使用 **Additional security groups**（其他安全组）值作为参考。
   +  **ApiServerEndpoint**：输入 EKS 集群的 API 服务器端点。可以在 EKS 集群控制台的“详细信息”部分中找到此信息
   +  **CertificateAuthorityData**：输入 base64 编码的证书颁发机构数据，这些数据也可以在 EKS 集群控制台的“详细信息”部分中找到。
   +  **ServiceCidr**：输入用于为集群内的 Kubernetes 服务分配 IP 地址的 CIDR 范围。可以在 EKS 集群控制台的“网络”选项卡中找到此信息。
   +  **AuthenticationMode**：查看 EKS 集群控制台中的访问选项卡，选择 EKS 集群中正在使用的身份验证模式。
   +  **NodeGroupName**：输入节点组的名称。稍后您可以使用此名称来标识为您的节点创建的自动扩缩节点组。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。
   +  **NodeAutoScalingGroupMinSize**：输入您的节点自动扩缩组可横向缩减到的最小节点数。
   +  **NodeAutoScalingGroupDesiredCapacity**：输入创建堆栈时要扩展到的所需节点数目。
   +  **NodeAutoScalingGroupMaxSize**：输入您的节点自动扩缩组可横向扩展到的最大节点数。
   +  **NodeInstanceType**：选择节点的实例类型。有关更多信息，请参阅 [选择最优的 Amazon EC2 节点实例类型](choosing-instance-type.md)。
   +  **NodeImageIdSSMParam**：使用用于某个变量 Kubernetes 版本最近的 Amazon EKS 优化版 Amazon Linux 2023 AMI 的 Amazon EC2 Systems Manager 参数进行预填充。要使用 Amazon EKS 支持的其他 Kubernetes 次要版本，可以将 *1.XX* 替换为不同的[支持版本](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)。我们建议您指定与您的集群相同的 Kubernetes 版本。

     您也可以将 *amazon-linux-2023* 替换为其它 AMI 类型。有关更多信息，请参阅 [检索建议的 Amazon Linux AMI ID](retrieve-ami-id.md)。
**注意**  
Amazon EKS 节点 AMI 基于 Amazon Linux。您可以在 [Amazon Linux 安全中心](https://alas.aws.amazon.com/alas2023.html)跟踪 Amazon Linux 2023 的安全和隐私事件，或订阅关联的 [RSS 源](https://alas.aws.amazon.com/AL2023/alas.rss)。安全和隐私事件包括问题的概述、受影响的程序包以及如何更新实例以解决问题。
   +  **NodeImageId**：（可选）如果使用自定义 AMI（而不是 Amazon EKS 优化型 AMI），则输入您 AWS 区域的节点 AMI ID。如果您在此处指定值，它会覆盖 **NodeImageIdSSMParam** 字段中的任意值。
   +  **NodeVolumeSize**：指定您的节点的根卷大小（以 GiB 为单位）。
   +  **NodeVolumeType**：指定您的节点的根卷类型。
   +  **KeyName**：输入 Amazon EC2 SSH 密钥对的名称，您可使用该密钥对来在节点启动后使用 SSH 连接到这些节点。如果还没有 Amazon EC2 密钥对，可以在 AWS 管理控制台 中创建一个。有关更多信息，请参阅*《Amazon EC2 用户指南》*中的 [Amazon EC2 密钥对](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)。
   +  **VpcId**：输入您创建的 [VPC](creating-a-vpc.md) 的 ID。
   +  **Subnets**（子网）：选择您为 VPC 创建的子网。如果您使用[为您的 Amazon EKS 集群创建 Amazon VPC](creating-a-vpc.md) 中描述的步骤创建了 VPC，则在 VPC 中仅指定私有子网以供您的节点启动到其中。您可以通过从集群的 **Networking**（联网）选项卡中打开每个子网链接来查看哪些子网是私有的。
**重要**  
如果其中的任何子网是公有子网，则其必须启用自动公有 IP 地址分配设置。如果没有为该公有子网启用该设置，则您部署到该公有子网的任何节点都不会分配到公有 IP 地址，也无法与集群或其它 AWS 服务进行通信。如果子网是在 2020 年 3 月 26 日之前使用任一 [Amazon EKS AWS CloudFormation VPC 模板](creating-a-vpc.md)部署的，或者是使用 `eksctl` 部署的，则会为这些公有子网禁用自动公有 IP 地址分配。有关如何为子网启用公有 IP 地址分配的信息，请参阅[修改子网的公有 IPv4 寻址属性](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip)。如果节点部署到私有子网，则可以通过 NAT 网关与集群和其它 AWS 服务进行通信。
如果子网没有 Internet 访问权限，请确保您了解[部署具有有限互联网访问权限的私有集群](private-clusters.md)中的注意事项和额外步骤。
如果您选择 AWS Outposts、Wavelength 或本地区域子网，则这些子网不得在您创建集群时就已传入。

1. 在 **Configure stack options**（配置堆栈选项）页面上选择所需选项，然后选择 **Next**（下一步）。

1. 选择**我了解 AWS CloudFormation 可能会创建 IAM 资源。**左侧的复选框，然后选择**创建堆栈**。

1. 完成创建堆栈后，在控制台中选中它，然后选择 **Outputs（输出）**。如果您使用的是 `EKS API` 或 `EKS API and ConfigMap` 身份验证模式，则这是最后一步。

1. 如果您使用的是 `ConfigMap` 身份验证模式，请记录已创建的节点组的 **NodeInstanceRole**。

 **第 2 步：使节点能够加入集群** 

**注意**  
只有在 EKS 集群内使用 Configmap 身份验证模式时，才需要执行以下两个步骤。此外，如果您在没有出站 Internet 访问的情况下在私有 VPC 内启动了节点，请确保使节点能够从 VPC 中加入您的集群。

1. 检查您是否已经应用拥有 `aws-auth` `ConfigMap`。

   ```
   kubectl describe configmap -n kube-system aws-auth
   ```

1. 如果您看到的是 `aws-auth` `ConfigMap`，则请根据需要对其进行更新。

   1. 打开 `ConfigMap` 文件进行编辑。

      ```
      kubectl edit -n kube-system configmap/aws-auth
      ```

   1. 根据需要添加新的 `mapRoles` 条目。将 `rolearn` 值设置为您在上一个步骤中记录的 **NodeInstanceRole** 值。

      ```
      [...]
      data:
        mapRoles: |
          - rolearn: <ARN of instance role (not instance profile)>
            username: system:node:{{EC2PrivateDNSName}}
            groups:
              - system:bootstrappers
              - system:nodes
      [...]
      ```

   1. 保存文件并退出文本编辑器。

1. 如果您收到错误提示 "`Error from server (NotFound): configmaps "aws-auth" not found`，则请使用库存 `ConfigMap`。

   1. 下载配置映射。

      ```
      curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/aws-auth-cm.yaml
      ```

   1. 在 `aws-auth-cm.yaml` 文件中，将 `rolearn` 值设置为您在上一个步骤中记录的 **NodeInstanceRole** 值。您可以使用文本编辑器或者通过替换 *my-node-instance-role* 和运行以下命令来执行此操作：

      ```
      sed -i.bak -e 's|<ARN of instance role (not instance profile)>|my-node-instance-role|' aws-auth-cm.yaml
      ```

   1. 应用配置。此命令可能需要几分钟才能完成。

      ```
      kubectl apply -f aws-auth-cm.yaml
      ```

1. 查看节点的状态并等待它们达到 `Ready` 状态。

   ```
   kubectl get nodes --watch
   ```

   输入 `Ctrl`\$1`C` 以返回到 Shell 提示符。
**注意**  
如果您收到任何授权或资源类型错误，请参阅故障排除主题中的 [未经授权或访问被拒绝 (`kubectl`)](troubleshooting.md#unauthorized)。

   如果节点无法加入集群，则请参阅故障排除一章中的 [节点未能加入集群](troubleshooting.md#worker-node-fail)。

1. （仅限 GPU 节点）如果选择 GPU 实例类型和 Amazon EKS 优化版加速型 AMI，则必须在集群上应用[适用于 Kubernetes 的 NVIDIA 设备插件](https://github.com/NVIDIA/k8s-device-plugin)作为 DaemonSet。将 *vX.X.X* 替换为您需要的 [NVIDIA/k8s-device-plugin](https://github.com/NVIDIA/k8s-device-plugin/releases) 版本，然后运行以下命令。

   ```
   kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/vX.X.X/deployments/static/nvidia-device-plugin.yml
   ```

 **第 3 步：其它操作** 

1. （可选）部署[示例应用程序](sample-deployment.md)以测试集群和 Linux 节点。

1. （可选）如果 **AmazonEKS\$1CNI\$1Policy** 托管 IAM 策略（如果您拥有 `IPv4` 集群）或 *AmazonEKS\$1CNI\$1IPv6\$1Policy*（如果您拥有 `IPv6` 集群时[自行创建](cni-iam-role.md#cni-iam-role-create-ipv6-policy)）附加到 [Amazon EKS 节点 IAM 角色](create-node-role.md)，我们建议将其分配给关联到 Kubernetes `aws-node` 服务账户的 IAM 角色。有关更多信息，请参阅 [配置 Amazon VPC CNI 插件以使用 IRSA](cni-iam-role.md)。

1. 如果满足以下条件，我们建议阻止容器组（pod）访问 IMDS：
   + 您计划将 IAM 角色分配给所有 Kubernetes 服务账户，以便容器组（pod）仅具有其所需的最低权限。
   + 集群中没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 Amazon EC2 实例元数据服务（IMDS）。

   有关更多信息，请参阅[限制对分配给工作节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

# 创建自主管理型 Bottlerocket 节点
<a name="launch-node-bottlerocket"></a>

**注意**  
托管节点组可能会为您的使用案例带来一些优势。有关更多信息，请参阅 [使用托管式节点组简化节点生命周期](managed-node-groups.md)。

本主题介绍了如何启动向 Amazon EKS 集群注册的 [Bottlerocket](https://aws.amazon.com/bottlerocket/) 节点的自动扩缩组。Bottlerocket 是 AWS 的基于 Linux 的开源操作系统，用于在虚拟机或裸机主机上运行容器。在这些节点加入集群后，您可以向其部署 Kubernetes 应用程序。有关 Bottlerocket 的更多信息，请参阅 GitHub 上的[将 Bottlerocket AMI 与 Amazon EKS 一起使用](https://github.com/bottlerocket-os/bottlerocket/blob/develop/QUICKSTART-EKS.md)和 `eksctl` 文档中的[自定义 AMI 支持](https://eksctl.io/usage/custom-ami-support/)。

有关就地升级的信息，请参阅 GitHub 上的 [Bottlerocket Update Operator](https://github.com/bottlerocket-os/bottlerocket-update-operator)。

**重要**  
Amazon EKS 节点是标准的 Amazon EC2 实例，您需要基于常规的 Amazon EC2 实例价格为其付费。有关更多信息，请参阅 [Amazon EC2 定价](https://aws.amazon.com/ec2/pricing/)。
您可以在 AWS Outpost 上的 Amazon EKS 扩展集群中启动 Bottlerocket 节点，但您无法在 AWS Outpost 上的本地集群中启动它们。有关更多信息，请参阅 [使用 AWS Outposts 在本地部署 Amazon EKS](eks-outposts.md)。
您可以部署到采用 `x86` 或 Arm 处理器的 Amazon EC2 实例。但是，您无法部署到具有 Inferentia 芯片的实例。
Bottlerocket 与 AWS CloudFormation 兼容。但是，没有可以复制用于为 Amazon EKS 部署 Bottlerocket 节点的官方 CloudFormation 模板。
Bottlerocket 映像不附带 SSH 服务器或 Shell。您可以使用带外访问方法来允许 SSH 启用管理员容器，并执行一些带有用户数据的引导启动配置步骤。有关更多信息，请参阅 GitHub 上的 [bottlerocket README.md](https://github.com/bottlerocket-os/bottlerocket)：  
 [Exploration (探索)](https://github.com/bottlerocket-os/bottlerocket#exploration) 
 [管理员容器](https://github.com/bottlerocket-os/bottlerocket#admin-container) 
 [Kubernetes 设置](https://github.com/bottlerocket-os/bottlerocket#kubernetes-settings) 

此过程需要 `eksctl` 版本 `0.215.0` 或更高版本。可以使用以下命令来查看您的版本：

```
eksctl version
```

有关如何安装或升级 `eksctl` 的说明，请参阅 `eksctl` 文档中的[安装](https://eksctl.io/installation)。注意：此过程仅适用于使用 `eksctl` 创建的集群。

1. 将以下内容复制到您的设备。将 *my-cluster* 替换为您的集群的名称。名称只能包含字母数字字符（区分大小写）和连字符。该名称必须以字母数字字符开头，且不得超过 100 个字符。对于您在其中创建集群的 AWS 区域和 AWS 账户，该名称必须在其内具有唯一性。将 *ng-bottlerocket* 替换为您的节点组名称。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。要在 Arm 实例上部署，请将 *m5.large* 替换为 Arm 实例类型。将 *my-ec2-keypair-name* 替换为 Amazon EC2 SSH 密钥对的名称，您可使用该密钥对来在节点启动后使用 SSH 连接到这些节点。如果还没有 Amazon EC2 密钥对，可以在 AWS 管理控制台 中创建一个。有关更多信息，请参阅*《Amazon EC2 用户指南》*中的 [Amazon EC2 密钥对](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)。将所有剩余 example values 替换为您自己的值。完成替换后，运行修改后的命令以创建 `bottlerocket.yaml` 文件。

   如果指定了 Arm Amazon EC2 实例类型，请在部署前查看 [Amazon EKS 优化版 Arm Amazon Linux AMI](eks-optimized-ami.md#arm-ami) 中的注意事项。有关使用自定义 AMI 进行部署的说明，请参阅 GitHub 上的[构建 Bottlerocket](https://github.com/bottlerocket-os/bottlerocket/blob/develop/BUILDING.md) 以及 `eksctl` 文档中的[自定义 AMI 支持](https://eksctl.io/usage/custom-ami-support/)。要部署托管节点组，请使用启动模板部署自定义 AMI。有关更多信息，请参阅 [使用启动模板自定义托管式节点](launch-templates.md)。
**重要**  
要将节点组部署到 AWS Outposts、AWS Wavelength 或 AWS Local Zones 子网，就不要在创建集群时传递 AWS Outposts、AWS Wavelength 或 AWS Local Zones 子网。您必须在以下示例中指定子网。有关更多信息，请参阅 `eksctl` 文档中的[从配置文件创建节点组](https://eksctl.io/usage/nodegroups/#creating-a-nodegroup-from-a-config-file)和 [Config 文件架构](https://eksctl.io/usage/schema/)。将 *region-code* 替换为您的集群所在的 AWS 区域。

   ```
   cat >bottlerocket.yaml <<EOF
   ---
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig
   
   metadata:
     name: my-cluster
     region: region-code
     version: '1.35'
   
   iam:
     withOIDC: true
   
   nodeGroups:
     - name: ng-bottlerocket
       instanceType: m5.large
       desiredCapacity: 3
       amiFamily: Bottlerocket
       ami: auto-ssm
       iam:
          attachPolicyARNs:
             - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
             - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
             - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
             - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
       ssh:
           allow: true
           publicKeyName: my-ec2-keypair-name
   EOF
   ```

1. 使用以下命令部署您的节点。

   ```
   eksctl create nodegroup --config-file=bottlerocket.yaml
   ```

   示例输出如下。

   创建节点时会输出几行。输出的最后几行类似于以下示例行。

   ```
   [✔]  created 1 nodegroup(s) in cluster "my-cluster"
   ```

1. （可选）使用 [Amazon EBS CSI 插件](https://github.com/kubernetes-sigs/aws-ebs-csi-driver)在 Bottlerocket 节点上创建 Kubernetes [持久性卷](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)。默认 Amazon EBS 驱动程序依赖于一些 Bottlerocket 中不包含的文件系统工具。有关使用驱动程序创建存储类的更多信息，请参阅 [将 Kubernetes 卷存储与 Amazon EBS 结合使用](ebs-csi.md)。

1. （可选）`kube-proxy` 默认将 `nf_conntrack_max` 内核参数设置为默认值，该值可能与 Bottlerocket 最初在启动时设置的值不同。要保留 Bottlerocket 的[默认设置](https://github.com/bottlerocket-os/bottlerocket-core-kit/blob/develop/packages/release/release-sysctl.conf)，请使用以下命令编辑 `kube-proxy` 配置。

   ```
   kubectl edit -n kube-system daemonset kube-proxy
   ```

   将 `--conntrack-max-per-core` 和 `--conntrack-min` 添加到以下示例中的 `kube-proxy` 参数。设置为 `0` 意味着没有变化。

   ```
         containers:
         - command:
           - kube-proxy
           - --v=2
           - --config=/var/lib/kube-proxy-config/config
           - --conntrack-max-per-core=0
           - --conntrack-min=0
   ```

1. （可选）部署[示例应用程序](sample-deployment.md)来测试您的 Bottlerocket 节点。

1. 如果满足以下条件，我们建议阻止容器组（pod）访问 IMDS：
   + 您计划将 IAM 角色分配给所有 Kubernetes 服务账户，以便容器组（pod）仅具有其所需的最低权限。
   + 集群中没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 Amazon EC2 实例元数据服务（IMDS）。

   有关更多信息，请参阅[限制对分配给工作节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

# 创建自主管理型 Microsoft Windows 节点
<a name="launch-windows-workers"></a>

本主题介绍了如何启动向 Amazon EKS 集群注册的 Windows 节点的自动扩缩组。在这些节点加入集群后，您可以向其部署 Kubernetes 应用程序。

**重要**  
Amazon EKS 节点是标准的 Amazon EC2 实例，您需要基于常规的 Amazon EC2 实例价格为其付费。有关更多信息，请参阅 [Amazon EC2 定价](https://aws.amazon.com/ec2/pricing/)。
您可以在 AWS Outpost 上的 Amazon EKS 扩展集群中启动 Windows 节点，但您无法在 AWS Outpost 上的本地集群中启动它们。有关更多信息，请参阅 [使用 AWS Outposts 在本地部署 Amazon EKS](eks-outposts.md)。

为集群启用 Windows 支持。我们建议您在启动 Windows 节点组之前查看重要的注意事项。有关更多信息，请参阅 [启用 Windows 支持](windows-support.md#enable-windows-support)。

您可以通过以下任一方法启动自主管理型 Windows 节点：
+  [`eksctl`](#eksctl_create_windows_nodes) 
+  [AWS 管理控制台](#console_create_windows_nodes) 

## `eksctl`
<a name="eksctl_create_windows_nodes"></a>

 **使用 `eksctl` 启动自主管理型 Windows 节点** 

此过程要求您已安装 `eksctl`，且您的 `eksctl` 版本至少为 `0.215.0`。可以使用以下命令来查看您的版本。

```
eksctl version
```

有关安装或升级 `eksctl` 的说明，请参阅 `eksctl` 文档中的 [Installation](https://eksctl.io/installation)。

**注意**  
此过程仅适用于使用 `eksctl` 创建的集群。

1. （可选）如果 **AmazonEKS\$1CNI\$1Policy** 托管 IAM 策略（如果您拥有 `IPv4` 集群）或 *AmazonEKS\$1CNI\$1IPv6\$1Policy*（如果您拥有 `IPv6` 集群时[自行创建](cni-iam-role.md#cni-iam-role-create-ipv6-policy)）附加到 [Amazon EKS 节点 IAM 角色](create-node-role.md)，我们建议将其分配给关联到 Kubernetes `aws-node` 服务账户的 IAM 角色。有关更多信息，请参阅 [配置 Amazon VPC CNI 插件以使用 IRSA](cni-iam-role.md)。

1. 此过程假设您已经有一个现有集群。如果还没有可添加 Windows 节点组的 Amazon EKS 集群和 Amazon Linux 节点组，则建议按照[开始使用 Amazon EKS – `eksctl`](getting-started-eksctl.md) 中的说明操作。该指南提供使用 Amazon Linux 节点创建 Amazon EKS 集群的完整演练。

   使用以下命令创建您的节点组。将 *region-code* 替换为您的集群所在的 AWS 区域。将 *my-cluster* 替换为您的集群名称。名称只能包含字母数字字符（区分大小写）和连字符。该名称必须以字母数字字符开头，且不得超过 100 个字符。对于您在其中创建集群的 AWS 区域和 AWS 账户，该名称必须在其内具有唯一性。将 *ng-windows* 替换为您的节点组名称。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。您可以将 *2019* 替换为 `2022` 以使用 Windows Server 2022，或替换为 `2025` 以使用 Windows Server 2025。将 example values 的剩余部分替换为您自己的值。
**重要**  
要将节点组部署到 AWS Outposts、AWS Wavelength 或 AWS 本地区域子网，在创建集群时不要传递 AWS Outposts、Wavelength 或本地区域子网。使用配置文件创建节点组，指定 AWS Outposts、Wavelength 或本地区域子网。有关更多信息，请参阅 `eksctl` 文档中的[从配置文件创建节点组](https://eksctl.io/usage/nodegroups/#creating-a-nodegroup-from-a-config-file)和 [Config 文件架构](https://eksctl.io/usage/schema/)。

   ```
   eksctl create nodegroup \
       --region region-code \
       --cluster my-cluster \
       --name ng-windows \
       --node-type t2.large \
       --nodes 3 \
       --nodes-min 1 \
       --nodes-max 4 \
       --managed=false \
       --node-ami-family WindowsServer2019FullContainer
   ```
**注意**  
如果节点无法加入集群，请参阅《故障排除指南》中的 [节点未能加入集群](troubleshooting.md#worker-node-fail)。
要查看 `eksctl` 命令可用选项，请输入以下命令。  

     ```
     eksctl command -help
     ```

   示例输出如下。创建节点时会输出几行。输出的最后几行类似于以下示例行。

   ```
   [✔]  created 1 nodegroup(s) in cluster "my-cluster"
   ```

1. （可选）部署[示例应用程序](sample-deployment.md)以测试您的集群和 Windows 节点。

1. 如果满足以下条件，我们建议阻止容器组（pod）访问 IMDS：
   + 您计划将 IAM 角色分配给所有 Kubernetes 服务账户，以便容器组（pod）仅具有其所需的最低权限。
   + 集群中没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 Amazon EC2 实例元数据服务（IMDS）。

   有关更多信息，请参阅[限制对分配给 Worker 节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

## AWS 管理控制台
<a name="console_create_windows_nodes"></a>

 **先决条件** 
+ 现有 Amazon EKS 集群和 Linux 节点组。如果您没有这些资源，我们建议您按照我[开始使用 Amazon EKS](getting-started.md)中的指南之一创建它们。这些指南介绍如何使用 Linux 节点创建 Amazon EKS 集群。
+ 符合 Amazon EKS 集群要求的现有 VPC 和安全组。有关更多信息，请参阅[查看 Amazon EKS 对 VPC 和子网的联网要求](network-reqs.md)和[查看集群的 Amazon EKS 安全组要求](sec-group-reqs.md)。[开始使用 Amazon EKS](getting-started.md) 中的指南创建符合要求的 VPC。或者，您可以按照[为 Amazon EKS 集群创建一个 Amazon VPC](creating-a-vpc.md) 中的说明，手动创建一个。
+ 现有 Amazon EKS 集群，它使用符合 Amazon EKS 集群要求的 VPC 和安全组。有关更多信息，请参阅 [创建一个 Amazon EKS 集群。](create-cluster.md)。如果您在启用了 AWS Outposts、AWS Wavelength 或 AWS 本地区域的 AWS 区域中拥有子网，则这些子网不得在您创建集群时就已传入。

 **第 1 步：使用 AWS 管理控制台 启动自行管理 Windows 节点** 

1. 等待集群状态显示为 `ACTIVE`。如果在集群处于活动状态之前启动节点，则节点将无法向集群注册，您需要重新启动节点。

1. 打开 [AWS CloudFormation 控制台](https://console.aws.amazon.com/cloudformation/) 

1. 选择**创建堆栈**。

1. 对于 **Specify template（指定模板）**，选择 **Amazon S3 URL**。

1. 复制以下 URL 并将其粘贴到 **Amazon S3 URL** 中。

   ```
   https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2023-02-09/amazon-eks-windows-nodegroup.yaml
   ```

1. 选择 **Next**（下一步）两次。

1. 在 **Quick create stack**（快速创建堆栈）页面上，相应地填写以下参数：
   +  **堆栈名称**：为 AWS CloudFormation 堆栈选择堆栈名称。例如，您可以将其命名为 `my-cluster-nodes`。
   +  **ClusterName**：输入您在创建 Amazon EKS 集群时使用的名称。
**重要**  
此名称必须与在[第 1 步：创建您的 Amazon EKS 集群](getting-started-console.md#eks-create-cluster)中使用的名称完全匹配。否则，您的节点无法加入集群。
   +  **ClusterControlPlaneSecurityGroup**：从您在创建 [VPC](creating-a-vpc.md) 时生成的 AWS CloudFormation 输出中，选择安全组。以下步骤显示了检索适用组的一种方法。

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

     1. 选择集群的名称。

     1. 选择 **Networking**（联网）选项卡。

     1. 从 **ClusterControlPlaneSecurityGroup** 下拉列表中选择时使用 **Additional security groups**（其他安全组）值作为参考。
   +  **NodeGroupName**：输入节点组的名称。稍后您可以使用此名称来标识为您的节点创建的自动扩缩节点组。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。
   +  **NodeAutoScalingGroupMinSize**：输入您的节点自动扩缩组可横向缩减到的最小节点数。
   +  **NodeAutoScalingGroupDesiredCapacity**：输入创建堆栈时要扩展到的所需节点数目。
   +  **NodeAutoScalingGroupMaxSize**：输入您的节点自动扩缩组可横向扩展到的最大节点数。
   +  **NodeInstanceType**：选择节点的实例类型。有关更多信息，请参阅 [选择最优的 Amazon EC2 节点实例类型](choosing-instance-type.md)。
**注意**  
GitHub 的 [vpc\$1ip\$1resource\$1limit.go](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/pkg/vpc/vpc_ip_resource_limit.go) 列出[适用于 Kubernetes 的 Amazon VPC CNI 插件](https://github.com/aws/amazon-vpc-cni-k8s)最新版本支持的实例类型。您可能需要更新 CNI 版本以使用最新的受支持实例类型。有关更多信息，请参阅 [使用 Amazon VPC CNI 将 IP 分配给容器组（pod）](managing-vpc-cni.md)。
   +  **NodeImageIdSSMParam**：预先填充了当前推荐的 Amazon EKS 优化版 Windows Core AMI ID 的 Amazon EC2 Systems Manager 参数。要使用完整版本的 Windows，请将 *Core* 替换为 `Full`。
   +  **NodeImageId**：（可选）如果使用自定义 AMI（而不是 Amazon EKS 优化型 AMI），则输入您 AWS 区域的节点 AMI ID。如果您为此字段指定值，它会覆盖 **NodeImageIdSSMParam** 字段中的任意值。
   +  **NodeVolumeSize**：指定您的节点的根卷大小（以 GiB 为单位）。
   +  **KeyName**：输入 Amazon EC2 SSH 密钥对的名称，您可使用该密钥对来在节点启动后使用 SSH 连接到这些节点。如果还没有 Amazon EC2 密钥对，可以在 AWS 管理控制台 中创建一个。有关更多信息，请参阅*《Amazon EC2 用户指南》*中的 [Amazon EC2 密钥对](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-key-pairs.html)。
**注意**  
如果此处不提供密钥对，AWS CloudFormation 堆栈创建将失败。
   +  **BootstrapArguments**：指定要传递给节点引导脚本的所有可选参数，如使用 `-KubeletExtraArgs` 的其他 `kubelet` 实际参数。
   +  **DisableIMDSv1**：预设情况下，每个节点支持实例元数据服务版本 1 (IMDSv1) 和 IMDSv2。您可以禁用 IMDSv1。要防止节点组中的未来节点和容器组（pod）使用 MDSv1，请将 **DisableIMDSv1** 设置为 **true**。有关 IMDS 的更多信息，请参阅[配置实例元数据服务](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)。
   +  **VpcId**：选择创建的 [VPC](creating-a-vpc.md) 的 ID。
   +  **NodeSecurityGroups**：选择在您创建 [VPC](creating-a-vpc.md) 时为您的 Linux 节点组创建的安全组。如果您的 Linux 节点附加了多个安全组，请指定所有安全组。例如，如果 Linux 节点组是使用创建的 `eksctl`。
   +  **子网**：选择创建的子网。如果您使用[为 Amazon EKS 集群创建 Amazon VPC](creating-a-vpc.md) 中的步骤创建了 VPC，则在 VPC 中仅指定私有子网以供您的节点启动到其中。
**重要**  
如果其中的任何子网是公有子网，则其必须启用自动公有 IP 地址分配设置。如果没有为该公有子网启用该设置，则您部署到该公有子网的任何节点都不会分配到公有 IP 地址，也无法与集群或其它 AWS 服务进行通信。如果子网是在 2020 年 3 月 26 日之前使用任一 [Amazon EKS AWS CloudFormation VPC 模板](creating-a-vpc.md)部署的，或者是使用 `eksctl` 部署的，则会为这些公有子网禁用自动公有 IP 地址分配。有关如何为子网启用公有 IP 地址分配的信息，请参阅[修改子网的公有 IPv4 寻址属性](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip)。如果节点部署到私有子网，则可以通过 NAT 网关与集群和其它 AWS 服务进行通信。
如果子网没有 Internet 访问权限，请确保您了解[部署具有有限互联网访问权限的私有集群](private-clusters.md)中的注意事项和额外步骤。
如果您选择 AWS Outposts、Wavelength 或本地区域子网，则这些子网不得在您创建集群时就已传入。

1. 确认堆栈可创建 IAM 资源，然后选择 **Create stack（创建堆栈）**。

1. 完成创建堆栈后，在控制台中选中它，然后选择 **Outputs（输出）**。

1. 记录已创建的节点组的 **NodeInstanceRole**。您在配置 Amazon EKS Windows 节点时需要此值。

 **第 2 步：使节点能够加入集群** 

1. 检查您是否已经应用拥有 `aws-auth` `ConfigMap`。

   ```
   kubectl describe configmap -n kube-system aws-auth
   ```

1. 如果您看到的是 `aws-auth` `ConfigMap`，则请根据需要对其进行更新。

   1. 打开 `ConfigMap` 文件进行编辑。

      ```
      kubectl edit -n kube-system configmap/aws-auth
      ```

   1. 根据需要添加新的 `mapRoles` 条目。将 `rolearn` 值设置为您在前面的步骤中记录的 **NodeInstanceRole** 值。

      ```
      [...]
      data:
        mapRoles: |
      - rolearn: <ARN of linux instance role (not instance profile)>
            username: system:node:{{EC2PrivateDNSName}}
            groups:
              - system:bootstrappers
              - system:nodes
          - rolearn: <ARN of windows instance role (not instance profile)>
            username: system:node:{{EC2PrivateDNSName}}
            groups:
              - system:bootstrappers
              - system:nodes
              - eks:kube-proxy-windows
      [...]
      ```

   1. 保存文件并退出文本编辑器。

1. 如果您收到错误提示 "`Error from server (NotFound): configmaps "aws-auth" not found`，则请使用库存 `ConfigMap`。

   1. 下载配置映射。

      ```
      curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/aws-auth-cm-windows.yaml
      ```

   1. 在 `aws-auth-cm-windows.yaml` 文件中，将 `rolearn` 值设置为您在前面的步骤中记录的 **NodeInstanceRole** 值。您可以使用文本编辑器或者通过替换 example values 和运行以下命令来执行此操作：

      ```
      sed -i.bak -e 's|<ARN of linux instance role (not instance profile)>|my-node-linux-instance-role|' \
          -e 's|<ARN of windows instance role (not instance profile)>|my-node-windows-instance-role|' aws-auth-cm-windows.yaml
      ```
**重要**  
请勿修改此文件中的任何其它行。
不要对 Windows 和 Linux 节点使用相同的 IAM 角色。

   1. 应用配置。此命令可能需要几分钟才能完成。

      ```
      kubectl apply -f aws-auth-cm-windows.yaml
      ```

1. 查看节点的状态并等待它们达到 `Ready` 状态。

   ```
   kubectl get nodes --watch
   ```

   输入 `Ctrl`\$1`C` 以返回到 Shell 提示符。
**注意**  
如果您收到任何授权或资源类型错误，请参阅故障排除主题中的 [未经授权或访问被拒绝 (`kubectl`)](troubleshooting.md#unauthorized)。

   如果节点无法加入集群，则请参阅故障排除一章中的 [节点未能加入集群](troubleshooting.md#worker-node-fail)。

 **第 3 步：其它操作** 

1. （可选）部署[示例应用程序](sample-deployment.md)以测试您的集群和 Windows 节点。

1. （可选）如果 **AmazonEKS\$1CNI\$1Policy** 托管 IAM 策略（如果您拥有 `IPv4` 集群）或 *AmazonEKS\$1CNI\$1IPv6\$1Policy*（如果您拥有 `IPv6` 集群时[自行创建](cni-iam-role.md#cni-iam-role-create-ipv6-policy)）附加到 [Amazon EKS 节点 IAM 角色](create-node-role.md)，我们建议将其分配给关联到 Kubernetes `aws-node` 服务账户的 IAM 角色。有关更多信息，请参阅 [配置 Amazon VPC CNI 插件以使用 IRSA](cni-iam-role.md)。

1. 如果满足以下条件，我们建议阻止容器组（pod）访问 IMDS：
   + 您计划将 IAM 角色分配给所有 Kubernetes 服务账户，以便容器组（pod）仅具有其所需的最低权限。
   + 集群中没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 Amazon EC2 实例元数据服务（IMDS）。

   有关更多信息，请参阅[限制对分配给工作节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

# 创建自主管理型 Ubuntu Linux 节点
<a name="launch-node-ubuntu"></a>

**注意**  
托管节点组可能会为您的使用案例带来一些优势。有关更多信息，请参阅 [使用托管式节点组简化节点生命周期](managed-node-groups.md)。

本主题介绍了如何启动向 Amazon EKS 集群注册的[适用于 Amazon Elastic Kubernetes Service（EKS）的 Ubuntu](https://cloud-images.ubuntu.com/aws-eks/) 节点自动扩缩组，或[适用于 Amazon Elastic Kubernetes Service（EKS）的 Ubuntu Pro](https://ubuntu.com/blog/ubuntu-pro-for-eks-is-now-generally-available) 节点的自动扩缩组。适用于 EKS 的 Ubuntu 和 Ubuntu Pro 基于官方的 Ubuntu Minimal LTS，包括与 AWS 共同开发并专门为 EKS 构建的自定义 AWS 内核。Ubuntu Pro 通过支持 EKS 延期支持期、内核 livepatch、FIPS 合规性以及运行无限制 Pro 容器的功能，增加了额外的安全覆盖。

在这些节点加入集群后，您可以向其部署容器化应用程序。有关更多信息，请访问有关 [AWS 上的 Ubuntu](https://documentation.ubuntu.com/aws/en/latest/) 的文档和 `eksctl` 文档中的[自定义 AMI 支持](https://eksctl.io/usage/custom-ami-support/)。

**重要**  
Amazon EKS 节点是标准的 Amazon EC2 实例，您需要基于常规的 Amazon EC2 实例价格为其付费。有关更多信息，请参阅 [Amazon EC2 定价](https://aws.amazon.com/ec2/pricing/)。
您可以在 AWS Outposts 上的 Amazon EKS 扩展集群中启动 Ubuntu 节点，但您无法在 AWS Outposts 上的本地集群中启动这些节点。有关更多信息，请参阅 [使用 AWS Outposts 在本地部署 Amazon EKS](eks-outposts.md)。
您可以部署到采用 `x86` 或 Arm 处理器的 Amazon EC2 实例。但是，具有 Inferentia 芯片的实例可能需要先安装 [Neuron SDK](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/)。

此过程需要 `eksctl` 版本 `0.215.0` 或更高版本。可以使用以下命令来查看您的版本：

```
eksctl version
```

有关如何安装或升级 `eksctl` 的说明，请参阅 `eksctl` 文档中的[安装](https://eksctl.io/installation)。注意：此过程仅适用于使用 `eksctl` 创建的集群。

1. 将以下内容复制到您的设备。将 `my-cluster` 替换为您的集群名称。名称只能包含字母数字字符（区分大小写）和连字符。该名称必须以字母字符开头，且不得超过 100 个字符。将 `ng-ubuntu` 替换为您的节点组名称。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。要在 Arm 实例上部署，请将 `m5.large` 替换为 Arm 实例类型。将 `my-ec2-keypair-name` 替换为 Amazon EC2 SSH 密钥对的名称，您可使用该密钥对来在节点启动后使用 SSH 连接到这些节点。如果还没有 Amazon EC2 密钥对，可以在 AWS 管理控制台 中创建一个。有关更多信息，请参阅《Amazon EC2 用户指南》中的 [Amazon EC2 密钥对](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)。将所有剩余 example values 替换为您自己的值。完成替换后，运行修改后的命令以创建 `ubuntu.yaml` 文件。
**重要**  
要将节点组部署到 AWS Outposts、AWS Wavelength 或 AWS Local Zones 子网，就不要在创建集群时传递 AWS Outposts、AWS Wavelength 或 AWS Local Zones 子网。您必须在以下示例中指定子网。有关更多信息，请参阅 `eksctl` 文档中的[从配置文件创建节点组](https://eksctl.io/usage/nodegroups/#creating-a-nodegroup-from-a-config-file)和 [Config 文件架构](https://eksctl.io/usage/schema/)。将 *region-code* 替换为您的集群所在的 AWS 区域。

   ```
   cat >ubuntu.yaml <<EOF
   ---
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig
   
   metadata:
     name: my-cluster
     region: region-code
     version: '1.35'
   
   iam:
     withOIDC: true
   
   nodeGroups:
     - name: ng-ubuntu
       instanceType: m5.large
       desiredCapacity: 3
       amiFamily: Ubuntu2204
       iam:
          attachPolicyARNs:
             - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
             - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
             - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
             - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
       ssh:
           allow: true
           publicKeyName: my-ec2-keypair-name
   EOF
   ```

   要创建 Ubuntu Pro 节点组，只需将 `amiFamily` 值更改为 `UbuntuPro2204`。

1. 使用以下命令部署您的节点。

   ```
   eksctl create nodegroup --config-file=ubuntu.yaml
   ```

   示例输出如下。

   创建节点时会输出几行。输出的最后几行类似于以下示例行。

   ```
   [✔]  created 1 nodegroup(s) in cluster "my-cluster"
   ```

1. （可选）部署[示例应用程序](sample-deployment.md)来测试 Ubuntu 节点。

1. 如果满足以下条件，我们建议阻止容器组（pod）访问 IMDS：
   + 您计划将 IAM 角色分配给所有 Kubernetes 服务账户，以便容器组（pod）仅具有其所需的最低权限。
   + 集群中没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 Amazon EC2 实例元数据服务（IMDS）。

   有关更多信息，请参阅[限制对分配给工作节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

# 更新集群的自行管理型节点
<a name="update-workers"></a>

当发布新的 Amazon EKS 优化版 AMI 时，考虑将您自行管理节点组中的节点替换为这一新的 AMI。同样，如果为 Amazon EKS 集群更新 Kubernetes 版本，则还应更新节点将其用于同一 Kubernetes 版本。

**重要**  
本主题介绍适用于自行管理的节点的节点更新。如果使用的是[托管式节点组](managed-node-groups.md)，请参阅[更新集群的托管式节点组](update-managed-node-group.md)。

有两种基本方法可以更新集群中自行管理的节点组以使用新 AMI：

 **[将应用程序迁移到新的节点组](migrate-stack.md)**   
创建一个新的节点组并将您的容器组（pod）迁移到该组。迁移到新节点组比简单地在现有 AWS CloudFormation 堆栈中更新 AMI ID 更好。这是因为迁移过程会将旧节点组[污染](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)为 `NoSchedule`，并在新堆栈准备好接受现有容器组（pod）工作负载之后耗尽节点。

 **[更新 AWS CloudFormation 节点堆栈](update-stack.md)**   
更新现有节点组的 AWS CloudFormation 堆栈以使用新 AMI。使用 `eksctl` 创建的节点组不支持此方法。

# 将应用程序迁移到新的节点组
<a name="migrate-stack"></a>

本主题介绍如何创建新的节点组，将您的现有应用程序自然地迁移到新组，然后从您的集群中删除旧的节点组。您可以使用 `eksctl` 或 AWS 管理控制台 迁移到新的节点组。
+  [`eksctl`](#eksctl_migrate_apps) 
+  [AWS 管理控制台 和 AWS CLI](#console_migrate_apps) 

## `eksctl`
<a name="eksctl_migrate_apps"></a>

 **使用 `eksctl` 将您的应用程序迁移到新的节点组** 

有关使用 eksctl 进行迁移的更多信息，请参阅 `eksctl` 文档中的[非托管节点组](https://eksctl.io/usage/nodegroup-unmanaged/)。

此过程需要 `eksctl` 版本 `0.215.0` 或更高版本。可以使用以下命令来查看您的版本：

```
eksctl version
```

有关安装或升级 `eksctl` 的说明，请参阅 `eksctl` 文档中的 [Installation](https://eksctl.io/installation)。

**注意**  
此过程仅适用于使用 `eksctl` 创建的集群和节点组。

1. 检索您现有节点组的名称，同时将 *my-cluster* 替换为您的集群名称。

   ```
   eksctl get nodegroups --cluster=my-cluster
   ```

   示例输出如下。

   ```
   CLUSTER      NODEGROUP          CREATED               MIN SIZE      MAX SIZE     DESIRED CAPACITY     INSTANCE TYPE     IMAGE ID
   default      standard-nodes   2019-05-01T22:26:58Z  1             4            3                    t3.medium         ami-05a71d034119ffc12
   ```

1. 用 `eksctl` 和下面的命令启动新节点组。将命令中的所有 *example value* 替换为您自己的值。版本号不能高于控制面板的 Kubernetes 版本，也不能比控制面板的 Kubernetes 版本低两个以上的次要版本。我们建议您使用与控制面板相同的版本。

   如果满足以下条件，我们建议阻止容器组（pod）访问 IMDS：
   + 您计划将 IAM 角色分配给所有 Kubernetes 服务账户，以便容器组（pod）仅具有其所需的最低权限。
   + 集群中没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 Amazon EC2 实例元数据服务（IMDS）。

     有关更多信息，请参阅[限制对分配给 Worker 节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

     要阻止容器组（pod）对 IMDS 的访问，请将 `--disable-pod-imds` 选项添加到以下命令。
**注意**  
有关更多可用标志及其说明，请参阅 https://eksctl.io/。

   ```
   eksctl create nodegroup \
     --cluster my-cluster \
     --version 1.35 \
     --name standard-nodes-new \
     --node-type t3.medium \
     --nodes 3 \
     --nodes-min 1 \
     --nodes-max 4 \
     --managed=false
   ```

1. 当上一个命令完成时，使用以下命令验证您的所有节点是否已达到 `Ready` 状态：

   ```
   kubectl get nodes
   ```

1. 使用以下命令删除原始节点组。在命令中，将所有 *example value* 替换为集群和节点组名称：

   ```
   eksctl delete nodegroup --cluster my-cluster --name standard-nodes-old
   ```

## AWS 管理控制台 和 AWS CLI
<a name="console_migrate_apps"></a>

 **使用 AWS 管理控制台和 AWS CLI 将您的应用程序迁移到新的节点组。**

1. 执行[创建自行管理的 Amazon Linux 节点](launch-workers.md)中概述的步骤，启动新的节点组。

1. 完成创建堆栈后，在控制台中选中它，然后选择 **Outputs（输出）**。

1.  记录已创建的节点组的 **NodeInstanceRole**。您需要它来将新的 Amazon EKS 节点添加到集群。
**注意**  
如果您已将任何其他 IAM 策略附加到旧节点组 IAM 角色，则应将这些相同的策略附加到新节点组 IAM 角色以在新组上保持该功能。这适用于为 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) 添加权限的情况。

1. 同时更新两个节点组的安全组，以便它们可以相互通信。有关更多信息，请参阅 [查看集群的 Amazon EKS 安全组要求](sec-group-reqs.md)。

   1. 记下两个节点组的安全组 ID。这在 AWS CloudFormation 堆栈输出中显示为 **NodeSecurityGroup** 值。

      您可以使用以下 AWS CLI 命令从堆栈名称中获取安全组 ID。在这些命令中，`oldNodes` 是您的较旧节点堆栈的 AWS CloudFormation 堆栈名称，`newNodes` 是要迁移到的堆栈的名称。将所有 *example value* 替换为您自己的值。

      ```
      oldNodes="old_node_CFN_stack_name"
      newNodes="new_node_CFN_stack_name"
      
      oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      ```

   1. 向每个节点安全组添加入口规则，以便它们接受彼此的流量。

      以下 AWS CLI 命令向每个安全组添加入站规则，以允许来自另一个安全组的所有协议上的所有流量。通过此配置，在您将工作负载迁移到新组时，每个节点组中的容器组（pod）都可以相互通信。

      ```
      aws ec2 authorize-security-group-ingress --group-id $oldSecGroup \
      --source-group $newSecGroup --protocol -1
      aws ec2 authorize-security-group-ingress --group-id $newSecGroup \
      --source-group $oldSecGroup --protocol -1
      ```

1. 编辑 `aws-auth` configmap 以在 RBAC 中映射新的节点实例角色。

   ```
   kubectl edit configmap -n kube-system aws-auth
   ```

   为新的节点组添加新的 `mapRoles` 条目。

   ```
   apiVersion: v1
   data:
     mapRoles: |
       - rolearn: ARN of instance role (not instance profile)
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes>
       - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-U11V27W93CX5
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes
   ```

   将 *ARN of instance role (not instance profile)* 代码段替换为在[上一步](#node-instance-role-step)中记录的 **NodeInstanceRole** 值。保存并关闭该文件以应用更新后的 configmap。

1. 查看节点的状态并等待新节点加入您的集群并达到 `Ready` 状态。

   ```
   kubectl get nodes --watch
   ```

1. （可选）如果使用 [Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)，请将部署缩减到 0 个副本以避免相互冲突的扩缩操作。

   ```
   kubectl scale deployments/cluster-autoscaler --replicas=0 -n kube-system
   ```

1. 使用以下命令，对要使用 `NoSchedule` 删除的每个节点执行 Taint 操作。如此一来，就不会在要替换的节点上调用或重新调用新的容器组（pod）。有关更多信息，请参阅 Kubernetes 文档中的 [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)。

   ```
   kubectl taint nodes node_name key=value:NoSchedule
   ```

   如果要将节点升级到新的 Kubernetes 版本，则可使用以下代码段来标识并污染特定 Kubernetes 版本（此示例中为 `1.33` 版本）的所有节点。版本号不能高于控制面板的 Kubernetes 版本，也不能比控制面板的 Kubernetes 版本低两个以上的次要版本。我们建议您使用与控制面板相同的版本。

   ```
   K8S_VERSION=1.33
   nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}")
   for node in ${nodes[@]}
   do
       echo "Tainting $node"
       kubectl taint nodes $node key=value:NoSchedule
   done
   ```

1.  确定集群的 DNS 提供商。

   ```
   kubectl get deployments -l k8s-app=kube-dns -n kube-system
   ```

   示例输出如下。此集群使用 CoreDNS 解析 DNS，但您的集群可能会返回 `kube-dns`）：

   ```
   NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
   coredns   1         1         1            1           31m
   ```

1. 如果您的当前部署所运行的副本少于 2 个，请将部署扩展到 2 个副本。如果您的上一个命令输出返回了该项，请将 *coredns* 替换为`kubedns`。

   ```
   kubectl scale deployments/coredns --replicas=2 -n kube-system
   ```

1. 使用以下命令耗尽要从集群中删除的每个节点：

   ```
   kubectl drain node_name --ignore-daemonsets --delete-local-data
   ```

   如果您要将节点升级到新的 Kubernetes 版本，请使用以下代码段标识并耗尽特定 Kubernetes 版本（此示例中为 *1.33* 版本）的所有节点。

   ```
   K8S_VERSION=1.33
   nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}")
   for node in ${nodes[@]}
   do
       echo "Draining $node"
       kubectl drain $node --ignore-daemonsets --delete-local-data
   done
   ```

1. 在旧节点耗尽后，请撤销您之前授权的安全组入口规则。然后删除 AWS CloudFormation 堆栈以终止实例。
**注意**  
如果您已将任何其它 IAM 策略附加到旧节点组 IAM 角色（例如，为 [Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) 添加权限），请先将这些附加策略与该角色分离，然后才能删除 AWS CloudFormation 堆栈。

   1. 撤销您之前为节点安全组创建的入站规则。在这些命令中，`oldNodes` 是您的较旧节点堆栈的 AWS CloudFormation 堆栈名称，`newNodes` 是要迁移到的堆栈的名称。

      ```
      oldNodes="old_node_CFN_stack_name"
      newNodes="new_node_CFN_stack_name"
      
      oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \
      --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \
      --output text)
      aws ec2 revoke-security-group-ingress --group-id $oldSecGroup \
      --source-group $newSecGroup --protocol -1
      aws ec2 revoke-security-group-ingress --group-id $newSecGroup \
      --source-group $oldSecGroup --protocol -1
      ```

   1. 打开 [AWS CloudFormation 控制台](https://console.aws.amazon.com/cloudformation/)。

   1. 选择您的旧节点堆栈。

   1. 选择**删除**。

   1. 在 **Delete stack**（删除堆栈）确认对话框中，请选择 **Delete stack**（删除堆栈）。

1. 编辑 `aws-auth` configmap 以从 RBAC 中删除旧节点实例角色。

   ```
   kubectl edit configmap -n kube-system aws-auth
   ```

   删除旧节点组的 `mapRoles` 条目。

   ```
   apiVersion: v1
   data:
     mapRoles: |
       - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-W70725MZQFF8
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes
       - rolearn: arn:aws:iam::111122223333:role/nodes-1-15-NodeInstanceRole-U11V27W93CX5
         username: system:node:{{EC2PrivateDNSName}}
         groups:
           - system:bootstrappers
           - system:nodes>
   ```

   保存并关闭该文件以应用更新后的 configmap。

1. （可选）如果您使用的是 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)，请将部署缩减为 1 个副本。
**注意**  
您还必须适当地标记新的自动扩缩组（例如，`k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster`）并将您的 Cluster Autoscaler 部署命令更新为指向新标记的自动扩缩组。有关更多信息，请参阅 [AWS 上的 Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/cluster-autoscaler-release-1.3/cluster-autoscaler/cloudprovider/aws)。

   ```
   kubectl scale deployments/cluster-autoscaler --replicas=1 -n kube-system
   ```

1. （可选）确认您使用的是最新版本的 [Kubernetes 的 Amazon VPC CNI 插件](https://github.com/aws/amazon-vpc-cni-k8s)。您可能需要更新 CNI 版本以使用最新的受支持实例类型。有关更多信息，请参阅 [使用 Amazon VPC CNI 将 IP 分配给容器组（pod）](managing-vpc-cni.md)。

1. 如果您的集群使用适用于 DNS 解析的 `kube-dns`（请参阅[[migrate-determine-dns-step]](#migrate-determine-dns-step)），请将 `kube-dns` 部署横向缩减为 1 个副本。

   ```
   kubectl scale deployments/kube-dns --replicas=1 -n kube-system
   ```

# 更新 AWS CloudFormation 节点堆栈
<a name="update-stack"></a>

本主题介绍如何使用新 AMI 更新现有 AWS CloudFormation 自行管理的节点堆栈。在集群更新后，可以使用此过程将节点更新为新版本的 Kubernetes。或者，您可以更新到针对现有 Kubernetes 版本的最新 Amazon EKS 优化 AMI。

**重要**  
本主题介绍适用于自行管理的节点的节点更新。有关[使用托管式节点组简化节点生命周期](managed-node-groups.md)的信息，请参阅[更新集群的托管式节点组](update-managed-node-group.md)。

最新的默认 Amazon EKS 节点 AWS CloudFormation 模板将配置为使用新 AMI 在集群中启动实例，然后再删除旧 AMI，一次删除一个。此配置可确保您在滚动更新期间始终具有集群中自动扩缩组所需的活动实例计数。

**注意**  
使用 `eksctl` 创建的节点组不支持此方法。如果您使用 `eksctl` 创建了集群或节点组，请参阅 [将应用程序迁移到新的节点组](migrate-stack.md)。

1. 确定集群的 DNS 提供商。

   ```
   kubectl get deployments -l k8s-app=kube-dns -n kube-system
   ```

   示例输出如下。此集群使用 CoreDNS 解析 DNS，但您的集群可能会返回 `kube-dns`。您的输出可能看起来有所不同，具体取决于您使用的 `kubectl` 版本。

   ```
   NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
   coredns   1         1         1            1           31m
   ```

1. 如果您的当前部署所运行的副本少于 2 个，请将部署扩展到 2 个副本。如果您的上一个命令输出返回了该项，请将 *coredns* 替换为`kube-dns`。

   ```
   kubectl scale deployments/coredns --replicas=2 -n kube-system
   ```

1. （可选）如果使用 [Kubernetes Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md)，请将部署缩减到 0 个副本以避免相互冲突的扩缩操作。

   ```
   kubectl scale deployments/cluster-autoscaler --replicas=0 -n kube-system
   ```

1.  确定当前节点组的实例类型和所需的实例计数。以后更新该组的 AWS CloudFormation 模板时将输入这些值。

   1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

   1. 请在左侧导航窗格中，选择 **Launch Configurations**（启动配置），然后记下现有节点启动配置的实例类型。

   1. 请在左侧导航窗格中，选择**自动扩缩组**，并记下现有节点自动扩缩组的**所需**实例计数。

1. 打开 [AWS CloudFormation 控制台](https://console.aws.amazon.com/cloudformation/)。

1. 选择您的节点组堆栈，然后选择 **Update（更新）**。

1. 选择**替换当前模板**，然后选择 **Amazon S3 URL**。

1. 对于 **Amazon S3 URL**，请将以下 URL 粘贴到文本区域中以确保您使用的是最新版本的节点 AWS CloudFormation 模板。接下来，选择 **Next**（下一步）：

   ```
   https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2022-12-23/amazon-eks-nodegroup.yaml
   ```

1. 在 **Specify stack details (指定堆栈详细信息)** 页面上，填写以下参数，然后选择 **Next (下一步)**：
   +  **NodeAutoScalingGroupDesiredCapacity** - 输入在[上一步](#existing-worker-settings-step)记录的所需实例计数。或者输入更新堆栈时要扩展到的所需节点数目。
   +  **NodeAutoScalingGroupMaxSize**：输入您的节点自动扩缩组可横向扩展到的最大节点数。此值必须比所需容量多至少一个节点。这样更新期间可以对节点进行滚动更新而不会减少节点数。
   +  **NodeInstanceType** - 选择在[上一步](#existing-worker-settings-step)记录的实例类型。也可以为节点选择不同的实例类型。在选择其它实例类型之前，请查看[选择最优的 Amazon EC2 节点实例类型](choosing-instance-type.md)。每种 Amazon EC2 实例类型支持最大数量的弹性网络接口（网络接口），每个网络接口都支持最大数量的 IP 地址。由于为每个 Worker 节点和容器组（pod）分配了自己的 IP 地址，请务必选择一个实例类型，该实例类型可以支持您希望在每个 Amazon EC2 节点上运行的最大数量的容器组（pod）。有关实例类型支持的网络接口和 IP 地址数量的列表，请参阅[每种实例类型的每个网络接口的 IP 地址数](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#AvailableIpPerENI)。例如，`m5.large` 实例类型最多支持 Worker 节点和容器组（pod）的 30 个 IP 地址。
**注意**  
最新版本[适用于 Kubernetes 的 Amazon VPC CNI 插件](https://github.com/aws/amazon-vpc-cni-k8s)支持的实例类型在 GitHub 上的 [vpc\$1ip\$1resource\$1limit.go](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/pkg/vpc/vpc_ip_resource_limit.go) 中显示。您可能需要更新适用于 Kubernetes 的 Amazon VPC CNI 插件版本，才能使用最新的受支持实例类型。有关更多信息，请参阅 [使用 Amazon VPC CNI 将 IP 分配给容器组（pod）](managing-vpc-cni.md)。
**重要**  
一些实例类型并非在所有 AWS 区域中都可用。
   +  **NodeImageIdSSMParam** – 要更新到的 AMI ID 的 Amazon EC2 Systems Manager 参数。以下值为 Kubernetes 版本 `1.35` 使用最新 Amazon EKS 优化版 AMI。

     ```
     /aws/service/eks/optimized-ami/1.35/amazon-linux-2/recommended/image_id
     ```

     您可以将 *1.35* 替换为相同的 [platform-version](https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html)。或者，它应该比控制面板运行的 Kubernetes 版本高最多一个版本。我们建议您将节点保持在与控制面板相同的版本。您也可以将 *amazon-linux-2* 替换为其它 AMI 类型。有关更多信息，请参阅 [检索建议的 Amazon Linux AMI ID](retrieve-ami-id.md)。
**注意**  
使用 Amazon EC2 Systems Manager 参数让您可以在以后更新节点而无需查找和指定 AMI ID。如果您的 AWS CloudFormation 堆栈使用此值，则任何堆栈更新将为您指定的 Kubernetes 版本始终启动最新建议的 Amazon EKS 优化版 AMI。即使不更改模板中的任何值，情况也是如此。
   +  **NodeImageId** – 要使用您的自定义 AMI，请输入要使用的 AMI 的 ID。
**重要**  
此值覆盖为 **NodeImageIdSSMParam** 指定的任意值。如果您要使用 **NodeImageIdSSMParam** 值，请确保 **NodeImageId** 的值为空白。
   +  **DisableIMDSv1** - 每个节点默认支持实例元数据服务版本 1 (IMDSv1) 和 IMDSv2。但可以禁用 IMDSv1。如果不希望节点组中调度的任何节点或任何容器组（pod）使用 IMDSv1，请选择 **true**。有关 IMDS 的更多信息，请参阅[配置实例元数据服务](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)。如果已实施服务账户的 IAM 角色，请将所需权限直接分配给需要访问 AWS 服务的所有容器组（pod）。这样，集群中就没有任何容器组（pod）需要出于其他原因（例如检索当前 AWS 区域）访问 IMDS。然后，对于不使用主机网络的容器组（pod），您还可以禁用 IMDSv2 的访问权限。有关更多信息，请参阅[限制对分配给工作节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。

1. （可选）在 **Options (选项)** 页面上，为您的堆栈资源添加标签。选择**下一步**。

1. 在 **Review（审核）**页面上审核您的信息，确认堆栈可创建 IAM 资源，然后选择 **Update stack（更新堆栈）**。
**注意**  
集群中每个节点的更新需要几分钟时间。等待所有节点更新完成，然后再执行后续步骤。

1. 如果您的集群的 DNS 提供商是 `kube-dns`，请将 `kube-dns` 部署横向缩减为 1 个副本。

   ```
   kubectl scale deployments/kube-dns --replicas=1 -n kube-system
   ```

1. （可选）如果您使用的是 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md)，请将部署缩减为所需数量的副本。

   ```
   kubectl scale deployments/cluster-autoscaler --replicas=1 -n kube-system
   ```

1. （可选）确认您使用的是最新版本的 [Kubernetes 的 Amazon VPC CNI 插件](https://github.com/aws/amazon-vpc-cni-k8s)。您可能需要更新适用于 Kubernetes 的 Amazon VPC CNI 插件版本，才能使用最新的受支持实例类型。有关更多信息，请参阅 [使用 Amazon VPC CNI 将 IP 分配给容器组（pod）](managing-vpc-cni.md)。