

 **帮助改进此页面** 

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

# 使用节点来管理计算资源
<a name="eks-compute"></a>

Kubernetes 节点是运行容器化应用程序的机器。每个节点包含下列组件：
+  **[容器运行时](https://kubernetes.io/docs/setup/production-environment/container-runtimes/)** – 负责运行容器的软件。
+  ** [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) ** – 确保容器运行状况良好且在关联的容器组（pod）中运行。
+  ** [kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/) ** – 维护允许与容器组（pod）通信的网络规则。

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

Amazon EKS 集群可以按照任意 [EKS 自动模式托管节点](automode.md)、[自主管理型节点](worker.md)、[Amazon EKS 托管节点组](managed-node-groups.md)、[AWS Fargate](fargate.md) 以及 [Amazon EKS 混合节点功能](hybrid-nodes-overview.md)组合调度容器组（pod）。要了解集群中部署的节点的更多信息，请参阅 [在 AWS 管理控制台中查看 Kubernetes 资源](view-kubernetes-resources.md)。

**注意**  
除混合节点外，节点必须位于与您创建集群时所选子网相同的 VPC 中。不过，节点不需要在相同子网中。

## 比较计算选项
<a name="_compare_compute_options"></a>

下表提供了在决定哪些选项最符合您的要求时需要评估的几个标准。另一个选项是自主管理型节点，此选项支持所列的所有标准，但需要更多的手动维护。有关更多信息，请参阅 [使用自行管理型节点来自行维护节点](worker.md)。

**注意**  
Bottlerocket 与此表中的一般信息有一些具体的区别。有关更多信息，请参阅 GitHub 上的 Bottlerocket [文档](https://github.com/bottlerocket-os/bottlerocket/blob/develop/README.md)。


| 标准 | EKS 托管节点组 | EKS 自动模式 | Amazon EKS 混合节点功能 | 
| --- | --- | --- | --- | 
|  可以部署到 [AWS Outposts](https://docs.aws.amazon.com/outposts/latest/userguide/what-is-outposts.html)   |  否  |  否  |  否  | 
|  可以部署到 [AWS 本地区域](local-zones.md)   |  是  |  否  |  否  | 
|  可以运行需要 Windows 的容器  |  是  |  否  |  否  | 
|  可以运行需要 Linux 的容器  |  支持  |  是  |  是  | 
|  可以运行需要 Inferentia 芯片的工作负载  |   [是](inferentia-support.md) – 仅限 Amazon Linux 节点  |  是  |  否  | 
|  可以运行需要 GPU 的工作负载  |   [是](eks-optimized-ami.md#gpu-ami) – 仅限 Amazon Linux 节点  |  支持  |  是  | 
|  可以运行需要 ARM 处理器的工作负载  |   [是](eks-optimized-ami.md#arm-ami)   |  是  |  是  | 
|  可以运行 AWS [ Bottlerocket](https://aws.amazon.com/bottlerocket/)   |  支持  |  是  |  否  | 
|  容器组之间共享 CPU、内存、存储和网络资源。  |  支持  |  是  |  是  | 
|  必须部署和管理 Amazon EC2 实例  |  是  |  否 – 了解 [EC2 托管式实例](automode-learn-instances.md)   |  是 – 本地物理计算机或虚拟机由您使用自己选择的工具进行管理。  | 
|  必须保护、维护和修补 Amazon EC2 实例的操作系统  |  是  |  否  |  是 – 在物理计算机或虚拟机上运行的操作系统由您使用自己选择的工具进行管理。  | 
|  可以在部署节点时提供引导参数，例如额外的 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) 实际参数。  |  是 – 使用 `eksctl` 或将[启动模板](launch-templates.md)与自定义 AMI 结合使用。  |  否 – [使用 `NodeClass` 配置节点](create-node-class.md)   |  是 – 可以使用 nodeadm 自定义引导参数。请参阅 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。  | 
|  可以从与分配给节点的 IP 地址不同的 CIDR 块为容器组（pod）分配 IP 地址。  |  是 – 结合使用启动模板和自定义 AMI。有关更多信息，请参阅 [使用启动模板自定义托管式节点](launch-templates.md)。  |  否  |  是 – 请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md)。  | 
|  可以通过 SSH 访问节点  |  是  |  否 – [了解如何进行节点故障排除](auto-troubleshoot.md)   |  是  | 
|  可以将您自己的自定义 AMI 部署到节点  |  是 – 使用[启动模板](launch-templates.md)   |  否  |  是  | 
|  可以将自己的自定义 CNI 部署到节点  |  是 – 结合使用[启动模板](launch-templates.md)和自定义 AMI  |  否  |  是  | 
|  必须自己更新节点 AMI  |   [是](update-managed-node-group.md) – 如果部署 Amazon EKS 优化版 AMI，更新可用时，Amazon EKS 控制台会通知您。可以在控制台中单击一键执行更新。如果部署自定义 AMI，更新可用时，Amazon EKS 控制台不会通知您。必须自己执行更新。  |  否  |  是 – 在物理计算机或虚拟机上运行的操作系统由您使用自己选择的工具进行管理。请参阅 [为混合节点准备操作系统](hybrid-nodes-os.md)。  | 
|  必须自己更新节点 Kubernetes 版本  |   [是](update-managed-node-group.md) – 如果部署 Amazon EKS 优化版 AMI，更新可用时，Amazon EKS 控制台会通知您。可以在控制台中单击一键执行更新。如果部署自定义 AMI，更新可用时，Amazon EKS 控制台不会通知您。必须自己执行更新。  |  否  |  是 – 您可以使用自己选择的工具或使用 `nodeadm` 来管理混合节点升级。请参阅 [升级集群的混合节点](hybrid-nodes-upgrade.md)。  | 
|  可以为容器组（pod）使用 Amazon EBS 存储  |   [是](ebs-csi.md)   |  是，作为一项集成功能。了解如何[创建存储类](create-storage-class.md)。  |  否  | 
|  可以为容器组（pod）使用 Amazon EFS 存储  |   [是](efs-csi.md)   |  是  |  否  | 
|  可以为容器组（pod）使用适用于 Lustre 的 Amazon FSx 存储  |   [是](fsx-csi.md)   |  是  |  否  | 
|  可以对服务使用 Network Load Balancer  |   [是](network-load-balancing.md)   |  是  |  是 – 必须使用目标类型 `ip`。  | 
|  Pod 可以在公有子网中运行  |  支持  |  是  |  否 – 容器组在本地环境中运行。  | 
|  可以将不同的 VPC 安全组分配给各个容器组（pod）  |   [是](security-groups-for-pods.md) – 仅限 Linux 节点  |  否  |  否  | 
|  可以运行 Kubernetes DaemonSets  |  支持  |  是  |  是  | 
|  支持容器组（pod）清单中的 `HostPort` 和 `HostNetwork`  |  支持  |  是  |  是  | 
|   AWS 区域可用性  |   [所有 Amazon EKS 支持的区域](https://docs.aws.amazon.com/general/latest/gr/eks.html)   |   [所有 Amazon EKS 支持的区域](https://docs.aws.amazon.com/general/latest/gr/eks.html)   |   [所有支持 Amazon EKS 的区域](https://docs.aws.amazon.com/general/latest/gr/eks.html)，AWS GovCloud（美国）区域和中国区域除外。  | 
|  可以在 Amazon EC2 专属主机上运行容器  |  是  |  否  |  否  | 
|  定价  |  运行多个容器组（pod）的 Amazon EC2 实例的成本。有关更多信息，请参阅 [Amazon EC2定价](https://aws.amazon.com/ec2/pricing/)。  |  在集群中启用 EKS 自动模式后，除标准的 EC2 实例费用外，您还需要为使用自动模式的计算能力启动的实例单独付费。具体金额因启动的实例类型和集群所在 AWS 区域而异。有关更多信息，请参阅 [Amazon EKS 定价](https://aws.amazon.com/eks/pricing/)。  |  每小时的混合节点 vCPU 成本。有关更多信息，请参阅 [Amazon EKS 定价](https://aws.amazon.com/eks/pricing/)。  | 

# 使用托管式节点组简化节点生命周期
<a name="managed-node-groups"></a>

Amazon EKS 托管节点组为 Amazon EKS Kubernetes 集群自动对节点（Amazon EC2 实例）进行预置和生命周期管理。

使用 Amazon EKS 托管节点组，您无需单独预置或注册 Amazon EC2 实例以提供计算容量来运行 Kubernetes 应用程序。您可以通过单个操作为集群创建、自动更新或终止节点。节点的更新和终止操作会自动耗尽节点，以确保您的应用程序保持为可用的状态。

所有托管节点均作为由 Amazon EKS 为您管理的 Amazon EC2 Auto Scaling 组的一部分进行预置。所有资源（包括实例和自动扩缩组在内）都在您的 AWS 账户中运行。每个节点组跨您定义的多个可用区运行。

托管式节点组还可以选择利用节点自动修复功能，从而持续监控节点的运行状况。此功能还会自动处理检测到的问题，并在可能的情况下替换节点。这有助于在尽可能减少手动干预的情况下提高集群的整体可用性。有关更多信息，请参阅 [检测节点运行状况问题并启用自动节点修复](node-health.md)。

您可以使用 Amazon EKS 控制台、`eksctl`、AWS CLI、AWS API 或基础设施即代码工具（包括 AWS CloudFormation），将托管式节点组添加到新的或现有集群中。作为托管节点组一部分启动的节点会自动进行标记，以便 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) 能自动发现这些节点。您可以使用节点组将 Kubernetes 标签应用到节点并随时更新它们。

使用 Amazon EKS 托管节点组没有额外的费用，您只需为预置的 AWS 资源付费。这些资源包括 Amazon EC2 实例、Amazon EBS 卷、Amazon EKS 集群小时数和任何其他 AWS 基础设施。无最低费用，无预先承诺。

要开始使用新 Amazon EKS 集群和托管节点组，请参阅 [开始使用 Amazon EKS – AWS 管理控制台和 AWS CLI](getting-started-console.md)。

要将托管节点组添加到现有集群，请参阅 [为集群创建托管式节点组](create-managed-node-group.md)。

## 托管节点组概念
<a name="managed-node-group-concepts"></a>
+ Amazon EKS 托管节点组为您创建和管理 Amazon EC2 实例。
+ 所有托管节点均作为由 Amazon EKS 为您管理的 Amazon EC2 Auto Scaling 组的一部分进行预置。此外，包括 Amazon EC2 实例和自动扩缩组在内的所有资源都在您的 AWS 账户中运行。
+ 托管节点组的弹性伸缩组涵盖您在创建组时指定的所有子网。
+ Amazon EKS 标记托管节点组资源，以便将其配置为使用 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md)。
**重要**  
如果要使用 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) 在由 Amazon EBS 卷支持的多个可用区中运行有状态应用程序，则应该配置多个节点组，且每个节点组的范围都限定为一个可用区。此外，您还应该启用 `--balance-similar-node-groups` 功能。
+ 在部署托管节点时，可以使用自定义启动模板以获得更大灵活性和自定义性。例如，您可以指定额外的 `kubelet` 参数并使用自定义 AMI。有关更多信息，请参阅 [使用启动模板自定义托管式节点](launch-templates.md)。如果首次创建托管节点组时没有使用自定义启动模板，则会有自动生成的启动模板。不要手动修改此自动生成的模板，否则会发生错误。
+ Amazon EKS 在托管节点组上遵循 CVE 和安全补丁的责任共担模式。当托管节点运行 Amazon EKS 优化版 AMI 时，Amazon EKS 负责在报告 Bug 或问题时构建 AMI 的修补版本。我们可以发布修复程序。但是，您负责将这些修补的 AMI 版本部署到托管节点组。当托管节点运行自定义 AMI 时，您要负责在报告 Bug 或问题时构建 AMI 的修补版本，然后部署 AMI。有关更多信息，请参阅 [更新集群的托管式节点组](update-managed-node-group.md)。
+ Amazon EKS 托管节点组既可以在公有子网也可以在私有子网中启动。如果您在不早于 2020 年 4 月 22 日启动了公有子网中的托管节点组，则子网必须将 `MapPublicIpOnLaunch` 设置为 true，这些实例才能成功加入集群。如果公有子网是使用 `eksctl` 或 [Amazon EKS 发布的 AWS CloudFormation 模板](creating-a-vpc.md)并在 2020 年 3 月 26 日或之后创建的，则此设置已设置为 true。如果在 2020 年 3 月 26 日之前创建了公有子网，则必须手动更改设置。有关更多信息，请参阅[修改子网的公有 IPv4 寻址属性](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip)。
+ 在私有子网中部署托管节点组时，必须确保它可以访问 Amazon ECR 来拉取容器映像。您可以通过将 NAT 网关连接到子网的路由表或添加以下 [AWS PrivateLink VPC 端点](https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html#ecr-setting-up-vpc-create)来实现此目的：
  + Amazon ECR API 端点接口 – `com.amazonaws.region-code.ecr.api` 
  + Amazon ECR Docker 注册表 API 端点接口 – `com.amazonaws.region-code.ecr.dkr` 
  + Amazon S3 网关端点 – `com.amazonaws.region-code.s3` 

  有关其他常用服务和端点的信息，请参阅 [部署具有有限互联网访问权限的私有集群](private-clusters.md)。
+ 托管节点组无法部署在 [AWS Outposts](eks-outposts.md) 上或 [AWS Wavelength](https://docs.aws.amazon.com/wavelength/) 中。托管节点组现已可在 [AWS Local Zones](https://aws.amazon.com/about-aws/global-infrastructure/localzones/) 中创建。有关更多信息，请参阅 [使用 AWS Local Zones 启动低延迟 EKS 集群](local-zones.md)。
+ 您可以在单个集群中创建多个托管节点组。例如，您可以为某些工作负载使用标准的 Amazon EKS 优化版 Amazon Linux AMI 创建一个节点组，为需要 GPU 支持的工作负载使用 GPU 变体创建另一个节点组。
+ 如果您的托管节点组遇到 [Amazon EC2 实例状况检查](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html)失败，则 Amazon EKS 会返回错误代码来帮助您诊断问题。有关更多信息，请参阅 [托管节点组错误代码](troubleshooting.md#troubleshoot-managed-node-groups)。
+ Amazon EKS 将 Kubernetes 标签添加到托管节点组实例。Amazon EKS 提供的这些标签带有前缀 `eks.amazonaws.com`。
+ 在终止或更新期间，Amazon EKS 使用 Kubernetes API 自动耗尽节点。
+ 使用 `AZRebalance` 终止节点或减少所需节点数量时，未遵守容器组（pod）中断预算。这些操作试图驱逐节点上的容器组（pod）。但如果超过 15 分钟，则无论节点上的所有容器组（pod）是否都被终止，该节点都会终止。要将时间延长至节点终止，请向自动扩缩组添加生命周期挂钩。有关更多信息，请参阅《Amazon EC2 Auto Scaling 用户指南》**中的[添加生命周期挂钩](https://docs.aws.amazon.com/autoscaling/ec2/userguide/adding-lifecycle-hooks.html)。
+ 为了在收到 Spot 中断通知或容量再平衡通知后正确运行耗尽进程，必须将 `CapacityRebalance` 设置为 `true`。
+ 更新托管节点组遵循您为容器组（pod）设置的容器组（pod）中断预算。有关更多信息，请参阅 [了解节点更新的各个阶段](managed-node-update-behavior.md)。
+ 使用 Amazon EKS 托管节点组不会产生额外的费用。您仅需为预置的AWS资源付费。
+ 如果要为节点加密 Amazon EBS 卷，可以使用启动模板部署节点。要在不使用启动模板的情况下部署包含加密 Amazon EBS 卷的托管节点，必须对账户中创建的所有新 Amazon EBS 卷进行加密。有关更多信息，请参阅 *Amazon EC2 用户指南*中的[默认加密](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html#encryption-by-default)。

## 托管节点组容量类型
<a name="managed-node-group-capacity-types"></a>

创建托管节点组时，您可以选择按需容量或 Spot 容量类型。Amazon EKS 使用 Amazon EC2 Auto Scaling 组部署托管节点组，该组只包含按需实例或只包含 Amazon EC2 竞价型实例。您可以将容错应用程序的容器组（pod）调度到 Spot 托管节点组，将容错应用程序调度到单个 Kubernetes 集群中的按需节点组。预设情况下，托管节点组部署按需 Amazon EC2 实例。

### 按需
<a name="managed-node-group-capacity-types-on-demand"></a>

使用按需实例，您按秒为计算容量支付费用，无需长期订阅。

预设情况下，如果您没有指定**容量类型**，则会使用按需实例预置托管节点组。托管节点组会代表您配置 Amazon EC2 Auto Scaling 组，并应用以下设置：
+ 预置按需容量的分配策略设置为 `prioritized`。托管节点组使用实例类型在 API 中的传入顺序，确定在满足按需容量时首先使用哪种实例类型。例如，您可以按以下顺序指定三种实例类型：`c5.large`、`c4.large` 和 `c3.large`。在启动您的按需实例时，托管节点组满足按需容量的顺序是从 `c5.large` 开始，然后是 `c4.large`，再然后是 `c3.large`。有关更多信息，请参阅 *Amazon EC2 Auto Scaling 用户指南*中的 [Amazon EC2 Auto Scaling 组](https://docs.aws.amazon.com/autoscaling/ec2/userguide/asg-purchase-options.html#asg-allocation-strategies)。
+ Amazon EKS 会向您指定了容量类型的托管节点组中的所有节点添加以下 Kubernetes 标注：`eks.amazonaws.com/capacityType: ON_DEMAND`。您可以使用此标注在按需节点上调度有状态或不容错的应用程序。

### Spot
<a name="managed-node-group-capacity-types-spot"></a>

Amazon EC2 Spot 实例是备用的 Amazon EC2 容量，价格相当于在按需实例价格上打了巨大折扣。当 EC2 需要收回容量时，Amazon EC2 Spot 实例可能中断并发出一个两分钟的中断通知。有关更多信息，请参阅 *Amazon EC2 用户指南*中的[竞价型实例](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html)。您可以使用 Amazon EC2 Spot 实例配置托管节点组，以优化 Amazon EKS 集群中运行的计算节点的成本。

要在托管节点组中使用 Spot 实例，请将容量类型设置为 `spot`，创建托管节点组。托管节点组使用以下 Spot 最佳实践代表您配置 Amazon EC2 Auto Scaling 组：
+ 为确保在最佳 Spot 容量池中预置 Spot 节点，将分配策略设置为以下策略之一：
  +  `price-capacity-optimized`（PCO）– 在 Kubernetes `1.28` 版本或更高版本的集群中创建新节点组时，将分配策略设置为 `price-capacity-optimized`。但是，对于在 Amazon EKS 托管节点组开始支持 PCO 之前使用 `capacity-optimized` 创建的节点组，分配策略不会更改。
  +  `capacity-optimized`（CO）– 在 Kubernetes `1.27` 版本或更低版本的集群中创建新节点组时，将分配策略设置为 `capacity-optimized`。

  要增加可用于分配容量的 Spot 容量池的数量，请将托管节点组配置为使用多个实例类型。
+ 启用了 Amazon EC2 Spot 容量再平衡，以便 Amazon EKS 能够顺畅地耗尽和重新平衡您的 Spot 节点，从而在 Spot 节点中断风险增加时最大限度地减少应用程序中断。有关更多信息，请参阅 *Amazon EC2 Auto Scaling 用户指南*中的 [Amazon EC2 Auto Scaling 容量再平衡](https://docs.aws.amazon.com/autoscaling/ec2/userguide/capacity-rebalance.html)。
  + Spot 节点收到再平衡建议时，Amazon EKS 会自动尝试启动新的替换 Spot 节点。
  + 如果 Spot 两分钟中断通知在替换 Spot 节点进入 `Ready` 状态之前到达时间，Amazon EKS 将开始耗尽收到再平衡建议的 Spot 节点。Amazon EKS 会尽最大努力耗尽节点。因此，无法保证 Amazon EKS 会等待替换节点加入集群后再耗尽现有节点。
  + 当替换 Spot 节点引导启动并在 Kubernetes 中处于 `Ready` 状态后，Amazon EKS 将封锁并耗尽收到再平衡建议的 Spot 节点。封锁 Spot 节点可确保服务控制器不会向此 Spot 节点发送任何新请求。它还将其从其运行状况良好的活动 Spot 节点列表中删除。耗尽 Spot 节点可确保正在运行的容器组（pod）被自然地逐出。
+ Amazon EKS 会向您指定了容量类型的托管节点组中的所有节点添加以下 Kubernetes 标注：`eks.amazonaws.com/capacityType: SPOT`。您可以使用此标注在 Spot 节点上安排容错应用程序。
**重要**  
EC2 会在终止您的竞价型实例前两分钟发出[竞价型实例中断通知](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-instance-termination-notices.html)。但是，竞价型实例节点上的容器组（pod）可能无法获得完整的 2 分钟正常关闭时段。当 EC2 发出通知时，Amazon EKS 开始驱逐容器组（pod）之前会有延迟。驱逐按顺序进行，以保护 Kubernetes API 服务器，因此在同时进行多次竞价型实例回收期间，某些容器组（pod）可能会收到延迟驱逐的通知。容器组（pod）可能会在未接收到终止信号的情况下被强制终止，尤其是在高密度的容器组（pod）节点上、并发回收期间或使用较长的终止宽限期时。对于竞价型实例工作负载，建议将应用程序设计为可承受中断，使用 30 秒或更短的终止宽限期，避免长时间运行的 PreStop 钩子，并监控容器组（pod）驱逐指标以了解集群中的实际宽限期。对于需要保证正常终止的工作负载，建议改用按需容量。

在决定是部署具有按需容量还是 Spot 容量的节点组时，应考虑以下条件：
+ Spot 实例适合无状态、容错且灵活的应用程序。其中包括批处理和机器学习培训工作负载、大数据 ETL（例如 Apache Spark）、队列处理应用程序和无状态 API 端点。由于 Spot 是备用 Amazon EC2 容量，这些容量可能会随时间变化，因此我们建议您对可容忍中断的工作负载使用 Spot 容量。更具体地说，Spot 容量适合可以容忍所需容量不可用的时段的工作负载。
+ 我们建议您为不容错的应用程序使用 On-Demand。这包括集群管理工具，例如监控和操作工具，需要 `StatefulSets` 的部署，以及有状态的应用程序，如数据库。
+ 为了在使用 Spot 实例时最大限度地提高应用程序的可用性，我们建议您将 Spot 托管节点组配置为使用多个实例类型。我们建议在使用多个实例类型时应用以下规则：
  + 在托管节点组中，如果使用 [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md)，我们建议使用具有相同数量 vCPU 和内存资源的灵活实例类型集。这是为了确保集群中的节点按预期进行扩缩。例如，如果需要 4 个 vCPU 和 8 GiB 内存，请使用 `c3.xlarge`、`c4.xlarge`、`c5.xlarge`、`c5d.xlarge`、`c5a.xlarge`、`c5n.xlarge` 或其他类似实例类型。
  + 为了提高应用程序可用性，我们建议部署多个 Spot 托管节点组。为此，每个组应使用一组具有相同 vCPU 和内存资源的灵活实例类型。例如，如果您需要 4 个 vCPU 和 8 GiB 内存，我们建议您使用 `c3.xlarge`、`c4.xlarge`、`c5.xlarge`、`c5d.xlarge`、`c5a.xlarge`、`c5n.xlarge` 或其他类似的实例类型创建一个托管节点组，并使用 `m3.xlarge`、`m4.xlarge`、`m5.xlarge`、`m5d.xlarge`、`m5a.xlarge`、`m5n.xlarge` 或其他类似的实例类型创建第二个托管节点组。
  + 用使用自定义启动模板的 Spot 容量类型部署节点组时，请使用 API 传递多个实例类型。不要通过启动模板传递单个实例类型。有关使用启动模板部署节点组的更多信息，请参阅 [使用启动模板自定义托管式节点](launch-templates.md)。

# 为集群创建托管式节点组
<a name="create-managed-node-group"></a>

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

如果这是您首次启动 Amazon EKS 托管节点组，建议您改为遵循[开始使用 Amazon EKS](getting-started.md)中的指南之一。这些指南提供了有关创建包含节点的 Amazon EKS 集群的演练。

**重要**  
Amazon EKS 节点是标准的 Amazon EC2 实例。将根据正常的 Amazon EC2 价格向您计费。有关更多信息，请参阅 [Amazon EC2 定价](https://aws.amazon.com/ec2/pricing/)。
您无法在启用了 AWS Outposts 或 AWS Wavelength 的 AWS 区域创建托管节点。您可以创建自行管理的节点。有关更多信息，请参阅 [创建自行管理的 Amazon Linux 节点](launch-workers.md)、[创建自主管理型 Microsoft Windows 节点](launch-windows-workers.md) 和 [创建自主管理型 Bottlerocket 节点](launch-node-bottlerocket.md)。您还可以在 Outpost 上创建自行管理的 Amazon Linux 节点组。有关更多信息，请参阅 [在 AWS Outpost 上创建 Amazon Linux 节点](eks-outposts-self-managed-nodes.md)。
如果您没有为包含在 Amazon EKS 优化版 Linux 或 Bottlerocket 中的 `bootstrap.sh` 文件[指定 AMI ID](launch-templates.md#launch-template-custom-ami)，则托管节点组会对 `maxPods` 的值强制实施最大数量。对于 vCPU 少于 30 个的实例，最大数量为 `110`。对于 vCPU 大于 30 个的实例，最大数量将跳至 `250`。此强制执行措施会覆盖其他 `maxPods` 配置，包括 `maxPodsExpression`。有关如何确定 `maxPods` 以及如何对其进行自定义的更多信息，请参阅 [如何确定 maxPods](choosing-instance-type.md#max-pods-precedence)。
+ 现有 Amazon EKS 集群。要部署一个角色，请参阅[创建一个 Amazon EKS 集群。](create-cluster.md)。
+ 供节点使用的现有 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 可能还有其他先决条件。
+ 要添加 Windows 托管节点组，必须先启用对集群的 Windows 支持。有关更多信息，请参阅 [在 EKS 集群上部署 Windows 节点](windows-support.md)。

您可以使用以下任一途径创建托管节点组：
+  [`eksctl`](#eksctl_create_managed_nodegroup) 
+  [AWS 管理控制台](#console_create_managed_nodegroup) 

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

 **使用 eksctl 创建托管节点组** 

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

```
eksctl version
```

有关安装或升级 `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. 使用或不使用自定义启动模板创建托管节点组。手动指定启动模板可允许对节点组进行更好的自定义。例如，它可以允许部署自定义 AMI 或向 Amazon EKS 优化的 AMI 中的 `boostrap.sh` 脚本提供参数。要查看所有可用选项和原定设置的完整列表，请输入以下命令。

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

   在以下命令中，将 *my-cluster* 替换为您的集群名称，并将 *my-mng* 替换为您的节点组名称。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。
**重要**  
如果首次创建托管节点组时没有使用自定义启动模板，则以后不要对节点组使用模板。如果没有指定自定义启动模板，系统会自动生成启动模板，我们不建议您手动修改该模板。手动修改此自动生成的启动模板可能会导致错误。

 **不使用启动模板** 

 `eksctl` 在您的账户中创建默认的 Amazon EC2 启动模板，并使用它根据您指定的选项创建的启动模板来部署节点组。在为 `--node-type` 指定值之前，请参阅 [选择最优的 Amazon EC2 节点实例类型](choosing-instance-type.md)。

将 *ami-family* 替换为允许的关键字。有关更多信息，请参阅 `eksctl` 文档中的 [Setting the node AMI Family](https://eksctl.io/usage/custom-ami-support/#setting-the-node-ami-family)（设置节点 AMI 系列）。将 *my-key* 替换为您的 Amazon EC2 密钥对或公有密钥的名称。此密钥用于在节点启动后通过 SSH 进入节点。

**注意**  
对于 Windows，此命令不会启用 SSH。反之，它会将 Amazon EC2 密钥对与实例关联，并允许您 RDP 到实例中。

如果还没有 Amazon EC2 密钥对，可以在 AWS 管理控制台 中创建一个。有关 Linux 信息，请参阅《Amazon EC2 用户指南》**中的 [Amazon EC2 密钥对和 Linux 实例](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)。有关 Windows 信息，请参阅《Amazon EC2 用户指南》**中的 [Amazon EC2 密钥对和 Windows 实例](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-key-pairs.html)。

如果满足以下条件，我们建议阻止容器组（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)。

如果要阻止容器组（pod）访问 IMDS，请将 `--disable-pod-imds` 选项添加到以下命令。

```
eksctl create nodegroup \
  --cluster my-cluster \
  --region region-code \
  --name my-mng \
  --node-ami-family ami-family \
  --node-type m5.large \
  --nodes 3 \
  --nodes-min 2 \
  --nodes-max 4 \
  --ssh-access \
  --ssh-public-key my-key
```

实例可以选择为容器组（pod）分配更多 IP 地址，为其他 CIDR 块（而不是实例的 CIDR 块）中的容器组（pod）分配 IP 地址，并将其部署到没有互联网访问的集群。有关更多信息，请参阅 [为带前缀的 Amazon EKS 节点分配更多 IP 地址](cni-increase-ip-addresses.md)、[使用自定义网络在备用子网中部署容器组（pod）](cni-custom-network.md) 和 [部署具有有限互联网访问权限的私有集群](private-clusters.md)，以获取要添加到上一个命令中的其他选项。

托管节点组将根据实例类型计算并应用单个值，以作为可以在节点组的每个节点上运行的最大容器组（pod）数量。如果创建具有不同实例类型的节点组，则在所有实例类型中计算得出的最小值将应用为可以在节点组中每种实例类型上运行的最大容器组（pod）数量。托管节点组会使用 中引用的脚本计算值。

 **使用启动模板** 

启动模板必须已存在，并且必须满足[启动模板配置基础知识](launch-templates.md#launch-template-basics)中指定的要求。如果满足以下条件，我们建议阻止容器组（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)。

如果要阻止容器组（pod）访问 IMDS，请在启动模板中指定必要的设置。

1. 将以下内容复制到您的设备。替换示例值，然后运行修改后的命令以创建 `eks-nodegroup.yaml` 文件。在不使用启动模板的情况下进行部署时指定的多个设置将移动到启动模板中。如果未指定 `version`，则使用模板的默认版本。

   ```
   cat >eks-nodegroup.yaml <<EOF
   apiVersion: eksctl.io/v1alpha5
   kind: ClusterConfig
   metadata:
     name: my-cluster
     region: region-code
   managedNodeGroups:
   - name: my-mng
     launchTemplate:
       id: lt-id
       version: "1"
   EOF
   ```

   有关 `eksctl` 配置文件设置的完整列表，请参阅 `eksctl` 文档中的[配置文件架构](https://eksctl.io/usage/schema/)。实例可以选择将更多的 IP 地址分配到容器组（pod），将 IP 地址分配到其他 CIDR 块（而不是实例的 CIDR 块）中的容器组（pod），并将其部署到没有出站互联网访问的集群。有关更多信息，请参阅[为带前缀的 Amazon EKS 节点分配更多 IP 地址](cni-increase-ip-addresses.md)、[使用自定义网络在备用子网中部署容器组（pod）](cni-custom-network.md)和[部署具有有限互联网访问权限的私有集群](private-clusters.md)，以获取添加到配置文件的其他选项。

   如果没有在启动模板中指定 AMI ID，则托管节点组将根据实例类型计算并应用单个值，以作为可以在节点组的每个节点上运行的最大容器组（pod）数量。如果创建具有不同实例类型的节点组，则在所有实例类型中计算得出的最小值将应用为可以在节点组中每种实例类型上运行的最大容器组（pod）数量。托管节点组会使用 中引用的脚本计算值。

   如果在启动模板中指定了 AMI ID，请指定可以在节点组的每个节点上运行的最大容器组（pod）数量（如果您使用的是[自定义网络](cni-custom-network.md)或者想要[增加分配给实例的 IP 地址数量](cni-increase-ip-addresses.md)）。有关更多信息，请参阅 。

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

   ```
   eksctl create nodegroup --config-file eks-nodegroup.yaml
   ```

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

 **使用 AWS 管理控制台创建托管节点组** 

1. 等待集群状态显示为 `ACTIVE`。无法为状态尚未处于 `ACTIVE` 的集群创建托管节点组。

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

1. 选择要在其中创建托管节点组的集群的名称。

1. 选择 **Compute**（计算）选项卡。

1. 请选择 **Add node group**（添加节点组）。

1. 在 **Configure node group (配置节点组)** 页面上，填写相应参数，然后选择 **Next (下一步)**。
   +  **名称** – 为托管节点组输入唯一名称。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。
   +  **节点 IAM 角色** – 选择要与节点组一起使用的节点实例角色。有关更多信息，请参阅 [Amazon EKS 节点 IAM 角色](create-node-role.md)。
**重要**  
您不能使用创建任何集群时使用的相同角色。
我们建议使用任何自行管理节点组当前未使用的角色。否则，计划与新的自行管理节点组配合使用。有关更多信息，请参阅 [从集群中删除托管式节点组](delete-managed-node-group.md)。
   +  **使用启动模板** -（可选）选择是否要使用现有启动模板。选择 **Launch Template Name**（启动模板名称）。然后，选择 **Launch template version**（启动模板版本）。如果您未选择版本，Amazon EKS 将使用模板的默认版本。启动模板允许您对节点组进行更多自定义，例如允许您部署自定义 AMI、将更多的 IP 地址分配给容器组（pod）、将 IP 地址分配给其他 CIDR 块（而不是实例的 CIDR 块）中的容器组（pod），并将节点部署到没有出站互联网访问的集群。有关更多信息，请参阅 [为带前缀的 Amazon EKS 节点分配更多 IP 地址](cni-increase-ip-addresses.md)、[使用自定义网络在备用子网中部署容器组（pod）](cni-custom-network.md) 和 [部署具有有限互联网访问权限的私有集群](private-clusters.md)。

     启动模板必须满足中的[使用启动模板自定义托管式节点](launch-templates.md)中的要求。如果您不使用自己的启动模板，Amazon EKS API 会在您的账户中创建默认 Amazon EC2 启动模板，并使用默认启动模板部署节点组。

     如果实施[服务账户的 IAM 角色](iam-roles-for-service-accounts.md)，请将必要的权限直接分配给需要访问 AWS 服务的所有容器组（pod）。如果集群中没有容器组（pod）出于其他原因（例如检索当前 AWS 区域）而需要访问 IMDS，您还可以在启动模板中为不使用主机网络的容器组（pod）禁用 IMDS 的访问权限。有关更多信息，请参阅[限制对分配给工作节点的实例配置文件的访问](https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node)。
   +  **Kubernetes 标签** –（可选）您可以选择对托管节点组中的节点应用 Kubernetes 标签。
   +  **Kubernetes 污点** –（可选）您可以选择对托管节点组中的节点应用 Kubernetes 污点。**Effect**（效果）菜单中的可用选项包括 ` NoSchedule `、` NoExecute ` 和 ` PreferNoSchedule `。有关更多信息，请参阅 [方案：防止在特定节点上调度容器组（pod）](node-taints-managed-node-groups.md)。
   +  **标签** –（可选）您可以选择对 Amazon EKS 托管节点组进行标记。这些标签不会传播到节点组中的其它资源，例如自动扩缩组或实例。有关更多信息，请参阅 [使用标签整理 Amazon EKS 资源](eks-using-tags.md)。

1. 在 **Set compute and scaling configuration（设置计算和扩展配置）**页面上，填写相应参数，然后选择 **Next（下一步）**。
   +  **AMI 类型** – 选择一个 AMI 类型。如果要部署 Arm 实例，请务必在部署前查看 [Amazon EKS 优化版 Arm Amazon Linux AMI](eks-optimized-ami.md#arm-ami) 中的注意事项。

     如果您在上一页指定了启动模板，并在启动模板中指定了 AMI，则无法选择值。此时将显示模板中的值。模板中指定的 AMI 必须满足[指定 AMI](launch-templates.md#launch-template-custom-ami) 中的要求。
   +  **容量类型** – 选择容量类型。有关选择容量类型的更多信息，请参阅 [托管节点组容量类型](managed-node-groups.md#managed-node-group-capacity-types)。不能在同一节点组中混合使用不同的容量类型。如果要同时使用这两种容量类型，请创建单独的节点组，每个节点组都有自己的容量和实例类型。有关预置和扩展由 GPU 加速的 Worker 节点的信息，请参阅[为托管节点组预留 GPU](https://docs.aws.amazon.com/eks/latest/userguide/capacity-blocks-mng.html)。
   +  **实例类型** – 默认指定一个或多个实例类型。要删除默认实例类型，请选择实例类型右侧的 `X`。选择要在托管节点组中使用的实例类型。有关更多信息，请参阅 [选择最优的 Amazon EC2 节点实例类型](choosing-instance-type.md)。

     控制台显示一组常用的实例类型。如果需要使用未显示的实例类型创建托管节点组，请使用 `eksctl`、AWS CLI、AWS CloudFormation 或 SDK 创建节点组。如果在上一页指定了启动模板，则无法选择值，因为必须在启动模板中指定实例类型。将显示启动模板中的值。如果为**容量类型**选择了 **Spot 实例**，我们建议您指定多个实例类型以增强可用性。
   +  **磁盘大小** – 输入要用于节点根卷的磁盘大小（单位为 GiB）。

     如果在上一页指定了启动模板，则无法选择值，因为必须在启动模板中指定该值。
   +  **所需大小** – 指定托管节点组在启动时应当维持的当前节点数量。
**注意**  
Amazon EKS 不会自动扩展或缩减节点组。但是，您可以配置 Kubernetes Cluster Autoscaler 来为您执行此操作。有关更多信息，请参阅 [AWS 上的 Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md)。
   +  **最小大小** – 指定托管节点组可以横向缩减到的最小节点数量。
   +  **最大大小** – 指定托管节点组可以横向扩展到的最大节点数量。
   +  **节点组更新配置** –（可选）您可以选择要并行更新的节点的数量或百分比。这些节点在更新期间将不可用。对于**最大不可用**，选择下列选项之一，然后指定一个**值**：
     +  **Number**（数字）– 选择并指定节点组中可以并行更新的节点数。
     +  **Percentage**（百分比）– 选择并指定节点组中可并行更新的节点的百分比。如果您的节点组中有大量节点，这将非常有用。
   +  **节点自动修复配置** –（可选）如果您激活了**启用节点自动修复**复选框，Amazon EKS 将在检测到问题时自动替换节点。有关更多信息，请参阅 [检测节点运行状况问题并启用自动节点修复](node-health.md)。

1. 在 **Specify networking（指定联网）**页面上，相应填写参数，然后选择 **Next（下一步）**。
   +  **子网** – 选择要在其中启动托管节点的子网。
**重要**  
如果要使用 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) 在由 Amazon EBS 卷支持的多个可用区中运行有状态应用程序，则应该配置多个节点组，且每个节点组的范围都限定为一个可用区。此外，您还应该启用 `--balance-similar-node-groups` 功能。
**重要**  
如果您选择公有子网，并且您的集群仅启用公有 API 服务器端点，则子网必须将 `MapPublicIPOnLaunch` 设置为 `true`，实例才能成功加入集群。如果子网是使用 `eksctl` 或 [Amazon EKS 发布的 AWS CloudFormation 模板](creating-a-vpc.md)在 2020 年 3 月 26 日或之后创建的，则此设置已设置为 `true`。如果子网是在 2020 年 3 月 26 日之前使用 `eksctl` 或 AWS CloudFormation 模板创建的，则需要手动更改设置。有关更多信息，请参阅[修改子网的公有 IPv4 寻址属性](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip)。
如果使用启动模板并指定多个网络接口，即使 `MapPublicIpOnLaunch` 设置 `true`，Amazon EC2 也不会自动分配公有 `IPv4` 地址。在这种情况下，要让节点加入集群，您必须启用集群的私有 API 服务器端点，或者在具有出站 Internet 访问的私有子网中启动节点（Internet 访问通过如 NAT 网关等其它方法提供）。有关更多信息，请参阅 *Amazon EC2 用户指南*中的 [Amazon EC2 实例 IP 寻址](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html)。
   +  **Configure SSH access to nodes**（配置对节点的 SSH 访问）（可选）。启用 SSH 后，如果出现问题，您可以连接到实例并收集诊断信息。我们强烈建议您在创建节点组时启用远程访问。创建节点组后，将无法启用远程访问。

     如果您选择使用启动模板，则不会显示此选项。要启用对节点的远程访问，请在启动模板中指定密钥对，并确保为您在启动模板中指定的安全组中的节点打开正确的端口。有关更多信息，请参阅 [使用自定义安全组](launch-templates.md#launch-template-security-groups)。
**注意**  
对于 Windows，此命令不会启用 SSH。反之，它会将 Amazon EC2 密钥对与实例关联，并允许您 RDP 到实例中。
   + 对于 **SSH 密钥对**（可选），请选择要使用的 Amazon EC2 SSH 密钥。有关 Linux 信息，请参阅《Amazon EC2 用户指南》**中的 [Amazon EC2 密钥对和 Linux 实例](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)。有关 Windows 信息，请参阅《Amazon EC2 用户指南》**中的 [Amazon EC2 密钥对和 Windows 实例](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-key-pairs.html)。如果您选择使用启动模板，则无法选择密钥对。使用 Bottlerocket AMI 为节点组提供 Amazon EC2 SSH 密钥后，还启用管理容器。有关更多信息，请参阅 GitHub 上的 [Admin 容器](https://github.com/bottlerocket-os/bottlerocket#admin-container)。
   + 对于 **Allow SSH remote access from**（允许来自以下的远程访问），如果要限制对特定实例的访问，请选择与这些实例关联的安全组。如果没有选择特定的安全组，则允许从 Internet 上的任何位置进行 SSH 访问（`0.0.0.0/0`）。

1. 在 **Review and create (审核并创建)** 页面上，审核托管节点组配置并选择 **Create (创建)**。

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

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

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

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
   ```

## 安装 Kubernetes 附加组件
<a name="_install_kubernetes_add_ons"></a>

现在，您已有使用节点运行的 Amazon EKS 集群，那么就可以准备开始安装 Kubernetes 附加组件并将应用程序部署到集群。以下文档主题可帮助您扩展集群的此功能。
+ 创建集群的 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html#iam-term-principal)是唯一可以使用 `kubectl` 或 AWS 管理控制台 调用 Kubernetes API 服务器的主体。如果您希望其他 IAM 主体拥有访问您的集群的权限，您需要添加它们。有关更多信息，请参阅[向 IAM 用户和角色授予对 Kubernetes API 的访问权限](grant-k8s-access.md)和[所需的权限](view-kubernetes-resources.md#view-kubernetes-resources-permissions)。
+ 如果满足以下条件，我们建议阻止容器组（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)。
+ 配置 Kubernetes [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) 以自动调整节点组中的节点数。
+ 将[示例应用程序](sample-deployment.md)部署到您的集群。
+  使用管理集群的重要工具来[组织和监控集群资源](eks-managing.md)。

# 更新集群的托管式节点组
<a name="update-managed-node-group"></a>

启动托管节点组更新后，Amazon EKS 会自动更新您的节点，完成[了解节点更新的各个阶段](managed-node-update-behavior.md)中列出的步骤。如果您使用的是 Amazon EKS 优化版 AMI，Amazon EKS 会自动将最新的安全补丁和操作系统更新应用到您的节点，作为最新 AMI 版本的一部分。

在几种情况下，需要更新 Amazon EKS 托管节点组的版本或配置：
+ 您已更新 Amazon EKS 集群的 Kubernetes 版本，并且您希望更新节点以使用相同 Kubernetes 版本。
+ 新 AMI 发行版本可用于您的托管节点组。有关 AMI 版本的更多信息，请参阅以下章节：
  +  [检索 Amazon Linux AMI 版本信息](eks-linux-ami-versions.md) 
  +  [使用优化版 Bottlerocket AMI 创建节点](eks-optimized-ami-bottlerocket.md) 
  +  [检索 Windows AMI 版本信息](eks-ami-versions-windows.md) 
+ 您希望调整托管节点组中的最少、最多或所需实例数。
+ 您希望对托管节点组中的实例添加或删除 Kubernetes 标签。
+ 您希望对托管节点组添加或删除 AWS 标签。
+ 您需要部署包含配置更改（如更新的自定义 AMI）的最新版本启动模板。
+ 您已部署了版本 `1.9.0` 或更高版本的 Amazon VPC CNI 附加组件，启用了前缀委派附加组件，并希望节点组中的新 AWS Nitro 实例支持数量显著增加的容器组（pod）。有关更多信息，请参阅 [为带前缀的 Amazon EKS 节点分配更多 IP 地址](cni-increase-ip-addresses.md)。
+ 您已为 Windows 节点启用了 IP 前缀委派，并希望节点组中的新 AWS Nitro System 实例支持数量显著增加的容器组（pod）。有关更多信息，请参阅 [为带前缀的 Amazon EKS 节点分配更多 IP 地址](cni-increase-ip-addresses.md)。

如果有相比您托管节点组的 Kubernetes 版本更新的 AMI 发行版，则可以将您节点组的版本更新为使用较新的 AMI 版本。同理，如果集群运行的 Kubernetes 版本比节点组更新，则可以将节点组更新为使用与集群 Kubernetes 版本匹配的最新 AMI 发行版。

如果托管节点组中的节点因扩展操作或更新而终止，则会先耗尽该节点中的容器组（pod）。有关更多信息，请参阅 [了解节点更新的各个阶段](managed-node-update-behavior.md)。

## 更新节点组版本
<a name="mng-update"></a>

您可以使用以下任一方式更新节点组版本：
+  [`eksctl`](#eksctl_update_managed_nodegroup) 
+  [AWS 管理控制台](#console_update_managed_nodegroup) 

您更新到的版本不能高于控制面板的版本。

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

 **使用 `eksctl` 更新托管节点组** 

使用以下命令，将托管节点组更新到节点上当前部署的相同 Kubernetes 版本的最新 AMI 版本。将所有 *example value* 替换为您自己的值。

```
eksctl upgrade nodegroup \
  --name=node-group-name \
  --cluster=my-cluster \
  --region=region-code
```

**注意**  
如果要将使用启动模板部署的节点组升级到新的启动模板版本，请将 `--launch-template-version version-number ` 添加到上述命令。启动模板必须满足[使用启动模板自定义托管节点](launch-templates.md)中所述的要求。如果启动模板包含自定义 AMI，则 AMI 必须满足[指定 AMI](launch-templates.md#launch-template-custom-ami) 中的要求。将节点组升级到启动模板的更新版本后，将回收所有节点，以匹配指定的启动模板版本的新配置。

您不能将未使用启动模板部署的节点组直接升级到新的启动模板版本。相反，您必须使用启动模板部署新的节点组，以将节点组更新为新的启动模板版本。

您可以将节点组升级到与控制面板的 Kubernetes 版本相同的版本。例如，如果您的集群运行 Kubernetes `1.35`，则您可以使用以下命令，将当前运行 Kubernetes `1.34` 的节点升级到版本 `1.35`。

```
eksctl upgrade nodegroup \
  --name=node-group-name \
  --cluster=my-cluster \
  --region=region-code \
  --kubernetes-version=1.35
```

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

 **要使用 AWS 管理控制台创建托管节点组** 

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

1. 选择包含要更新的节点组的集群。

1. 如果至少有一个节点组具有可用更新，则页面顶部将出现一个提示框，通知存在可用的更新。如果选择**计算**选项卡，则在具有可用更新的节点组的**节点组**表中，**AMI 发行版本**列会显示**立即更新**。要更新节点组，请选择 **Update now**（立即更新）。

   对于使用自定义 AMI 部署的节点组，不会显示通知。如果您的节点是使用自定义 AMI 部署的，请完成以下步骤以部署更新的自定义 AMI。

   1. 创建 AMI 的新版本。

   1. 使用新 AMI ID 创建新的启动模板版本。

   1. 将节点升级到新版本的启动模板。

1. 在 **Update node group version**（更新节点组版本）对话框中，激活或停用以下选项：
   +  **Update node group version**（更新节点组版本）：如果您部署了自定义 AMI，或者您的 Amazon EKS 优化版 AMI 当前位于集群的最新版本上，则此选项不可用。
   +  **Change launch template version**（更改启动模板版本）：如果部署节点组时没有使用自定义启动模板，则此选项不可用。您只能更新已使用自定义启动模板部署的节点组的启动模板版本。选择要将节点组更新到的 **Launch template version**（启动模板版本）。如果您的节点组配置了自定义 AMI，则您选择的版本还必须指定 AMI。升级到更新版本的启动模板后，所有节点都会被回收，以匹配指定的启动模板版本的新配置。

1. 对于 **Update strategy**（更新策略），选择下列选项之一：
   +  **滚动更新** – 此选项会考虑集群的容器组（pod）中断预算。如果容器组（pod）中断预算问题导致 Amazon EKS 无法正常耗尽在此节点组上运行的容器组（pod），则更新将失败。
   +  **强制更新** – 此选项不考虑容器组（pod）中断预算。通过强制节点重新启动，无论是否存在容器组（pod）中断预算问题，都会发生更新。

1. 选择**更新**。

## 编辑节点组配置
<a name="mng-edit"></a>

您可以修改托管节点组的某些配置。

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

1. 选择包含要编辑的节点组的集群。

1. 选择**计算**选项卡。

1. 选择要编辑的节点组，然后选择 **Edit**（编辑）。

1. （可选）在**编辑节点组**页面上，执行以下操作：

   1. 编辑 **Node group scaling configuration**（节点组扩展配置）。
      +  **所需大小** – 指定托管节点组应当维持的当前节点数量。
      +  **最小大小** – 指定托管节点组可以横向缩减到的最小节点数量。
      +  **最大大小** – 指定托管节点组可以横向扩展到的最大节点数量。有关节点组中支持的最大节点数，请参阅 [查看和管理 Amazon EKS 和 Fargate 服务配额](service-quotas.md)。

   1. （可选）向节点组中的节点添加或删除 **Kubernetes 标签**。此处显示的标签仅为已应用于 Amazon EKS 的标签。节点上可能存在此处未显示的其它标签。

   1. （可选）向节点组中的节点添加或删除 **Kubernetes 污点**。添加的污点可以具有 ` NoSchedule `、` NoExecute ` 或 ` PreferNoSchedule ` 效果。有关更多信息，请参阅 [方案：防止在特定节点上调度容器组（pod）](node-taints-managed-node-groups.md)。

   1. （可选）向节点组资源添加或删除 **Tags**（标签）。这些标签仅应用于 Amazon EKS 节点组。这些标签不会传播到其它资源，例如节点组中的子网或 Amazon EC2 实例。

   1. （可选）编辑**节点组更新配置**。选择**数字**或**百分比**。
      +  **Number**（数字）– 选择并指定节点组中可以并行更新的节点数。这些节点在更新过程中将不可用。
      +  **Percentage**（百分比）– 选择并指定节点组中可并行更新的节点的百分比。这些节点在更新过程中将不可用。如果您的节点组中有大量节点，这将非常有用。

   1. 编辑完成后，选择**保存更改**。

**重要**  
更新节点组配置时，修改 [https://docs.aws.amazon.com/eks/latest/APIReference/API_NodegroupScalingConfig.html](https://docs.aws.amazon.com/eks/latest/APIReference/API_NodegroupScalingConfig.html) 不会考虑容器组（pod）中断预算（PDB）。与[更新节点组](managed-node-update-behavior.md)进程（在升级阶段耗尽节点并考虑 PDB）不同，更新扩展配置会导致通过自动扩缩组（ASG）缩减调用立即终止节点。这种情况在不考虑 PDB 的情况下发生，无论缩减到什么目标大小。这意味着，当您减少 Amazon EKS 托管节点组的 `desiredSize` 时，只要节点终止，容器组（pod）就会立即被驱逐，而不考虑任何 PDB。

# 了解节点更新的各个阶段
<a name="managed-node-update-behavior"></a>

Amazon EKS 托管 Worker 节点升级策略有四个不同的阶段，将在以下各节中介绍。

## 设置阶段
<a name="managed-node-update-set-up"></a>

设置阶段有以下步骤：

1. 为与节点组关联的自动扩缩组创建新的 Amazon EC2 启动模板版本。新的启动模板版本使用目标 AMI 或自定义启动模板版本进行更新。

1. 对自动扩缩组进行更新，以便使用最新的启动模板版本。

1. 使用节点组的 `updateConfig` 属性确定要并行升级的节点最大数量。最大不可用的配额为 100 个节点。原定设置值为一个节点。有关更多信息，请参阅《Amazon EKS API 参考》**中的 [updateConfig](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateNodegroupConfig.html#API_UpdateNodegroupConfig_RequestSyntax) 属性。

## 扩展阶段
<a name="managed-node-update-scale-up"></a>

升级托管节点组中的节点时，已升级的节点将在与正在升级的节点在相同可用区中启动。为了保证这一点，我们使用 Amazon EC2 的可用区重新平衡。有关更多信息，请参阅 *Amazon EC2 Auto Scaling 用户指南*的[可用区重新平衡](https://docs.aws.amazon.com/autoscaling/ec2/userguide/auto-scaling-benefits.html#AutoScalingBehavior.InstanceUsage)。为了满足此要求，将为托管节点组中的每个可用区启动最多两个实例。

扩展阶段有以下步骤：

1. 它增加自动扩缩组的最大大小和所需大小，增加幅度为以下两者中的较大者：
   + 部署自动扩缩组可用区数量的最多两倍。
   + 升级不可用的最大值。

     例如，如果节点组有五个可用区，`maxUnavailable` 为 1，则升级过程可以启动最多 10 个节点。但是如果 `maxUnavailable` 为 20（或者任何高于 10 的值），则该过程将启动 20 个新节点。

1. 扩展 Auto Scaling 组后，将检查节点组中是否存在使用最新配置的节点。只有在满足以下标准时，此步骤才会成功：
   + 在节点所在的每个可用区中启动至少一个新节点。
   + 每个新节点都应该处于 `Ready` 状态。
   + 新节点应该有应用 Amazon EKS 的标签。

     以下是常规节点组中的 Worker 节点上应用 Amazon EKS 的标签：
     +  `eks.amazonaws.com/nodegroup-image=$amiName` 
     +  `eks.amazonaws.com/nodegroup=$nodeGroupName` 

     以下是自定义启动模板或 AMI 节点组中的 Worker 节点上应用 Amazon EKS 的标签：
     +  `eks.amazonaws.com/nodegroup-image=$amiName` 
     +  `eks.amazonaws.com/nodegroup=$nodeGroupName` 
     +  `eks.amazonaws.com/sourceLaunchTemplateId=$launchTemplateId` 
     +  `eks.amazonaws.com/sourceLaunchTemplateVersion=$launchTemplateVersion` 

1. 将节点标记为不可调度，避免调度新的容器组（pod）。它还使用 `node.kubernetes.io/exclude-from-external-load-balancers=true` 标记节点，以便在终止节点之前从负载均衡器中移除旧节点。

下面是导致这一阶段 `NodeCreationFailure` 出现错误的已知原因：

 **可用区中容量不足**   
可用区可能没有请求的实例类型的容量。建议在创建托管节点组时配置多种实例类型。

 **账户的 EC2 实例限制**   
可能需要使用服务配额增加账户可以同时运行的 Amazon EC2 实例数量。有关更多信息，请参阅*适用于 Linux 实例的 Amazon Elastic Compute Cloud 用户指南*中的 [EC2 Service Quotas](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html)。

 **自定义用户数据**   
自定义用户数据有时会中断引导过程。这种情况可能导致节点不启动 `kubelet`，或者节点上没有获得预期的 Amazon EKS 标签。有关更多信息，请参阅 [指定 AMI](launch-templates.md#launch-template-custom-ami)。

 **使节点不正常或未就绪的任何更改**   
节点磁盘压力、内存压力和类似情况可能导致节点无法进入 `Ready` 状态。

 **每个节点的引导时间最多不超过 15 分钟**   
如果任何节点引导和加入集群的时间超过 15 分钟，则会导致升级超时。这是从需要新节点开始到新节点加入集群为止测量的引导新节点的总运行时间。升级托管节点组时，时间计数器会在自动扩缩组的大小增加后启动。

## 升级阶段
<a name="managed-node-update-upgrade"></a>

升级阶段有两种行为方式，具体取决于*更新策略*。更新策略分为**默认**策略和**最小**策略这两种。

建议在大多数情况下使用默认策略。该策略会在终止旧节点之前创建新节点，这样就能在升级阶段保持可用容量。在资源或成本受限的情况下，例如使用 GPU 等硬件加速器，最小策略非常有用。该策略会在创建新节点之前终止旧节点，这样总容量永远不会超过配置的数量。

*默认*更新策略包含如下步骤：

1. 增加自动扩缩组中的节点数量（所需数量），导致该节点组创建更多节点。

1. 它随机选择一个需要更新的节点，最多为该节点组配置的最大不可用性。

1. 耗尽节点的容器组（pod）。如果容器组（pod）在 15 分钟内没有离开节点并且没有强制标志，则升级阶段将失败并显示 `PodEvictionFailure` 错误。对于这种情况，您可以使用 `update-nodegroup-version` 请求应用强制标志来删除容器组（pod）。

1. 在每个容器组（pod）被驱逐后封锁节点并等待 60 秒钟。这样做是为了防止服务控制器向此节点发送任何新请求，并将此节点从活动节点列表中删除。

1. 它向封锁节点的自动扩缩组发送终止请求。

1. 它重复以前的升级步骤，直到节点组中没有使用早期版本启动模板部署的节点。

*最小*更新策略包括如下步骤：

1. 首先会封锁节点组中的所有节点，确保服务控制器不会向这些节点发送任何新请求。

1. 它随机选择一个需要更新的节点，最多为该节点组配置的最大不可用性。

1. 耗尽选定节点的容器组（pod）。如果容器组（pod）在 15 分钟内没有离开节点并且没有强制标志，则升级阶段将失败并显示 `PodEvictionFailure` 错误。对于这种情况，您可以使用 `update-nodegroup-version` 请求应用强制标志来删除容器组（pod）。

1. 将所有容器组弹出并等待 60 秒后，它会向选定节点的自动扩缩组发出一条终止请求。该自动扩缩组会创建新节点（数量与选定的节点数相同）来替换缺失的容量。

1. 它重复以前的升级步骤，直到节点组中没有使用早期版本启动模板部署的节点。

### 升级期间的 `PodEvictionFailure` 错误
<a name="_podevictionfailure_errors_during_the_upgrade_phase"></a>

下面是导致这一阶段 `PodEvictionFailure` 出现错误的已知原因：

 **积极的 PDB**   
积极的 PDB 在容器组（pod）上定义，或者有多个 PDB 指向同一个容器组（pod）。

 **容忍所有污点的部署**   
一旦每个容器组（pod）被逐出，预计该节点将为空，因为该节点在前面的步骤中[受到污染](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)。但是，如果部署容忍每个污点，则该节点更有可能是非空的，导致容器组（pod）驱逐失败。

## 缩减阶段
<a name="managed-node-update-scale-down"></a>

缩减阶段将自动扩缩组的最大大小和所需大小减小一，返回更新开始之前的值。

如果升级工作流确定 Cluster Autoscaler 在工作流缩减阶段扩展节点组，则会立即退出，而不会使节点组恢复原始大小。

# 使用启动模板自定义托管式节点
<a name="launch-templates"></a>

为实现最高级别的自定义，您可以根据此页面上的步骤使用自己的启动模板部署托管节点。使用启动模板可以实现以下功能：在部署节点期间提供引导参数（例如，额外的 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) 参数），从与分配给节点的 IP 地址不同的 CIDR 数据块为容器组（pod）分配 IP 地址，将自己的自定义 AMI 部署到节点，或者将自己的自定义 CNI 部署到节点。

如果您在首次创建托管节点组时提供自己的启动模板，则以后也将具有更大的灵活性。只要使用自己的启动模板部署托管节点组，您就可以使用同一启动模板的不同版本对其进行迭代更新。将节点组更新为启动模板的其他版本时，将回收组中的所有节点，以匹配指定启动模板版本的新配置。

托管式节点组始终部署用于 Amazon EC2 Auto Scaling 组的启动模板。当您不提供启动模板时，Amazon EKS API 会在您的账户中自动创建一个具有默认值的模板。但是，我们建议不要修改自动生成的启动模板。而且，无法直接更新不使用自定义启动模板的现有节点组。相反，您必须使用自定义启动模板创建新的节点组才能执行此操作。

## 启动模板配置基础知识
<a name="launch-template-basics"></a>

您可以使用 AWS 管理控制台、AWS CLI 或 AWS SDK 创建 Amazon EC2 Auto Scaling 启动模板。有关更多信息，请参阅《Amazon EC2 Auto Scaling 用户指南》**中的[为自动扩缩组创建启动模板](https://docs.aws.amazon.com/autoscaling/ec2/userguide/create-launch-template.html)。启动模板中的某些设置类似于用于托管节点配置的设置。使用启动模板部署或更新节点组时，必须在节点组配置或启动模板中指定某些设置。不要在两个位置都指定一个设置。如果某个设置出现在错误的位置，则创建或更新节点组之类的操作将失败。

下表列出启动模板中禁止的设置，它还列出托管节点组配置中所需的类似设置（如果有）。列出的设置是显示在控制台中的设置。它们在 AWS CLI 和 SDK 中可能具有相似但不同的名称。


| 启动模板 - 已禁止 | Amazon EKS 节点组配置 | 
| --- | --- | 
|   **Network interfaces（网络接口）**（**Add network interface（添加网络接口）**）下的**Subnet（子网）**  |   **Specify networking**（指定联网）页面上 **Node group network configuration**（节点组网络配置）下的 **Subnets**（子网）  | 
|   **Advanced details（高级详细信息）**下的 **IAM instance profile（IAM 实例配置文件）**   |   **Configure Node group**（配置节点组）页面上 **Node group configuration**（节点组配置）下的 **Node IAM role**（节点 IAM 角色）  | 
|   **Advanced details（高级详细信息）**下的 **Shutdown behavior（关机行为）**和 **Stop - Hibernate behavior（停止 - 休眠行为）**。在启动模板中，对于两个设置都保留默认的**不包含在启动模板设置中**。  |  无等效项 Amazon EKS 必须控制实例生命周期，而不是自动扩缩组。  | 

下表列出托管节点组配置中禁止的设置，还列出启动模板中所需的类似设置（如果有）。列出的设置是显示在控制台中的设置。它们在 AWS CLI 和 SDK 中可能有类似的名称。


| Amazon EKS 节点组配置 – 已禁止 | 启动模板 | 
| --- | --- | 
|  （仅当在启动模板中指定了自定义 AMI 时）**设置计算和扩缩配置**页面上**节点组计算配置**下的 **AMI 类型** – 控制台显示**已在启动模板中指定**和指定的 AMI ID。 如果未在启动模板中指定**应用程序和操作系统映像（Amazon 机器映像）**，则可以在节点组配置中选择 AMI。  |   **Launch template contents**（启动模板内容）下的 **Application and OS Images (Amazon Machine Image)**（应用程序和操作系统映像（Amazon 机器映像））– 如果您有以下任一要求，则必须指定 ID： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/launch-templates.html)  | 
|   **Set compute and scaling configuration**（设置计算和扩展配置）页面上 **Node group compute configuration**（节点组计算配置）下的 **Disk size**（磁盘大小）– 控制台显示 **Specified in launch template**（已在启动模板中指定）。  |   **Storage (Volumes)（存储（卷））**（**Add new volume（添加新卷）**）下的 **Size（大小）**。您必须在启动模板中指定此项。  | 
|   **Specify Networking**（指定网络）页面上 **Node group configuration**（节点组配置）下的 **SSH key pair**（SSH 密钥对）– 控制台显示在启动模板中指定的密钥或显示 **Not specified in launch template**（未在启动模板中指定）。  |   **Key pair (login)（密钥对（登录））**下的 **Key pair name（密钥对名称**。  | 
|  在使用启动模板时，您无法指定允许远程访问的源安全组。  |   实例的 **Network settings（网络设置）**下的 **Security groups（安全组）**，或者 **Network interfaces（网络接口）**（**Add network interface（添加网络接口）**）下的 **Security groups（安全组）**，但不能同时兼具。有关更多信息，请参阅 [使用自定义安全组](#launch-template-security-groups)。  | 

**注意**  
如果使用启动模板部署节点组，请在启动模板的 **Launch template contents**（启动模板内容）下指定 0 或 1 个 **Instance type**（实例类型）。您也可以为控制台 **Set compute and scaling configuration**（设置计算和扩缩配置）页面的 **Instance types**（实例类型）指定 0-20 个实例类型。或者，您可以使用其他使用 Amazon EKS API 的工具来执行此操作。如果您在启动模板中指定实例类型，并使用该启动模板部署节点组，则无法在控制台中或通过使用 Amazon EKS API 的其它工具指定任何实例类型。如果没有在启动模板、控制台中或通过使用 Amazon EKS API 的其它工具指定实例类型，则使用 `t3.medium` 实例类型。如果您的节点组使用 Spot 容量类型，我们建议您使用控制台指定多个实例类型。有关更多信息，请参阅 [托管节点组容量类型](managed-node-groups.md#managed-node-group-capacity-types)。
如果部署到节点组的任何容器使用实例元数据服务版本 2，请确保在启动模板中将**Metadata response hop limit**（元数据响应跃点限制）设置为 `2`。有关更多信息，请参阅《Amazon EC2 用户指南**》中的[实例元数据和用户数据](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)。
启动模板不支持 `InstanceRequirements` 功能，借助该功能可以灵活选择实例类型。

## 为 Amazon EC2 实例添加标签
<a name="launch-template-tagging"></a>

您可以使用启动模板的 `TagSpecification` 参数来指定将哪些标签应用于节点组中的 Amazon EC2 实例。调用 `CreateNodegroup` 或 `UpdateNodegroupVersion` API 的 IAM 实体必须具有 `ec2:RunInstances` 和 `ec2:CreateTags` 的权限，并且必须将标签添加到启动模板中。

## 使用自定义安全组
<a name="launch-template-security-groups"></a>

您可以使用启动模板指定自定义 Amazon EC2 [安全组](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)以应用到节点组中的实例。这可以在实例级安全组参数中，也可以作为网络接口配置参数的一部分。但是，您无法创建同时指定实例级安全组和网络接口安全组的启动模板。请考虑以下适用于为托管节点组使用自定义安全组的条件：
+ 使用 AWS 管理控制台时，Amazon EKS 仅允许使用具有单个网络接口规范的启动模板。
+ 预设情况下，Amazon EKS 将[集群安全组](sec-group-reqs.md)应用于节点组中的实例，以便于节点和控制层面之间的通信。如果您使用前面提到的任一选项在启动模板中指定自定义安全组，则 Amazon EKS 不会添加集群安全组。因此，您必须确保安全组的入站和出站规则启用了与集群端点的通信。如果您的安全组规则不正确，则 worker 节点无法加入集群。有关安全组规则的更多信息，请参阅 [查看集群的 Amazon EKS 安全组要求](sec-group-reqs.md)。
+ 如果需要对节点组中的实例进行 SSH 访问，请确保包含允许该访问的安全组。

## Amazon EC2 用户数据
<a name="launch-template-user-data"></a>

启动模板包括自定义用户数据的部分。您可以在此部分为节点组指定配置设置，而无需手动创建单个自定义 AMI。有关 Bottlerocket 可用设置的更多信息，请参阅 GitHub 上的[使用用户数据](https://github.com/bottlerocket-os/bottlerocket#using-user-data)。

在启动实例时，您可以使用 `cloud-init` 在启动模板中提供 Amazon EC2 用户数据。有关更多信息，请参阅 [cloud-init 文档](https://cloudinit.readthedocs.io/en/latest/index.html)。您的用户数据可用于执行常见配置操作。其中包括以下操作：
+  [包含用户或组](https://cloudinit.readthedocs.io/en/latest/topics/examples.html#including-users-and-groups) 
+  [安装程序包](https://cloudinit.readthedocs.io/en/latest/topics/examples.html#install-arbitrary-packages) 

启动模板中用于托管节点组的 Amazon EC2 用户数据必须采用 [MIME 分段归档](https://cloudinit.readthedocs.io/en/latest/topics/format.html#mime-multi-part-archive)格式（用于 Amazon Linux AMI）和 TOML 格式（用于 Bottlerocket AMI）。这是因为您的用户数据与节点加入集群所需的 Amazon EKS 用户数据合并。不要在用户数据中指定任何启动或修改 `kubelet` 的命令。这是作为 Amazon EKS 合并的用户数据的一部分执行的。某些 `kubelet` 参数（例如节点上的设置标签）可以直接通过托管节点组 API 进行配置。

**注意**  
如果需要高级 `kubelet` 自定义，包括手动启动或传入自定义配置参数，请参阅 [指定 AMI](#launch-template-custom-ami)。如果在启动模板中指定自定义 AMI ID，Amazon EKS 不会合并用户数据。

以下详细信息提供有关用户数据部分的更多信息。

 **Amazon Linux 2 用户数据**   
您可以将多个用户数据块合并到一个 MIME 分段文件中。例如，您可以将配置 Docker 守护进程的云 Boothook 与安装自定义软件包的用户数据 Shell 脚本合并。MIME 分段文件包含以下组成部分：  
+ 内容类型和段边界声明 - `Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="` 
+ MIME 版本声明 - `MIME-Version: 1.0` 
+ 一个或多个用户数据块，其包含以下组成部分：
  + 开口边界，表示用户数据块的开头 - `--==MYBOUNDARY==` 
  + 数据块的内容类型声明：`Content-Type: text/cloud-config; charset="us-ascii"`。有关内容类型的更多信息，请参阅 [cloud-init](https://cloudinit.readthedocs.io/en/latest/topics/format.html) 文档。
  + 用户数据的内容（例如 Shell 命令或 `cloud-init` 指令的列表）。
  + 封闭边界，表示 MIME 分段文件的结尾：`--==MYBOUNDARY==--`

  以下是 MIME 分段文件的示例，您可以用它来创建您自己的文件。

```
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
echo "Running custom user data script"

--==MYBOUNDARY==--
```

 **Amazon Linux 2023 用户数据**   
Amazon Linux 2023（AL2023）引入了使用 YAML 配置架构的新节点初始化流程 `nodeadm`。如果您使用的是自行管理的节点组或带有启动模板的 AMI，则在创建新节点组时，现在需要明确提供其它集群元数据。以下是最低必需参数的[示例](https://awslabs.github.io/amazon-eks-ami/nodeadm/)，其中 `apiServerEndpoint`、`certificateAuthority` 和服务 `cidr` 是必需的：  

```
---
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name: my-cluster
    apiServerEndpoint: https://example.com
    certificateAuthority: Y2VydGlmaWNhdGVBdXRob3JpdHk=
    cidr: 10.100.0.0/16
```
通常，您将在用户数据中设置此配置，无论是按原样设置还是嵌入 MIME 多部分文档中：  

```
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="BOUNDARY"

--BOUNDARY
Content-Type: application/node.eks.aws

---
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig spec: [...]

--BOUNDARY--
```
在 AL2 中，来自这些参数的元数据是从 Amazon EKS `DescribeCluster` API 调用中发现的。使用 AL2023，这种行为发生了变化，因为在大型节点纵向扩展期间，额外的 API 调用有节流风险。如果您使用的是没有启动模板的托管节点组或者 Karpenter，则此更改不会对您产生影响。有关 `certificateAuthority` 和服务 `cidr` 的更多信息，请参阅《Amazon EKS API 参考》**中的 [https://docs.aws.amazon.com/eks/latest/APIReference/API_DescribeCluster.html](https://docs.aws.amazon.com/eks/latest/APIReference/API_DescribeCluster.html)。  
以下是一个完整的 AL2023 用户数据示例，该实例将用于自定义节点（例如安装程序包或预缓存容器映像）的 shell 脚本与所需的 `nodeadm` 配置进行组合。该示例展示了常见的自定义设置，包括：\$1 安装附加系统程序包 \$1 预缓存容器影响以缩短容器组（pod）启动时间 \$1 设置 HTTP 代理配置 \$1 配置用于节点标记的 `kubelet` 标志  

```
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="BOUNDARY"

--BOUNDARY
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset

# Install additional packages
yum install -y htop jq iptables-services

# Pre-cache commonly used container images
nohup docker pull public.ecr.aws/eks-distro/kubernetes/pause:3.2 &

# Configure HTTP proxy if needed
cat > /etc/profile.d/http-proxy.sh << 'EOF'
export HTTP_PROXY="http://proxy.example.com:3128"
export HTTPS_PROXY="http://proxy.example.com:3128"
export NO_PROXY="localhost,127.0.0.1,169.254.169.254,.internal"
EOF

--BOUNDARY
Content-Type: application/node.eks.aws

apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name: my-cluster
    apiServerEndpoint: https://example.com
    certificateAuthority: Y2VydGlmaWNhdGVBdXRob3JpdHk=
    cidr: 10.100.0.0/16
  kubelet:
    config:
      clusterDNS:
      - 10.100.0.10
    flags:
    - --node-labels=app=my-app,environment=production

--BOUNDARY--
```

 **Bottlerocket 用户数据**   
Bottlerocket 采用 TOML 格式构建用户数据。您可以提供要与 Amazon EKS 提供的用户数据合并的用户数据。例如，您可以提供额外的 `kubelet` 设置。  

```
[settings.kubernetes.system-reserved]
cpu = "10m"
memory = "100Mi"
ephemeral-storage= "1Gi"
```
有关支持设置的更多信息，请参阅 GitHub 上的 [Bottlerocket 文档](https://github.com/bottlerocket-os/bottlerocket)。您可以在用户数据中配置节点标签和[污点](node-taints-managed-node-groups.md)。但是，我们建议在节点组中对其进行配置。在您这样做时，Amazon EKS 应用这些配置。  
合并用户数据时，不保留格式，但内容保持不变。您在用户数据中提供的配置将覆盖 Amazon EKS 配置的任何设置。所以，如果设置 `settings.kubernetes.max-pods` 或 `settings.kubernetes.cluster-dns-ip`，用户数据中的这些值将应用到节点。  
Amazon EKS 不支持所有有效的 TOM。以下是已知不受支持的格式的列表：  
+ 引用的键中的引号：`'quoted "value"' = "value"`
+ 值中的转义引号：`str = "I’m a string. \"You can quote me\""`
+ 混合浮点数和整数：`numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]`
+ 数组中的混合类型：`contributors = ["[foo@example.com](mailto:foo@example.com)", { name = "Baz", email = "[baz@example.com](mailto:baz@example.com)" }]`
+ 带引用键的括号标题：`[foo."bar.baz"]`

 **Windows 用户数据**   
Windows 用户数据使用 PowerShell 命令。创建托管节点组时，您的自定义用户数据与 Amazon EKS 托管用户数据结合使用。您的 PowerShell 命令排在首位，然后是托管用户数据命令，所有这些命令都在一个 `<powershell></powershell>` 标签内。  
创建 Windows 节点组时，Amazon EKS 会更新 `aws-auth` `ConfigMap`，以便允许基于 Linux 的节点加入集群。该服务不会自动配置 Windows AMI 权限。如果使用的是 Windows 节点，则需要通过访问条目 API 或通过直接更新 `aws-auth` `ConfigMap` 来管理访问权限。有关更多信息，请参阅 [在 EKS 集群上部署 Windows 节点](windows-support.md)。
如果在启动模板中未指定 AMI ID，请勿在用户数据中使用 Windows Amazon EKS 引导脚本来配置 Amazon EKS。
用户数据示例如下所示。  

```
<powershell>
Write-Host "Running custom user data script"
</powershell>
```

## 指定 AMI
<a name="launch-template-custom-ami"></a>

如果您具有以下任一要求，请在启动模板的 `ImageId` 字段中指定一个 AMI ID。选择您对其他信息的要求。

### 提供用户数据，将参数传递给随 Amazon EKS 优化版 Linux/Bottlerocket AMI 一起提供的 `bootstrap.sh` 文件
<a name="mng-specify-eks-ami"></a>

Bootstrapping（引导启动）是一个术语，用于描述添加可以在实例启动时运行的命令。例如，引导允许使用额外的 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) 参数。您可以使用 `eksctl` 将参数传递给 `bootstrap.sh` 脚本，无需指定启动模板。或者，您可以在启动模板的用户数据部分中指定信息来实现此目标。

 **eksctl 无需指定启动模板**   
创建一个名为 *my-nodegroup.yaml* 的文件，其中包含以下内容。将所有 *example value* 替换为您自己的值。`--apiserver-endpoint`、`--b64-cluster-ca` 和 `--dns-cluster-ip` 参数是可选的。但是，定义它们可使 `bootstrap.sh` 脚本避免进行 `describeCluster` 调用。在私有集群设置或频繁扩展节点的集群中，这是非常有用的。有关 `bootstrap.sh` 脚本的更多信息，请参阅 GitHub 上的 [bootstrap.sh](https://github.com/awslabs/amazon-eks-ami/blob/main/templates/al2/runtime/bootstrap.sh) 文件。  
+ 唯一必需的参数是集群名称（*my-cluster*）。
+ 要检索 `ami-1234567890abcdef0 ` 的优化版 AMI ID，请参阅以下部分：
  +  [检索建议的 Amazon Linux AMI ID](retrieve-ami-id.md) 
  +  [检索建议的 Bottlerocket AMI ID](retrieve-ami-id-bottlerocket.md) 
  +  [检索建议的 Microsoft Windows AMI ID](retrieve-windows-ami-id.md) 
+ 要检索您的集群的 *certificate-authority*，请运行以下命令。

  ```
  aws eks describe-cluster --query "cluster.certificateAuthority.data" --output text --name my-cluster --region region-code
  ```
+ 要检索您的集群的 *api-server-endpoint*，请运行以下命令。

  ```
  aws eks describe-cluster --query "cluster.endpoint" --output text --name my-cluster --region region-code
  ```
+ `--dns-cluster-ip` 的值是您的服务 CIDR，末尾为 `.10`。要检索您的集群的 *service-cidr*，请运行以下命令。例如，如果返回值为 `ipv4 10.100.0.0/16`，则您的值为 *10.100.0.10*。

  ```
  aws eks describe-cluster --query "cluster.kubernetesNetworkConfig.serviceIpv4Cidr" --output text --name my-cluster --region region-code
  ```
+ 此示例使用包含在 Amazon EKS 优化版 AMI 中的 `bootstrap.sh` 脚本提供一个 `kubelet` 参数来设置一个自定义 `max-pods` 值。节点组名称的长度不能超过 63 个字符。它必须以字母或数字开头，但也可以包括其余字符的连字符和下划线。有关选择 *my-max-pods-value* 的帮助，请参阅 。有关使用托管节点组时如何确定 `maxPods` 的更多信息，请参阅 [如何确定 maxPods](choosing-instance-type.md#max-pods-precedence)。

  ```
  ---
  apiVersion: eksctl.io/v1alpha5
  kind: ClusterConfig
  
  metadata:
    name: my-cluster
    region: region-code
  
  managedNodeGroups:
    - name: my-nodegroup
      ami: ami-1234567890abcdef0
      instanceType: m5.large
      privateNetworking: true
      disableIMDSv1: true
      labels: { x86-al2-specified-mng }
      overrideBootstrapCommand: |
        #!/bin/bash
        /etc/eks/bootstrap.sh my-cluster \
          --b64-cluster-ca certificate-authority \
          --apiserver-endpoint api-server-endpoint \
          --dns-cluster-ip service-cidr.10 \
          --kubelet-extra-args '--max-pods=my-max-pods-value' \
          --use-max-pods false
  ```

  对于每一个可用的 `eksctl` `config` 文件选项，请参阅 `eksctl` 文档中的[配置文件架构](https://eksctl.io/usage/schema/)。`eksctl` 实用程序仍会为您创建启动模板，并使用您在 `config` 文件中提供的数据填充其用户数据。

  使用以下命令创建节点组。

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

 **启动模板中的用户数据**   
在启动模板的用户数据部分指定以下信息。将所有 *example value* 替换为您自己的值。`--apiserver-endpoint`、`--b64-cluster-ca` 和 `--dns-cluster-ip` 参数是可选的。但是，定义它们可使 `bootstrap.sh` 脚本避免进行 `describeCluster` 调用。在私有集群设置或频繁扩展节点的集群中，这是非常有用的。有关 `bootstrap.sh` 脚本的更多信息，请参阅 GitHub 上的 [bootstrap.sh](https://github.com/awslabs/amazon-eks-ami/blob/main/templates/al2/runtime/bootstrap.sh) 文件。  
+ 唯一必需的参数是集群名称（*my-cluster*）。
+ 要检索您的集群的 *certificate-authority*，请运行以下命令。

  ```
  aws eks describe-cluster --query "cluster.certificateAuthority.data" --output text --name my-cluster --region region-code
  ```
+ 要检索您的集群的 *api-server-endpoint*，请运行以下命令。

  ```
  aws eks describe-cluster --query "cluster.endpoint" --output text --name my-cluster --region region-code
  ```
+ `--dns-cluster-ip` 的值是您的服务 CIDR，末尾为 `.10`。要检索您的集群的 *service-cidr*，请运行以下命令。例如，如果返回值为 `ipv4 10.100.0.0/16`，则您的值为 *10.100.0.10*。

  ```
  aws eks describe-cluster --query "cluster.kubernetesNetworkConfig.serviceIpv4Cidr" --output text --name my-cluster --region region-code
  ```
+ 此示例使用包含在 Amazon EKS 优化版 AMI 中的 `bootstrap.sh` 脚本提供一个 `kubelet` 参数来设置一个自定义 `max-pods` 值。有关选择 *my-max-pods-value* 的帮助，请参阅 。有关使用托管节点组时如何确定 `maxPods` 的更多信息，请参阅 [如何确定 maxPods](choosing-instance-type.md#max-pods-precedence)。

  ```
  MIME-Version: 1.0
  Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="
  
  --==MYBOUNDARY==
  Content-Type: text/x-shellscript; charset="us-ascii"
  
  #!/bin/bash
  set -ex
  /etc/eks/bootstrap.sh my-cluster \
    --b64-cluster-ca certificate-authority \
    --apiserver-endpoint api-server-endpoint \
    --dns-cluster-ip service-cidr.10 \
    --kubelet-extra-args '--max-pods=my-max-pods-value' \
    --use-max-pods false
  
  --==MYBOUNDARY==--
  ```

### 提供用户数据，将参数传递给随 Amazon EKS 优化版 Windows AMI 一起提供的 `Start-EKSBootstrap.ps1` 文件
<a name="mng-specify-eks-ami-windows"></a>

Bootstrapping（引导启动）是一个术语，用于描述添加可以在实例启动时运行的命令。您可以使用 `eksctl` 将参数传递给 `Start-EKSBootstrap.ps1` 脚本，无需指定启动模板。或者，您可以在启动模板的用户数据部分中指定信息来实现此目标。

如果您想指定自定义 Windows AMI ID，请记住以下注意事项：
+ 您必须使用启动模板并在用户数据部分提供所需的引导命令。要检索所需的 Windows ID，您可以使用[使用优化版 Windows AMI 创建节点](eks-optimized-windows-ami.md)中的表。
+ 有一些限制和条件。例如，您必须将 `eks:kube-proxy-windows` 添加到您的 AWS IAM 身份验证器配置映射中。有关更多信息，请参阅 [指定 AMI ID 时的限制和条件](#mng-ami-id-conditions)。

在启动模板的用户数据部分指定以下信息。将所有 *example value* 替换为您自己的值。`-APIServerEndpoint`、`-Base64ClusterCA` 和 `-DNSClusterIP` 参数是可选的。但是，定义它们可使 `Start-EKSBootstrap.ps1` 脚本避免进行 `describeCluster` 调用。
+ 唯一必需的参数是集群名称（*my-cluster*）。
+ 要检索您的集群的 *certificate-authority*，请运行以下命令。

  ```
  aws eks describe-cluster --query "cluster.certificateAuthority.data" --output text --name my-cluster --region region-code
  ```
+ 要检索您的集群的 *api-server-endpoint*，请运行以下命令。

  ```
  aws eks describe-cluster --query "cluster.endpoint" --output text --name my-cluster --region region-code
  ```
+ `--dns-cluster-ip` 的值是您的服务 CIDR，末尾为 `.10`。要检索您的集群的 *service-cidr*，请运行以下命令。例如，如果返回值为 `ipv4 10.100.0.0/16`，则您的值为 *10.100.0.10*。

  ```
  aws eks describe-cluster --query "cluster.kubernetesNetworkConfig.serviceIpv4Cidr" --output text --name my-cluster --region region-code
  ```
+ 有关更多参数，请参阅 [引导脚本配置参数](eks-optimized-windows-ami.md#bootstrap-script-configuration-parameters)。
**注意**  
如果您使用自定义服务 CIDR，则需要使用 `-ServiceCIDR` 参数进行指定。否则，集群中的容器组（pod）DNS 解析将失败。

```
<powershell>
[string]$EKSBootstrapScriptFile = "$env:ProgramFiles\Amazon\EKS\Start-EKSBootstrap.ps1"
& $EKSBootstrapScriptFile -EKSClusterName my-cluster `
	 -Base64ClusterCA certificate-authority `
	 -APIServerEndpoint api-server-endpoint `
	 -DNSClusterIP service-cidr.10
</powershell>
```

### 由于特定的安全性、合规性或内部策略要求，运行自定义 AMI
<a name="mng-specify-custom-ami"></a>

有关更多信息，请参阅《Amazon EC2 用户指南》**中的[亚马逊机器映像（AMI）](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)。Amazon EKS AMI 构建规范包含用于构建基于 Amazon Linux 的自定义 Amazon EKS AMI 的资源和配置脚本。有关更多信息，请参阅 GitHub 上的 [Amazon EKS AMI 构建规范](https://github.com/awslabs/amazon-eks-ami/)。要构建与其他操作系统一起安装的自定义 AMI，请参阅 GitHub 上的 [Amazon EKS 示例自定义 AMI](https://github.com/aws-samples/amazon-eks-custom-amis)。

在与托管式节点组一起使用的启动模板中，AMI ID 不能使用动态参数引用。

**重要**  
在指定 AMI 时，Amazon EKS 不会将您的 AMI 中嵌入的 Kubernetes 版本与您的集群控制面板版本进行比对验证。您有责任确保您的自定义 AMI 的 Kubernetes 版本符合 [Kubernetes 版本偏斜策略](https://kubernetes.io/releases/version-skew-policy)：  
您节点上的 `kubelet` 版本不得高于您的集群版本
您节点上的 `kubelet` 版本必须与集群版本相同，或者比集群版本低 3 个或更少的次要版本（对于 Kubernetes 版本 `1.28` 或更高版本）；或者比集群版本低 2 个或更少的次要版本（对于 Kubernetes 版本 `1.27` 或更低版本）  
创建存在版本偏差违规情况的托管节点组可能会导致：
节点未能加入集群
未定义的行为或 API 不兼容
集群不稳定或工作负载故障
指定 AMI 时，Amazon EKS 不会合并任何用户数据。实际上，您要负责提供节点加入集群所需的 `bootstrap` 命令。如果您的节点无法加入集群，那么 Amazon EKS `CreateNodegroup` 和 `UpdateNodegroupVersion` 操作也会失败。

## 指定 AMI ID 时的限制和条件
<a name="mng-ami-id-conditions"></a>

使用托管节点组指定 AMI ID 所涉及的限制和条件如下：
+ 您必须创建一个新的节点组，以便在在启动模板中指定 AMI ID 和不指定 AMI ID 之间进行切换。
+ 当有较新的 AMI 版本可用时，控制台中不会通知您。要将节点组更新为更新的 AMI 版本，需要使用更新的 AMI ID 创建新版本的启动模板。然后需要使用新的启动模板版本更新节点组。
+ 如果您指定 AMI ID，则无法在 API 中设置以下字段：
  +  `amiType` 
  +  `releaseVersion` 
  +  `version` 
+ 如果您指定 AMI ID，则会异步应用 API 中的任何 `taints` 设置。要在节点加入集群之前应用污点，必须使用 `--register-with-taints` 命令行标志将污点传递到用户数据中的 `kubelet`。有关更多信息，请参阅 Kubernetes 文档中的 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)。
+ 为 Windows 托管节点组指定自定义 AMI ID 时，请将 `eks:kube-proxy-windows` 添加到您的 AWS IAM 身份验证器配置映射中。需要执行此操作 DNS 才能正常运行。

  1. 打开 AWS IAM 身份验证器配置映射进行编辑。

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

  1. 将此条目添加到每个与 Windows 节点关联的 `rolearn` 下的 `groups` 列表中。您的配置图应该看起来像 [aws-auth-cm-windows.yaml](https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/aws-auth-cm-windows.yaml)。

     ```
     - eks:kube-proxy-windows
     ```

  1. 保存文件并退出文本编辑器。
+ 对于使用自定义启动模板的任何 AMI，托管节点组的默认 `HttpPutResponseHopLimit` 均设置为 `2`。

# 从集群中删除托管式节点组
<a name="delete-managed-node-group"></a>

本主题介绍如何删除 Amazon EKS 托管节点组。删除托管式节点组时，Amazon EKS 会首先将自动扩缩组的最小、最大和所需大小设置为零。然后，这会导致节点组缩小。

在每个实例终止前，Amazon EKS 会发送一个信号对该节点执行排空操作。在节点排空流程中，Kubernetes 会对节点上的每个容器组（pod）执行以下操作：运行所有已配置的 `preStop` 生命周期挂钩，向容器发送 `SIGTERM` 信号，随后等待 `terminationGracePeriodSeconds` 完成正常关闭。如果 5 分钟后节点仍未完成排空，Amazon EKS 会允许自动扩缩组继续执行实例的强制终止操作。终止所有实例后，将删除自动扩缩组。

**重要**  
如果您删除的托管节点组使用的节点 IAM 角色未由集群中任何其它托管节点组使用，则该角色将从 `aws-auth` `ConfigMap` 中移除。如果集群中的任何自行托管节点组使用相同的节点 IAM 角色，则自行管理的节点将变为 `NotReady` 状态。此外，集群操作也被中断。如果您的集群的平台版本至少为[使用 EKS 访问条目向 IAM 用户授予对 Kubernetes 的访问权限](access-entries.md) 的先决条件部分中列出的最低版本，要为仅用于自行管理的节点组的角色添加映射，请参阅[创建访问条目](creating-access-entries.md)。如果您的平台版本早于访问条目所需的最低版本，则可以将该条目重新添加到 `aws-auth` `ConfigMap`。要了解更多信息，请在您的终端中输入 `eksctl create iamidentitymapping --help`。

您可以使用以下工具删除托管节点组：
+  [`eksctl`](#eksctl-delete-managed-nodegroup) 
+  [AWS 管理控制台](#console-delete-managed-nodegroup) 
+  [AWS CLI](#awscli-delete-managed-nodegroup) 

## `eksctl`
<a name="eksctl-delete-managed-nodegroup"></a>

 **用 `eksctl` 删除托管节点组** 

输入以下命令。将每个 `<example value>` 替换为您自己的值。

```
eksctl delete nodegroup \
  --cluster <my-cluster> \
  --name <my-mng> \
  --region <region-code>
```

有关更多选项，请参阅 `eksctl` 文档中的[删除和清空节点组](https://eksctl.io/usage/nodegroups/#deleting-and-draining-nodegroups)。

## AWS 管理控制台
<a name="console-delete-managed-nodegroup"></a>

 **用 AWS 管理控制台删除托管节点组** 

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

1. 在**集群**页面上，请选择包含要删除的节点组的集群。

1. 在所选集群页面上，请选择**计算**选项卡。

1. 在 **Node groups**（节点组）部分中，选择要删除的节点组。然后选择**删除**。

1. 在**删除节点组**确认对话框中，请输入节点组的名称。然后选择**删除**。

## AWS CLI
<a name="awscli-delete-managed-nodegroup"></a>

 **用 AWS CLI 删除托管节点组** 

1. 输入如下命令。将每个 `<example value>` 替换为您自己的值。

   ```
   aws eks delete-nodegroup \
     --cluster-name <my-cluster> \
     --nodegroup-name <my-mng> \
     --region <region-code>
   ```

1. 若 CLI 配置中已设置 `cli_pager=`，则使用键盘上的方向键滚动查看响应输出内容。完成后按 `q` 键。

   有关更多选项，请参阅 *AWS CLI 命令参考*中的 ` [delete-nodegroup](https://docs.aws.amazon.com/cli/latest/reference/eks/delete-nodegroup.html) ` 命令。

# 使用自行管理型节点来自行维护节点
<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)。

# 使用 AWS Fargate 简化计算管理
<a name="fargate"></a>

本主题讨论使用 Amazon EKS 在 AWS Fargate 上运行 Kubernetes 容器组（pod）。Fargate 是一种为[容器](https://aws.amazon.com/what-are-containers)按需提供大小合适的计算容量的技术。使用 Fargate，您不必再自己预置、配置或扩展虚拟机组即可运行容器。您无需再选择服务器类型、确定扩展节点组的时间和优化集群打包。

您可以控制要在 Fargate 上启动的容器组（pod）及其如何利用 [Fargate 配置文件](fargate-profile.md)运行。Fargate 配置文件被定义为 Amazon EKS 集群的一部分。Amazon EKS 使用由 AWS 构建的控制器（使用 Kubernetes 提供的上游可扩展模型）将 Kubernetes 与 Fargate 集成。这些控制器作为 Amazon EKS 托管的 Kubernetes 控制面板的一部分运行，负责将本机 Kubernetes 容器组（pod）调度到 Fargate 上。除了若干转换和验证准入控制器外，Fargate 控制器还包括一个与默认 Kubernetes 调度器一起运行的新调度器。在启动满足 Fargate 上的运行条件的容器组（pod）时，集群中运行的 Fargate 控制器会识别、更新容器组（pod）并将其安排到 Fargate 上。

本主题介绍 Fargate 上运行的容器组（pod）的不同组件，还列出了将 Fargate 与 Amazon EKS 结合使用时的特别注意事项。

## AWS Fargate 注意事项
<a name="fargate-considerations"></a>

以下是使用 Amazon EKS 上的 Fargate 时要考虑的一些事项。
+ 在 Fargate 上运行的每个容器组都有自己的计算边界，不与其他容器组（pod）共享底层内核、CPU 资源、内存资源或弹性网络接口。
+ 网络负载均衡器和 Application Load Balancer (ALB) 只能与具有 IP 目标的 Fargate 一起使用。有关更多信息，请参阅[创建网络负载均衡器](network-load-balancing.md#network-load-balancer)和[使用应用程序负载均衡器路由应用程序和 HTTP 流量](alb-ingress.md)。
+ Fargate 暴露的服务仅在目标类型 IP 模式下运行，而不是在节点 IP 模式下运行。推荐通过服务名称进行连接来检查托管节点上运行的服务和 Fargate 上运行服务的连接性。
+ 在对容器组（pod）进行安排时，它们必须与 Fargate 配置文件匹配，才能在 Fargate 上运行。与 Fargate 配置文件不匹配的容器组可能会卡在 `Pending` 状态。如果存在匹配的 Fargate 配置文件，您可以删除已创建的待处理容器组（pod），将之重新调度到 Fargate 上。
+ Fargate 上不支持 Daemonset。如果应用程序需要进程守护程序，则应将该进程守护程序重新配置为在容器组（pod）中作为边车容器运行。
+ Fargate 上不支持特权容器。
+ 在 Fargate 上运行的容器组（pod）无法在容器组（pod）清单中指定 `HostPort` 或 `HostNetwork`。
+ 对于 Fargate 容器组（pod），默认 `nofile` 和 `nproc` 软限制为 1024，硬限制为 65535。
+ GPU 目前在 Fargate 上不可用。
+ 在 Fargate 上运行的容器组（pod）仅在私有子网上受支持（对 AWS 服务具有 NAT 网关访问权限，但没有到互联网网关的直接路由），因此您的集群的 VPC 必须具有可用的私有子网。对于没有出站 Internet 访问的集群，请参阅 [部署具有有限互联网访问权限的私有集群](private-clusters.md)。
+ 您可以按照[使用 Vertical Pod Autoscaler 调整容器组（pod）资源](vertical-pod-autoscaler.md)来设置 Fargate 容器组（pod）的正确初始 CPU 和内存大小，然后按照[使用 Horizontal Pod Autoscaler 扩展容器组（pod）部署](horizontal-pod-autoscaler.md)来扩展那些容器组（pod）。如果希望 Vertical Pod Autoscaler 自动将容器组（pod）重新部署到具有更大 CPU 和内存组合的 Fargate，请将 Vertical Pod Autoscaler 的模式设置为 `Auto` 或 `Recreate`，确保功能正常运行。有关更多信息，请参阅 GitHub 上的 [Vertical Pod Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#quick-start) 文档。
+ 必须为 VPC 启用 DNS 解析和 DNS 主机名。有关详细信息，请参阅[查看和更新您的 VPC 的 DNS 支持](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-updating)。
+ Amazon EKS Fargate 通过将虚拟机 (VM) 中的每个容器组隔离出来，从而为 Kubernetes 应用程序添加深度防御。此 VM 边界可防止在容器逃离情况下访问其他容器组使用的基于主机的资源，容器逃离是攻击容器化应用程序和获取容器外部资源访问权限的常见方法。

  使用 Amazon EKS 不会更改您在[责任共担模式](security.md)下的责任。您应该仔细考虑集群安全和治理控制的配置。隔离应用程序的最安全方法始终是在单独的集群中运行该程序。
+ Fargate 配置文件支持从 VPC 辅助 CIDR 块指定子网。您可能想要指定辅助 CIDR 块。这是因为子网中可用 IP 地址的数量是有限的。因此，可在集群中创建的容器组（pod）数量受到限制。对容器组（pod）使用不同的子网，您可以增加可用 IP 地址的数量。有关更多信息，请参阅[向 VPC 中添加 IPv4 CIDR 块](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html#vpc-resize)。
+ 部署到 Fargate 节点的容器组（pod）无法使用 Amazon EC2 实例元数据服务（IMDS）。如果在 Fargate 部署了需要 IAM 凭证的容器组（pod），请使用[服务账户的 IAM 角色](iam-roles-for-service-accounts.md)将之分配到容器组（pod）。如果容器组（pod）需要通过 IMDS 访问其他可用信息，则必须将此信息硬编码到容器组（pod）规范中。这包括容器组（pod）部署到的 AWS 区域或可用区。
+ 您不能将 Fargate 容器组（pod）部署到 AWS Outposts、AWS Wavelength 或 AWS Local Zones。
+ Amazon EKS 必须定期修补 Fargate 容器组（pod）来确保它们的安全。我们以减少影响的方式尝试更新，但是有时候，如果没有成功驱逐容器组（pod），必须删除它们。您可以采取一些措施来尽量减少中断。有关更多信息，请参阅 [为 AWS Fargate 操作系统补丁事件设置操作](fargate-pod-patching.md)。
+ [适用于 Amazon EKS 的 Amazon VPC CNI 插件](https://github.com/aws/amazon-vpc-cni-plugins)安装在 Fargate 节点上。您不能将[适用于 Amazon EKS 集群的 Alternate CNI 插件](alternate-cni-plugins.md)用于 Fargate 节点。
+ Fargate 上运行的容器组（pod）会自动挂载 Amazon EFS 文件系统，无需手动执行驱动程序安装步骤。您不能将动态持久性卷预置与 Fargate 节点结合使用，但可以使用静态预置。
+ Amazon EKS 不支持 Fargate Spot。
+ 您无法将 Amazon EBS 卷挂载到 Fargate 容器组（pod）。
+ 您可以在 Fargate 节点上运行 Amazon EBS CSI 控制器，但 Amazon EBS CSI 节点 DaemonSet 只能在 Amazon EC2 实例上运行。
+ 在 [Kubernetes 作业](https://kubernetes.io/docs/concepts/workloads/controllers/job/)被标记为 `Completed` 或 `Failed` 后，作业创建的容器组（pod）通常会继续存在。此行为允许您查看日志和结果，但在使用 Fargate 的情况下，如果您过后不清理作业，则将会产生费用。

  要在作业完成或失败后自动删除相关的容器组（pod），您可以使用生存时间（TTL）控制器指定时间段。以下示例显示了在作业清单中指定 `.spec.ttlSecondsAfterFinished`。

  ```
  apiVersion: batch/v1
  kind: Job
  metadata:
    name: busybox
  spec:
    template:
      spec:
        containers:
        - name: busybox
          image: busybox
          command: ["/bin/sh", "-c", "sleep 10"]
        restartPolicy: Never
    ttlSecondsAfterFinished: 60 # <-- TTL controller
  ```

## Fargate 比较表
<a name="_fargate_comparison_table"></a>


| 标准 |  AWS Fargate | 
| --- | --- | 
|  可以部署到 [AWS Outposts](https://docs.aws.amazon.com/outposts/latest/userguide/what-is-outposts.html)   |  否  | 
|  可以部署到 [AWS 本地区域](local-zones.md)   |  否  | 
|  可以运行需要 Windows 的容器  |  否  | 
|  可以运行需要 Linux 的容器  |  是  | 
|  可以运行需要 Inferentia 芯片的工作负载  |  否  | 
|  可以运行需要 GPU 的工作负载  |  否  | 
|  可以运行需要 ARM 处理器的工作负载  |  否  | 
|  可以运行 AWS [ Bottlerocket](https://aws.amazon.com/bottlerocket/)   |  否  | 
|  容器组（pod）之间共享内核运行时环境  |  否 – 每个容器组（pod）拥有专用的内核  | 
|  容器组之间共享 CPU、内存、存储和网络资源。  |  否 – 每个容器组（pod）都有专用资源，并且可以独立调整大小，能够最大限度地提高资源利用率。  | 
|  容器组（pod）可以使用多于容器组（pod）规范中所请求的硬件和内存  |  否 – 但是，可以使用更大的 vCPU 和内存配置重新部署容器组（pod）。  | 
|  必须部署和管理 Amazon EC2 实例  |  否  | 
|  必须保护、维护和修补 Amazon EC2 实例的操作系统  |  否  | 
|  可以在部署节点时提供引导参数，例如额外的 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) 实际参数。  |  否  | 
|  可以从与分配给节点的 IP 地址不同的 CIDR 块为容器组（pod）分配 IP 地址。  |  否  | 
|  可以通过 SSH 访问节点  |  否 – 没有主机操作系统要通过 SSH 访问的节点。  | 
|  可以将您自己的自定义 AMI 部署到节点  |  否  | 
|  可以将自己的自定义 CNI 部署到节点  |  否  | 
|  必须自己更新节点 AMI  |  否  | 
|  必须自己更新节点 Kubernetes 版本  |  否 – 您不管理节点。  | 
|  可以为容器组（pod）使用 Amazon EBS 存储  |  否  | 
|  可以为容器组（pod）使用 Amazon EFS 存储  |   [是](efs-csi.md)   | 
|  可以为容器组（pod）使用适用于 Lustre 的 Amazon FSx 存储  |  否  | 
|  可以对服务使用 Network Load Balancer  |  是，当使用[创建网络负载均衡器](network-load-balancing.md#network-load-balancer)时   | 
|  Pod 可以在公有子网中运行  |  否  | 
|  可以将不同的 VPC 安全组分配给各个容器组（pod）  |  是  | 
|  可以运行 Kubernetes DaemonSets  |  否  | 
|  支持容器组（pod）清单中的 `HostPort` 和 `HostNetwork`  |  否  | 
|   AWS 区域可用性  |   [部分 Amazon EKS 支持的区域](https://docs.aws.amazon.com/general/latest/gr/eks.html)   | 
|  可以在 Amazon EC2 专属主机上运行容器  |  否  | 
|  定价  |  单个 Fargate 内存和 CPU 配置的成本。每个容器组（pod）都有自己的成本。有关更多信息，请参阅 [AWS Fargate 定价](https://aws.amazon.com/fargate/pricing/)。  | 

# 开始将 AWS Fargate 用于集群
<a name="fargate-getting-started"></a>

本主题介绍如何通过 Amazon EKS 集群开始在 AWS Fargate 上运行容器组（pod）。

如果使用 CIDR 块限制对集群的公有端点的访问，建议您还启用私有端点访问。通过这种方式，Fargate 容器组（pod）可以与集群通信。在未启用私有端点的情况下，您指定用于公有访问的 CIDR 块必须包含来自 VPC 的出站源。有关更多信息，请参阅 [集群 API 服务器端点](cluster-endpoint.md)。

**先决条件**  
现有集群。如果您还没有 Amazon EKS 集群，请参阅[开始使用 Amazon EKS](getting-started.md)。

## 第 1 步：确保现有节点可以与 Fargate 容器组（pod）进行通信
<a name="fargate-gs-check-compatibility"></a>

如果您使用的是没有节点的新集群，或是只有托管节点组的集群（请参阅[使用托管式节点组简化节点生命周期](managed-node-groups.md)），可以跳至[第 2 步：创建 Fargate 容器组（pod）执行角色](#fargate-sg-pod-execution-role)。

假设您正在使用已有关联节点的现有集群。确保这些节点上的容器组（pod）可以与 Fargate 上运行的容器组（pod）自由通信。在 Fargate 上运行的容器组（pod）会自动配置为使用与其关联的集群的集群安全组。确保集群中的任何现有节点都可以向集群安全组发送流量以及接收来自集群安全组的流量。托管节点组也会自动配置为使用集群安全组，所以您无需修改或检查它们是否具有此兼容性（请参阅[使用托管式节点组简化节点生命周期](managed-node-groups.md)）。

针对已使用 `eksctl` 或者 Amazon EKS 管理 AWS CloudFormation 模板创建的现有节点组，您可以手动将集群安全组添加到节点。您也可以修改节点组的自动扩缩组启动模板，以便将集群安全组附加到实例。有关更多信息，请参阅《Amazon VPC 用户指南》**中的[更改实例的安全组](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html#SG_Changing_Group_Membership)。

您可以在 AWS 管理控制台 中集群的 **Networking**（联网）部分下，检查您集群的安全组。或者，您可以使用下面的 AWS CLI 命令进行这项操作。使用此命令时，请将 `<my-cluster>` 替换为您的集群名称。

```
aws eks describe-cluster --name <my-cluster> --query cluster.resourcesVpcConfig.clusterSecurityGroupId
```

## 第 2 步：创建 Fargate 容器组（pod）执行角色
<a name="fargate-sg-pod-execution-role"></a>

当您的集群在 AWS Fargate 上创建容器组（pod）时，在 Fargate 基础设施上运行的组件必须代表您调用 AWS API。Amazon EKS 容器组（pod）执行角色提供执行此操作的 IAM 权限。要创建 AWS Fargate 容器组（pod）执行角色，请参阅 [Amazon EKS 容器组（pod）执行 IAM 角色](pod-execution-role.md)。

**注意**  
如果您使用 `--fargate` 选项通过 `eksctl` 创建了集群，则集群已具有容器组（pod）执行角色，您可以使用模式 `eksctl-my-cluster-FargatePodExecutionRole-ABCDEFGHIJKL` 在 IAM 控制台中找到该角色。同理，如果您使用 `eksctl` 创建 Fargate 配置文件，则 `eksctl` 会创建您的容器组（pod）执行角色（如果尚未创建）。

## 第 3 步：为集群创建 Fargate 配置文件
<a name="fargate-gs-create-profile"></a>

您必须先定义一个 Fargate 配置文件，指定在启动时哪些容器组（pod）使用 Fargate，然后才能调度在集群中的 Fargate 上运行的容器组（pod）。有关更多信息，请参阅 [定义启动时将使用 AWS Fargate 的容器组（pod）](fargate-profile.md)。

**注意**  
如果您使用 `--fargate` 选项通过 `eksctl` 创建了集群，则已经为您的集群创建了 Fargate 配置文件，而且其包含 `kube-system` 和 `default` 命名空间中所有容器组（pod）的选择器。使用以下程序为您想要用于 Fargate 的任何其他命名空间创建 Fargate 配置文件。

您可以使用以下任一工具创建 Fargate 配置文件：
+  [`eksctl`](#eksctl_fargate_profile_create) 
+  [AWS 管理控制台](#console_fargate_profile_create) 

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

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

```
eksctl version
```

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

 **使用 `eksctl` 创建 Fargate 配置文件** 

使用以下 `eksctl` 命令创建 Fargate 配置文件，并将所有 `<example value>` 替换为您自己的值。您需要指定命名空间。但是，`--labels` 选项不是必选。

```
eksctl create fargateprofile \
    --cluster <my-cluster> \
    --name <my-fargate-profile> \
    --namespace <my-kubernetes-namespace> \
    --labels <key=value>
```

您可以将某些通配符用于 `<my-kubernetes-namespace>` 和 `<key=value>` 标签。有关更多信息，请参阅 [Fargate 配置文件通配符](fargate-profile.md#fargate-profile-wildcards)。

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

 **使用 AWS 管理控制台 创建 Fargate 配置文件** 

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

1. 选择要为其创建 Fargate 配置文件的集群。

1. 请选择 **Compute**（计算）选项卡。

1. 在 **Fargate profiles（Fargate 配置文件）**下，选择 **Add Fargate profile（添加 Fargate 配置文件）**。

1. 在 **Configure Fargate profile**（配置 Fargate 配置文件）页面上，执行以下操作：

   1. 对于 **Name**（名称），为 Fargate 配置文件输入名称。名称必须唯一。

   1. 对于**容器组（pod）执行角色**，选择要用于您 Fargate 配置文件的容器组（pod）执行角色。将仅显示具有 `eks-fargate-pods.amazonaws.com` 服务委托人的 IAM 角色。如果您未看到列出的任何角色，则必须创建一个角色。有关更多信息，请参阅 [Amazon EKS 容器组（pod）执行 IAM 角色](pod-execution-role.md)。

   1. 根据需要修改选定的**子网**。
**注意**  
Fargate 上运行的容器组（pod）仅支持私有子网。

   1. 对于 **Tags（标签）**，您可以自行选择是否为 Fargate 配置文件添加标签。这些标签不会传播到与配置文件关联的其他资源，如容器组（pod）。

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

1. 在**配置容器组（pod）选择**页面上，执行以下操作：

   1. 对于**命名空间**，输入与容器组（pod）匹配的命名空间。
      + 您可以使用匹配的特定命名空间，例如 `kube-system` 或 `default`。
      + 您可以使用某些通配符（例如 `prod-*`）以匹配多个命名空间（例如，`prod-deployment` 和 `prod-test`)。有关更多信息，请参阅 [Fargate 配置文件通配符](fargate-profile.md#fargate-profile-wildcards)。

   1. （可选）将 Kubernetes 标签添加到选择器中。特别是将它们添加到指定命名空间中的容器组（pod）需要匹配的那个。
      + 您可以将标签 `infrastructure: fargate` 添加到选择器中，以便只有指定命名空间中也具有 `infrastructure: fargate` Kubernetes 标签的容器组（pod）与选择器匹配。
      + 您可以使用某些通配符（例如 `key?: value?`）以匹配多个命名空间（例如，`keya: valuea` 和 `keyb: valueb`)。有关更多信息，请参阅 [Fargate 配置文件通配符](fargate-profile.md#fargate-profile-wildcards)。

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

1. 在 **Review and create（查看和创建）**页面上，查看 Fargate 配置文件的信息，然后选择 **Create（创建）**。

## 第 4 步：更新 CoreDNS
<a name="fargate-gs-coredns"></a>

预设情况下，CoreDNS 配置为在 Amazon EKS 集群的 Amazon EC2 基础设施上运行。如果*仅*在集群中的 Fargate 上运行容器组（pod），请完成以下步骤。

**注意**  
如果使用 `--fargate` 选项用 `eksctl` 创建集群，则可以跳至 [后续步骤](#fargate-gs-next-steps)。

1. 使用以下命令为 CoreDNS 创建 Fargate 配置文件。将 `<my-cluster>` 替换为您的集群名称，将 `<111122223333>` 替换为您的账户 ID，将 `<AmazonEKSFargatePodExecutionRole>` 替换为您的容器组（pod）执行角色名称，并将 `<000000000000000a>`、`<000000000000000b>` 和 `<000000000000000c>` 替换为您的私有子网 ID。如果没有容器组（pod）执行角色，则必须先创建一个（请参阅[第 2 步：创建 Fargate 容器组（pod）执行角色](#fargate-sg-pod-execution-role)）。
**重要**  
角色 ARN 不能包含 `/` 之外的[路径](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-friendly-names)。例如，如果您的角色名称为 `development/apps/AmazonEKSFargatePodExecutionRole`，则需要在为该角色指定 ARN 时将其更改为 `AmazonEKSFargatePodExecutionRole`。角色 ARN 的格式必须为 ` arn:aws:iam::<111122223333>:role/<AmazonEKSFargatePodExecutionRole>`。

   ```
   aws eks create-fargate-profile \
       --fargate-profile-name coredns \
       --cluster-name <my-cluster> \
       --pod-execution-role-arn arn:aws:iam::<111122223333>:role/<AmazonEKSFargatePodExecutionRole> \
       --selectors namespace=kube-system,labels={k8s-app=kube-dns} \
       --subnets subnet-<000000000000000a> subnet-<000000000000000b> subnet-<000000000000000c>
   ```

1. 触发 `coredns` 部署的推出。

   ```
   kubectl rollout restart -n kube-system deployment coredns
   ```

## 后续步骤
<a name="fargate-gs-next-steps"></a>
+ 您可以开始使用以下工作流迁移现有应用程序来在 Fargate 上运行现有应用程序。

  1.  [创建 Fargate 配置文件](fargate-profile.md#create-fargate-profile)，该配置文件与您应用程序的 Kubernetes 命名空间和 Kubernetes 标签匹配。

  1. 删除并重新创建所有现有的容器组（pod），以便可以在 Fargate 上调度容器组。修改 `<namespace>` 和 `<deployment-type>` 以更新您的特定容器组（pod）。

     ```
     kubectl rollout restart -n <namespace> deployment <deployment-type>
     ```
+ 部署 [使用应用程序负载均衡器路由应用程序和 HTTP 流量](alb-ingress.md)，允许在 Fargate 上运行的容器组（pod）的入口对象。
+ 您可以使用 [使用 Vertical Pod Autoscaler 调整容器组（pod）资源](vertical-pod-autoscaler.md) 为 Fargate 容器组（pod）设置正确的初始 CPU 和内存大小，然后使用 [使用 Horizontal Pod Autoscaler 扩展容器组（pod）部署](horizontal-pod-autoscaler.md) 来扩展这些容器组（pod）。如果您希望 Vertical Pod Autoscaler 自动将容器组（pod）重新部署到具有更高 CPU 和内存组合的 Fargate，请将 Vertical Pod Autoscaler 的模式设置为 `Auto` 或 `Recreate`。这是为了确保正确的功能。有关更多信息，请参阅 GitHub 上的 [Vertical Pod Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#quick-start) 文档。
+ 您可以依照[这些说明](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-EKS-otel.html)设置 [AWS Distro for OpenTelemetry](https://aws.amazon.com/otel) (ADOT) 收集器，用于监控应用程序。

# 定义启动时将使用 AWS Fargate 的容器组（pod）
<a name="fargate-profile"></a>

您必须先定义至少一个 Fargate 配置文件，指定在启动时哪些容器组（pod）使用 Fargate，然后才能调度集群中的 Fargate 上的容器组（pod）。

作为管理员，您可以使用 Fargate 配置文件声明哪些容器组（pod）在 Fargate 上运行。您可以通过配置文件的选择器执行此操作。您最多可以为每个配置文件添加五个选择器。每个选择器都必须包含一个命名空间。选择器还可以包含标签。标注字段由多个可选键值对组成。与选择器匹配的容器组（pod）被安排在 Fargate 上。容器组（pod）使用选择器中指定的命名空间和标签进行匹配。如果定义了没有标签的命名空间选择器，Amazon EKS 会尝试使用配置文件将在该命名空间中运行的所有容器组（pod）调度到 Fargate。如果待调度的容器组（pod）与 Fargate 配置文件中的任意一个选择器都匹配，则该容器组（pod）将被调度到 Fargate 上。

如果容器组（pod）匹配多个 Fargate 配置文件，您可以指定容器组（pod）使用的配置文件，方法为将以下 Kubernetes 标签添加到容器组（pod）规范：`eks.amazonaws.com/fargate-profile: my-fargate-profile`。但是，容器组（pod）仍必须匹配该配置文件中的选择器，才能被调度到 Fargate 上。Kubernetes 亲和性/反亲和性规则不适用，Amazon EKS Fargate 容器组（pod）并不需要这些规则。

创建 Fargate 配置文件时，必须指定容器组（pod）执行角色。此执行角色适用于使用配置文件在 Fargate 基础设施上运行的 Amazon EKS 组件。该角色将被添加到集群的 Kubernetes [基于角色的访问控制](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)（RBAC）以进行授权。这样，Fargate 基础设施上运行的 `kubelet` 可以注册到您的 Amazon EKS 集群，并在您的集群中作为节点显示。容器组（pod）执行角色还提供对 Fargate 基础设施的 IAM 权限，以允许对 Amazon ECR 映像存储库进行读取访问。有关更多信息，请参阅 [Amazon EKS 容器组（pod）执行 IAM 角色](pod-execution-role.md)。

您无法更改 Fargate 配置文件。但是，您可以创建新的更新配置文件来替换现有配置文件，然后删除原始配置文件。

**注意**  
删除配置文件后，使用 Fargate 配置文件运行的任何容器组（pod）都会停止并进入待处理状态。

如果集群中有任何 Fargate 配置文件处于 `DELETING` 状态，您必须等待删除该 Fargate 配置文件后，才能在该集群中创建其他配置文件。

**注意**  
Fargate 目前不支持 Kubernetes [topologySpreadConstraints](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)。

Amazon EKS 和 Fargate 将容器组（pod）分布在 Fargate 配置文件定义的每个子网中。但是，最终可能会出现不均匀的分布。如果您必须获得均匀的分布，请使用两个 Fargate 配置文件。在您希望部署两个副本并且不希望造成任何停机的方案中，均匀的分布非常重要。我们建议每个配置文件只有一个子网。

## Fargate 配置文件组件
<a name="fargate-profile-components"></a>

Fargate 配置文件中包含以下组件。

 **Pod 执行角色**   
当您的集群在 AWS Fargate 上创建容器组（pod）时，在 Fargate 基础设施上运行的 `kubelet` 必须代表您调用 AWS API。例如，它需要调用才能从 Amazon ECR 提取容器镜像。Amazon EKS 容器组（pod）执行角色提供执行此操作的 IAM 权限。  
创建 Fargate 配置文件时，必须指定要用于容器组（pod）的容器组（pod）执行角色。此角色将被添加到集群的 Kubernetes [基于角色的访问控制](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)（RBAC）以进行授权。这允许在 Fargate 基础设施上运行的 `kubelet` 注册到您的 Amazon EKS 集群，以便它可以作为节点显示在您的集群中。有关更多信息，请参阅 [Amazon EKS 容器组（pod）执行 IAM 角色](pod-execution-role.md)。

 **子网**   
将容器组（pod）启动到其中的使用此配置文件的子网的 ID。目前，在 Fargate 上运行的容器组（pod）没有分配公有 IP 地址。因此，此参数仅接受私有子网（没有到互联网网关的直接路由）。

 **选择器**   
要匹配容器组（pod）以使用此 Fargate 配置文件的选择器。您最多可以在 Fargate 配置文件中指定五个选择器。选择器具有以下组件：  
+  **命名空间** – 您必须为选择器指定命名空间。选择器仅匹配在此命名空间中创建的容器组（pod）。但是，您可以创建多个选择器来定位多个命名空间。
+  **标签** – 您可以选择指定 Kubernetes 标签来匹配选择器。选择器只匹配具有在选择器中指定的所有标签的容器组（pod）。

## Fargate 配置文件通配符
<a name="fargate-profile-wildcards"></a>

除了 Kubernetes 允许的字符外，您还可以在命名空间、标签键和标签值的选择器标准中使用 `*` 和 `?`：
+  `*` 表示无、一个或多个字符。例如，`prod*` 可以表示 `prod` 和 `prod-metrics`。
+  `?` 表示单个字符（例如，`value?` 可以表示 `valuea`)。但是，它不能表示 `value` 和 `value-a`，因为 `?` 只能准确地表示一个字符。

这些通配符可以在任何位置组合使用（例如，`prod*`、`*dev` 以及 `frontend*?`)。不支持其他通配符和模式匹配形式，例如正则表达式。

如果容器组（pod）规范中有多个配置文件与命名空间和标签匹配，Fargate 会根据配置文件名称的字母数字排序来选取配置文件。例如，如果配置文件 A（名称为 `beta-workload`）和配置文件 B（名称为 `prod-workload`）都有匹配的选择器可供要启动的容器组（pod）使用，Fargate 会为容器组（pod）选取配置文件 A (`beta-workload`)。容器组（pod）具有标签，显示容器组（pod）上有配置文件 A（例如 `eks.amazonaws.com/fargate-profile=beta-workload`）。

如果要将现有 Fargate 容器组（pod）迁移到使用通配符的新配置文件中，有两种方法可执行此操作：
+ 使用匹配的选择器创建一个新的配置文件，然后删除旧的配置文件。标有旧配置文件的容器组（pod）将被重新安排到新的匹配配置文件中。
+ 若要迁移工作负载，但不确定每个 Fargate 容器组（pod）上有哪些 Fargate 标签，则可以使用以下方法。创建一个新的配置文件，首先在同一个集群上的配置文件中按字母数字排序配置文件名称。然后，回收需要迁移到新配置文件的 Fargate 容器组（pod）。

## 创建 Fargate 配置文件
<a name="create-fargate-profile"></a>

这一部分介绍如何创建 Fargate 配置文件。您还必须已经创建了要用于 Fargate 配置文件的容器组（pod）执行角色。有关更多信息，请参阅 [Amazon EKS 容器组（pod）执行 IAM 角色](pod-execution-role.md)。在 Fargate 上运行的容器组（pod）仅在私有子网上受支持（对 AWS 服务具有 [NAT 网关](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)访问权限，但没有到互联网网关的直接路由）。因此，您的集群的 VPC 必须有可用的私有子网。

您可以使用以下工具创建配置文件。
+  [`eksctl`](#eksctl_create_a_fargate_profile) 
+  [AWS 管理控制台](#console_create_a_fargate_profile) 

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

 **使用 `eksctl` 创建 Fargate 配置文件** 

使用以下 `eksctl` 命令创建 Fargate 配置文件，并将所有示例值替换为您自己的值。您需要指定命名空间。但是，`--labels` 选项不是必选。

```
eksctl create fargateprofile \
    --cluster my-cluster \
    --name my-fargate-profile \
    --namespace my-kubernetes-namespace \
    --labels key=value
```

您可以将某些通配符用于 `my-kubernetes-namespace` 和 `key=value` 标签。有关更多信息，请参阅 [Fargate 配置文件通配符](#fargate-profile-wildcards)。

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

 **使用 AWS 管理控制台 创建 Fargate 配置文件** 

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

1. 选择要为其创建 Fargate 配置文件的集群。

1. 请选择 **Compute**（计算）选项卡。

1. 在 **Fargate profiles（Fargate 配置文件）**下，选择 **Add Fargate profile（添加 Fargate 配置文件）**。

1. 在 **Configure Fargate profile**（配置 Fargate 配置文件）页面上，执行以下操作：

   1. 对于 **Name**（名称），为 Fargate 配置文件输入唯一名称，例如 `my-profile`。

   1. 对于**容器组（pod）执行角色**，选择要用于您 Fargate 配置文件的容器组（pod）执行角色。将仅显示具有 `eks-fargate-pods.amazonaws.com` 服务委托人的 IAM 角色。如果您未看到列出的任何角色，则必须创建一个角色。有关更多信息，请参阅 [Amazon EKS 容器组（pod）执行 IAM 角色](pod-execution-role.md)。

   1. 根据需要修改选定的**子网**。
**注意**  
Fargate 上运行的容器组（pod）仅支持私有子网。

   1. 对于 **Tags（标签）**，您可以自行选择是否为 Fargate 配置文件添加标签。这些标签不会传播到与配置文件关联的其他资源，例如容器组（pod）。

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

1. 在**配置容器组（pod）选择**页面上，执行以下操作：

   1. 对于**命名空间**，输入与容器组（pod）匹配的命名空间。
      + 您可以使用匹配的特定命名空间，例如 `kube-system` 或 `default`。
      + 您可以使用某些通配符（例如 `prod-*`）以匹配多个命名空间（例如，`prod-deployment` 和 `prod-test`)。有关更多信息，请参阅 [Fargate 配置文件通配符](#fargate-profile-wildcards)。

   1. （可选）将 Kubernetes 标签添加到选择器中。特别是将它们添加到指定命名空间中的容器组（pod）需要匹配的那个。
      + 您可以将标签 `infrastructure: fargate` 添加到选择器中，以便只有指定命名空间中也具有 `infrastructure: fargate` Kubernetes 标签的容器组（pod）与选择器匹配。
      + 您可以使用某些通配符（例如 `key?: value?`）以匹配多个命名空间（例如，`keya: valuea` 和 `keyb: valueb`)。有关更多信息，请参阅 [Fargate 配置文件通配符](#fargate-profile-wildcards)。

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

1. 在 **Review and create（查看和创建）**页面上，查看 Fargate 配置文件的信息，然后选择 **Create（创建）**。

# 删除 Fargate 配置文件
<a name="delete-fargate-profile"></a>

本主题介绍如何删除 Fargate 配置文件。当您删除 Fargate 配置文件时，使用该配置文件调度到 Fargate 的所有容器组（pod）都将被删除。如果这些容器组（pod）与另一个 Fargate 配置文件匹配，则将使用该配置文件在 Fargate 上调度这些容器组（pod）。如果它们不再匹配任何 Fargate 配置文件，则不会被安排到 Fargate，并仍可能处于待处理状态。

集群中一次只能有一个 Fargate 配置文件处于 `DELETING` 状态。等待 Fargate 配置文件完成删除，然后才能删除该集群中的任何其他配置文件。

可以使用以下任一工具删除配置文件：
+  [`eksctl`](#eksctl_delete_a_fargate_profile) 
+  [AWS 管理控制台](#console_delete_a_fargate_profile) 
+  [AWS CLI](#awscli_delete_a_fargate_profile) 

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

 **使用 `eksctl` 删除 Fargate 配置文件** 

使用以下命令从集群中删除配置文件。将所有 *example value* 替换为您自己的值。

```
eksctl delete fargateprofile  --name my-profile --cluster my-cluster
```

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

 **使用 AWS 管理控制台删除 Fargate 配置文件** 

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

1. 在左侧导航窗格中，选择**集群**。在集群列表中，选择要从中删除 Fargate 配置文件的集群。

1. 请选择 **Compute**（计算）选项卡。

1. 选择要删除的 Fargate 配置文件，然后选择 **Delete**（删除）。

1. 在 **Delete Fargate profile**（删除 Fargate 配置文件）页面上，输入配置文件的名称，然后选择 **Delete**（删除）。

## AWS CLI
<a name="awscli_delete_a_fargate_profile"></a>

 **使用 AWS CLI 删除 Fargate 配置文件** 

使用以下命令从集群中删除配置文件。将所有 *example value* 替换为您自己的值。

```
aws eks delete-fargate-profile --fargate-profile-name my-profile --cluster-name my-cluster
```

# 了解 Fargate 容器组（pod）配置详细信息
<a name="fargate-pod-configuration"></a>

本节介绍在 AWS Fargate 上运行 Kubernetes 容器组（pod）的一些唯一容器组（pod）配置详细信息。

## Pod CPU 和内存
<a name="fargate-cpu-and-memory"></a>

使用 Kubernetes，您可以定义请求、最低 vCPU 量以及分配给容器组（pod）中每个容器的内存资源。Kubernetes 会调度容器组（pod），确保至少每个容器组（pod）的请求资源可用于计算资源。有关更多信息，请参阅 Kubernetes 文档中的[管理容器的计算资源](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/)。

**注意**  
由于 Amazon EKS Fargate 对每个节点只运行一个容器组（pod），因此在资源较少的情况下不会出现驱逐容器组（pod）的情况。所有 Amazon EKS Fargate 容器组（pod）都以担保优先级运行，因此请求的 CPU 和内存必须等于所有容器的限制。有关更多信息，请参阅 Kubernetes 文档中的[为 Pod（一组容器）配置服务质量](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/)。

在 Fargate 上调度容器组（pod）后，容器组（pod）规格中的 vCPU 和内存预留将确定为容器组（pod）预置的 CPU 和内存量。
+ 超出所有 Init 容器的最大请求用于确定 Init 请求 vCPU 和内存要求。
+ 将所有长时间运行的容器的请求相加来确定长时间运行的请求的 vCPU 和内存要求。
+ 然后为要用于容器组（pod）的 vCPU 和内存请求选择先前两个值中较大的值。
+ Fargate 会为所需 Kubernetes 组件（`kubelet`、`kube-proxy` 和 `containerd`）的每个容器组（pod）的内存预留增加 256 MB。

Fargate 向上舍入到下列最接近 vCPU 与内存请求总和的计算配置，确保容器组（pod）始终拥有运行所需的资源。

如果未指定 vCPU 和内存组合，则使用最小的可用组合（0.25 vCPU 和 0.5GB 内存）。

下表显示了 Fargate 上运行的容器组（pod）可以使用的 vCPU 和内存组合。


| vCPU 值 | 内存值 | 
| --- | --- | 
|  .25 vCPU  |  0.5GB、1GB、2GB  | 
|  .5 vCPU  |  1GB、2GB、3GB、4GB  | 
|  1 个 vCPU  |  2GB、3GB、4GB、5GB、6GB、7GB、8GB  | 
|  2 个 vCPU  |  4GB 到 16GB 之间（以 1GB 为增量）  | 
|  4 个 vCPU  |  8GB 到 30GB 之间（以 1GB 为增量）  | 
|  8 个 vCPU  |  介于 16GB 到 60GB 之间（以 4GB 为增量）  | 
|  16 个 vCPU  |  介于 32GB 到 120GB 之间（以 8GB 为增量）  | 

为 Kubernetes 组件保留的额外内存可能会导致 Fargate 任务的 vCPUs 数量超过请求预置的 vCPU 数量。例如，由于没有具有 1 个 vCPU 和 9 GB 内存的任务可用，因此如果请求内容为 1 个 vCPU 和 8 GB 内存，则会为其内存请求增加 256 MB，并会为 Fargate 任务预置 2 个 vCPU 和 9 GB 内存。

Fargate 上运行的容器组（pod）大小与 Kubernetes 使用 `kubectl get nodes` 报告的节点大小之间没有相关性。报告的节点大小通常大于容器组（pod）的容量。您可以使用以下命令验证容器组（pod）容量。将 *default* 替换为容器组（pod）的命名空间，并将 *pod-name* 替换为容器组（pod）的名称。

```
kubectl describe pod --namespace default pod-name
```

示例输出如下。

```
[...]
annotations:
    CapacityProvisioned: 0.25vCPU 0.5GB
[...]
```

`CapacityProvisioned` 注释表示强制执行的容器组（pod）容量，决定了在 Fargate 上运行的容器组（pod）的成本。有关这些计算配置的定价信息，请参阅 [AWS Fargate 定价](https://aws.amazon.com/fargate/pricing/)。

## Fargate 存储
<a name="fargate-storage"></a>

Fargate 上运行的容器组（pod）会自动挂载 Amazon EFS 文件系统，无需手动执行驱动程序安装步骤。您不能将动态持久性卷预置与 Fargate 节点结合使用，但可以使用静态预置。有关更多信息，请参阅 GitHub 上的 [Amazon EFS CSI 驱动程序](https://github.com/kubernetes-sigs/aws-efs-csi-driver/blob/master/docs/README.md)。

完成预置后，在 Fargate 上运行的每个容器组（pod）都会获得 20 GiB 的默认临时存储空间。这种类型的存储将在容器组（pod）停止后被删除。在 Fargate 上启动的新容器组（pod）会默认启用临时存储卷加密。使用 AWS Fargate 托管密钥通过 AES-256 加密算法对临时容器组（pod）存储进行加密。

**注意**  
在 Fargate 上运行的 Amazon EKS 容器组（pod）的默认可用存储空间值小于 20 GiB。这是因为部分空间会被 `kubelet` 以及 Kubernetes 内部加载的其他容器组（pod）模块使用。

您最高可以将临时存储总量增加到 175GiB。要使用 Kubernetes 配置大小，请指定一个容器组（pod）中每个容器的 `ephemeral-storage` 资源请求数。在调度容器组（pod）时，Kubernetes 会确保每个容器组（pod）的资源请求总和小于 Fargate 任务的容量。有关更多信息，请参阅 Kubernetes 文档中的[为 Pod 和容器管理资源](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/)。

Amazon EKS Fargate 预置的临时存储空间会高于请求的容量，以满足系统使用的需要。例如，假设您请求 100GiB 的空间，则系统会为 Fargate 任务预置 115GiB 的临时存储空间。

# 为 AWS Fargate 操作系统补丁事件设置操作
<a name="fargate-pod-patching"></a>

Amazon EKS 定期修补 AWS Fargate 节点的操作系统以确保它们的安全。作为修补过程的一部分，我们会回收节点来安装操作系统补丁。尝试更新的方式对您的服务造成的影响最小。但是，如果容器组（pod）没有成功被驱逐，有时必须删除容器组。以下是您可以采取的最大限度减少潜在中断的操作：
+ 设置适当的容器组（pod）中断预算（PDB），控制同时关闭的容器组（pod）数量。
+ 创建 Amazon EventBridge 规则，在删除容器组（pod）之前处理失败的驱逐。
+ 在您所收通知中发布的驱逐日期之前，手动重启受影响的容器组（pod）。
+ 在 AWS 用户通知中创建通知配置。

Amazon EKS 与 Kubernetes 社区密切合作，以便尽快提供错误修复和安全补丁。所有 Fargate 容器组（pod）都从最新的 Kubernetes 修补程序版本开始，可从集群的 Kubernetes 版本的 Amazon EKS 中获取。如果您的容器组（pod）具有较旧的修补程序版本，Amazon EKS 可能会回收容器组，以便将其更新到最新版本。这可以确保您的容器组（pod）配备了最新的安全更新。这样一来，如果存在关键[常见漏洞和风险](https://cve.mitre.org/)（CVE）问题，您可以随时了解最新信息以降低安全风险。

AWS Fargate 操作系统更新后，Amazon EKS 将向您发送通知，其中包含受影响的资源和即将驱逐容器组（pod）的日期。如果提供的日期不便进行驱逐，您可以在通知中于选择发布的驱逐日期之前，手动重启受影响的容器组（pod）。系统将驱逐您在收到通知之前创建的任何容器组（pod）。有关如何手动重启容器组（pod）的更多说明，请参阅 [Kubernetes 文档](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_restart)。

要限制在回收容器组（pod）时同时停机的容器组数量，您可以设置容器组（pod）中断预算（PDB）。您可以使用 PDB 根据每个应用程序的要求定义最低可用性，同时仍允许进行更新。PDB 的最低可用性必须低于 100%。有关更多信息，请参阅 Kubernetes 文档中的[为应用程序设置干扰预算](https://kubernetes.io/docs/tasks/run-application/configure-pdb/)。

Amazon EKS 使用[驱逐 API](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/#eviction-api) 在遵守您为应用程序设置的 PDB 的同时安全地耗尽容器组（pod）。容器组（pod）被可用区驱逐出来，以最大限度地减少影响。如果驱逐成功，新容器组（pod）将获得最新的补丁，无需进一步操作。

当容器组（pod）的驱逐失败时，Amazon EKS 会向您的账户发送一个事件，其中包含驱逐失败的容器组（pod）的详细信息。您可以在计划的终止时间之前对消息采取行动。具体时间根据补丁的紧迫性而有所不同。时间一到，Amazon EKS 会尝试再次驱逐容器组（pod）。但是，如果驱逐失败，这次不会发送新的事件。如果驱逐再次失败，则会定期删除您现有的容器组（pod），以便新容器组（pod）可以拥有最新的补丁。

以下是在容器组（pod）驱逐失败时收到的示例事件。其中包含有关集群、容器组（pod）名称、容器组（pod）命名空间、Fargate 配置文件和计划终止时间的详细信息。

```
{
    "version": "0",
    "id": "12345678-90ab-cdef-0123-4567890abcde",
    "detail-type": "EKS Fargate Pod Scheduled Termination",
    "source": "aws.eks",
    "account": "111122223333",
    "time": "2021-06-27T12:52:44Z",
    "region": "region-code",
    "resources": [
        "default/my-database-deployment"
    ],
    "detail": {
        "clusterName": "my-cluster",
        "fargateProfileName": "my-fargate-profile",
        "podName": "my-pod-name",
        "podNamespace": "default",
        "evictErrorMessage": "Cannot evict pod as it would violate the pod's disruption budget",
        "scheduledTerminationTime": "2021-06-30T12:52:44.832Z[UTC]"
    }
}
```

此外，将多个 PDB 与一个容器组（pod）关联可能会导致驱逐失败事件。此事件将返回以下错误消息。

```
"evictErrorMessage": "This pod has multiple PodDisruptionBudget, which the eviction subresource does not support",
```

您可以基于此事件创建所需的操作。例如，要控制驱逐容器组（pod）的方式，您可以调整容器组（pod）中断预算（PDB）。更具体地说，假设您从指定可用容器组（pod）的目标百分比的 PDB 开始。在升级期间强制终止容器组（pod）之前，您可以将 PDB 调整为不同百分比的容器组（pod）。要接收此事件，您必须在 AWS 账户和集群所属的 AWS 区域中创建 Amazon EventBridge 规则。该规则必须使用以下**自定义模式**。有关更多信息，请参阅《Amazon EventBridge 用户指南》中的[创建对事件作出反应的 Amazon EventBridge 规则](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule.html)。

```
{
  "source": ["aws.eks"],
  "detail-type": ["EKS Fargate Pod Scheduled Termination"]
}
```

可以为事件设置合适的目标来捕获它。有关可用目标的完整列表，请参阅《Amazon EventBridge 用户指南》中的 [Amazon EventBridge 目标](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-targets.html)。您还可以在 AWS 用户通知中创建通知配置。使用 AWS 管理控制台创建通知时，在**事件规则**下，为 **AWS 服务名称**选择 **Elastic Kubernetes Service（EKS）**，为**事件类型**选择 **EKS Fargate 容器组（pod）计划的终止**。有关更多信息，请参阅《AWS 用户通知用户指南》中的[AWS 用户通知入门](https://docs.aws.amazon.com/notifications/latest/userguide/getting-started.html)。

有关 EKS 容器组（pod）驱逐的常见问题，请参阅 *AWS re:Post* 中的[常见问题解答：Fargate 容器组（pod）驱逐通知](https://repost.aws/knowledge-center/fargate-pod-eviction-notice)。

# 收集 AWS Fargate 应用程序和使用情况指标
<a name="monitoring-fargate-usage"></a>

您可以收集系统指标和 AWS Fargate 的 CloudWatch 使用量指标。

## 应用程序指标
<a name="fargate-application-metrics"></a>

对于在 Amazon EKS 和 AWS Fargate 上运行的应用程序，您可以使用适用于 OpenTelemetry 的 AWS Distro（ADOT）。ADOT 允许您收集系统指标并将其发送到 CloudWatch Container Insights 控制面板。要开始为在 Fargate 上运行的应用程序使用 ADOT，请参阅 ADOT 文档中的[将 CloudWatch Container Insights 与 AWS Distro for OpenTelemetry 结合使用](https://aws-otel.github.io/docs/getting-started/container-insights)。

## 使用情况指标
<a name="fargate-usage-metrics"></a>

您可以使用 CloudWatch 使用情况指标来提供账户资源使用情况的可见性。这些指标可在 CloudWatch 图表和控制面板上直观呈现当前的服务使用情况。

 AWS Fargate 用量指标与 AWS 服务配额对应。您可以配置警报，以在用量接近服务配额时向您发出警报。有关 Fargate 服务配额的更多信息，请参阅 [查看和管理 Amazon EKS 和 Fargate 服务配额](service-quotas.md)。

 AWS Fargate 在 ` AWS/Usage` 命名空间中发布以下指标。


| 指标 | 说明 | 
| --- | --- | 
|   `ResourceCount`   |  您账户中运行的指定资源的总数量。资源由与指标关联的维度定义。  | 

以下维度用于优化由 AWS Fargate 发布的使用情况指标。


| 维度 | 描述 | 
| --- | --- | 
|   `Service`   |  包含该资源的 AWS 服务的名称。对于 AWS Fargate 用量指标，此维度的值为 `Fargate`。  | 
|   `Type`   |  正在报告的实体的类型。目前，AWS Fargate 用量指标的唯一有效值为 `Resource`。  | 
|   `Resource`   |  正在运行的资源的类型。 目前，AWS Fargate 会返回有关 Fargate 按需使用情况的信息。Fargate 按需使用情况的资源值为 `OnDemand`。 [注意] ==== Fargate 按需使用情况结合了使用 Fargate 的 Amazon EKS Pod、使用 Fargate 启动类型的 Amazon ECS 任务和使用 `FARGATE` 容量提供程序的 Amazon ECS 任务。 ====  | 
|   `Class`   |  所跟踪的资源的类。目前，AWS Fargate 不使用类维度。  | 

### 创建 CloudWatch 警报以监控 Fargate 资源使用情况指标
<a name="service-quota-alarm"></a>

 AWS Fargate 提供 CloudWatch 使用情况指标，这些指标与 Fargate 按需资源使用情况的 AWS 服务配额相对应。在 Service Quotas 控制台中，您可以在图表上可视化您的使用情况。还可以配置警报，以在用量接近服务配额时向您发出警报。有关更多信息，请参阅 [收集 AWS Fargate 应用程序和使用情况指标](#monitoring-fargate-usage)。

使用以下步骤根据 Fargate 资源使用情况指标创建 CloudWatch 警报。

1. 访问 https://console.aws.amazon.com/servicequotas/，打开服务配额控制台。

1. 在左侧导航窗格中，选择 **AWS 服务**。

1. 从 **AWS 服务**列表中，搜索并选择 **AWS Fargate**。

1. 在 **Service quotas**（服务配额）列表中，选择要为其创建警报的 Fargate 使用情况配额。

1. 在 Amazon CloudWatch 警报部分中，选择 **Create**（创建）。

1. 对于**警报阈值**，选择要设置为警报值的适用配额值的百分比。

1. 对于**警报名称**，输入警报名称，然后选择**创建**。

# 为集群启动 AWS Fargate 日志记录
<a name="fargate-logging"></a>

Fargate 上的 Amazon EKS 提供了一个基于 Fluent Bit 的内置日志路由器。这意味着您没有明确地将 Fluent Bit 容器作为边车容器运行，但 Amazon 会为您运行该容器。您只需配置日志路由器即可。通过必须满足以下条件的专用 `ConfigMap` 进行配置：
+ 名为 `aws-logging` 
+ 在名为 `aws-observability` 的专用命名空间中创建 
+ 不能超过 5300 个字符。

一旦您创建了 `ConfigMap`，Fargate 上的 Amazon EKS 会自动检测到它并使用它来配置日志路由器。Fargate 使用 AWS for Fluent Bit 的版本是 Fluent Bit 的一种上游合规发行版，由AWS托管。有关更多信息，请参阅 GitHub 上的 [AWS for Fluent Bit](https://github.com/aws/aws-for-fluent-bit)。

日志路由器允许您使用广泛的AWS服务进行日志分析和存储。您可以将日志从 Fargate 直接流式传输到 Amazon CloudWatch、Amazon OpenSearch Service。您还可以通过 [Amazon Data Firehose](https://aws.amazon.com/kinesis/data-firehose/) 将日志流式传输到 [Amazon S3](https://aws.amazon.com/s3/)、[Amazon Kinesis Data Streams](https://aws.amazon.com/kinesis/data-streams/) 和合作伙伴工具等目标。
+ 现有的 Fargate 配置文件，用于指定您将 Fargate 容器组（pod）部署到的现有 Kubernetes 命名空间。有关更多信息，请参阅 [第 3 步：为集群创建 Fargate 配置文件](fargate-getting-started.md#fargate-gs-create-profile)。
+ 现有的 Fargate 容器组（pod）执行角色。有关更多信息，请参阅 [第 2 步：创建 Fargate 容器组（pod）执行角色](fargate-getting-started.md#fargate-sg-pod-execution-role)。

## 日志路由器配置
<a name="fargate-logging-log-router-configuration"></a>

**重要**  
要成功发布日志，必须允许集群所在的 VPC 对日志目标的网络访问权限。这主要涉及用户为其 VPC 自定义出口规则。有关使用 CloudWatch 的示例，请参阅《Amazon CloudWatch Logs 用户指南》中的 [Using CloudWatch Logs with interface VPC endpoints](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch-logs-and-interface-VPC.html)**。

在以下步骤中，将所有 *example value* 替换为您自己的值。

1. 创建一个名为 `aws-observability` 的专用 Kubernetes 命名空间。

   1. 将以下内容保存到计算机上名为 `aws-observability-namespace.yaml` 的文件中。`name` 的值必须为 `aws-observability`，并且 `aws-observability: enabled` 标注是必需的。

      ```
      kind: Namespace
      apiVersion: v1
      metadata:
        name: aws-observability
        labels:
          aws-observability: enabled
      ```

   1. 创建命名空间。

      ```
      kubectl apply -f aws-observability-namespace.yaml
      ```

1. 创建带有 `Fluent Conf` 数据值的 `ConfigMap`，以将容器日志发送到某个目标。Fluent Conf 为 Fluent Bit，是一种快速轻量级日志处理器配置语言，用于将容器日志路由到您选择的日志目标。有关更多信息，请参阅 Fluent Bit 文档中的[配置文件](https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/classic-mode/configuration-file)。
**重要**  
典型 `Fluent Conf` 中包含的主要部分为 `Service`、`Input`、`Filter` 和 `Output`。但是，Fargate 日志路由器仅接受：  
`Filter` 和 `Output` 部分。
`Parser` 部分。
如果您提供任何其他部分，将被拒绝。

   Fargate 日志路由器管理 `Service` 和 `Input` 部分。它包含以下 `Input` 部分，无法修改，并且您的 `ConfigMap` 也不需要该部分。但是，您可以从中获取见解，例如内存缓冲区限制和应用于日志的标签。

   ```
   [INPUT]
       Name tail
       Buffer_Max_Size 66KB
       DB /var/log/flb_kube.db
       Mem_Buf_Limit 45MB
       Path /var/log/containers/*.log
       Read_From_Head On
       Refresh_Interval 10
       Rotate_Wait 30
       Skip_Long_Lines On
       Tag kube.*
   ```

   在创建 `ConfigMap` 时，请考虑 Fargate 用于验证字段的以下规则：
   +  `[FILTER]`、`[OUTPUT]` 和 `[PARSER]` 应该在每个相应的键下指定。例如，`[FILTER]` 必须在 `filters.conf` 下。在 `filters.conf` 下可以有一个或多个 `[FILTER]`。`[OUTPUT]` 和 `[PARSER]` 部分也应在其相应的键下。通过指定多个 `[OUTPUT]` 部分，您可以同时将日志路由到不同的目标。
   + Fargate 会验证每个部分所需的键。`Name` 和 `match` 是每个 `[FILTER]` 和 `[OUTPUT]` 所必需的。`Name` 和 `format` 是每个 `[PARSER]` 所必需的。键不区分大小写。
   + 在 `ConfigMap` 中不允许使用环境变量（例如 `${ENV_VAR}`）。
   + 对于每个 `filters.conf`、`output.conf` 和 `parsers.conf` 中的指令或键值对，缩进必须是相同的。键值对的缩进必须多于指令。
   + Fargate 根据以下受支持的筛选条件进行验证：`grep`、`parser`、`record_modifier`、`rewrite_tag`、`throttle`、`nest`、`modify` 和 `kubernetes`。
   + Fargate 根据以下受支持的输出进行验证：`es`、`firehose`、`kinesis_firehose`、`cloudwatch`、`cloudwatch_logs` 和 `kinesis`。
   + `ConfigMap` 中必须至少提供一个受支持的 `Output` 插件才能启用日志记录。不需要 `Filter` 和 `Parser` 即可启用日志记录。

     您还可以使用所需的配置在 Amazon EC2 上运行 Fluent Bit，以对验证过程中出现的任何问题进行故障排除。使用以下示例之一创建您的 `ConfigMap`。
**重要**  
Amazon EKS Fargate 日志记录不支持 `ConfigMap` 的动态配置。对 `ConfigMap` 所做的任何更改都只会应用于新容器组（pod）。不会将更改应用于现有容器组（pod）。

     使用所需日志目标的示例创建 `ConfigMap`。
**注意**  
您也可以将 Amazon Kinesis Data Streams 用作您的日志目的地。如果您使用 Kinesis Data Streams，则请确保容器组（pod）执行角色已被授予 `kinesis:PutRecords` 权限。有关更多信息，请参阅《Fluent Bit：官方手册》**中的 Amazon Kinesis Data Streams [权限](https://docs.fluentbit.io/manual/pipeline/outputs/kinesis#permissions)。  
**Example**  

------
#### [ CloudWatch ]

   使用 CloudWatch 视时，您有两个输出选项：
   +  [用 C 语言编写的输出插件](https://docs.fluentbit.io/manual/v/1.5/pipeline/outputs/cloudwatch) 
   +  [用 Golang 编写的输出插件](https://github.com/aws/amazon-cloudwatch-logs-for-fluent-bit) 

   以下示例为您展示了如何使用 `cloudwatch_logs` 插件将日志发送到 CloudWatch。

   1. 将以下内容保存到名为 `aws-logging-cloudwatch-configmap.yaml` 的文件中。将 *region-code* 替换为您的集群所在的 AWS 区域。`[OUTPUT]` 下的参数是必需的。

      ```
      kind: ConfigMap
      apiVersion: v1
      metadata:
        name: aws-logging
        namespace: aws-observability
      data:
        flb_log_cw: "false"  # Set to true to ship Fluent Bit process logs to CloudWatch.
        filters.conf: |
          [FILTER]
              Name parser
              Match *
              Key_name log
              Parser crio
          [FILTER]
              Name kubernetes
              Match kube.*
              Merge_Log On
              Keep_Log Off
              Buffer_Size 0
              Kube_Meta_Cache_TTL 300s
        output.conf: |
          [OUTPUT]
              Name cloudwatch_logs
              Match   kube.*
              region region-code
              log_group_name my-logs
              log_stream_prefix from-fluent-bit-
              log_retention_days 60
              auto_create_group true
        parsers.conf: |
          [PARSER]
              Name crio
              Format Regex
              Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>P|F) (?<log>.*)$
              Time_Key    time
              Time_Format %Y-%m-%dT%H:%M:%S.%L%z
      ```

   1. 将清单应用于集群。

      ```
      kubectl apply -f aws-logging-cloudwatch-configmap.yaml
      ```

------
#### [ Amazon OpenSearch Service ]

   如果您想要将日志发送到 Amazon OpenSearch Service，则可以使用 [es](https://docs.fluentbit.io/manual/v/1.5/pipeline/outputs/elasticsearch) 输出，这是一个用 C 语言编写的插件。以下示例介绍如何使用该插件将日志发送到 OpenSearch。

   1. 将以下内容保存到名为 `aws-logging-opensearch-configmap.yaml` 的文件中。将所有 *example value* 替换为您自己的值。

      ```
      kind: ConfigMap
      apiVersion: v1
      metadata:
        name: aws-logging
        namespace: aws-observability
      data:
        output.conf: |
          [OUTPUT]
            Name  es
            Match *
            Host  search-example-gjxdcilagiprbglqn42jsty66y.region-code.es.amazonaws.com
            Port  443
            Index example
            Type  example_type
            AWS_Auth On
            AWS_Region region-code
            tls   On
      ```

   1. 将清单应用于集群。

      ```
      kubectl apply -f aws-logging-opensearch-configmap.yaml
      ```

------
#### [ Firehose ]

   将日志发送到 Firehose 时，您有两个输出选项：
   +  [kinesis\$1firehose](https://docs.fluentbit.io/manual/pipeline/outputs/firehose) – 用 C 语言编写的输出插件。
   +  [firehose](https://github.com/aws/amazon-kinesis-firehose-for-fluent-bit) – 用 Golang 语言编写的输出插件。

     以下示例向您展示了如何使用 `kinesis_firehose` 插件将日志发送到 Firehose。

     1. 将以下内容保存到名为 `aws-logging-firehose-configmap.yaml` 的文件中。将 *region-code* 替换为您的集群所在的 AWS 区域。

        ```
        kind: ConfigMap
        apiVersion: v1
        metadata:
          name: aws-logging
          namespace: aws-observability
        data:
          output.conf: |
            [OUTPUT]
             Name  kinesis_firehose
             Match *
             region region-code
             delivery_stream my-stream-firehose
        ```

     1. 将清单应用于集群。

        ```
        kubectl apply -f aws-logging-firehose-configmap.yaml
        ```

------

1. 为 Fargate 容器组执行角色设置向目标发送日志的权限。

   1. 将目标的 IAM 策略下载到您的计算机。  
**Example**  

------
#### [ CloudWatch ]

      将 CloudWatch IAM policy 下载到您的计算机。您还可以在 GitHub 上[查看策略](https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/cloudwatchlogs/permissions.json)。

      ```
      curl -O https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/cloudwatchlogs/permissions.json
      ```

------
#### [ Amazon OpenSearch Service ]

      将 OpenSearch IAM policy 下载到您的计算机。您还可以在 GitHub 上[查看策略](https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/amazon-elasticsearch/permissions.json)。

      ```
      curl -O https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/amazon-elasticsearch/permissions.json
      ```

      确保 OpenSearch 控制面板的访问控制配置正确。OpenSearch 控制面板中的 `all_access role` 需要映射 Fargate 容器组（pod）执行角色和 IAM 角色。必须为 `security_manager` 角色执行同样的映射。您可以添加以前的映射，方法为：选择 `Menu`，然后依次选择 `Security` 和 `Roles`，再选择相应的角色。有关更多信息，请参阅[如何对 CloudWatch Logs 进行故障排除，以便将其流式传输到我的 Amazon ES 域？](https://aws.amazon.com/tr/premiumsupport/knowledge-center/es-troubleshoot-cloudwatch-logs/)

------
#### [ Firehose ]

      将 Firehose IAM 策略下载到您的计算机。您还可以在 GitHub 上[查看策略](https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/kinesis-firehose/permissions.json)。

      ```
      curl -O https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/kinesis-firehose/permissions.json
      ```

------

   1. 使用下载的策略文件创建一个 IAM 策略。

      ```
      aws iam create-policy --policy-name eks-fargate-logging-policy --policy-document file://permissions.json
      ```

   1. 使用以下命令将 IAM policy 附加到为 Fargate 配置文件指定的容器组（pod）执行角色。请将 *111122223333* 替换为您的账户 ID。将 *AmazonEKSFargatePodExecutionRole* 替换为容器组（pod）执行角色（有关更多信息，请参阅[第 2 步：创建 Fargate 容器组（pod）执行角色](fargate-getting-started.md#fargate-sg-pod-execution-role)）。

      ```
      aws iam attach-role-policy \
        --policy-arn arn:aws:iam::111122223333:policy/eks-fargate-logging-policy \
        --role-name AmazonEKSFargatePodExecutionRole
      ```

### Kubernetes 筛选器支持
<a name="fargate-logging-kubernetes-filter"></a>

Fluent Bit Kubernetes 筛选器允许您将 Kubernetes 元数据添加到日志文件中。有关筛选器的更多信息，请参阅 Fluent Bit 文档中的 [Kubernetes](https://docs.fluentbit.io/manual/pipeline/filters/kubernetes)。您可以使用 API 服务器终端节点应用筛选器。

```
filters.conf: |
    [FILTER]
        Name             kubernetes
        Match            kube.*
        Merge_Log           On
        Buffer_Size         0
        Kube_Meta_Cache_TTL 300s
```

**重要**  
 `Kube_URL`、`Kube_CA_File`、`Kube_Token_Command` 和 `Kube_Token_File` 是服务拥有的配置参数，不能指定。Amazon EKS Fargate 填充这些值。
 `Kube_Meta_Cache_TTL` 是 Fluent Bit 与 API 服务器通信以获取最新元数据等待的时间。如果未指定 `Kube_Meta_Cache_TTL`，则 Amazon EKS Fargate 会追加原定设置值 30 分钟，以减轻 API 服务器的负载。

### 将 Fluent Bit 进程日志发送到您的账户
<a name="ship-fluent-bit-process-logs"></a>

您可以选择使用下面的 `ConfigMap`，将 Fluent Bit 进程日志发送到 Amazon CloudWatch。将 Fluent Bit 进程日志发送到 CloudWatch 需要额外的日志摄取和存储成本。将 *region-code* 替换为您的集群所在的 AWS 区域。

```
kind: ConfigMap
apiVersion: v1
metadata:
  name: aws-logging
  namespace: aws-observability
  labels:
data:
  # Configuration files: server, input, filters and output
  # ======================================================
  flb_log_cw: "true"  # Ships Fluent Bit process logs to CloudWatch.

  output.conf: |
    [OUTPUT]
        Name cloudwatch
        Match kube.*
        region region-code
        log_group_name fluent-bit-cloudwatch
        log_stream_prefix from-fluent-bit-
        auto_create_group true
```

日志位于集群所在 AWS 区域的 CloudWatch 中。日志组名称为 ` my-cluster-fluent-bit-logs`，Fluent Bit 日志流名称为 `fluent-bit-podname-pod-namespace `。

**注意**  
仅当 Fluent Bit 流程成功开始后，才会发送流程日志。如果启动 Fluent Bit 时出现故障，则会丢失流程日志。您只能将流程日志发送到 CloudWatch。
要调试将流程日志传输到您的账户，可以应用以前的 `ConfigMap` 获取流程日志。Fluent Bit 启动失败通常是启动时 Fluent Bit 未解析或接受 `ConfigMap` 导致的。

### 停止发送 Fluent Bit 进程日志
<a name="stop-fluent-bit-process-logs"></a>

将 Fluent Bit 进程日志发送到 CloudWatch 需要额外的日志摄取和存储成本。要排除现有 `ConfigMap` 设置中的进程日志，请执行以下步骤。

1. 在启用 Fargate 日志记录后，找到为 Amazon EKS 集群的 Fluent Bit 进程日志自动创建的 CloudWatch 日志组。它遵循格式 ` my-cluster-fluent-bit-logs`。

1. 删除 CloudWatch 日志组中为每个容器组（pod）的进程日志创建的现有 CloudWatch 日志流。

1. 编辑 `ConfigMap` 并设置 `flb_log_cw: "false"`。

1. 重启集群中的任何现有容器组（pod）。

## 测试应用程序
<a name="fargate-logging-test-application"></a>

1. 部署示例容器组（pod）。

   1. 将以下内容保存到计算机上名为 `sample-app.yaml` 的文件中。

      ```
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: sample-app
        namespace: same-namespace-as-your-fargate-profile
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
              - name: nginx
                image: nginx:latest
                ports:
                  - name: http
                    containerPort: 80
      ```

   1. 将清单应用于集群。

      ```
      kubectl apply -f sample-app.yaml
      ```

1. 使用您在 `ConfigMap` 中配置的目标查看 NGINX 日志。

## 大小注意事项
<a name="fargate-logging-size-considerations"></a>

我们建议您为日志路由器规划最多 50MB 的内存。如果您希望应用程序以非常高的吞吐量生成日志，那么您应该规划高达 100MB 的内存。

## 故障排除
<a name="fargate-logging-troubleshooting"></a>

要确认日志记录功能是否因某种原因（例如无效 `ConfigMap`）而启用还是禁用，以及无效的原因，请使用 `kubectl describe pod pod-name ` 检查您的容器组（pod）事件。输出可能包含澄清是否已启用日志记录的容器组（pod）事件，例如以下示例输出。

```
[...]
Annotations:          CapacityProvisioned: 0.25vCPU 0.5GB
                      Logging: LoggingDisabled: LOGGING_CONFIGMAP_NOT_FOUND
[...]
Events:
  Type     Reason           Age        From                                                           Message
  ----     ------           ----       ----                                                           -------
  Warning  LoggingDisabled  <unknown>  fargate-scheduler                                              Disabled logging because aws-logging configmap was not found. configmap "aws-logging" not found
```

容器组（pod）事件是短暂的，时间长短取决于设置。您也可以使用 `kubectl describe pod pod-name ` 查看容器组（pod）的注释。容器组（pod）注释中包含有关日志记录功能是已启用还是已禁用状态以及对应原因的信息。

# 选择最优的 Amazon EC2 节点实例类型
<a name="choosing-instance-type"></a>

Amazon EC2 提供 Worker 节点的各种不同的实例类型。每种实例类型提供不同的计算、内存、存储和网络功能。每个实例也按照这些功能分组到实例系列。有关列表，请参阅《Amazon EC2 用户指南》**中的[可用实例类型](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html#AvailableInstanceTypes)。Amazon EKS 发布了多种 Amazon EC2 AMI 的变体以启用支持。要确保您选择的实例类型与 Amazon EKS 兼容，请考虑以下标准。
+ 所有 Amazon EKS AMI 当前均不支持 `mac` 系列。
+ Arm 和非加速 Amazon EKS AMI 不支持 `g3`、`g4`、`inf` 和 `p` 系列。
+ 加速 Amazon EKS AMI 不支持 `a`、`c`、`hpc`、`m` 和 `t` 系列。
+ 对于基于 Arm 的实例，Amazon Linux 2023（AL2023）仅支持使用 Graviton2 或更高版本处理器的实例类型。AL2023 不支持 `A1` 实例。

在选择 Amazon EKS 支持的实例类型时，请考虑每种类型的以下功能。

 **节点组中的实例数**   
一般来说，数量较少、规模较大的实例更好，当您有很多 Daemonset 时更是如此。每个实例都需要对 API 服务器进行 API 调用，因此您拥有的实例越多，API 服务器上的负载就越多。

 **操作系统**   
查看 [Linux](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html)、[Windows](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/instance-types.html) 和 [Bottlerocket](https://aws.amazon.com/bottlerocket/faqs/) 支持的实例类型。创建 Windows 实例之前，请查看[在 EKS 集群上部署 Windows 节点](windows-support.md)。

 **硬件架构**   
您需要 x86 还是 Arm？ 部署 Arm 实例之前，请查看 [Amazon EKS 优化版 Arm Amazon Linux AMI](eks-optimized-ami.md#arm-ami)。您需要基于 Nitro System（[Linux](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html#ec2-nitro-instances) 或 [Windows](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/instance-types.html#ec2-nitro-instances)）构建的实例或是拥有[加速](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/accelerated-computing-instances.html)功能的实例吗？ 如果您需要加速功能，则只能将 Linux 与 Amazon EKS 结合使用。

 **最大容器组（pod）数量**   
由于每个容器组（pod）都分配到了自己的 IP 地址，因此实例类型支持的 IP 地址数量是决定可以在实例上运行的容器组（pod）数量的因素之一。要手动确定实例类型支持多少个容器组（pod），请参阅。  
 [AWS Nitro System](https://aws.amazon.com/ec2/nitro/) 实例类型可选择性地支持比非 Nitro System 实例类型多得多的 IP 地址。但是，并非为实例分配的所有 IP 地址都可用于容器组（pod）。要为您的实例分配大量的 IP 地址，您必须在集群中安装 `1.9.0` 版或更高版本的 Amazon VPC CNI 附加组件并进行适当配置。有关更多信息，请参阅 [为带前缀的 Amazon EKS 节点分配更多 IP 地址](cni-increase-ip-addresses.md)。要为实例分配最大数量的 IP 地址，您必须在集群中安装 `1.10.1` 版或更高版本的 Amazon VPC CNI 附加组件，然后使用 `IPv6` 系列部署集群。

 **IP 系列**   
您可以在将 `IPv4` 系列用于集群时使用任何受支持的实例类型，以便集群将私有 `IPv4` 地址分配到容器组（pod）和服务。但是，如果您想将 `IPv6` 系列用于集群，则您必须使用 [AWS Nitro System](https://aws.amazon.com/ec2/nitro/) 实例类型或裸机实例类型。Windows 实例仅支持 `IPv4`。您的集群必须运行 `1.10.1` 版或更高版本的 Amazon VPC CNI 附加组件。有关使用 `IPv6` 的更多信息，请参阅[了解如何将 IPv6 地址分配给集群、容器组（pod）和服务](cni-ipv6.md)。

 **您正在运行的 Amazon VPC CNI 附加组件的版本**   
适用于 Kubernetes 的最新版本的 [Amazon VPC CNI 插件](https://github.com/aws/amazon-vpc-cni-k8s)支持[这些实例类型](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/pkg/vpc/vpc_ip_resource_limit.go)。您可能需要更新 Amazon VPC CNI 附加组件版本来利用最新的受支持的实例类型。有关更多信息，请参阅 [使用 Amazon VPC CNI 将 IP 分配给容器组（pod）](managing-vpc-cni.md)。最新版本支持与 Amazon EKS 一起使用的最新功能。以前版本并不支持所有功能。您可以在 GitHub 上的 [Changelog](https://github.com/aws/amazon-vpc-cni-k8s/blob/master/CHANGELOG.md) 中查看不同版本支持的功能。

 **您在其中创建节点的 AWS 区域**   
并非所有实例类型在所有 AWS 区域中都可用。

 **是否将安全组用于容器组（pod）**   
如果将安全组用于容器组（pod），则仅支持特定的实例类型。有关更多信息，请参阅 [将安全组分配给各个容器组（pod）](security-groups-for-pods.md)。

## 如何确定 maxPods
<a name="max-pods-precedence"></a>

应用于节点的最终 `maxPods` 值取决于几个按照特定的优先级顺序进行交互的组件。了解此顺序有助于您在自定义 `maxPods` 时避免出现意外情况。

 **优先顺序（从高到低）：**

1.  **托管节点组强制执行**：当您使用没有[自定义 AMI](launch-templates.md#launch-template-custom-ami) 的托管节点组时，Amazon EKS 会对节点的用户数据中的 `maxPods` 施加限制。对于 vCPU 少于 30 个的实例，上限为 `110`。对于 vCPU 多于 30 个的实例，上限为 `250`。此值优先于任何其他 `maxPods` 配置，包括 `maxPodsExpression`。

1.  **kubelet `maxPods` 配置**：如果您直接在 kubelet 配置中设置 `maxPods`（例如，通过带有自定义 AMI 的启动模板），则该值优先于 `maxPodsExpression`。

1.  **nodeadm `maxPodsExpression`**：如果您在 `NodeConfig` 中使用 [https://awslabs.github.io/amazon-eks-ami/nodeadm/doc/examples/#defining-a-max-pods-expression](https://awslabs.github.io/amazon-eks-ami/nodeadm/doc/examples/#defining-a-max-pods-expression)，nodeadm 会评估计算 `maxPods` 的表达式。只有当该值尚未由优先级较高的源设置时，这才会有效。

1.  **基于 ENI 的默认计算**：如果未设置其他值，则 AMI 将根据实例类型支持的弹性网络接口和 IP 地址的数量计算 `maxPods`。这等同于公式 `(number of ENIs × (IPs per ENI − 1)) + 2`。`+ 2` 将每个节点上运行的 Amazon VPC CNI 和 `kube-proxy` 考虑在内，这些组件不会消耗容器组（Pod）IP 地址。

**重要**  
如果您使用托管节点组并在 `NodeConfig` 中设置 `maxPodsExpression`，则托管节点组的强制执行会覆盖您的表达式。要将自定义的 `maxPods` 值用于托管节点组，您必须在启动模板中指定自定义 AMI 并直接设置 `maxPods`。有关更多信息，请参阅 [使用启动模板自定义托管式节点](launch-templates.md)。

 **托管节点组与自主管理节点** 

对于托管节点组（不包含自定义 AMI），Amazon EKS 会将 `maxPods` 值注入到节点的引导用户数据中。这意味着：
+ `maxPods` 值的上限始终为 `110` 或 `250`，具体取决于实例大小。
+ 您配置的任何 `maxPodsExpression` 都会被此注入值所覆盖。
+ 要使用不同的 `maxPods` 值，请在启动模板中指定自定义 AMI，然后将 `--use-max-pods false` 与 `--kubelet-extra-args '--max-pods=my-value'` 一起传递到 `bootstrap.sh` 脚本。有关示例，请参阅 [使用启动模板自定义托管式节点](launch-templates.md)。

使用自主管理的节点，您将能够完全控制引导过程。您可以在 `NodeConfig` 中使用 `maxPodsExpression`，或将 `--max-pods` 直接传递给 `bootstrap.sh`。

## EKS 自动模式注意事项
<a name="_considerations_for_eks_auto_mode"></a>

EKS 自动模式会将节点上的容器组（pod）数量限制为以下两项中较小的一个：
+ 110 个容器组硬上限
+ 上述最大容器组数量的计算结果。

# 使用预先构建的优化型映像创建节点
<a name="eks-optimized-amis"></a>

使用托管式节点组或自主管理型节点时，您可以通过预构建的 Amazon EKS 优化型[亚马逊机器映像](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)（AMI）或您自己的自定义 AMI 来部署节点。如果您运行的是混合节点，请参阅[为混合节点准备操作系统](hybrid-nodes-os.md)。有关每种类型的 Amazon EKS 优化版 AMI 的信息，请参阅以下主题之一。有关如何创建您自己的自定义 AMI 的说明，请参阅 [构建自定义 EKS 优化版 Linux AMI](eks-ami-build-scripts.md)。

使用 Amazon EKS 自动模式时，EKS 负责管理 EC2 实例，包括选择和更新 AMI。

**Topics**
+ [EKS AL2 和 AL2 加速型 AMI 过渡功能指南](eks-ami-deprecation-faqs.md)
+ [使用优化型 Amazon Linux AMI 创建节点](eks-optimized-ami.md)
+ [使用优化版 Bottlerocket AMI 创建节点](eks-optimized-ami-bottlerocket.md)
+ [使用优化版 Ubuntu Linux AMI 创建节点](eks-partner-amis.md)
+ [使用优化版 Windows AMI 创建节点](eks-optimized-windows-ami.md)

# EKS AL2 和 AL2 加速型 AMI 过渡功能指南
<a name="eks-ami-deprecation-faqs"></a>

**警告**  
Amazon EKS 已于 2025 年 11 月 26 日停止发布 EKS 优化型 Amazon Linux 2（AL2）AMI。基于 AL2023 和 Bottlerocket 的 Amazon EKS AMI 适用于所有支持的 Kubernetes 版本（包括 1.33 和更高版本）。

 AWS 将于 2025 年 11 月 26 日终止对 EKS AL2 优化型和 AL2 加速型 AMI 的支持。尽管您可以在终止支持（EOS）日期（2025 年 11 月 26 日）之后继续使用 EKS AL2 AMI，但在该日期之后，EKS 将不再为 AL2 AMI 发布任何新的 Kubernetes 版本或更新，包括次要版本、补丁和错误修复。我们建议升级到 Amazon Linux 2023（AL2023）或 Bottlerocket AMI：
+ AL2023 启用了默认安全方法，包括预配置的安全策略、允许模式下的 SELinux、默认启用仅 IMDSv2 模式、优化的启动时间以及改进的程序包管理，增强了安全性和性能，非常适合需要大量自定义（例如直接操作系统级访问或大量节点更改）的基础设施。要了解更多信息，请参阅 [AL2023 常见问题](https://aws.amazon.com/linux/amazon-linux-2023/faqs/)，或查阅我们的详细迁移指引（[从 Amazon Linux 2 升级到 Amazon Linux 2023](al2023.md)）。
+ Bottlerocket 采用专门构建的容器优化设计，可增强安全性、缩短启动时间和缩小攻击面，从而提高效率，非常适合节点自定义极少的容器原生方法。要了解更多信息，请参阅 [Bottlerocket 常见问题](https://aws.amazon.com/bottlerocket/faqs/)，或查阅我们的详细迁移指引（[使用优化版 Bottlerocket AMI 创建节点](eks-optimized-ami-bottlerocket.md)）。

另外，您可以在 EOS 日期（2025 年 11 月 26 日）之前，[构建自定义 EKS 优化版 Linux AMI](eks-ami-build-scripts.md)。此外，您可以在 Amazon Linux 2 EOS 日期（2026 年 6 月 30 日）之前，使用 Amazon Linux 2 基础实例构建自定义 AMI。

## 迁移和支持常见问题
<a name="_migration_and_support_faqs"></a>

### 如何从 AL2 迁移到 AL2023 AMI？
<a name="_how_do_i_migrate_from_my_al2_to_an_al2023_ami"></a>

我们建议您制定和实施迁移计划，其中应包括全面的应用程序工作负载测试和正式记录的回滚程序，然后按照 EKS 官方文档中[从 Amazon Linux 2 升级到 Amazon Linux 2023](https://docs.aws.amazon.com/eks/latest/userguide/al2023.html) 中的分步说明进行操作。

### 我能否在 EKS 终止支持（EOS）日期之后用 EKS 优化型 AL2 AMI 构建自定义 AL2 AMI？
<a name="_can_i_build_a_custom_al2_ami_past_the_eks_end_of_support_eos_date_for_eks_optimized_al2_amis"></a>

虽然我们建议迁移到官方支持和发布的 EKS 优化型 AL2023 或 Bottlerocket AMI，不过您可以在 AL2 AMI EOS 日期（2025 年 11 月 26 日）之前构建自定义 EKS AL2 优化型和 AL2 加速型 AMI。您也可以在 Amazon Linux 2 EOS 日期（2026 年 6 月 30 日）之前使用 Amazon Linux 2 基础实例构建自定义 AMI。有关构建自定义 EKS AL2 优化型和 AL2 加速型 AMI 的分步说明，请参阅 EKS 官方文档中的[构建自定义 Amazon Linux AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-ami-build-scripts.html)。

### EKS Kubernetes 版本支持政策是否适用于 Amazon Linux 发行版？
<a name="_does_the_eks_kubernetes_version_support_policy_apply_to_amazon_linux_distributions"></a>

否。EKS AL2 优化型和 AL2 加速型 AMI 的 EOS 日期与 EKS 对 Kubernetes 版本的标准支持和扩展支持时间表无关。即使您使用 EKS 扩展支持，也需要迁移到 AL2023 或 Bottlerocket。

### 从 cgroupv1 迁移到 cgroupv2 会如何影响我们的迁移？
<a name="_how_does_the_shift_from_cgroupv1_to_cgroupv2_affect_my_migration"></a>

[Kubernetes 社区](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4569-cgroup-v1-maintenance-mode/README.md)已将（AL2 使用的）`cgroupv1` 支持改为维护模式，这意味着不会添加任何新功能，只会提供关键的安全和重要错误修复。要在 Kubernetes 中采用 `cgroupv2`，需要确保操作系统、内核、容器运行时和 Kubernetes 组件之间兼容。这需要使用默认启用 `cgroupv2` 的 Linux 发行版，例如 AL2023、Bottlerocket、Red Hat Enterprise Linux（RHEL）9\$1、Ubuntu 22.04\$1 或 Debian 11\$1。这些发行版附带的内核版本 ≥5.8，即在 Kubernetes 中支持 `cgroupv2` 的最低要求。要了解详情，请参阅 [About cgroup v2](https://kubernetes.io/docs/concepts/architecture/cgroups/)。

### 如果我的自定义 AL2 AMI 需要使用 Neuron，该怎么办？
<a name="_what_do_i_do_if_i_need_neuron_in_my_custom_al2_ami"></a>

您无法在基于 AL2 的 AMI 上以原生方式运行完全由 Neuron 驱动的应用程序。要在 AL2 AMI 上使用 AWS Neuron，您必须使用支持 Neuron 且具有非 AL2 Linux 发行版（例如 Ubuntu 22.04、Amazon Linux 2023 等）的容器对应用程序进行容器化，然后将这些容器部署到安装了 Neuron Driver (`aws-neuronx-dkms`) 的 AL2 AMI 上。

### EKS AL2 AMI EOS 日期（2025 年 11 月 26 日）之后，我是否应该切换到原生 Amazon Linux 2 基础实例？
<a name="_should_i_switch_to_a_bare_amazon_linux_2_base_instance_after_the_eks_al2_ami_eos_date_november_26_2025"></a>

切换至原生 Amazon Linux 2 基础实例，会缺失官方 EKS AL2 优化版 AMI 与 AL2 加速型 AMI 所提供的专属优化、容器运行时配置及定制化内容。若必须继续使用基于 AL2 的方案，建议通过[构建自定义 EKS 优化版 Linux AMI](eks-ami-build-scripts.md) 或 [Amazon EKS AMI Build Specification](https://github.com/awslabs/amazon-eks-ami) 中的 EKS AMI 构建模板，来制作自定义 AMI。此举可确保与现有工作负载的兼容性，并可在 Amazon Linux 2 EOS 日期（2026 年 6 月 30 日）前，持续获取 AL2 内核更新。

### 在 EKS AL2 AMI EOS 日期（2025 年 11 月 26 日）之后，若通过 EKS AMI GitHub 存储库构建自定义 AL2 AMI，来自 amzn2-core 与 amzn2extra-docker 等软件源的软件包可获得何种支持？
<a name="_when_building_a_custom_al2_ami_using_the_eks_ami_github_repository_after_the_eks_al2_ami_eos_date_november_26_2025_what_support_is_available_for_packages_from_repositories_like_amzn2_core_and_amzn2extra_docker"></a>

[Amazon EKS AMI Build Specification](https://github.com/awslabs/amazon-eks-ami) 中的 EKS AMI 构建模板，会通过 YUM 工具从 [amzn2-core](https://docs.aws.amazon.com/linux/al2/ug/managing-software.html)、[amzn2extra-docker](https://docs.aws.amazon.com/linux/al2/ug/managing-software.html) 等标准 Amazon Linux 2 软件源拉取软件包。在 EKS AL2 AMI EOS 日期（2025 年 11 月 26 日）之后，上述软件源仍会持续提供支持，直至 Amazon Linux 2 的整体 EOS 日期（2026 年 6 月 30 日）。需注意，此期间的支持范围仅限内核更新，意即需手动管理并应用其他软件包更新、安全补丁及所有非内核依赖项，以保障系统的安全性与兼容性。

### 在搭载 AL2023 的 Amazon EKS 上运行且使用旧版 JDK8 的 Java 应用，为何可能出现内存不足（OOM）异常与容器组（pod）重启问题？该如何解决此问题？
<a name="_why_might_java_applications_using_older_versions_of_jdk8_on_amazon_eks_with_al2023_experience_out_of_memory_oom_exceptions_and_pod_restarts_and_how_can_this_be_resolved"></a>

在 Amazon EKS AL2023 节点上运行时，依赖 `jdk8u372` 之前版本 JDK 8 的 Java 应用，可能会引发 OOM 异常与容器组（pod）重启，原因在于这些版本的 JVM 与 `cgroupv2` 不兼容。此问题的具体成因是：在 Amazon Linux 2023 的默认配置下，JVM 无法通过 `cgroupv2` 机制识别容器的内存限制。因此，JVM 会基于节点的总内存进行堆内存分配，而非基于容器组（pod）中定义的内存限制。该问题的根源是 `cgroupv2` 变更了内存限制数据的存储路径，导致旧版 Java 无法正确读取可用内存信息，误将节点级别的资源当作容器可用资源。以下是几种可行的解决办法：
+  **升级 JDK 版本**：升级到 `jdk8u372` 或更高版本，或升级到完全支持 `cgroupv2` 的新版 JDK，即可解决此问题。有关完全兼容 `cgroupv2` 的 Java 版本列表，请参阅[关于 cgroup v2](https://kubernetes.io/docs/concepts/architecture/cgroups/)。
+  **构建自定义 AMI**：若必须继续使用基于 AL2 的方案，可通过[构建自定义 EKS 优化版 Linux AMI](eks-ami-build-scripts.md) 或 [Amazon EKS AMI Build Specification](https://github.com/awslabs/amazon-eks-ami)，构建基于 AL2 的自定义 AMI（支持至 2025 年 11 月 26 日）。例如，您可构建基于 AL2 的 v1.33 AMI（支持到 2025 年 11 月 26 日）。Amazon EKS 会在 EKS AL2 EOS 日期（2025 年 11 月 26 日）之前，持续提供基于 AL2 的 AMI。在 EOS 日期（2025 年 11 月 26 日）之后，您需自行构建 AMI。
+  **启用 cgroupv1**：若必须继续使用 `cgroupv1`，可在 EKS AL2023 AMI 上启用 `cgroupv1`。执行命令 `sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0"`，重启系统（例如运行 Amazon Linux 2023 的 EC2 实例或节点），即可完成启用。此操作会修改系统的启动参数（例如，在 GRUB 配置中添加内核参数 systemd.unified\$1cgroup\$1hierarchy=0，指示 systemd 使用传统的 `cgroupv1` 层级架构），从而启用 `cgroupv1`。需注意，执行该 grubby 命令后，系统内核的启动配置会被修改为启用 `cgroupv1` 且禁用 `cgroupv2`。节点上仅会采用其中一种 cgroup 版本进行活跃的资源管理。此模式与“启用 `cgroupv2` 并兼容 `cgroupv1` API 向后兼容”的模式并不相同。

**警告**  
我们不建议继续使用 `cgroupv1`，而是推荐迁移到 `cgroupv2`。Kubernetes 社区已将 `cgroupv1` 的支持（即 AL2 所采用的版本）调整为维护模式。这意味着该版本将不再新增功能或推送更新，仅会针对严重安全漏洞与重大程序缺陷提供修复补丁。`cgroupv1` 的支持功能预计将在后续版本中被完全移除，不过官方尚未公布具体的移除日期。若在使用 `cgroupv1` 时遇到相关问题，AWS 将无法提供技术支持，同时会建议升级到 `cgroupv2`。

## 兼容性与版本
<a name="_compatibility_and_versions"></a>

### AL2 AMI 支持的 Kubernetes 版本
<a name="_supported_kubernetes_versions_for_al2_amis"></a>

Kubernetes 版本 1.32 是 Amazon EKS 将为其发布 AL2（Amazon Linux 2）AMI 的最后一个版本。对于不高于 1.32 的[受支持](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html) Kubernetes 版本，EKS 将在 2025 年 11 月 26 日之前继续发布 AL2 AMI（AL2\$1ARM\$164、AL2\$1x86\$164）和 AL2 加速型 AMI（AL2\$1x86\$164\$1GPU）。在该日期之后，EKS 将停止为所有 Kubernetes 版本发布 AL2 优化型和 AL2 加速型 AMI。请注意，EKS AL2 优化型和 AL2 加速型 AMI 的 EOS 日期与 EKS 对 Kubernetes 版本的标准支持和扩展支持时间表无关。

### AL2、AL2023 和 Bottlerocket AMI 支持的驱动程序和 Linux 内核版本比较
<a name="_supported_drivers_and_linux_kernel_versions_comparison_for_al2_al2023_and_bottlerocket_amis"></a>


| 组件 | EKS AL2 AMI | EKS AL2023 AMI | EKS Bottlerocket AMI | 
| --- | --- | --- | --- | 
|  基础操作系统兼容性  |  RHEL7/CentOS 7  |  Fedora/CentOS 9  |  不适用  | 
|   [CUDA 用户模式驱动程序](https://docs.nvidia.com/deploy/cuda-compatibility/why-cuda-compatibility.html#why-cuda-compatibility)   |  12.x  |  12.x、13.x  |  12.x、13.x  | 
|  NVIDIA GPU 驱动程序  |  R570  |  R580  |  R570、R580  | 
|   AWS Neuron 驱动程序  |  2.20\$1  |  2.20\$1  |  2.20\$1  | 
|  Linux 内核  |  5.10  |  6.1、6.12  |  6.1、6.12  | 

有关 NVIDIA 驱动程序及 CUDA 兼容性的更多信息，请参阅 [NVIDIA 文档](https://docs.nvidia.com/datacenter/tesla/drivers/index.html#supported-drivers-and-cuda-toolkit-versions)。

### AWS Neuron 与 AL2 AMI 的兼容性
<a name="shared_aws_neuron_compatibility_with_al2_amis"></a>

从 [AWS Neuron 版本 2.20](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/release-notes/prev/rn.html#neuron-2-20-0-whatsnew) 起，基于 EKS AL 的 AMI 所用 Neuron 运行时 (`aws-neuronx-runtime-lib`) 不再支持 Amazon Linux 2（AL2）。Neuron 驱动程序 (`aws-neuronx-dkms`) 现在是唯一支持 Amazon Linux 2 的 AWS Neuron 程序包。这意味着您无法在基于 AL2 的 AMI 上以原生方式运行由 Neuron 驱动的应用程序。要在 AL2023 AMI 上安装 Neuron，请参阅 [AWS Neuron 安装](https://awsdocs-neuron.readthedocs-hosted.com/en/latest/general/setup/index.html#setup-guide-index)指南。

### Kubernetes 与 AL2 AMI 的兼容性
<a name="_kubernetes_compatibility_with_al2_amis"></a>

Kubernetes 社区已将（AL2 使用的）`cgroupv1` 支持改为维护模式。这意味着不会添加任何新功能，只会提供关键的安全和重要错误修复。任何依赖于 cgroupv2 的 Kubernetes 功能（例如 MemoryQoS 和增强的资源隔离），都不支持 AL2。此外，Amazon EKS Kubernetes 1.32 版本是最后一个支持 AL2 AMI 的版本。为保持与最新 Kubernetes 版本的兼容性，我们建议迁移到 AL2023 或 Bottlerocket，因为其已默认启用 `cgroupv2`。

### Linux 版本与 AL2 AMI 的兼容性
<a name="_linux_version_compatibility_with_al2_amis"></a>

在终止支持（EOS）日期（2026 年 6 月 30 日）之前，AWS 将为 Amazon Linux 2（AL2）提供支持。但随着 AL2 的过时，整个 Linux 社区对新应用程序和功能的支持变得越来越少。AL2 AMI 基于 [Linux 内核 5.10](https://docs.aws.amazon.com/linux/al2/ug/kernel.html)，而 AL2023 使用 [Linux 内核 6.1](https://docs.aws.amazon.com/linux/al2023/ug/compare-with-al2-kernel.html)。与 AL2023 不同，整个 Linux 社区对 AL2 的支持十分有限。这意味着许多上游 Linux 程序包和工具需要向后移植才能兼容 AL2 使用的早期内核版本；同时由于内核版本过时，无法支持某些现代 Linux 功能和安全改进，许多开源项目已弃用或限制了对较早内核版本（如 5.10）的支持。

### AL2023 中未包含已弃用的程序包
<a name="_deprecated_packages_not_included_in_al2023"></a>

AL2023 中未包含或已更改的一些最常见程序包包括：
+ Amazon Linux 2023 不再包含 [Amazon Linux 2 中的某些源二进制包](https://docs.aws.amazon.com/linux/al2023/release-notes/removed-AL2023.6-AL2.html)
+ Amazon Linux 在 AL2023 中更改了支持不同版本程序包（例如 [amazon-linux-extras system](https://repost.aws/questions/QUWGU3VFJMRSGf6MDPWn4tLg/how-to-resolve-amazon-linux-extras-in-al2023)）的方式
+  AL2023 不支持[适用于 Enterprise Linux 的附加程序包（EPEL）](https://docs.aws.amazon.com/linux/al2023/ug/epel.html)
+  AL2023 不支持 [32 位应用程序](https://docs.aws.amazon.com/linux/al2023/ug/deprecated-al2.html#deprecated-32bit-rpms)

要了解更多信息，请参阅 [Comparing AL2 and AL2023](https://docs.aws.amazon.com/linux/al2023/ug/compare-with-al2.html)。

### AL2、AL2023 和 Bottlerocket 的 FIPS 验证方式比较
<a name="_fips_validation_comparison_across_al2_al2023_and_bottlerocket"></a>

Amazon Linux 2（AL2）、Amazon Linux 2023（AL2023）和 Bottlerocket 提供了对《联邦信息处理标准》（FIPS）合规性的支持。
+ AL2 通过了 FIPS 140-2 认证，AL2023 通过了 FIPS 140-3 认证。要在 AL2023 上启用 FIPS 模式，请在您的 Amazon EC2 实例上安装必要的程序包，然后按照 [Enable FIPS Mode on AL2023](https://docs.aws.amazon.com/linux/al2023/ug/fips-mode.html) 中的说明完成配置步骤即可。要了解更多信息，请参阅 [AL2023 常见问题](https://aws.amazon.com/linux/amazon-linux-2023/faqs)。
+ Bottlerocket 提供了特别针对 FIPS 构建的专用变体，将内核和用户空间组件限制为使用已提交给 FIPS 140-3 加密模块验证计划的加密模块。

### EKS AMI 驱动程序和版本更改日志
<a name="_eks_ami_driver_and_versions_changelog"></a>

有关所有 EKS AMI 组件及其版本的完整列表，请参阅 GitHub 上的 [Amazon EKS AMI Release Notes](https://github.com/awslabs/amazon-eks-ami/releases)。

# 使用优化型 Amazon Linux AMI 创建节点
<a name="eks-optimized-ami"></a>

Amazon Elastic Kubernetes Service（Amazon EKS）提供了专用的亚马逊机器映像（AMI），这类映像针对 Kubernetes Worker 节点的运行需求做了优化处理。这些 EKS 优化版 Amazon Linux（AL）AMI，已预配置各类核心组件，例如 `kubelet`、AWS IAM 身份验证器及 `containerd`，以此保障与集群的无缝集成，同时提升集群的安全性。本指南详细列出了当前可用的 AMI 版本，并概述了针对加速计算架构及基于 Arm 架构的专属配置方案。

## 注意事项
<a name="ami-considerations"></a>
+ 您可以在 [Amazon Linux 安全中心](https://alas.aws.amazon.com/)通过选择所需版本的选项卡来跟踪 Amazon Linux 的安全和隐私事件。您也可以订阅相应的 RSS 源。安全和隐私事件包括问题的概述、受影响的程序包以及如何更新实例以解决问题。
+ 在部署加速型 AMI 或 Arm AMI 之前，请先查看 [Amazon EKS 优化版加速型 Amazon Linux AMI](#gpu-ami) 和 [Amazon EKS 优化版 Arm Amazon Linux AMI](#arm-ami) 中的相关信息。
+ Amazon EKS 不支持 Amazon EC2 `P2` 实例，因为它们需要 `NVIDIA` 驱动程序版本 470 或更早版本。
+ 在版本 `1.30` 或更高版本中新创建的任何托管节点组都将自动默认使用 AL2023 作为节点操作系统。

## Amazon EKS 优化版加速型 Amazon Linux AMI
<a name="gpu-ami"></a>

Amazon EKS 优化版加速型 Amazon Linux（AL）AMI 基于标准的 Amazon EKS 优化版 Amazon Linux AMI 构建。并配置作为 Amazon EKS 节点的可选映像，用来支持基于 GPU、[Inferentia](https://aws.amazon.com/machine-learning/inferentia/) 和 [Trainium](https://aws.amazon.com/machine-learning/trainium/) 的工作负载。

有关更多信息，请参阅 [为 GPU 实例使用 EKS 优化版加速 AMI](ml-eks-optimized-ami.md)。

## Amazon EKS 优化版 Arm Amazon Linux AMI
<a name="arm-ami"></a>

Arm 实例可以为横向扩展和基于 Arm 的应用程序（例如 Web 服务器、容器化微服务、缓存队列以及分布式数据存储）节省大量成本。当将 Arm 节点添加到集群时，请查看以下注意事项。
+ 如果您的集群是在 2020 年 8 月 17 日之前部署的，则必须对关键集群附加组件清单进行一次性升级。这样，Kubernetes 可以为集群中使用的每个硬件架构提取正确映像。有关更新集群附加组件的更多信息，请参阅 [第 1 步：准备升级](update-cluster.md#update-existing-cluster)。如果您在 2020 年 8 月 17 日当天或之后部署了集群，则 CoreDNS、`kube-proxy` 以及适用于 Kubernetes 附加组件的 Amazon VPC CNI 插件已经具备多架构功能。
+ 部署到 Arm 节点的应用程序必须针对 Arm 进行编译。
+ 如果您在现有集群中部署了 DaemonSet，或者希望将之部署到同时要在其中部署 Arm 节点的新集群中，请验证 DaemonSet 是否可以在集群中的所有硬件架构上运行。
+ 您可以在同一集群中运行 Arm 节点组和 x86 节点组。如果要这样做，请考虑将多架构容器映像部署到容器存储库（如 Amazon Elastic Container Registry），然后将节点选择器添加到清单中，以便 Kubernetes 知道要将容器组（pod）部署到哪个硬件架构。有关更多信息，请参阅 *Amazon ECR 用户指南*中的[推送多架构映像](https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-multi-architecture-image.html)和 [Amazon ECR 的多架构容器映像简介](https://aws.amazon.com/blogs/containers/introducing-multi-architecture-container-images-for-amazon-ecr)博客文章。

## 更多信息
<a name="linux-more-information"></a>

有关使用 Amazon EKS 优化版 Amazon Linux AMI 的更多信息，请参阅以下部分：
+ 要将 Amazon Linux 与托管节点组一起使用，请参阅 [使用托管式节点组简化节点生命周期](managed-node-groups.md)。
+ 要启动自行管理的 Amazon Linux 节点，请参阅 [检索建议的 Amazon Linux AMI ID](retrieve-ami-id.md)。
+ 有关版本信息，请参阅 [检索 Amazon Linux AMI 版本信息](eks-linux-ami-versions.md)。
+ 要获取 Amazon EKS 优化版 Amazon Linux AMI 的最新 ID，请参阅[检索建议的 Amazon Linux AMI ID](retrieve-ami-id.md)。
+ 要获取用于构建 Amazon EKS 优化版 AMI 的开源脚本，请参阅[构建自定义 EKS 优化版 Linux AMI](eks-ami-build-scripts.md)。

# 从 Amazon Linux 2 升级到 Amazon Linux 2023
<a name="al2023"></a>

**警告**  
Amazon EKS 已于 2025 年 11 月 26 日停止发布 EKS 优化型 Amazon Linux 2（AL2）AMI。基于 AL2023 和 Bottlerocket 的 Amazon EKS AMI 适用于所有支持的 Kubernetes 版本（包括 1.33 和更高版本）。

AL2023 是一款基于 Linux 的操作系统，旨在为云应用程序提供安全、稳定和高性能的环境。它是 Amazon Web Services 推出的下一代 Amazon Linux，适用于所有支持的 Amazon EKS 版本。

AL2023 比 AL2 提供了多项改进。有关完整比较，请参阅《Amazon Linux 2023 用户指南》**中的[比较 AL2 和 Amazon Linux 2023](https://docs.aws.amazon.com/linux/al2023/ug/compare-with-al2.html)。已在 AL2 中添加、升级和移除了多个程序包。强烈建议在升级之前使用 AL2023 测试您的应用程序。有关 AL2023 中所有程序包更改的列表，请参阅《Amazon Linux 2023 发行说明》**中的 [Amazon Linux 2023 的程序包更改](https://docs.aws.amazon.com/linux/al2023/release-notes/compare-packages.html)。

除了这些更改之外，您还应了解以下事项：
+ AL2023 引入了使用 YAML 配置架构的新节点初始化流程 `nodeadm`。如果您使用的是自行管理的节点组或带有启动模板的 AMI，则在创建新节点组时，现在需要明确提供其它集群元数据。以下是最低必需参数的[示例](https://awslabs.github.io/amazon-eks-ami/nodeadm/)，其中 `apiServerEndpoint`、`certificateAuthority` 和服务 `cidr` 是必需的：

  ```
  ---
  apiVersion: node.eks.aws/v1alpha1
  kind: NodeConfig
  spec:
    cluster:
      name: my-cluster
      apiServerEndpoint: https://example.com
      certificateAuthority: Y2VydGlmaWNhdGVBdXRob3JpdHk=
      cidr: 10.100.0.0/16
  ```

  在 AL2 中，来自这些参数的元数据是从 Amazon EKS `DescribeCluster` API 调用中发现的。使用 AL2023，这种行为发生了变化，因为在大型节点纵向扩展期间，额外的 API 调用有节流风险。如果您使用的是没有启动模板的托管节点组或者 Karpenter，则此更改不会对您产生影响。有关 `certificateAuthority` 和服务 `cidr` 的更多信息，请参阅《Amazon EKS API 参考》**中的 [https://docs.aws.amazon.com/eks/latest/APIReference/API_DescribeCluster.html](https://docs.aws.amazon.com/eks/latest/APIReference/API_DescribeCluster.html)。
+ 对于 AL2023，`nodeadm` 也可以使用 [https://awslabs.github.io/amazon-eks-ami/nodeadm/doc/api/#nodeconfigspec](https://awslabs.github.io/amazon-eks-ami/nodeadm/doc/api/#nodeconfigspec) 来更改格式，将参数应用于每个节点的 `kubelet`。而在 AL2 中，这通过 `--kubelet-extra-args` 参数完成。这通常用于向节点添加标签和污点。以下示例显示了如何将 `maxPods` 和 `--node-labels` 应用于节点。

  ```
  ---
  apiVersion: node.eks.aws/v1alpha1
  kind: NodeConfig
  spec:
    cluster:
      name: test-cluster
      apiServerEndpoint: https://example.com
      certificateAuthority: Y2VydGlmaWNhdGVBdXRob3JpdHk=
      cidr: 10.100.0.0/16
    kubelet:
      config:
        maxPods: 110
      flags:
        - --node-labels=karpenter.sh/capacity-type=on-demand,karpenter.sh/nodepool=test
  ```
+ AL2023 需要 Amazon VPC CNI 版本 `1.16.2` 或更高版本。
+ 默认情况下，AL2023 需要 `IMDSv2`。`IMDSv2` 有多项益处，可助于改善安全状况。它使用面向会话的身份验证方法，需要在简单的 HTTP PUT 请求中创建密钥令牌才能启动会话。会话令牌的有效时间可以介于 1 秒到 6 小时之间。有关如何从 `IMDSv1` 转换到 `IMDSv2` 的更多信息，请参阅[转换到使用实例元数据服务版本 2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-transition-to-version-2.html) 和[获取 IMDSv2 的全部优势并在 AWS 基础设施中禁用 IMDSv1](https://aws.amazon.com/blogs/security/get-the-full-benefits-of-imdsv2-and-disable-imdsv1-across-your-aws-infrastructure)。如果您想使用 `IMDSv1`，则您仍然可以通过使用实例元数据选项启动属性手动覆盖设置来做到这一点。
**注意**  
对于使用 AL2023 的 `IMDSv2`，托管节点组的默认跳数可能会有所不同：  
不使用启动模板时，默认值设置为 `1`。这意味着，容器无法使用 IMDS 访问节点的凭证。如果您需要容器访问节点的凭证，仍然可以通过使用[自定义 Amazon EC2 启动模板](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-metadataoptions.html)来实现。
在启动模板中使用自定义 AMI 时，默认 `HttpPutResponseHopLimit` 设置为 `2`。您可以手动覆盖启动模板中的 `HttpPutResponseHopLimit`。
或者，您可以使用 [Amazon EKS 容器组身份](pod-identities.md)来提供凭证，而不是 `IMDSv2`。
+ AL2023 采用下一代统一控制组层次结构 (`cgroupv2`)。`cgroupv2` 用于实施容器运行时，并由 `systemd` 实施。虽然 AL2023 仍然包含可以使用 `cgroupv1` 使系统运行的代码，但这不是建议或支持的配置。此配置将在未来的 Amazon Linux 主要版本中完全移除。
+  `eksctl` 需要 `eksctl` 版本 `0.176.0` 或更高版本才能支持 AL2023。

对于以前存在的托管节点组，您可以执行就地升级或蓝/绿升级，具体取决于您所使用的启动模板的方式：
+ 如果您在托管节点组中使用自定义 AMI，则可以通过交换启动模板中的 AMI ID 来执行就地升级。在执行此升级策略之前，您应确保您的应用程序和所有用户数据首先传输到 AL2023。
+ 如果您将托管节点组与标准启动模板或未指定 AMI ID 的自定义启动模板结合使用，则需要使用蓝/绿策略升级。蓝/绿升级通常更复杂，需要创建一个全新的节点组，在其中指定 AL2023 作为 AMI 类型。然后，需要小心配置新的节点组，以确保来自 AL2 节点组的所有自定义数据都与新操作系统兼容。在应用程序中对新节点组进行测试和验证后，容器组（pod）可以从旧节点组迁移到新的节点组。迁移完成之后，您就可以删除旧节点组。

如果您使用的是 Karpenter 且希望使用 AL2023，则需使用 AL2023 修改 `EC2NodeClass` `amiFamily` 字段。默认情况下，偏差在 Karpenter 中启用。这意味着，`amiFamily` 字段更改后，Karpenter 会自动将 Worker 节点更新为最新的 AMI（如果有）。

## 有关 nodeadm 的其他信息
<a name="_additional_information_about_nodeadm"></a>

在使用 EKS 优化的 Amazon Linux 2023 AMI 或通过 amazon-eks-ami GitHub 官方存储库中提供的 Packer 脚本构建自定义 EKS Amazon Linux 2023 AMI 时，应避免在 EC2 用户数据中或作为自定义 AMI 的一部分明确运行 nodeadm init。

如果您想在用户数据中生成动态 NodeConfig，可以将该配置写入到 `/etc/eks/nodeadm.d` 中的嵌入式 yaml 或 json 文件中。这些配置文件在启动过程后期 nodeadm init 自动启动时被合并并应用于您的节点。例如：

```
cat > /etc/eks/nodeadm.d/additional-node-labels.yaml << EOF
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  kubelet:
    flags:
      - --node-labels=foo=bar
EOF
```

经 EKS 优化的 Amazon Linux 2023 AMI 会通过两个独立的 systemd 服务分两个阶段自动执行 nodeadm init 操作：nodeadm-config 在用户数据执行之前运行，而 nodeadm-run 则在之后运行。nodeadm-config 服务在用户数据运行之前为 containerd 和 kubelet 建立基准配置。nodeadm-run 服务运行选定的系统进程守护程序，并在用户数据执行后完成所有最终配置。如果通过用户数据或自定义 AMI 再次运行 nodeadm init 命令，可能会破坏关于执行顺序的假设，从而导致意想不到的结果，包括配置错误的 ENI。

# 检索 Amazon Linux AMI 版本信息
<a name="eks-linux-ami-versions"></a>

Amazon EKS 优化版 Amazon Linux AMI 按 Kubernetes 版本和 AMI 的发布日期进行版本控制，格式如下：

```
k8s_major_version.k8s_minor_version.k8s_patch_version-release_date
```

每个 AMI 发行版都包含若干 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)、Linux 内核及 [containerd](https://containerd.io/) 版本。加速型 AMI 还包括 NVIDIA 驱动程序的各种版本。您可以在 GitHub 上的 [Changelog](https://github.com/awslabs/amazon-eks-ami/blob/main/CHANGELOG.md) 中找到该版本信息。

# 检索建议的 Amazon Linux AMI ID
<a name="retrieve-ami-id"></a>

部署节点时，您可以为预先构建的 Amazon EKS 优化版亚马逊机器映像（AMI）指定 ID。要检索符合所需配置的 AMI ID，请查询 AWS Systems Manager Parameter Store API。使用此 API，您无需手动查找 Amazon EKS 优化版 AMI ID。有关更多信息，请参阅 [GetParameter](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html)。您使用的 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html#iam-term-principal)必须具有 `ssm:GetParameter` IAM 权限才能检索 Amazon EKS 优化版 AMI 元数据。

您可以使用以下命令检索最新推荐 Amazon EKS 优化版 AMI 的映像 ID，该命令使用子参数 `image_id`。根据需要对该命令进行以下修改，然后运行修改后的命令：
+ 将 `<kubernetes-version>` 替换为 [Amazon EKS 支持的版本](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)。
+ 将 *ami-type* 替换为以下选项之一。有关 Amazon EC2 实例类型的信息，请参阅 [Amazon EC2 实例类型](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html)。
  + 将 *amazon-linux-2023/x86\$164/standard* 用于基于 Amazon Linux 2023（AL2023）`x86` 的实例。
  + 将 *amazon-linux-2023/arm64/standard* 用于 AL2023 ARM 实例，例如基于 [AWS Graviton](https://aws.amazon.com/ec2/graviton/) 的实例。
  + 将 *amazon-linux-2023/x86\$164/nvidia* 用于最新批准的基于 AL2023 NVIDIA `x86` 的实例。
  + 将 *amazon-linux-2023/arm64/nvidia* 用于最新批准的基于 AL2023 NVIDIA `arm64` 的实例。
  + 将 *amazon-linux-2023/x86\$164/neuron* 用于最新的 AL2023 [AWS Neuron](https://aws.amazon.com/machine-learning/neuron/) 实例。
+ 请将 `<region-code>` 替换为您需要 AMI ID 的 [Amazon EKS 支持的 AWS 区域](https://docs.aws.amazon.com/general/latest/gr/eks.html)。

```
aws ssm get-parameter --name /aws/service/eks/optimized-ami/<kubernetes-version>/<ami-type>/recommended/image_id \
    --region <region-code> --query "Parameter.Value" --output text
```

以下是替换占位符后的命令示例。

```
aws ssm get-parameter --name /aws/service/eks/optimized-ami/1.31/amazon-linux-2023/x86_64/standard/recommended/image_id \
    --region us-west-2 --query "Parameter.Value" --output text
```

示例输出如下。

```
ami-1234567890abcdef0
```

# 构建自定义 EKS 优化版 Linux AMI
<a name="eks-ami-build-scripts"></a>

**警告**  
Amazon EKS 已于 2025 年 11 月 26 日停止发布 EKS 优化型 Amazon Linux 2（AL2）AMI。基于 AL2023 和 Bottlerocket 的 Amazon EKS AMI 适用于所有支持的 Kubernetes 版本（包括 1.33 和更高版本）。

Amazon EKS 在 [Amazon EKS AMI Build Specification](https://github.com/awslabs/amazon-eks-ami) 存储库中提供开源构建脚本，您可通过这些脚本查看 `kubelet`、运行时环境及适用于 Kubernetes 的 AWS IAM 身份验证器的相关配置，同时也能从头构建基于 AL 的自有 AMI。

此存储库包含[适用于 AL2 的专用引导脚本](https://github.com/awslabs/amazon-eks-ami/blob/main/templates/al2/runtime/bootstrap.sh)，以及在开机阶段运行的[适用于 AL2023 的 nodeadm 工具](https://awslabs.github.io/amazon-eks-ami/nodeadm/)。这些脚本可配置实例的证书数据、控制面板端点、集群名称等内容。这些脚本是 Amazon EKS 优化版 AMI 生成的可信来源，因此您可关注 GitHub 存储库以监控对 AMI 所做的更改。

以 EKS 优化版 AMI 为基础构建自定义 AMI 时，不建议且不提供技术支持运行操作系统升级（即 `dnf upgrade`），亦不建议升级 EKS 优化版 AMI 中预装的任何 Kubernetes 或 GPU 相关软件包，因为此类操作可能破坏组件间的兼容性。若仍选择对 EKS 优化版 AMI 中的操作系统或软件包执行升级操作，建议先在开发或预发布环境中开展全面测试，再部署至生产环境。

针对 GPU 实例构建自定义 AMI 时，建议为计划运行的各代实例类型及实例系列分别构建独立的自定义 AMI。EKS 优化版加速型 AMI 会在运行时阶段，根据底层实例的代次与系列选择性安装驱动程序及软件包。有关[安装](https://github.com/awslabs/amazon-eks-ami/blob/main/templates/al2023/provisioners/install-nvidia-driver.sh)及[运行时](https://github.com/awslabs/amazon-eks-ami/blob/main/templates/al2023/runtime/gpu/nvidia-kmod-load.sh)的详细信息，请参阅 EKS AMI 脚本。

## 先决条件
<a name="_prerequisites"></a>
+  [安装 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)。
+  [安装 HashiCorp Packer v1.9.4\$1](https://developer.hashicorp.com/packer/downloads) 
+  [安装 GNU Make](https://www.gnu.org/software/make/) 

## 快速入门
<a name="_quickstart"></a>

本快速入门指南将演示在 AWS 账户中创建自定义 AMI 所需执行的命令。要了解有关可用于自定义 AMI 的配置的更多信息，请参阅 [Amazon Linux 2023](https://awslabs.github.io/amazon-eks-ami/usage/al2023/) 页面上的模板变量。

### 先决条件
<a name="_prerequisites_2"></a>

安装所需的 [Amazon Q 插件](https://developer.hashicorp.com/packer/integrations/hashicorp/amazon)。例如：

```
packer plugins install github.com/hashicorp/amazon
```

### 步骤 1：设置您的环境
<a name="_step_1_setup_your_environment"></a>

克隆或复刻 Amazon EKS AMI 官方存储库。例如：

```
git clone https://github.com/awslabs/amazon-eks-ami.git
cd amazon-eks-ami
```

确认已安装 Packer：

```
packer --version
```

### 步骤 2：创建自定义 AMI
<a name="_step_2_create_a_custom_ami"></a>

以下是用于各种自定义 AMI 的示例命令。

 **基本 NVIDIA AL2 AMI：**

```
make k8s=1.31 os_distro=al2 \
  enable_accelerator=nvidia \
  nvidia_driver_major_version=560 \
  enable_efa=true
```

 **基本 NVIDIA AL2023 AMI：**

```
make k8s=1.31 os_distro=al2023 \
  enable_accelerator=nvidia \
  nvidia_driver_major_version=560 \
  enable_efa=true
```

 **符合 STIG 标准的 Neuron AL2023 AMI：**

```
make k8s=1.31 os_distro=al2023 \
  enable_accelerator=neuron \
  enable_fips=true \
  source_ami_id=ami-0abcd1234efgh5678 \
  kms_key_id=alias/aws-stig
```

运行这些命令后，Packer 将执行以下操作：\$1 启动临时 Amazon EC2 实例。\$1 安装 Kubernetes 组件、驱动程序和配置。在 AWS 账户中创建 AMI。

预期输出应如下所示：

```
==> Wait completed after 8 minutes 42 seconds

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
us-west-2: ami-0e139a4b1a7a9a3e9

--> amazon-ebs: AMIs were created:
us-west-2: ami-0e139a4b1a7a9a3e9

--> amazon-ebs: AMIs were created:
us-west-2: ami-0e139a4b1a7a9a3e9
```

### 步骤 3：查看默认值
<a name="_step_3_view_default_values"></a>

要查看默认值和其他选项，请运行以下命令：

```
make help
```

# 使用优化版 Bottlerocket AMI 创建节点
<a name="eks-optimized-ami-bottlerocket"></a>

 [Bottlerocket](https://aws.amazon.com/bottlerocket/) 是由 AWS 赞助和支持的开源 Linux 发行版。Bottlerocket 专为托管容器工作负载而构建。您可以借助 Bottlerocket 实现容器基础设施自动更新，由此提高容器化部署的可用性，降低运营成本。Bottlerocket 仅包含运行容器所需的必备软件，可提高资源利用率、减少安全威胁并降低管理开销。Bottlerocket AMI 包括 `containerd`、`kubelet` 和 AWS IAM 身份验证器。除了托管节点组和自主管理型节点外，Bottlerocket 还受 [Karpenter](https://karpenter.sh/) 支持。

## 优点
<a name="bottlerocket-advantages"></a>

将 Bottlerocket 与 Amazon EKS 集群结合使用有以下优势：
+  **正常运行时间更长，运营成本和管理复杂性更低** – 与其他 Linux 发行版相比，Bottlerocket 资源占用量更小，启动时间更短，更不容易受到安全威胁。Bottlerocket 占用量更小，因此可通过使用更少的存储、计算和网络资源来帮助用户降低成本。
+  **自动操作系统更新可提高安全性** – Bottlerocket 的更新作为单个单元应用，必要时可以回滚。这消除了更新损坏或失败的风险，这些情况可能会使系统处于不可用状态。借助 Bottlerocket，安全更新能在可用时以中断最少的方式自动应用，并在出现故障时回滚。
+  **Premium Support** – AWS 在 Amazon EC2 上提供的 Bottlerocket 发行版包含在相同的 AWS Support 计划中，这些计划还涵盖 Amazon EC2、Amazon EKS 和 Amazon ECR 等 AWS 服务。

## 注意事项
<a name="bottlerocket-considerations"></a>

将 Bottlerocket 用于 AMI 类型时，请考虑以下事项：
+ Bottlerocket 支持采用 `x86_64` 和 `arm64` 处理器的 Amazon EC2 实例。
+ Bottlerocket 系统支持搭载 GPU 的 Amazon EC2 实例。有关更多信息，请参阅 [为 GPU 实例使用 EKS 优化版加速 AMI](ml-eks-optimized-ami.md)。
+ Bottlerocket 映像不附带 SSH 服务器或 Shell。您可以使用带外访问方法来允许 SSH。这些方法会启用管理员容器，并利用用户数据来执行一些引导配置步骤。有关更多信息，请参阅 GitHub 上 [Bottlerocket OS](https://github.com/bottlerocket-os/bottlerocket/blob/develop/README.md) 一文中的以下章节：
  +  [探索](https://github.com/bottlerocket-os/bottlerocket/blob/develop/README.md#exploration) 
  +  [管理员容器](https://github.com/bottlerocket-os/bottlerocket/blob/develop/README.md#admin-container) 
  +  [Kubernetes 设置](https://github.com/bottlerocket-os/bottlerocket/blob/develop/README.md#kubernetes-settings) 
+ Bottlerocket 使用不同的容器类型：
  + 默认情况下，将启用[控制容器](https://github.com/bottlerocket-os/bottlerocket-control-container)。该容器运行 [AWS Systems Manager 代理](https://github.com/aws/amazon-ssm-agent)，可以用于在 Amazon EC2 Bottlerocket 实例上运行命令或启动 Shell 会话。有关更多信息，请参阅 *AWS Systems Manager 用户指南*中的[设置会话管理器](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-getting-started.html)。
  + 如果创建节点组时提供 SSH 密钥，则会启用管理员容器。我们建议仅将管理员容器用于开发和测试场景。我们建议不要在生产环境中使用此模式。有关更多信息，请参阅 GitHub 上的 [Admin 容器](https://github.com/bottlerocket-os/bottlerocket/blob/develop/README.md#admin-container)。

## 更多信息
<a name="bottlerocket-more-information"></a>

有关使用 Amazon EKS 优化版 Bottlerocket AMI 的更多信息，请参阅以下章节：
+ 有关 Bottlerocket 的详细信息，请参阅 [Bottlerocket Documentation](https://bottlerocket.dev/en/)。
+ 有关版本信息资源，请参阅 [检索 Bottlerocket AMI 版本信息](eks-ami-versions-bottlerocket.md)。
+ 要将 Bottlerocket 与托管节点组一起使用，请参阅[使用托管式节点组简化节点生命周期](managed-node-groups.md)。
+ 要启动自主管理型 Bottlerocket 节点，请参阅[创建自主管理型 Bottlerocket 节点](launch-node-bottlerocket.md)。
+ 要检索 Amazon EKS 优化版 Bottlerocket AMI 的最新 ID，请参阅[检索建议的 Bottlerocket AMI ID](retrieve-ami-id-bottlerocket.md)。
+ 有关合规支持的详细信息，请参阅 [使用 Bottlerocket 满足合规性要求](bottlerocket-compliance-support.md)。

# 检索 Bottlerocket AMI 版本信息
<a name="eks-ami-versions-bottlerocket"></a>

每个 Bottlerocket AMI 发行版都包含若干 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)、Bottlerocket 内核及 [containerd](https://containerd.io/) 版本。加速型 AMI 版本还包括若干 NVIDIA 驱动程序版本。您可以在 *Bottlerocket 文档*的[操作系统](https://bottlerocket.dev/en/os/)主题中找到此版本信息。在此页面上，导航到相应的*版本信息*子主题。

 *Bottlerocket 文档*中的信息有时会落后于 GitHub 上提供的版本。您可以在 GitHub 上的 [releases](https://github.com/bottlerocket-os/bottlerocket/releases) 中找到最新版本更改的列表。

# 检索建议的 Bottlerocket AMI ID
<a name="retrieve-ami-id-bottlerocket"></a>

部署节点时，您可以为预先构建的 Amazon EKS 优化版亚马逊机器映像（AMI）指定 ID。要检索符合所需配置的 AMI ID，请查询 AWS Systems Manager Parameter Store API。使用此 API，您无需手动查找 Amazon EKS 优化版 AMI ID。有关更多信息，请参阅 [GetParameter](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html)。您使用的 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html#iam-term-principal)必须具有 `ssm:GetParameter` IAM 权限才能检索 Amazon EKS 优化版 AMI 元数据。

您可以使用以下 AWS CLI 命令检索最新推荐 Amazon EKS 优化版 Bottlerocket AMI 的映像 ID，该命令使用子参数 `image_id`。根据需要对该命令进行以下修改，然后运行修改后的命令：
+ 将 *kubernetes-version* 替换为支持的 [platform-version](https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html)。
+ 将 *-flavor* 替换为以下选项之一。
  + 对于没有 GPU 的变体，请移除 *-flavor*。
  + 将 *-nvidia* 用于支持 GPU 的变体。
  + 对启用 FIPS 的变体使用 *-fips*。
+ 将 *architecture* 替换为以下选项之一。
  + 将 *x86\$164* 用于基于 `x86` 的实例。
  + 将 *arm64* 用于 ARM 实例。
+ 将 *region-code* 替换为您需要 AMI ID 的 [Amazon EKS 支持的 AWS 区域](https://docs.aws.amazon.com/general/latest/gr/eks.html)。

```
aws ssm get-parameter --name /aws/service/bottlerocket/aws-k8s-kubernetes-version-flavor/architecture/latest/image_id \
    --region region-code --query "Parameter.Value" --output text
```

以下是替换占位符后的命令示例。

```
aws ssm get-parameter --name /aws/service/bottlerocket/aws-k8s-1.31/x86_64/latest/image_id \
    --region us-west-2 --query "Parameter.Value" --output text
```

示例输出如下。

```
ami-1234567890abcdef0
```

# 使用 Bottlerocket 满足合规性要求
<a name="bottlerocket-compliance-support"></a>

Bottlerocket 符合多个组织制定的建议：
+ 相关人士定义了适用于 Bottlerocket 的 [CIS 基准](https://www.cisecurity.org/benchmark/bottlerocket)。在默认配置中，Bottlerocket 映像具有 CIS 1 级配置配置文件所要求的大部分控件。您可以实现 CIS 2 级配置配置文件所要求的控制。有关更多信息，请参阅 AWS 博客上的[根据 CIS 基准验证 Amazon EKS 优化版 Bottlerocket AMI](https://aws.amazon.com/blogs/containers/validating-amazon-eks-optimized-bottlerocket-ami-against-the-cis-benchmark)。
+ 经优化的功能集和更小的攻击面意味着 Bottlerocket 实例只需更少的配置便可满足 PCI DSS 要求。[适用于 Bottlerocket 的 CIS 基准](https://www.cisecurity.org/benchmark/bottlerocket)是固化指南的理想资源，可支持您达到要求，实现符合 PCI DSS 要求 2.2 规定的安全配置标准。您还可以利用 [Fluent Bit](https://opensearch.org/blog/technical-post/2022/07/bottlerocket-k8s-fluent-bit/) 来支持您满足要求，实现符合 PCI DSS 要求 10.2 规定的操作系统级别审核日志记录。AWS 会定期发布新的（经修补的）Bottlerocket 实例，帮助您满足 PCI DSS 要求 6.2（适用于 v3.2.1）和要求 6.3.3（适用于 v4.0）。
+ Bottlerocket 是一项符合 HIPAA 要求的功能，已获授权用于 Amazon EC2 和 Amazon EKS 的受监管工作负载。有关更多信息，请参阅[符合 HIPAA 要求的服务参考](https://aws.amazon.com/compliance/hipaa-eligible-services-reference/)。
+ 预配置为使用经过 FIPS 140-3 验证的加密模块的 Bottlerocket AMI 已可供使用。这包括 Amazon Linux 2023 内核加密 API 加密模块和 AWS-LC 加密模块。有关更多信息，请参阅 [使用 Bottlerocket FIPS AMI 让 Worker 节点进入 FIPS 就绪状态](bottlerocket-fips-amis.md)。

# 使用 Bottlerocket FIPS AMI 让 Worker 节点进入 FIPS 就绪状态
<a name="bottlerocket-fips-amis"></a>

“联邦信息处理标准（FIPS）第 140-3 号出版物”是美国和加拿大的一项政府标准，其中规定了对保护敏感信息的加密模块的安全要求。Bottlerocket 提供具有 FIPS 内核的 AMI，以便更容易地符合 FIPS 标准。

这些 AMI 已预配置为使用经过 FIPS 140-3 验证的加密模块。这包括 Amazon Linux 2023 内核加密 API 加密模块和 AWS-LC 加密模块。

使用 Bottlerocket FIPS AMI 可使 Worker 节点进入“FIPS 就绪”状态，但不会自动使其“符合 FIPS 标准”。有关更多信息，请参阅[美国联邦信息处理标准（FIPS）140-3](https://aws.amazon.com/compliance/fips/)。

## 注意事项
<a name="_considerations"></a>
+ 如果集群使用隔离子网，可能无法访问 Amazon ECR FIPS 端点。这可能会导致节点引导失败。确保网络配置允许访问必要的 FIPS 端点。有关更多信息，请参阅《AWS PrivateLink 指南**》中的[通过资源 VPC 端点访问资源](https://docs.aws.amazon.com/vpc/latest/privatelink/use-resource-endpoint.html)。
+ 如果集群使用带有 [PrivateLink](vpc-interface-endpoints.md) 的子网，则映像提取将失败，因为 Amazon ECR FIPS 端点无法通过 PrivateLink 进行访问。

## 使用 Bottlerocket FIPS AMI 创建托管式节点组
<a name="_create_a_managed_node_group_with_a_bottlerocket_fips_ami"></a>

Bottlerocket FIPS AMI 提供四种支持工作负载的变体：
+  `BOTTLEROCKET_x86_64_FIPS` 
+  `BOTTLEROCKET_ARM_64_FIPS` 
+  `BOTTLEROCKET_x86_64_NVIDIA_FIPS` 
+  `BOTTLEROCKET_ARM_64_NVIDIA_FIPS` 

要使用 Bottlerocket FIPS AMI 创建托管式节点组，请在创建过程中选择适用的 AMI 类型。有关更多信息，请参阅 [为集群创建托管式节点组](create-managed-node-group.md)。

有关选择启用 FIPS 的变体的更多信息，请参阅[检索建议的 Bottlerocket AMI ID](retrieve-ami-id-bottlerocket.md)。

## 为不受支持的 AWS 区域禁用 FIPS 端点
<a name="disable_the_fips_endpoint_for_non_supported_shared_aws_regions"></a>

美国，包括 AWS GovCloud（美国）区域，直接支持 Bottlerocket FIPS AMI。对于提供 AMI 但不直接支持的 AWS 区域，仍可通过启动模板创建托管式节点组来使用 AMI。

Bottlerocket FIPS AMI 在引导期间依赖于 Amazon ECR FIPS 端点，而该端点通常在美国以外地区不可用。要在不支持 Amazon ECR FIPS 端点的 AWS 区域中使用 AMI 作为其 FIPS 内核，请执行以下步骤以禁用 FIPS 端点：

1. 创建包含以下内容的新配置文件，或将内容合并到现有的配置文件中。

```
[default]
use_fips_endpoint=false
```

1. 将文件内容以 Base64 格式编码。

1. 在启动模板的 `UserData` 中，使用 TOML 格式添加以下编码字符串：

```
[settings.aws]
config = "<your-base64-encoded-string>"
```

有关其他设置，请参阅 GitHub 上的 Bottlerocket [Description of settings](https://github.com/bottlerocket-os/bottlerocket?tab=readme-ov-file#description-of-settings)。

以下是启动模板中 `UserData` 的示例：

```
[settings]
motd = "Hello from eksctl!"
[settings.aws]
config = "W2RlZmF1bHRdCnVzZV9maXBzX2VuZHBvaW50PWZhbHNlCg==" # Base64-encoded string.
[settings.kubernetes]
api-server = "<api-server-endpoint>"
cluster-certificate = "<cluster-certificate-authority>"
cluster-name = "<cluster-name>"
...<other-settings>
```

有关创建包含用户数据的启动模板的更多信息，请参阅[使用启动模板自定义托管式节点](launch-templates.md)。

# 使用优化版 Ubuntu Linux AMI 创建节点
<a name="eks-partner-amis"></a>

Canonical 还与 Amazon EKS 合作创建了可在您的集群中使用的节点 AMI。

 [Canonical](https://www.canonical.com/) 提供专用的 Kubernetes 节点操作系统映像。这是针对 Amazon EKS 优化的最小化 Ubuntu 镜像，包含与AWS联合开发的自定义AWS内核。有关更多信息，请参阅 [Amazon Elastic Kubernetes Service（EKS）上的 Ubuntu](https://cloud-images.ubuntu.com/aws-eks/) 和[创建自主管理型 Ubuntu Linux 节点](launch-node-ubuntu.md)。有关支持的更多信息，请参阅 *AWS Premium Support 常见问题解答*中的[第三方软件](https://aws.amazon.com/premiumsupport/faqs/#Third-party_software)部分。

# 使用优化版 Windows AMI 创建节点
<a name="eks-optimized-windows-ami"></a>

Windows Amazon EKS 优化版 AMI 基于 Windows Server 2019、Windows Server 2022 和 Windows Server 2025 构建。它们被配置作为 Amazon EKS 节点的基本映像。默认情况下，AMI 包括以下组件：
+  [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) 
+  [kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/) 
+  [适用于 Kubernetes 的 AWS IAM 身份验证器](https://github.com/kubernetes-sigs/aws-iam-authenticator) 
+  [csi-proxy](https://github.com/kubernetes-csi/csi-proxy) 
+  [containerd](https://containerd.io/) 

**注意**  
您可以使用 [Microsoft 安全更新指南](https://portal.msrc.microsoft.com/en-us/security-guidance)跟踪 Windows Server 的安全或隐私事件。

Amazon EKS 提供了已针对 Windows 容器进行了优化的 AMI，包括以下变体：
+ Amazon EKS 优化版 Windows Server 2019 Core AMI
+ Amazon EKS 优化版 Windows Server 2019 Full AMI
+ Amazon EKS 优化版 Windows Server 2022 Core AMI
+ Amazon EKS 优化版 Windows Server 2022 Full AMI
+ Amazon EKS 优化版 Windows Server 2025 Core AMI
+ Amazon EKS 优化版 Windows Server 2025 Full AMI

**重要**  
Amazon EKS 优化版 Windows Server 20H2 Core AMI 已弃用。不会发布此 AMI 的任何新版本。
为了确保您在默认情况下安装了最新的安全更新，Amazon EKS 将维持最近 4 个月的优化版 Windows AMI。自首次发布之日起，每个新 AMI 的可用期为 4 个月。在此期限之后，较旧的 AMI 将变为私有且不能再访问。我们鼓励使用最新的 AMI，以避免出现安全漏洞，避免无法访问已达到其支持生命周期尽头的旧 AMI。虽然我们不能保证可以提供对已设为私有的 AMI 的访问权限，但您可以通过向 AWS Support 提交服务单来请求访问权限。

## 发布日历
<a name="windows-ami-release-calendar"></a>

下表列出了 Amazon EKS 上的 Windows 版本的发布日期和支持终止日期。如果终止日期为空，则是因为相应版本仍受支持。


| Windows 版本 | Amazon EKS 版本 | Amazon EKS 支持终止 | 
| --- | --- | --- | 
|  Windows Server 2025 Core  |  01/27/2026  |  | 
|  Windows Server 2025 Full  |  01/27/2026  |  | 
|  Windows Server 2022 Core  |  10/17/2022  |  | 
|  Windows Server 2022 Full  |  10/17/2022  |  | 
|  Windows Server 20H2 Core  |  8/12/2021  |  8/9/2022  | 
|  Windows Server 2004 Core  |  8/19/2020  |  12/14/2021  | 
|  Windows Server 2019 Core  |  10/7/2019  |  | 
|  Windows Server 2019 Full  |  10/7/2019  |  | 
|  Windows Server 1909 Core  |  10/7/2019  |  12/8/2020  | 

## 引导脚本配置参数
<a name="bootstrap-script-configuration-parameters"></a>

创建 Windows 节点时，节点上有一个允许配置不同参数的脚本。根据您的设置，可以在节点上类似于以下位置：`C:\Program Files\Amazon\EKS\Start-EKSBootstrap.ps1` 找到此脚本。您可以通过将自定义参数值指定为引导脚本的参数。例如，您可以更新启动模板中的用户数据。有关更多信息，请参阅 [Amazon EC2 用户数据](launch-templates.md#launch-template-user-data)。

此脚本包含以下命令行参数：
+  `-EKSClusterName`：指定此 Worker 节点要加入的 Amazon EKS 集群名称。
+  `-KubeletExtraArgs`：为 `kubelet` 指定额外的参数（可选）。
+  `-KubeProxyExtraArgs`：为 `kube-proxy` 指定额外的参数（可选）。
+  `-APIServerEndpoint`：指定 Amazon EKS 集群 API 服务器端点（可选）。仅在与 `-Base64ClusterCA` 一起使用时才有效。绕过调用 `Get-EKSCluster`。
+  `-Base64ClusterCA`：指定 base64 编码的集群 CA 内容（可选）。仅在与 `-APIServerEndpoint` 一起使用时才有效。绕过调用 `Get-EKSCluster`。
+  `-DNSClusterIP`：覆盖用于集群内 DNS 查询的 IP 地址（可选）。基于主接口的 IP 地址，默认值为 `10.100.0.10` 或 `172.20.0.10`。
+  `-ServiceCIDR` – 覆盖从中寻址集群服务的 Kubernetes 服务 IP 地址范围。基于主接口的 IP 地址，默认值为 `172.20.0.0/16` 或 `10.100.0.0/16`。
+  `-ExcludedSnatCIDRs` – 要从源网络地址转换（SNAT）中排除的 `IPv4` CIDR 列表。这意味着，VPC 可寻址的容器组（pod）私有 IP 不会转换为用于出站流量的实例 ENI 主 `IPv4` 地址的 IP 地址。默认情况下，系统会添加 Amazon EKS Windows 节点的 VPC 的 `IPv4` CIDR。为该参数指定 CIDR 还会另外排除所指定的 CIDR。有关更多信息，请参阅 [为容器组（pod）启用出站互联网访问权限](external-snat.md)。

除了命令行参数之外，您还可以指定一些环境变量参数。指定命令行参数时，它优先于相应的环境变量。环境变量应定义为机器（或系统）作用范围，因为引导脚本只会读取机器范围的变量。

该脚本考虑以下环境变量：
+  `SERVICE_IPV4_CIDR` — 有关定义，请参阅 `ServiceCIDR` 命令行参数。
+  `EXCLUDED_SNAT_CIDRS` — 应为以逗号分隔的字符串。有关定义，请参阅 `ExcludedSnatCIDRs` 命令行参数。

### gMSA 身份验证支持
<a name="ad-and-gmsa-support"></a>

Amazon EKS Windows 容器组（pod）允许不同类型的组托管服务账户（gMSA）身份验证。
+ Amazon EKS 支持使用 Active Directory 域身份进行身份验证。有关加入域的 gMSA 的更多信息，请参阅 AWS 博客上的 [Windows Authentication on Amazon EKS Windows pods](https://aws.amazon.com/blogs/containers/windows-authentication-on-amazon-eks-windows-pods)。
+ Amazon EKS 提供一个插件，可让未加入域的 Windows 节点使用移动用户标识号检索 gMSA 凭证。有关无域 gMSA 的更多信息，请参阅 AWS 博客上的 [Domainless Windows Authentication for Amazon EKS Windows pods](https://aws.amazon.com/blogs/containers/domainless-windows-authentication-for-amazon-eks-windows-pods)。

## 缓存的容器映像
<a name="windows-cached-container-images"></a>

Amazon EKS Windows 优化版 AMI 缓存了某些容器映像，用于 `containerd` 运行时。使用 Amazon 托管的构建组件构建自定义 AMI 时，系统会缓存容器映像。有关更多信息，请参阅 [使用 Amazon 托管的构建组件](eks-custom-ami-windows.md#custom-windows-ami-build-component)。

以下缓存的容器映像适用于 `containerd` 运行时系统：
+  `amazonaws.com/eks/pause-windows` 
+  `mcr.microsoft.com/windows/nanoserver` 
+  `mcr.microsoft.com/windows/servercore` 

## 更多信息
<a name="windows-more-information"></a>

有关使用 Amazon EKS 优化版 Windows AMI 的更多信息，请参阅以下章节：
+ 有关在 Amazon EKS 优化加速型 Windows AMI 上运行工作负载的详细信息，请参阅[运行 GPU 加速容器（EC2 G 系列上的 Windows）](ml-eks-windows-optimized-ami.md)。
+ 要将 Windows 与托管节点组一起使用，请参阅[使用托管式节点组简化节点生命周期](managed-node-groups.md)。
+ 要启动自主管理型 Windows 节点，请参阅[创建自主管理型 Microsoft Windows 节点](launch-windows-workers.md)。
+ 有关版本信息，请参阅 [检索 Windows AMI 版本信息](eks-ami-versions-windows.md)。
+ 要检索 Amazon EKS 优化版 Windows AMI 的最新 ID，请参阅[检索建议的 Microsoft Windows AMI ID](retrieve-windows-ami-id.md)。
+ 要使用 Amazon EC2 Image Builder 创建自定义 Amazon EKS 优化版 Windows AMI，请参阅[使用 Image Builder 构建自定义 Windows AMI](eks-custom-ami-windows.md)。
+ 有关最佳实践，请参阅 *EKS 最佳实践指南*中的[Amazon EKS 优化版 Windows AMI 管理](https://aws.github.io/aws-eks-best-practices/windows/docs/ami/)。

# 使用 `eksctl` 创建自主管理型 Windows Server 2022 节点
<a name="self-managed-windows-server-2022"></a>

您可以将以下 `test-windows-2022.yaml` 用作参考，创建自主管理型 Windows Server 2022 节点。将所有 *example value* 替换为您自己的值。

**注意**  
您必须使用 `eksctl` 版本 [0.116.0](https://github.com/weaveworks/eksctl/releases/tag/v0.116.0) 或更高版本来运行自主管理型 Windows Server 2022 节点。

```
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: windows-2022-cluster
  region: region-code
  version: '1.35'

nodeGroups:
  - name: windows-ng
    instanceType: m5.2xlarge
    amiFamily: WindowsServer2022FullContainer
    volumeSize: 100
    minSize: 2
    maxSize: 3
  - name: linux-ng
    amiFamily: AmazonLinux2
    minSize: 2
    maxSize: 3
```

然后，可以使用以下命令创建节点组。

```
eksctl create cluster -f test-windows-2022.yaml
```

# 检索 Windows AMI 版本信息
<a name="eks-ami-versions-windows"></a>

本主题列出了 Amazon EKS 优化版 Windows AMI 的版本及其 [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)、[containerd](https://containerd.io/) 和 [csi-proxy](https://github.com/kubernetes-csi/csi-proxy) 的相应版本。

每个变体的 Amazon EKS 优化版 AMI 元数据（包括 AMI ID）均可通过编程方式检索。有关更多信息，请参阅 [检索建议的 Microsoft Windows AMI ID](retrieve-windows-ami-id.md)。

AMI 按 Kubernetes 版本和 AMI 的发布日期进行版本控制，格式如下：

```
k8s_major_version.k8s_minor_version-release_date
```

**注意**  
Amazon EKS 托管节点组支持 2022 年 11 月及更高版本的 Windows AMI。

要接收此特定文档页面的所有源文件更改通知，您可以通过 RSS 阅读器订阅以下 URL：

```
https://github.com/awsdocs/amazon-eks-user-guide/commits/mainline/latest/ug/nodes/eks-ami-versions-windows.adoc.atom
```

## Amazon EKS 优化版 Windows Server 2025 Core AMI
<a name="eks-ami-versions-windows-2025-core"></a>

以下各表列出了 Amazon EKS 优化版 Windows Server 2025 Core AMI 的当前版本和先前版本。

**Example**  


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.35-2026.02.16`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.35-2026-01-22`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 

## Amazon EKS 优化版 Windows Server 2025 Full AMI
<a name="eks-ami-versions-windows-2025-full"></a>

以下各表列出了 Amazon EKS 优化版 Windows Server 2025 Full AMI 的当前版本和先前版本。

**Example**  


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.35-2026.02.16`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.35-2026-01-22`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 

## Amazon EKS 优化版 Windows Server 2022 Core AMI
<a name="eks-ami-versions-windows-2022-core"></a>

以下各表列出了 Amazon EKS 优化版 Windows Server 2022 Core AMI 的当前版本和先前版本。

**Example**  


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.35-2026.02.16`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.35-2026-01-22`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.34-2026.02.13`   |   `1.34.3`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.34-2026.01.22`   |   `1.34.2`   |   `2.1.6`   |   `1.2.1`   |  已将 `containerd` 升级到 `2.1.6`。  | 
|   `1.34-2025.12.15`   |   `1.34.2`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.11.14`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.10.18`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.09.13`   |   `1.34.0`   |   `2.1.4`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.33-2026.02.13`   |   `1.33.7`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.33-2026.01.22`   |   `1.33.5`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.33-2025.12.15`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.11.14`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.10.18`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.09.13`   |   `1.33.4`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.33-2025.08.18`   |   `1.33.3`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.07.16`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.06.13`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.05.17`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.32-2026.02.13`   |   `1.32.11`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.32-2026.01.22`   |   `1.32.9`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.32-2025.12.15`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.11.14`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.10.18`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.09.13`   |   `1.32.8`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.32-2025.08.18`   |   `1.32.7`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.07.16`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.06.13`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.32-2025.05.17`   |   `1.32.5`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.32-2025.04.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.03.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.02.18`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.01.15`   |   `1.32.0`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.31-2026.02.13`   |   `1.31.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.31-2026.01.22`   |   `1.31.13`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.31-2025.12.15`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.11.14`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.10.18`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.09.13`   |   `1.31.12`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.31-2025.08.18`   |   `1.31.11`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.07.16`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.06.13`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.31-2025.05.17`   |   `1.31.9`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.31-2025.04.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.03.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.02.15`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.15`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.01`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.31-2024.12.13`   |   `1.31.3`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.11.12`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.08`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.01`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.09.10`   |   `1.31.0`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.30-2026.02.13`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.30-2026.01.22`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.30-2025.12.15`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.11.21`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.10.18`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.09.13`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.30-2025.08.18`   |   `1.30.14`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.07.16`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.06.13`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.30-2025.05.17`   |   `1.30.13`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.30-2025.04.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.30-2025.03.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.30-2025.02.15`   |   `1.30.9`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.15`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.01`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.30-2024.12.11`   |   `1.30.7`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.11.12`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.10.08`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.09.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.08.13`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.07.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.30-2024.06.17`   |   `1.30.0`   |   `1.7.14`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.14`。  | 
|   `1.30-2024.05.15`   |   `1.30.0`   |   `1.6.28`   |   `1.1.2`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.29-2026.02.13`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.29-2026.01.22`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.29-2025.12.15`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.11.14`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.10.18`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.09.13`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.29-2025.08.18`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.07.16`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.06.13`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.29-2025.05.17`   |   `1.29.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.29-2025.04.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.29-2025.03.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.29-2025.02.15`   |   `1.29.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.15`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.01`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.29-2024.12.11`   |   `1.29.10`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.11.12`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.10.08`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.09.10`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.08.13`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.07.10`   |   `1.29.6`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.29-2024.06.17`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  | 
|   `1.29-2024.05.15`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。已将 `kubelet` 升级到 `1.29.3`。  | 
|   `1.29-2024.04.09`   |   `1.29.0`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.29-2024.03.12`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.13`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.06`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  修复了以下错误：`kubelet` 垃圾回收进程错误删除了暂停映像。  | 
|   `1.29-2024.01.11`   |   `1.29.0`   |   `1.6.18`   |   `1.1.2`   |  不包括 Windows Server 2022 Core AMI 上的独立 Windows 更新 [KB5034439](https://support.microsoft.com/en-au/topic/kb5034439-windows-recovery-environment-update-for-azure-stack-hci-version-22h2-and-windows-server-2022-january-9-2024-6f9d26e6-784c-4503-a3c6-0beedda443ca)。知识库仅适用于具有单独 WinRE 分区的 Windows 安装，不包含在我们的任何 Amazon EKS 优化版 Windows AMI 中。  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.28-2025.11.14`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.10.18`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.09.13`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.28-2025.08.18`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.07.16`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.06.13`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.28-2025.05.17`   |   `1.28.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.28-2025.04.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.28-2025.03.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.28-2025.02.15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025.01.15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025-01-01`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.28-2024.12.11`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.11.12`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.10.08`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.09.10`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.08.13`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.07.10`   |   `1.28.11`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.28-2024.06.17`   |   `1.28.8`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。  | 
|   `1.28-2024.05.14`   |   `1.28.8`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已将 `kubelet` 升级到 `1.28.8`。  | 
|   `1.28-2024.04.09`   |   `1.28.5`   |   `1.6.25`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.25`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.28-2024.03.12`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.02.13`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.01.11`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  不包括 Windows Server 2022 Core AMI 上的独立 Windows 更新 [KB5034439](https://support.microsoft.com/en-au/topic/kb5034439-windows-recovery-environment-update-for-azure-stack-hci-version-22h2-and-windows-server-2022-january-9-2024-6f9d26e6-784c-4503-a3c6-0beedda443ca)。知识库仅适用于具有单独 WinRE 分区的 Windows 安装，不包含在我们的任何 Amazon EKS 优化版 Windows AMI 中。  | 
|   `1.28-2023.12.12`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2023.11.14`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  包括 `CVE-2023-5528` 的补丁。  | 
|   `1.28-2023.10.19`   |   `1.28.2`   |   `1.6.18`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.18`。添加了新的[引导脚本环境变量](eks-optimized-windows-ami.md#bootstrap-script-configuration-parameters)（`SERVICE_IPV4_CIDR` 和 `EXCLUDED_SNAT_CIDRS`）。  | 
|   `1.28-2023-09.27`   |   `1.28.2`   |   `1.6.6`   |   `1.1.2`   |  修复了 `kubelet` 中的[安全通告](https://github.com/advisories/GHSA-6xv5-86q9-7xr8)。  | 
|   `1.28-2023.09.12`   |   `1.28.1`   |   `1.6.6`   |   `1.1.2`   |  | 

## Amazon EKS 优化版 Windows Server 2022 Full AMI
<a name="eks-ami-versions-windows-2022-full"></a>

以下各表列出了 Amazon EKS 优化版 Windows Server 2022 Full AMI 的当前版本和先前版本。

**Example**  


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.35-2026.02.16`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.35-2026-01-22`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.34-2026.02.13`   |   `1.34.3`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.34-2026.01.22`   |   `1.34.2`   |   `2.1.6`   |   `1.2.1`   |  已将 `containerd` 升级到 `2.1.6`。  | 
|   `1.34-2025.12.15`   |   `1.34.2`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.11.14`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.10.18`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.09.13`   |   `1.34.0`   |   `2.1.4`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.33-2026.02.13`   |   `1.33.7`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.33-2026.01.22`   |   `1.33.5`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.33-2025.12.15`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.11.14`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.10.18`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.09.13`   |   `1.33.4`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.33-2025.08.18`   |   `1.33.3`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.07.16`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.06.13`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.05.17`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.32-2026.02.13`   |   `1.32.11`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.32-2026.01.22`   |   `1.32.9`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.32-2025.12.15`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.11.14`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.10.18`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.09.13`   |   `1.32.8`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.32-2025.08.18`   |   `1.32.7`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.07.16`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.06.13`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  已将 `containrd` 升级到 `1.7.27`   | 
|   `1.32-2025.05.17`   |   `1.32.5`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.32-2025.04.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.03.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.02.18`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.01.01`   |   `1.32.0`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.31-2026.02.13`   |   `1.31.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.31-2026.01.22`   |   `1.31.13`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.31-2025.12.15`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.11.14`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.10.18`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.09.13`   |   `1.31.12`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.31-2025.08.18`   |   `1.31.11`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.07.16`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.06.13`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.31-2025.05.17`   |   `1.31.9`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.31-2025.04.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.03.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.02.15`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.15`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.01`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.31-2024.12.13`   |   `1.31.3`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.11.12`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.08`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.01`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.09.10`   |   `1.31.0`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.30-2026.02.13`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.30-2026.01.22`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.30-2025.12.15`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.11.21`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.10.18`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.09.13`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.30-2025.08.18`   |   `1.30.14`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.07.16`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.06.13`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.30-2025.05.17`   |   `1.30.13`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.30-2025.04.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.30-2025.03.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  已将 `contianerd` 升级到 `1.7.20`。  | 
|   `1.30-2025.02.15`   |   `1.30.9`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.15`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.01`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.30-2024.12.11`   |   `1.30.7`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.11.12`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.10.08`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.09.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.08.13`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.07.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.30-2024.06.17`   |   `1.30.0`   |   `1.7.14`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.14`。  | 
|   `1.30-2024.05.15`   |   `1.30.0`   |   `1.6.28`   |   `1.1.2`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.29-2026.02.13`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.29-2026.01.22`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.29-2025.12.15`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.11.14`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.10.18`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.09.13`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.29-2025.08.18`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.07.16`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.06.13`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.29-2025.05.17`   |   `1.29.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.29-2025.04.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.29-2025.03.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.29-2025.02.15`   |   `1.29.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.15`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.01`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.29-2024.12.11`   |   `1.29.10`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.11.12`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.10.08`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.09.10`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.08.13`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.07.10`   |   `1.29.6`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.29-2024.06.17`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  | 
|   `1.29-2024.05.15`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。已将 `kubelet` 升级到 `1.29.3`。  | 
|   `1.29-2024.04.09`   |   `1.29.0`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.29-2024.03.12`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.13`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.06`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  修复了以下错误：`kubelet` 垃圾回收进程错误删除了暂停映像。  | 
|   `1.29-2024.01.09`   |   `1.29.0`   |   `1.6.18`   |   `1.1.2`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.28-2025.11.14`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.10.18`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.09.13`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.28-2025.08.18`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.07.16`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.06.13`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.28-2025.05.17`   |   `1.28.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.28-2025.04.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.28-2025.03.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.28-2025.02.15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025.01.15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025.01.01`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.28-2024.12.11`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.11.12`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.10.08`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.09.10`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.08.13`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.07.10`   |   `1.28.11`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.28-2024.06.17`   |   `1.28.8`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。  | 
|   `1.28-2024.05.14`   |   `1.28.8`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已将 `kubelet` 升级到 `1.28.8`。  | 
|   `1.28-2024.04.09`   |   `1.28.5`   |   `1.6.25`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.25`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.28-2024.03.12`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.02.13`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.01.09`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2023.12.12`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2023.11.14`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  包括 `CVE-2023-5528` 的补丁。  | 
|   `1.28-2023.10.19`   |   `1.28.2`   |   `1.6.18`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.18`。添加了新的[引导脚本环境变量](eks-optimized-windows-ami.md#bootstrap-script-configuration-parameters)（`SERVICE_IPV4_CIDR` 和 `EXCLUDED_SNAT_CIDRS`）。  | 
|   `1.28-2023-09.27`   |   `1.28.2`   |   `1.6.6`   |   `1.1.2`   |  修复了 `kubelet` 中的[安全通告](https://github.com/advisories/GHSA-6xv5-86q9-7xr8)。  | 
|   `1.28-2023.09.12`   |   `1.28.1`   |   `1.6.6`   |   `1.1.2`   |  | 

## Amazon EKS 优化版 Windows Server 2019 Core AMI
<a name="eks-ami-versions-windows-2019-core"></a>

以下各表列出了 Amazon EKS 优化版 Windows Server 2019 Core AMI 的当前版本和先前版本。

**Example**  


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.35-2026.02.16`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.35-2026-01-22`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.34-2026.02.13`   |   `1.34.3`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.34-2026.01.22`   |   `1.34.2`   |   `2.1.6`   |   `1.2.1`   |  已将 `containerd` 升级到 `2.1.6`。  | 
|   `1.34-2025.12.15`   |   `1.34.2`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.11.14`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.10.18`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.09.13`   |   `1.34.0`   |   `2.1.4`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.33-2026.02.13`   |   `1.33.7`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.33-2026.01.22`   |   `1.33.5`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.33-2025.12.15`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.11.14`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.10.18`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.09.13`   |   `1.33.4`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.33-2025.08.18`   |   `1.33.3`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.07.16`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.06.13`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.05.17`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.32-2026.02.13`   |   `1.32.11`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.32-2026.01.22`   |   `1.32.9`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.32-2025.12.15`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.11.14`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.10.18`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.09.13`   |   `1.32.8`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.32-2025.08.18`   |   `1.32.7`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.07.16`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.06.13`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.32-2025.05.17`   |   `1.32.5`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.32-2025.04.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.03.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.02.18`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.01.15`   |   `1.32.4`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.31-2026.02.13`   |   `1.31.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.31-2026.01.22`   |   `1.31.13`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.31-2025.12.15`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.11.14`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.10.18`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.09.13`   |   `1.31.12`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.31-2025.08.18`   |   `1.31.11`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.07.16`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.06.13`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.31-2025.05.17`   |   `1.31.9`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.31-2025.04.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.03.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.02.15`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.15`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.01`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.31-2024.12.13`   |   `1.31.3`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.11.12`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.08`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.01`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.09.10`   |   `1.31.0`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.30-2026.02.13`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.30-2026.01.22`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.30-2025.12.15`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.11.21`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.10.18`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.09.13`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.30-2025.08.18`   |   `1.30.14`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.07.16`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.06.13`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.30-2025.05.17`   |   `1.30.13`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.30-2025.04.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.30-2025.03.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.30-2025-02-15`   |   `1.30.9`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.15`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.01`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.30-2024.12.11`   |   `1.30.7`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.11.12`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.10.08`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.09.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.08.13`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.07.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.30-2024.06.17`   |   `1.30.0`   |   `1.7.14`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.14`。  | 
|   `1.30-2024.05.15`   |   `1.30.0`   |   `1.6.28`   |   `1.1.2`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.29-2026.02.13`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.29-2026.01.22`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.29-2025.12.15`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.11.14`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.10.18`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.09.13`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.29-2025.08.18`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.07.16`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.06.13`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.29-2025.05.17`   |   `1.29.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.29-2025.04.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.29-2025.03.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.29-2025.02.15`   |   `1.29.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.15`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.01`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.29-2024.12.11`   |   `1.29.10`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.11.12`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.10.08`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.09.10`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.08.13`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.07.10`   |   `1.29.6`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.29-2024.06.17`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  | 
|   `1.29-2024.05.15`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。已将 `kubelet` 升级到 `1.29.3`。  | 
|   `1.29-2024.04.09`   |   `1.29.0`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.29-2024.03.13`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.13`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.06`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  修复了以下错误：`kubelet` 垃圾回收进程错误删除了暂停映像。  | 
|   `1.29-2024.01.09`   |   `1.29.0`   |   `1.6.18`   |   `1.1.2`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.28-2025.11.14`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.10.18`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.09.13`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.28-2025.08.18`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.07.16`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.06.13`   |   `1.28.15`   |   `1.7.20`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.28-2025.05.17`   |   `1.28.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.28-2025.04.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.28-2025.03.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.28-2025.02.15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025-01-15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025-01-01`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.28-2024.12.11`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.11.12`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.10.08`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.09.10`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.08.13`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.07.10`   |   `1.28.11`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.28-2024.06.17`   |   `1.28.8`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。  | 
|   `1.28-2024.05.14`   |   `1.28.8`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已将 `kubelet` 升级到 `1.28.8`。  | 
|   `1.28-2024.04.09`   |   `1.28.5`   |   `1.6.25`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.25`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.28-2024.03.13`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.02.13`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.01.09`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2023.12.12`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2023.11.14`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  包括 `CVE-2023-5528` 的补丁。  | 
|   `1.28-2023.10.19`   |   `1.28.2`   |   `1.6.18`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.18`。添加了新的[引导脚本环境变量](eks-optimized-windows-ami.md#bootstrap-script-configuration-parameters)（`SERVICE_IPV4_CIDR` 和 `EXCLUDED_SNAT_CIDRS`）。  | 
|   `1.28-2023-09.27`   |   `1.28.2`   |   `1.6.6`   |   `1.1.2`   |  修复了 `kubelet` 中的[安全通告](https://github.com/advisories/GHSA-6xv5-86q9-7xr8)。  | 
|   `1.28-2023.09.12`   |   `1.28.1`   |   `1.6.6`   |   `1.1.2`   |  | 

## Amazon EKS 优化版 Windows Server 2019 Full AMI
<a name="eks-ami-versions-windows-2019-full"></a>

以下各表列出了 Amazon EKS 优化版 Windows Server 2019 Full AMI 的当前版本和先前版本。

**Example**  


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.35-2026.02.16`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.35-2026-01-22`   |   `1.35.0`   |   `2.1.6`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.34-2026.02.13`   |   `1.34.3`   |   `2.1.6`   |   `1.2.1`   |  | 
|   `1.34-2026.01.22`   |   `1.34.2`   |   `2.1.6`   |   `1.2.1`   |  已将 `containerd` 升级到 `2.1.6`。  | 
|   `1.34-2025.12.15`   |   `1.34.2`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.11.14`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.10.18`   |   `1.34.1`   |   `2.1.4`   |   `1.2.1`   |  | 
|   `1.34-2025.09.13`   |   `1.34.0`   |   `2.1.4`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.33-2026.02.13`   |   `1.33.7`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.33-2026.01.22`   |   `1.33.5`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.33-2025.12.15`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.11.14`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.10.18`   |   `1.33.5`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.33-2025.09.13`   |   `1.33.4`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.33-2025.08.18`   |   `1.33.3`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.07.16`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.06.13`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.33-2025.05.17`   |   `1.33.1`   |   `1.7.27`   |   `1.2.1`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.32-2026.02.13`   |   `1.32.11`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.32-2026.01.22`   |   `1.32.9`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.32-2025.12.15`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.11.14`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.10.18`   |   `1.32.9`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.32-2025.09.13`   |   `1.32.8`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.32-2025.08.18`   |   `1.32.7`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.07.16`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.32-2025.06.13`   |   `1.32.5`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.32-2025.05.17`   |   `1.32.5`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.32-2025.04.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.03.14`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.02.18`   |   `1.32.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.32-2025.01.15`   |   `1.32.0`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.31-2026.02.13`   |   `1.31.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.31-2026.01.22`   |   `1.31.13`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.31-2025.12.15`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.11.14`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.10.18`   |   `1.31.13`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.31-2025.09.13`   |   `1.31.12`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.31-2025.08.18`   |   `1.31.11`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.07.16`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.31-2025.06.13`   |   `1.31.9`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.31-2025.05.17`   |   `1.31.9`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.31-2025.04.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.03.14`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.02.15`   |   `1.31.5`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.15`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2025.01.01`   |   `1.31.4`   |   `1.7.20`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.31-2024.12.13`   |   `1.31.3`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.11.12`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.08`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.10.01`   |   `1.31.1`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.31-2024.09.10`   |   `1.31.0`   |   `1.7.20`   |   `1.1.3`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.30-2026.02.13`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.30-2026.01.22`   |   `1.30.14`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.30-2025.12.15`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.11.21`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.10.18`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.30-2025.09.13`   |   `1.30.14`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.30-2025.08.18`   |   `1.30.14`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.07.16`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.30-2025.06.13`   |   `1.30.13`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.30-2025.05.17`   |   `1.30.13`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.30-2025.04.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.30-2025.03.14`   |   `1.30.9`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.30-2025.02.15`   |   `1.30.9`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.15`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2025.01.01`   |   `1.30.8`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.30-2024.12.11`   |   `1.30.7`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.11.12`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.10.08`   |   `1.30.4`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.09.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.08.13`   |   `1.30.2`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.30-2024.07.10`   |   `1.30.2`   |   `1.7.14`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.30-2024.06.17`   |   `1.30.0`   |   `1.7.14`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.14`。  | 
|   `1.30-2024.05.15`   |   `1.30.0`   |   `1.6.28`   |   `1.1.2`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.29-2026.02.13`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  | 
|   `1.29-2026.01.22`   |   `1.29.15`   |   `1.7.30`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.30`。  | 
|   `1.29-2025.12.15`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.11.14`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.10.18`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.29-2025.09.13`   |   `1.29.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.29-2025.08.18`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.07.16`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.29-2025.06.13`   |   `1.29.15`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.29-2025.05.17`   |   `1.29.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.29-2025.04.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.29-2025.03.14`   |   `1.29.13`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.29-2025.02.15`   |   `1.29.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.15`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2025.01.01`   |   `1.29.12`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.29-2024.12.11`   |   `1.29.10`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.11.12`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.10.08`   |   `1.29.8`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.09.10`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.08.13`   |   `1.29.6`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.29-2024.07.10`   |   `1.29.6`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.29-2024.06.17`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  | 
|   `1.29-2024.05.15`   |   `1.29.3`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。已将 `kubelet` 升级到 `1.29.3`。  | 
|   `1.29-2024.04.09`   |   `1.29.0`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.29-2024.03.13`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.13`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  | 
|   `1.29-2024.02.06`   |   `1.29.0`   |   `1.6.25`   |   `1.1.2`   |  修复了以下错误：`kubelet` 垃圾回收进程错误删除了暂停映像。  | 
|   `1.29-2024.01.09`   |   `1.29.0`   |   `1.6.18`   |   `1.1.2`   |  | 


| AMI 版本 | kubelet 版本 | containerd 版本 | csi-proxy 版本 | 发行说明 | 
| --- | --- | --- | --- | --- | 
|   `1.28-2025.11.14`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.10.18`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  | 
|   `1.28-2025.09.13`   |   `1.28.15`   |   `1.7.28`   |   `1.2.1`   |  将 GMSA 插件日志变更为 Windows 事件  | 
|   `1.28-2025.08.18`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.07.16`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  | 
|   `1.28-2025.06.13`   |   `1.28.15`   |   `1.7.27`   |   `1.2.1`   |  已将 `containerd` 升级到 `1.7.27`。  | 
|   `1.28-2025.05.17`   |   `1.28.15`   |   `1.7.20`   |   `1.2.1`   |  | 
|   `1.28-2025.04.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  | 
|   `1.28-2025.03.14`   |   `1.28.15`   |   `1.7.20`   |   `1.1.3`   |  已将 `containerd` 升级到 `1.7.20`。  | 
|   `1.28-2025.02.15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025-01-15`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2025-01-01`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  包括 `CVE-2024-9042` 的补丁。  | 
|   `1.28-2024.12.11`   |   `1.28.15`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.11.12`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.10.08`   |   `1.28.13`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.09.10`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.08.13`   |   `1.28.11`   |   `1.7.14`   |   `1.1.3`   |  | 
|   `1.28-2024.07.10`   |   `1.28.11`   |   `1.7.11`   |   `1.1.2`   |  包括 `CVE-2024-5321` 的补丁。  | 
|   `1.28-2024.06.17`   |   `1.28.8`   |   `1.7.11`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.7.11`。  | 
|   `1.28-2024.05.14`   |   `1.28.8`   |   `1.6.28`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.28`。已将 `kubelet` 升级到 `1.28.8`。  | 
|   `1.28-2024.04.09`   |   `1.28.5`   |   `1.6.25`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.25`。已使用 `golang 1.22.1` 重建 CNI 和 `csi-proxy`。  | 
|   `1.28-2024.03.13`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.02.13`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2024.01.09`   |   `1.28.5`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2023.12.12`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  | 
|   `1.28-2023.11.14`   |   `1.28.3`   |   `1.6.18`   |   `1.1.2`   |  包括 `CVE-2023-5528` 的补丁。  | 
|   `1.28-2023.10.19`   |   `1.28.2`   |   `1.6.18`   |   `1.1.2`   |  已将 `containerd` 升级到 `1.6.18`。添加了新的[引导脚本环境变量](eks-optimized-windows-ami.md#bootstrap-script-configuration-parameters)（`SERVICE_IPV4_CIDR` 和 `EXCLUDED_SNAT_CIDRS`）。  | 
|   `1.28-2023-09.27`   |   `1.28.2`   |   `1.6.6`   |   `1.1.2`   |  修复了 `kubelet` 中的[安全通告](https://github.com/advisories/GHSA-6xv5-86q9-7xr8)。  | 
|   `1.28-2023.09.12`   |   `1.28.1`   |   `1.6.6`   |   `1.1.2`   |  | 

# 检索建议的 Microsoft Windows AMI ID
<a name="retrieve-windows-ami-id"></a>

部署节点时，您可以为预先构建的 Amazon EKS 优化版亚马逊机器映像（AMI）指定 ID。要检索符合所需配置的 AMI ID，请查询 AWS Systems Manager Parameter Store API。使用此 API，您无需手动查找 Amazon EKS 优化版 AMI ID。有关更多信息，请参阅 [GetParameter](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html)。您使用的 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html#iam-term-principal)必须具有 `ssm:GetParameter` IAM 权限才能检索 Amazon EKS 优化版 AMI 元数据。

您可以使用以下命令检索最新推荐 Amazon EKS 优化版 Windows AMI 的映像 ID，该命令使用子参数 `image_id`。根据需要对该命令进行以下修改，然后运行修改后的命令：
+ 将 *release* 替换为以下选项之一。
  + 将 *2025* 用于 Windows Server 2025。
  + 将 *2022* 用于 Windows Server 2022。
  + 将 *2019* 用于 Windows Server 2019。
+ 将 *installation-option* 替换为以下选项之一。有关更多信息，请参阅 [Windows Server 中服务器核心安装选项简介](https://learn.microsoft.com/en-us/windows-server/administration/server-core/what-is-server-core)。
  + 将 *Core* 用于攻击面更小的最低限度安装。
  + 使用 *Full* 包含 Windows 桌面体验。
+ 将 *kubernetes-version* 替换为支持的 [platform-version](https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html)。
+ 将 *region-code* 替换为您需要 AMI ID 的 [Amazon EKS 支持的 AWS 区域](https://docs.aws.amazon.com/general/latest/gr/eks.html)。

```
aws ssm get-parameter --name /aws/service/ami-windows-latest/Windows_Server-release-English-installation-option-EKS_Optimized-kubernetes-version/image_id \
    --region region-code --query "Parameter.Value" --output text
```

以下是替换占位符后的命令示例。

```
aws ssm get-parameter --name /aws/service/ami-windows-latest/Windows_Server-2022-English-Core-EKS_Optimized-k8s-n-2/image_id \
    --region us-west-2 --query "Parameter.Value" --output text
```

示例输出如下。

```
ami-1234567890abcdef0
```

# 使用 Image Builder 构建自定义 Windows AMI
<a name="eks-custom-ami-windows"></a>

您可以通过以下任一方式，使用 EC2 Image Builder 创建自定义 Amazon EKS 优化版 Windows AMI：
+  [使用 Amazon EKS 优化版 Windows AMI 作为基础](#custom-windows-ami-as-base) 
+  [使用 Amazon 托管的构建组件](#custom-windows-ami-build-component) 

无论采用哪种方式，您必须创建自己的 Image Builder 配方。有关更多信息，请参阅《Image Builder 用户指南》中的[创建映像配方的新版本](https://docs.aws.amazon.com/imagebuilder/latest/userguide/create-image-recipes.html)。

**重要**  
以下 **Amazon 托管的** `eks` 组件包括 `CVE-2024-5321` 的补丁。  
 `1.28.2` 和更高版本
 `1.29.2` 和更高版本
 `1.30.1` 和更高版本
所有 Kubernetes 1.31 及更高版本

## 使用 Amazon EKS 优化版 Windows AMI 作为基础
<a name="custom-windows-ami-as-base"></a>

推荐使用该选项构建自定义 Windows AMI。我们提供的 Amazon EKS 优化版 Windows AMI 比 Amazon 托管的构建组件更新得更频繁。

1. 开启新的 Image Builder 配方。

   1. 打开位于 https://console.aws.amazon.com/imagebuilder 的 EC2 Image Builder 控制台。

   1. 在左侧导航窗格中，选择**映像配方**。

   1. 选择**创建映像配方**。

1. 在**配方详细信息**部分中，输入**名称**和**版本**。

1. 在**基础映像**部分指定 Amazon EKS 优化版 Windows AMI 的 ID。

   1. 选择**输入自定义 AMI ID**。

   1. 检索所需 Windows 操作系统版本的 AMI ID。有关更多信息，请参阅 [检索建议的 Microsoft Windows AMI ID](retrieve-windows-ami-id.md)。

   1. 输入自定义 **AMI ID**。如果找不到 AMI ID，请确保 AMI ID 的 AWS 区域与控制台右上角显示的 AWS 区域相匹配。

1. （可选）要获取最新的安全更新，请在**构建组件 - **部分中添加 `update-windows` 组件。

   1. 在**按名称查找组件**搜索框右侧的下拉列表中，选择 **Amazon 托管**。

   1. 在**按名称查找组件**搜索框中，输入 `update-windows`。

   1. 选中 **`update-windows`** 搜索结果的复选框。此组件包括操作系统的最新 Windows 补丁。

1. 使用所需配置完成剩余的映像配方输入。有关更多信息，请参阅《Image Builder 用户指南》中的[创建新的映像配方版本（控制台）](https://docs.aws.amazon.com/imagebuilder/latest/userguide/create-image-recipes.html#create-image-recipe-version-console)。

1. 选择**创建配方**。

1. 在新的或现有的映像管道中使用新的映像配方。映像管道成功运行后，您的自定义 AMI 将作为输出映像列出并随时可用。有关更多信息，请参阅[使用 EC2 Image Builder 控制台向导创建映像管道](https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html)。

## 使用 Amazon 托管的构建组件
<a name="custom-windows-ami-build-component"></a>

当使用 Amazon EKS 优化版 Windows AMI 作为基本操作系统不可行时，您可以改用 Amazon 托管的构建组件。此选项可能落后于支持的最新 Kubernetes 版本。

1. 开启新的 Image Builder 配方。

   1. 打开位于 https://console.aws.amazon.com/imagebuilder 的 EC2 Image Builder 控制台。

   1. 在左侧导航窗格中，选择**映像配方**。

   1. 选择**创建映像配方**。

1. 在**配方详细信息**部分中，输入**名称**和**版本**。

1. 在**基础映像**部分中确定您将使用哪个选项来创建自定义 AMI：
   +  **选择托管映像** – 为您的**映像操作系统（OS）**选择 **Windows**。然后，为**映像来源**选择以下选项之一。
     +  **快速入门（Amazon 托管）**– 在**映像名称**下拉列表中，选择一个 Amazon EKS 支持的 Windows Server 版本。有关更多信息，请参阅 [使用优化版 Windows AMI 创建节点](eks-optimized-windows-ami.md)。
     +  **我拥有的映像** – 对于**映像名称**，请选择具有自带许可证的自有映像的 ARN。您提供的镜像尚未安装 Amazon EKS 组件。
   +  **输入自定义 AMI ID** – 对于 AMI ID，请输入具有自带许可证的 AMI 的 ID。您提供的镜像尚未安装 Amazon EKS 组件。

1. 在**构建组件 – Windows** 部分中，执行以下操作：

   1. 在**按名称查找组件**搜索框右侧的下拉列表中，选择 **Amazon 托管**。

   1. 在**按名称查找组件**搜索框中，输入 `eks`。

   1. 选中**`eks-optimized-ami-windows`** 搜索结果的复选框，即使返回的结果可能不是您想要的版本。

   1. 在**按名称查找组件**搜索框中，输入 `update-windows`。

   1. 选中 **update-windows** 搜索结果的复选框。此组件包括操作系统的最新 Windows 补丁。

1. 在**选定的组件**部分中，执行以下操作：

   1. 选择 **`eks-optimized-ami-windows`** 的**版本控制选项**。

   1. 选择**指定组件版本**。

   1. 在**组件版本**字段中，输入 *version.x*，将 *version* 替换为支持的 Kubernetes 版本。在版本号部分输入 *x* 表示使用与您明确定义的版本相应部分也相符的最新组件版本。注意控制台输出，因为它会就您所需版本是否作为托管组件提供给出建议。请记住，最新 Kubernetes 版本可能不适用于构建组件。有关可用版本的更多信息，请参阅 [检索有关 `eks-optimized-ami-windows` 组件版本的信息](#custom-windows-ami-component-versions)。

1. 使用所需配置完成剩余的映像配方输入。有关更多信息，请参阅《Image Builder 用户指南》中的[创建新的映像配方版本（控制台）](https://docs.aws.amazon.com/imagebuilder/latest/userguide/create-image-recipes.html#create-image-recipe-version-console)。

1. 选择**创建配方**。

1. 在新的或现有的映像管道中使用新的映像配方。映像管道成功运行后，您的自定义 AMI 将作为输出映像列出并随时可用。有关更多信息，请参阅[使用 EC2 Image Builder 控制台向导创建映像管道](https://docs.aws.amazon.com/imagebuilder/latest/userguide/start-build-image-pipeline.html)。

## 检索有关 `eks-optimized-ami-windows` 组件版本的信息
<a name="custom-windows-ami-component-versions"></a>

您可以检索有关每个组件所安装内容的特定信息。例如，您可以验证安装了哪个 `kubelet` 版本。这些组件在 Amazon EKS 支持的 Windows 操作系统版本上进行功能测试。有关更多信息，请参阅 [发布日历](eks-optimized-windows-ami.md#windows-ami-release-calendar)。未列为受支持或已进入终止支持状态的任何其他 Windows 操作系统版本可能与组件不兼容。

1. 打开位于 https://console.aws.amazon.com/imagebuilder 的 EC2 Image Builder 控制台。

1. 在左侧导航窗格中选择**组件**。

1. 在**按名称查找组件**搜索框右侧的下拉列表中，将**我拥有的**更改为**快速入门（Amazon 托管）**。

1. 在 **Find components by name（按名称查找组件）**框中，输入 `eks`。

1. （可选）如果您使用的是最新版本，请选择两次，按降序对**版本**列进行排序。

1. 选择具有所需版本的 **`eks-optimized-ami-windows`** 链接。

结果页面中的**描述**显示了具体信息。

# 检测节点运行状况问题并启用自动节点修复
<a name="node-health"></a>

节点运行状况是指节点的运行状态以及有效运行工作负载的能力。运行正常的节点可以保持预期的网络连接，拥有充分的计算和存储资源，并能成功运行工作负载而不中断。

为帮助保持 EKS 集群中运行正常的节点，EKS 提供了*节点监控代理*和*节点自动修复*功能。这些功能在 EKS Auto Mode 计算中会自动启用。您也可以将自动节点修复与 EKS 托管节点组和 Karpenter 结合使用，并可以将 EKS 节点监控代理与除 AWS Fargate 之外的任何 EKS 计算类型结合使用。EKS 节点监控代理和自动节点修复功能结合使用效果最佳，但也可以在 EKS 集群中单独使用。

**重要**  
*节点监控代理*和*节点自动修复*功能仅支持 Linux。这些功能不支持 Windows。

## 节点监控代理
<a name="node-monitoring-agent"></a>

Amazon EKS 节点监控代理会读取节点日志以检测运行状况问题。此代理会解析节点日志以检测故障，并显示有关节点运行状况的状态信息。对于检测到的每一类问题，代理都会对工作节点应用专用的 `NodeCondition`Worker 节点。有关 EKS 节点监控代理检测到的节点运行状况问题的详细信息，请参阅 [使用 EKS 节点监控代理检测节点运行状况问题](node-health-nma.md)。

EKS Auto Mode 计算包含节点监控代理。对于其他 EKS 计算类型，您可以将节点监控代理作为 EKS 附加组件添加，或者使用 Kubernetes 工具（如 Helm）进行管理。有关更多信息，请参阅 [配置节点监控代理](node-health-nma.md#node-monitoring-agent-configure)。

使用 EKS 节点监控代理，以下类别的节点运行状况问题会以节点状况的形式呈现。注意、`Ready`、`DiskPressure` 和 `MemoryPressure` 是标准的 Kubernetes 节点状况，即使没有 EKS 节点监控代理也会呈现。


| 节点状况 | 说明 | 
| --- | --- | 
|  AcceleratedHardwareReady  |  AcceleratedHardwareReady 表示节点上的加速硬件（GPU、Neuron）是否正常运行。  | 
|  ContainerRuntimeReady  |  ContainerRuntimeReady 表示容器运行时（containererd 等）是否正常运行并能运行容器。  | 
|  DiskPressure  |  DiskPressure 是一个标准的 Kubernetes 状况，表示节点正在经历磁盘压力（磁盘空间不足或 I/O 过高）。  | 
|  KernelReady  |  KernelReady 表示内核是否运行正常，无严重错误、死锁或资源耗尽问题。  | 
|  MemoryPressure  |  MemoryPressure 是一个标准的 Kubernetes 状况，表示节点正在经历内存压力（可用内存不足）。  | 
|  NetworkingReady  |  NetworkingReady 表示节点的网络堆栈（接口、路由、连接）是否正常运行。  | 
|  StorageReady  |  StorageReady 表示节点的存储子系统（磁盘、文件系统、I/O）是否正常运行。  | 
|  Ready  |  Ready 是标准的 Kubernetes 状况，表示节点运行正常并已准备好接收容器组（pod）。  | 

## 自动节点修复
<a name="node-auto-repair"></a>

EKS 自动节点修复会持续监控节点运行状况，对检测到的问题做出响应，并在可能时替换或重启节点。这能以最少的人工干预提高集群可靠性，并有助于减少应用程序停机时间。

单独使用时，EKS 自动节点修复会对 kubelet 的 `Ready` 状况、任何手动删除的节点对象以及未能加入集群的 EKS 托管节点组实例做出响应。当启用 EKS 自动节点修复并安装了节点监控代理时，EKS 自动节点修复会对以下额外的节点状况做出响应：`AcceleratedHardwareReady`、`ContainerRuntimeReady`、`KernelReady`、`NetworkingReady` 和 `StorageReady`。

EKS 的自动节点修复不会对标准的 Kubernetes `DiskPressure`、`MemoryPressure` 或 `PIDPressure` 节点状况做出响应。这些情况通常表明是应用程序行为、工作负载配置或资源限制方面存在问题，而非节点层面出现故障所致，因此难以确定合适的默认修复措施。在这些场景中，工作负载受到 Kubernetes [节点压力驱逐行为](https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction)的约束。

有关 EKS 自动节点修复的更多信息，请参阅 [自动修复 EKS 集群中的节点](node-repair.md)。

**Topics**

# 使用 EKS 节点监控代理检测节点运行状况问题
<a name="node-health-nma"></a>

本主题详细介绍了 EKS 节点监控代理检测到的节点运行状况问题、如何将这些问题显示为节点条件或事件，以及如何配置节点监控代理。

无论是否使用 EKS 自动节点修复，均可使用 EKS 节点监控代理。有关 EKS 自动节点修复的更多信息，请参阅 [自动修复 EKS 集群中的节点](node-repair.md)。

EKS 节点监控代理的源代码发布在 GitHub 上的 [aws/eks-node-monitoring-agent](https://github.com/aws/eks-node-monitoring-agent) 存储库中。

## 节点运行状况问题
<a name="node-health-issues"></a>

下表介绍了节点监控代理可能会检测到的节点运行状况问题。问题有两种类型：
+ 状况 – 需要采取补救措施（例如替换实例或重启实例）的终端问题。启用自动修复后，Amazon EKS 将执行修复操作，可能是替换或重启节点。有关更多信息，请参阅 [节点状况](learn-status-conditions.md#status-node-conditions)。
+ 事件 – 暂时性问题或节点配置不佳问题。不会执行任何自动修复操作。有关更多信息，请参阅 [节点事件](learn-status-conditions.md#status-node-events)。

## AcceleratedHardware 节点运行状况问题
<a name="node-health-AcceleratedHardware"></a>

监控条件是下表中严重性为“状况”的问题的 `AcceleratedHardwareReady`。下表中的事件和条件适用于与 NVIDIA 和 Neuron 相关的节点运行状况问题。


| 名称 | 严重性 | 说明 | 修复操作 | 
| --- | --- | --- | --- | 
|  DCGMDiagnosticFailure  |  条件  |  DCGM 主动诊断测试套件中的测试用例失败。  |  无  | 
|  DCGMError  |  条件  |  到 DCGM 主机进程的连接已断开或无法建立。  |  无  | 
|  DCGMFieldError[Code]  |  事件  |  DCGM 通过字段标识符检测到 GPU 降级。  |  无  | 
|  DCGMHealthCode[Code]  |  事件  |  DCGM 运行状况检查以非致命方式失败。  |  无  | 
|  DCGMHealthCode[Code]  |  条件  |  DCGM 运行状况检查以致命方式失败。  |  无  | 
|  NeuronDMAError  |  条件  |  DMA 引擎遇到不可恢复的错误。  |  Replace（替换）  | 
|  NeuronHBMUncorrectableError  |  条件  |  HBM 遇到无法纠正的错误并产生了不正确的结果。  |  Replace（替换）  | 
|  NeuronNCUncorrectableError  |  条件  |  检测到无法纠正的 Neuron Core 内存错误。  |  Replace（替换）  | 
|  NeuronSRAMUncorrectableError  |  条件  |  片上 SRAM 遇到奇偶校验错误并产生了不正确的结果。  |  Replace（替换）  | 
|  NvidiaDeviceCountMismatch  |  事件  |  通过 NVML 可见的 GPU 数量与文件系统中的 NVIDIA 设备计数不一致。  |  无  | 
|  NvidiaDoubleBitError  |  条件  |  GPU 驱动程序产生了双比特错误。  |  Replace（替换）  | 
|  NvidiaNCCLError  |  事件  |  NVIDIA Collective Communications 库中出现段错误 (`libnccl`)。  |  无  | 
|  NvidiaNVLinkError  |  条件  |  GPU 驱动程序报告了 NVLink 错误。  |  Replace（替换）  | 
|  NvidiaPCIeError  |  事件  |  触发 PCIe 重播是为了从传输错误中恢复过来。  |  无  | 
|  NvidiaPageRetirement  |  事件  |  GPU 驱动程序已将内存页标记为停用。如果出现单个双比特错误或在同一地址遇到两个单比特错误，则可能会发生这种情况。  |  无  | 
|  NvidiaPowerError  |  事件  |  GPU 的功率利用率超过了允许的阈值。  |  无  | 
|  NvidiaThermalError  |  事件  |  GPU 的散热状态超过了允许的阈值。  |  无  | 
|  NvidiaXID[Code]Error  |  条件  |  出现严重的 GPU 错误。  |  更换或重启  | 
|  NvidiaXID[Code]Warning  |  事件  |  出现了非严重的 GPU 错误。  |  无  | 

## NVIDIA XID 错误代码
<a name="nvidia-xid-codes"></a>

节点监控代理从 GPU 内核日志中检测 NVIDIA XID 错误。XID 错误分为两类：
+  **众所周知的 XID 代码**–关键错误会设置节点条件 (`AcceleratedHardwareReady=False`)，并在启用时触发自动修复。推理代码格式为 `NvidiaXID[Code]Error`。EKS 节点监控代理检测到的众所周知的 XID 代码可能不代表需要修复操作的 NVIDIA XID 代码的完整列表。
+  **未知的 XID 代码**–仅作为 Kubernetes 事件记录。这些不会触发自动修复。推理代码格式为 `NvidiaXID[Code]Warning`。要调查未知的 XID 错误，请使用 `dmesg | grep -i nvrm` 查看内核日志。

有关 XID 错误的更多信息，请参阅《NVIDIA GPU 部署和管理文档》中的 [Xid Errors](https://docs.nvidia.com/deploy/xid-errors/index.html#topic_5_1)**。有关单个 XID 消息的更多信息，请参阅《NVIDIA GPU 部署和管理文档》中的 [Understanding Xid Messages](https://docs.nvidia.com/deploy/gpu-debug-guidelines/index.html#understanding-xid-messages)**。

下表列出了众所周知的 XID 代码、其含义以及启用后的默认节点修复操作（如果启用）。


| XID 代码 | 说明 | 修复操作 | 
| --- | --- | --- | 
|  13  |  图形引擎异常–出现 GPU 图形引擎错误，通常由软件问题或驱动程序错误引起。  |  Reboot  | 
|  31  |  GPU 内存页面错误–应用程序试图访问无法映射或无法访问的 GPU 内存。  |  Reboot  | 
|  48  |  双位 ECC 错误–GPU 内存中发生无法纠正的双位错误，表示可能出现硬件性能下降。  |  Reboot  | 
|  63  |  GPU 内存重新映射事件–由于检测到错误，GPU 驱动程序重新映射了部分 GPU 内存。这通常是可以恢复的。  |  Reboot  | 
|  64  |  GPU 内存重新映射失败–GPU 无法重新映射有缺陷的内存，这表明存在硬件问题。  |  Reboot  | 
|  74  |  NVLink 错误–GPU 之间的高速 NVLink 互连出现错误。  |  Replace（替换）  | 
|  79  |  GPU 已从总线上掉线–GPU 已无法通过 PCIe 访问，这通常表示硬件故障或电源问题。  |  Replace（替换）  | 
|  94  |  受控内存错误 – 发生了内存错误，但该错误已被隔离，未影响其他应用程序。  |  Reboot  | 
|  95  |  未受控内存错误–发生了可能影响其他应用程序或系统内存的内存错误。  |  Reboot  | 
|  119  |  GSP RPC 超时–与 GPU 系统处理器的通信超时，可能是由于固件问题导致。  |  Replace（替换）  | 
|  120  |  GSP 错误–GPU 系统处理器中发生错误。  |  Replace（替换）  | 
|  121  |  C2C 错误–芯片间互连（用于多芯片 GPU）发生错误。  |  Replace（替换）  | 
|  140  |  ECC 未恢复错误–ECC 错误突破了隔离范围，可能导致数据损坏。  |  Replace（替换）  | 

要查看与 GPU 运行状况相关的当前节点运行状况状况，请运行以下命令。

```
kubectl get nodes -o custom-columns='NAME:.metadata.name,ACCELERATOR_READY:.status.conditions[?(@.type=="AcceleratedHardwareReady")].status,REASON:.status.conditions[?(@.type=="AcceleratedHardwareReady")].reason'
```

要查看集群中与 XID 相关的事件，请运行以下命令之一。

```
kubectl get events | grep -i "NvidiaXID"
```

## ContainerRuntime 节点运行状况问题
<a name="node-health-ContainerRuntime"></a>

监控条件是下表中严重性为“状况”的问题的 `ContainerRuntimeReady`。


| 名称 | 严重性 | 说明 | 修复操作 | 
| --- | --- | --- | --- | 
|  ContainerRuntimeFailed  |  事件  |  容器运行时创建容器失败，如果反复发生，则可能与任何报告的问题有关。  |  无  | 
|  DeprecatedContainerdConfiguration  |  事件  |  使用已弃用映像清单版本 2、架构 1 的容器映像最近通过 `containerd` 拉取到了节点上。  |  无  | 
|  KubeletFailed  |  事件  |  kubelet 处于某个失败状态。  |  无  | 
|  LivenessProbeFailures  |  事件  |  检测到存活探针失败，如果反复发生，则可能指示应用程序代码问题或超时值不足。  |  无  | 
|  PodStuckTerminating  |  条件  |  容器组正在或曾经过长时间停滞在正在终止状态，这可能是因 CRI 错误阻止容器组状态进展造成的。  |  Replace（替换）  | 
|  ReadinessProbeFailures  |  事件  |  检测到就绪探针失败，如果反复发生，则可能指示应用程序代码问题或超时值不足。  |  无  | 
|  [Name]RepeatedRestart  |  事件  |  systemd 单元频繁重启。  |  无  | 
|  ServiceFailedToStart  |  事件  |  系统单元启动失败。  |  无  | 

## 节点内核运行状况问题
<a name="node-health-Kernel"></a>

监控条件是下表中严重性为“状况”的问题的 `KernelReady`。


| 名称 | 严重性 | 说明 | 修复操作 | 
| --- | --- | --- | --- | 
|  AppBlocked  |  事件  |  任务被长时间禁止调度，这通常是由于在输入或输出时被屏蔽所致。  |  无  | 
|  AppCrash  |  事件  |  节点上的应用程序已崩溃。  |  无  | 
|  ApproachingKernelPidMax  |  事件  |  根据当前 `kernel.pid_max` 设置，进程数量已接近可用 PID 的最大数量，之后将无法启动更多进程。  |  无  | 
|  ApproachingMaxOpenFiles  |  事件  |  按照当前内核设置，打开的文件数已接近可能打开的最大文件数，之后打开新文件将失败。  |  无  | 
|  ConntrackExceededKernel  |  事件  |  连接跟踪超出内核的最大值且无法建立新连接可能会导致数据包丢失。  |  无  | 
|  ExcessiveZombieProcesses  |  事件  |  无法完全回收的进程正在大量积累，这指示存在应用程序问题，并且可能导致达到系统进程限制。  |  无  | 
|  ForkFailedOutOfPIDs  |  条件  |  由于系统进程 ID 或内存不足，fork 或 exec 调用失败，这可能是僵尸进程或物理内存耗尽造成的。  |  Replace（替换）  | 
|  KernelBug  |  事件  |  Linux 内核本身检测到并报告了内核错误，但这有时可能是由节点的 CPU 或内存使用率过高，导致事件处理延迟造成的。  |  无  | 
|  LargeEnvironment  |  事件  |  此进程的环境变量数大于预期，这可能是因许多将 `enableServiceLinks` 设置为 true 的服务造成的，因为这可能导致性能问题。  |  无  | 
|  RapidCron  |  事件  |  cron 作业在此节点上的运行速度超过每五分钟一次，如果该作业消耗大量资源，则可能会影响性能。  |  无  | 
|  SoftLockup  |  事件  |  CPU 在给定时间停滞。  |  无  | 

## 节点联网运行状况问题
<a name="node-health-Networking"></a>

监控条件是下表中严重性为“状况”的问题的 `NetworkingReady`。


| 名称 | 严重性 | 说明 | 修复操作 | 
| --- | --- | --- | --- | 
|  BandwidthInExceeded  |  事件  |  因入站总带宽超过实例的最大值，导致数据包已排队或被丢弃。  |  无  | 
|  BandwidthOutExceeded  |  事件  |  因出站总带宽超过实例的最大值，导致数据包已排队或被丢弃。  |  无  | 
|  ConntrackExceeded  |  事件  |  连接跟踪超出实例的最大值且无法建立新连接，这可能会导致数据包丢失。  |  无  | 
|  EFAErrorMetric  |  事件  |  EFA 驱动程序指标显示存在性能下降的接口。  |  无  | 
|  IPAMDInconsistentState  |  事件  |  磁盘上 IPAMD 检查点的状态不反映容器运行时中的 IP。  |  无  | 
|  IPAMDNoIPs  |  事件  |  IPAMD 的 IP 地址已用完。  |  无  | 
|  IPAMDNotReady  |  条件  |  IPAMD 无法连接到 API 服务器。  |  Replace（替换）  | 
|  IPAMDNotRunning  |  条件  |  未发现 Amazon VPC CNI 进程正在运行。  |  Replace（替换）  | 
|  IPAMDRepeatedlyRestart  |  事件  |  IPAMD 服务已多次重启。  |  无  | 
|  InterfaceNotRunning  |  条件  |  此接口似乎未运行或存在网络问题。  |  Replace（替换）  | 
|  InterfaceNotUp  |  条件  |  此接口似乎未启动或存在网络问题。  |  Replace（替换）  | 
|  KubeProxyNotReady  |  事件  |  Kube-proxy 无法观察或列出资源。  |  无  | 
|  LinkLocalExceeded  |  事件  |  由于到本地代理服务的流量 PPS 超出网络接口的最大值，数据包被丢弃。  |  无  | 
|  MACAddressPolicyMisconfigured  |  事件  |  systemd-networkd 链接配置的值 `MACAddressPolicy` 不正确。  |  无  | 
|  MissingDefaultRoutes  |  事件  |  缺少默认路由规则。  |  无  | 
|  MissingIPRoutes  |  事件  |  容器组（pod）IP 缺少路由。  |  无  | 
|  MissingIPRules  |  事件  |  容器组（pod）IP 缺少规则。  |  无  | 
|  MissingLoopbackInterface  |  条件  |  此实例缺少环回接口，导致服务失败，具体取决于本地连接。  |  Replace（替换）  | 
|  NetworkSysctl  |  事件  |  此节点的网络 `sysctl` 设置可能不正确。  |  无  | 
|  PPSExceeded  |  事件  |  因双向 PPS 超过实例的最大值，数据包已排队或被丢弃。  |  无  | 
|  PortConflict  |  事件  |  如果容器组（pod）使用 hostPort，则可能写入会覆盖主机已经绑定端口的 `iptables` 规则，这可能会阻止 API 服务器访问 `kubelet`。  |  无  | 
|  UnexpectedRejectRule  |  事件  |  在 `iptables` 中发现了可能阻止预期流量的异常 `REJECT` 或 `DROP` 规则。  |  无  | 

## 节点存储运行状况问题
<a name="node-health-Storage"></a>

监控条件是下表中严重性为“状况”的问题的 `StorageReady`。


| 名称 | 严重性 | 说明 | 修复操作 | 
| --- | --- | --- | --- | 
|  EBSInstanceIOPSExceeded  |  事件  |  已超过实例的最大 IOPS。  |  无  | 
|  EBSInstanceThroughputExceeded  |  事件  |  已超过实例的最大吞吐量。  |  无  | 
|  EBSVolumeIOPSExceeded  |  事件  |  已超过特定 EBS 卷的最大 IOPS。  |  无  | 
|  EBSVolumeThroughputExceeded  |  事件  |  已超过特定 Amazon EBS 卷的最大吞吐量。  |  无  | 
|  EtcHostsMountFailed  |  事件  |  由于在 `kubelet-container` 操作过程中进行了用户数据重新挂载 `/var/lib/kubelet/pods`，因此挂载 kubelet 生成的 `/etc/hosts` 失败。  |  无  | 
|  IODelays  |  事件  |  在进程中检测到输入或输出延迟，如果过长，则可能表明预调配的输入输出读写操作次数不足。  |  无  | 
|  KubeletDiskUsageSlow  |  事件  |  `kubelet` 报告在尝试访问文件系统时磁盘使用率降低。这可能表示磁盘输入输出不足或存在文件系统问题。  |  无  | 
|  XFSSmallAverageClusterSize  |  事件  |  XFS 平均集群大小很小，这表示可用空间碎片过多。这可能会阻止文件创建，尽管有索引节点或可用空间可用。  |  无  | 

## 配置节点监控代理
<a name="node-monitoring-agent-configure"></a>

EKS 节点监控代理以 DaemonSet 形式部署。当将其作为 EKS 插件部署时，您可以通过以下配置值自定义安装。有关默认配置，请参阅 EKS 节点监控代理 [Helm 图表](https://github.com/aws/eks-node-monitoring-agent/blob/main/charts/eks-node-monitoring-agent/values.yaml)。


| 配置选项 | 说明 | 
| --- | --- | 
|   `monitoringAgent.resources.requests.cpu`   |  监控代理的 CPU 资源请求。  | 
|   `monitoringAgent.resources.requests.memory`   |  监控代理的内存资源请求。  | 
|   `monitoringAgent.resources.limits.cpu`   |  监控代理的 CPU 资源限制。  | 
|   `monitoringAgent.resources.limits.memory`   |  监控代理的内存资源限制。  | 
|   `monitoringAgent.tolerations`   |  在受污染节点上调度监控代理的容差。  | 
|   `monitoringAgent.additionalArgs`   |  要传递给监控代理的其他命令行参数。  | 

**注意**  
您可以通过 EKS 插件或 Helm 安装将 `hostname-override` 和 `verbosity` 配置为 `monitoringAgent.additionalArgs`。目前，您无法通过 EKS 插件或 Helm 安装的额外参数来自定义节点监控代理的 `probe-address`（`8002`）或 `metrics-address`（`8003`）。

节点监控代理包含一个用于监控 NVIDIA GPU 的 NVIDIA DCGM（数据中心 GPU 管理器）服务器组件（`nv-hostengine`）。此组件仅在属于 NVIDIA GPU 实例类型的节点上运行，如代理的 [Helm 图表](https://github.com/aws/eks-node-monitoring-agent/blob/main/charts/eks-node-monitoring-agent/values.yaml)中的 `nodeAffinity` 所示。您无法将现有的 NVIDIA DCGM 安装与 EKS 节点监控代理配合使用，如有此功能需求，请通过 EKS 路线图 [GitHub issue \$12763 ](https://github.com/aws/containers-roadmap/issues/2763)提供反馈。

当您将 EKS 节点监控代理作为 EKS 附加组件部署时，可以通过以下配置值自定义 NVIDIA DCGM 的安装。


| 配置选项 | 说明 | 
| --- | --- | 
|   `dcgmAgent.resources.requests.cpu`   |  DCGM 代理的 CPU 资源请求。  | 
|   `dcgmAgent.resources.requests.memory`   |  DCGM 代理的内存资源请求。  | 
|   `dcgmAgent.resources.limits.cpu`   |  DCGM 代理的 CPU 资源限制。  | 
|   `dcgmAgent.resources.limits.memory`   |  DCGM 代理的内存资源限制。  | 
|   `dcgmAgent.tolerations`   |  在受污染节点上调度 DCGM 代理的容忍度。  | 

您可以使用以下 AWS CLI 命令来获取有关 EKS 节点监控代理 EKS 附加组件的版本和架构的有用信息。

获取适用于您的 Kubernetes 版本的最新代理附加组件版本。将 `1.35` 替换为您的 Kubernetes 版本。

```
aws eks describe-addon-versions \
  --addon-name eks-node-monitoring-agent \
  --kubernetes-version 1.35 \
  --query='addons[].addonVersions[].addonVersion'
```

获取 EKS 附加组件中支持的代理附加组件架构。将 `v1.5.1-eksbuild.1` 替换为您的代理版本。

```
aws eks describe-addon-configuration \
  --addon-name eks-node-monitoring-agent \
  --addon-version v1.5.1-eksbuild.1
```

# 自动修复 EKS 集群中的节点
<a name="node-repair"></a>

本主题详细介绍 EKS 自动节点修复的行为以及如何根据您的需求进行配置。EKS 自动节点修复在 EKS Auto Mode 中默认启用，并且可以与 EKS 托管节点组和 Karpenter 一起使用。

下表总结了默认的 EKS 自动节点修复操作，这些操作适用于 EKS Auto Mode 、EKS 托管节点组和 Karpenter 的行为。当使用 EKS Auto Mode 或 Karpenter 时，所有 `AcceleratedHardwareReady` 修复操作均为 `Replace`，只有 EKS 托管节点组支持 `Reboot` 作为修复操作。

有关 EKS 节点监控代理检测到的节点运行状况问题及其相应的节点修复操作的详细列表，请参阅 [使用 EKS 节点监控代理检测节点运行状况问题](node-health-nma.md)。


| 节点状况 | 说明 | 修复等待时间 | 修复操作 | 
| --- | --- | --- | --- | 
|  AcceleratedHardwareReady  |  AcceleratedHardwareReady 表示节点上的加速硬件（GPU、Neuron）是否正常运行。  |  10m  |  更换或重启  | 
|  ContainerRuntimeReady  |  ContainerRuntimeReady 表示容器运行时（containererd 等）是否正常运行并能运行容器。  |  30m  |  Replace（替换）  | 
|  DiskPressure  |  DiskPressure 是一个标准的 Kubernetes 状况，表示节点正在经历磁盘压力（磁盘空间不足或 I/O 过高）。  |  不适用  |  无  | 
|  KernelReady  |  KernelReady 表示内核是否运行正常，无严重错误、死锁或资源耗尽问题。  |  30m  |  Replace（替换）  | 
|  MemoryPressure  |  MemoryPressure 是一个标准的 Kubernetes 状况，表示节点正在经历内存压力（可用内存不足）。  |  不适用  |  无  | 
|  NetworkingReady  |  NetworkingReady 表示节点的网络堆栈（接口、路由、连接）是否正常运行。  |  30m  |  Replace（替换）  | 
|  StorageReady  |  StorageReady 表示节点的存储子系统（磁盘、文件系统、I/O）是否正常运行。  |  30m  |  Replace（替换）  | 
|  Ready  |  Ready 是标准的 Kubernetes 状况，表示节点运行正常并已准备好接收容器组（pod）。  |  30m  |  Replace（替换）  | 

默认情况下，EKS 自动节点修复操作在以下场景中处于禁用状态。在每个场景中，正在进行的节点修复操作仍在继续。有关如何覆盖这些默认设置的信息，请参阅 [配置自动节点修复](#configure-node-repair)。

 **EKS 托管式节点组** 
+ 节点组的节点数量超过五个，并且节点组中超过 20% 的节点运行状况不佳。
+ 集群的可用区转移通过应用程序恢复控制器（ARC）触发。

 **EKS Auto Mode 和 Karpenter** 
+ NodePool 中超过 20% 的节点运行状况不佳。
+ 对于独立的 nodeClaims，集群中有 20% 的节点运行状况不佳。

## 配置自动节点修复
<a name="configure-node-repair"></a>

使用 EKS Auto Mode 时，自动节点修复无法配置，并且始终以与 Karpenter 相同的默认设置启用。

### Karpenter
<a name="configure-node-repair-karpenter"></a>

要将自动节点修复与 Karpenter 结合使用，请启用功能门控 `NodeRepair=true`。您可以通过 Karpenter 部署中的 `--feature-gates` CLI 选项或 `FEATURE_GATES` 环境变量来启用功能门控。有关更多信息，请参阅 [Karpenter](https://karpenter.sh/docs/concepts/disruption/#node-auto-repair) 文档。

### 托管节点组
<a name="configure-node-repair-mng"></a>

您可以在创建新的 EKS 托管节点组时或通过更新现有 EKS 托管节点组来启用自动节点修复。
+  **Amazon EKS 控制台**–为托管节点组选中**启用节点自动修复**复选框。有关更多信息，请参阅 [为集群创建托管式节点组](create-managed-node-group.md)。
+  **AWS CLI**–将 `--node-repair-config enabled=true` 添加到 [https://docs.aws.amazon.com/cli/latest/reference/eks/create-nodegroup.html](https://docs.aws.amazon.com/cli/latest/reference/eks/create-nodegroup.html) 或 [https://docs.aws.amazon.com/cli/latest/reference/eks/update-nodegroup-config.html](https://docs.aws.amazon.com/cli/latest/reference/eks/update-nodegroup-config.html) 命令中。
+  **eksctl**–配置 `managedNodeGroups.nodeRepairConfig.enabled: true`，参见 [eksctl GitHub](https://github.com/eksctl-io/eksctl/blob/main/examples/44-node-repair.yaml) 中的示例。

使用 EKS 托管节点组时，您可以通过以下设置控制节点自动修复行为。

要控制节点自动修复何时停止执行操作，请根据节点组中运行状况不佳节点的数量设置一个阈值。设置绝对数量或百分比，但不要同时设置两者。


| 设置 | 说明 | 
| --- | --- | 
|   `maxUnhealthyNodeThresholdCount`   |  节点自动修复停止执行操作的运行状况不佳节点的绝对数量。用于限制修复范围。  | 
|   `maxUnhealthyNodeThresholdPercentage`   |  停止节点自动修复的运行状况不佳节点百分比（0-100）。  | 

要控制同时修复的节点数量，您可以配置修复并行度。与运行状况不佳节点阈值一样，设置绝对数量或百分比，但不要同时设置两者。


| 设置 | 说明 | 
| --- | --- | 
|   `maxParallelNodesRepairedCount`   |  可同时修复的最大节点数量。  | 
|   `maxParallelNodesRepairedPercentage`   |  要同时修复的运行状况不佳节点的最大百分比 (0–100)。  | 

使用 `nodeRepairConfigOverrides`，您可以为特定状况自定义修复行为。当您需要对不同问题类型采取不同的修复操作或等待时间时，请使用此功能。

每个覆盖配置都需要以下所有字段：


| 字段 | 说明 | 
| --- | --- | 
|   `nodeMonitoringCondition`   |  节点监控代理报告的节点状况类型。例如：`AcceleratedHardwareReady`、`NetworkingReady`、`StorageReady`、`KernelReady`。  | 
|   `nodeUnhealthyReason`   |  运行状况不佳的具体原因代码。例如：`NvidiaXID31Error`、`IPAMDNotRunning`。  | 
|   `minRepairWaitTimeMins`   |  在节点符合修复条件之前，该情况必须持续的最短时间（以分钟为单位）。使用此选项可以避免因临时问题修复节点。  | 
|   `repairAction`   |  条件满足时采取的操作。有效值：`Replace`（终止并替换节点）、`Reboot`（重新启动节点）或`NoAction`（不执行修复操作）。  | 

以下 AWS CLI 示例创建了一个具有自定义修复设置的节点组。

```
aws eks create-nodegroup \
  --cluster-name my-cluster \
  --nodegroup-name my-nodegroup \
  --node-role arn:aws:iam::111122223333:role/NodeRole \
  --subnets subnet-0123456789abcdef0 \
  --node-repair-config '{
    "enabled": true,
    "maxUnhealthyNodeThresholdPercentage": 10,
    "maxParallelNodesRepairedCount": 3,
    "nodeRepairConfigOverrides": [
      {
        "nodeMonitoringCondition": "AcceleratedHardwareReady",
        "nodeUnhealthyReason": "NvidiaXID64Error",
        "minRepairWaitTimeMins": 5,
        "repairAction": "Replace"
      },
      {
        "nodeMonitoringCondition": "AcceleratedHardwareReady",
        "nodeUnhealthyReason": "NvidiaXID31Error",
        "minRepairWaitTimeMins": 15,
        "repairAction": "NoAction"
      }
    ]
  }'
```

此配置执行以下操作：
+ 启用节点自动修复
+ 当超过 10% 的节点运行状况不佳时，停止修复操作
+ 一次最多修复 3 个节点
+ 覆盖 XID 64 错误（GPU 内存重新映射失败），在 5 分钟后替换节点。默认是在 10 分钟后重启。
+ 覆盖 XID 31 错误（GPU 内存页面故障），不采取任何操作。默认是在 10 分钟后重启。

# 查看节点运行状况检查状态
<a name="learn-status-conditions"></a>

本主题介绍可用于监控 Amazon EKS 集群中节点运行状况检查状态的工具和方法。这些信息涵盖有助您识别和诊断节点级别问题的节点状况、事件和检测案例。使用本文描述的命令和模式来检查节点运行状况资源、解释状态条件，以及分析节点事件以进行运行故障排除。

您可以对所有节点使用 Kubernetes 命令来获取节点的某些运行状况信息。如果您通过 Amazon EKS 自动模式或 Amazon EKS 托管式附加组件使用节点监控代理，则将可获得更多种类的节点信号来帮助进行故障排除。对于节点监控代理检测到的运行状况问题，相关描述也可以在可观测性控制面板中查看。有关更多信息，请参阅 [使用 EKS 节点监控代理检测节点运行状况问题](node-health-nma.md)。

## 节点状况
<a name="status-node-conditions"></a>

节点状况表示需要采取补救措施（例如更换实例或重启实例）的终端问题。

 **获取所有节点的状况：**

```
kubectl get nodes -o 'custom-columns=NAME:.metadata.name,CONDITIONS:.status.conditions[*].type,STATUS:.status.conditions[*].status'
```

 **获取特定节点的详细状况** 

```
kubectl describe node node-name
```

 **正常节点的状况输出示例：**

```
  - lastHeartbeatTime: "2024-11-21T19:07:40Z"
    lastTransitionTime: "2024-11-08T03:57:40Z"
    message: Monitoring for the Networking system is active
    reason: NetworkingIsReady
    status: "True"
    type: NetworkingReady
```

 **出现网络问题的不正常节点的状况示例：**

```
  - lastHeartbeatTime: "2024-11-21T19:12:29Z"
    lastTransitionTime: "2024-11-08T17:04:17Z"
    message: IPAM-D has failed to connect to API Server which could be an issue with
      IPTable rules or any other network configuration.
    reason: IPAMDNotReady
    status: "False"
    type: NetworkingReady
```

## 节点事件
<a name="status-node-events"></a>

节点事件指示暂时性问题或配置不佳问题。

 **获取节点监控代理报告的所有事件** 

当节点监控代理可用时，您可以运行以下命令。

```
kubectl get events --field-selector=reportingComponent=eks-node-monitoring-agent
```

示例输出：

```
LAST SEEN   TYPE      REASON       OBJECT                                              MESSAGE
4s          Warning   SoftLockup   node/ip-192-168-71-251.us-west-2.compute.internal   CPU stuck for 23s
```

 **获取所有节点的事件** 

```
kubectl get events --field-selector involvedObject.kind=Node
```

 **获取特定节点的事件** 

```
kubectl get events --field-selector involvedObject.kind=Node,involvedObject.name=node-name
```

 **实时观察事件** 

```
kubectl get events -w --field-selector involvedObject.kind=Node
```

 **事件输出示例：**

```
LAST SEEN   TYPE     REASON           OBJECT         MESSAGE
2m          Warning  MemoryPressure   Node/node-1    Node experiencing memory pressure
5m          Normal   NodeReady        Node/node-1    Node became ready
```

## 常用故障排除命令
<a name="status-node-troubleshooting"></a>

```
# Get comprehensive node status
kubectl get node node-name -o yaml

# Watch node status changes
kubectl get nodes -w

# Get node metrics
kubectl top node
```

# 使用 kubectl 和 S3 检索托管式节点的节点日志
<a name="auto-get-logs"></a>

了解如何检索具有节点监控代理的 Amazon EKS 托管式节点的节点日志。

## 先决条件
<a name="_prerequisites"></a>

确保您已满足以下条件：
+ 一个具有节点监控代理的现有 Amazon EKS 集群。有关更多信息，请参阅 [检测节点运行状况问题并启用自动节点修复](node-health.md)。
+ 已安装并配置好 `kubectl` 命令行工具，以便与您的集群通信。
+ 已安装 AWS CLI 并登录，并且拥有创建 S3 存储桶和对象的充分权限。
+ 已安装 Python 3 的最新版本
+ 已安装适用于 Python 3、Boto 3 的 AWS SDK。

## 第 1 步：创建 S3 存储桶目标（可选）
<a name="_step_1_create_s3_bucket_destination_optional"></a>

如果您还没有用来存储日志的 S3 存储桶，请创建一个。使用以下 AWS CLI 命令。存储桶默认为 `private` 访问控制列表。将 *bucket-name* 替换为您选择的唯一存储桶名称。

```
aws s3api create-bucket --bucket <bucket-name>
```

## 第 2 步：创建用于 HTTP Put 的预签名 S3 URL
<a name="_step_2_create_pre_signed_s3_url_for_http_put"></a>

Amazon EKS 通过对您指定的 URL 执行 HTTP PUT 操作来返回节点日志。在本教程中，我们将生成一个预签名的 S3 HTTP PUT URL。

日志将以 gzip 压缩包的形式返回，扩展名为 `.tar.gz`。

**注意**  
您必须使用 AWS API 或 SDK 创建预签名的 S3 上传 URL，以便 EKS 上传日志文件。您无法使用 AWS CLI 创建预签名的 S3 上传 URL。

1. 确定要用于存储桶日志的位置。例如，可能将 *2024-11-12/logs1.tar.gz* 作为键。

1. 将以下 Python 代码保存到 *presign-upload.py* 文件中。替换 *<bucket-name>* 和 *<key>*。键应以 `.tar.gz` 结尾。

   ```
   import boto3; print(boto3.client('s3').generate_presigned_url(
      ClientMethod='put_object',
      Params={'Bucket': '<bucket-name>', 'Key': '<key>'},
      ExpiresIn=1000
   ))
   ```

1. 运行脚本

   ```
   python presign-upload.py
   ```

1. 记下 URL 输出。在下一步中，请将此值用作 *http-put-destination*。

有关更多信息，请参阅适用于 Python 的 AWS Boto3 SDK 文档中的 [Generate a presigned URL to upload a file](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html#generating-a-presigned-url-to-upload-a-file)。

## 第 3 步：创建节点诊断资源
<a name="_step_3_create_nodediagnostic_resource"></a>

确定需要从中收集日志的节点的名称。

创建一个 `NodeDiagnostic` 清单，将节点名称作为资源名称，并提供 HTTP PUT URL 目标位置。

```
apiVersion: eks.amazonaws.com/v1alpha1
kind: NodeDiagnostic
metadata:
    name: <node-name>
spec:
    logCapture:
        destination: http-put-destination
```

将清单应用于集群。

```
kubectl apply -f nodediagnostic.yaml
```

您可以通过描述 `NodeDiagnostic` 资源来检查收集状态：
+ 如果状态为 `Success` 或 `SuccessWithErrors`，则表示任务已完成且日志已上传到提供的目标位置（`SuccessWithErrors` 表示可能缺失某些日志）
+ 如果状态为“失败”，请确认上传 URL 格式正确且未过期。

```
kubectl describe nodediagnostics.eks.amazonaws.com/<node-name>
```

## 第 4 步：从 S3 下载日志
<a name="_step_4_download_logs_from_s3"></a>

等待大约一分钟，然后再尝试下载日志。然后使用 S3 CLI 下载日志。

```
# Once NodeDiagnostic shows Success status, download the logs
aws s3 cp s3://<bucket-name>/key ./<path-to-node-logs>.tar.gz
```

## 第 5 步：清除节点诊断资源
<a name="_step_5_clean_up_nodediagnostic_resource"></a>
+  `NodeDiagnostic` 资源不会被自动删除。获取日志构件后，您需要自行清理这些文件

```
# Delete the NodeDiagnostic resource
kubectl delete nodediagnostics.eks.amazonaws.com/<node-name>
```

## NodeDiagnostic `node` 目标
<a name="_nodediagnostic_node_destination"></a>

从 Node Monitoring Agent 的 `v1.6.0` 版本开始，可以选择将日志收集目标设置为 `node`。使用此目标将导致日志在节点上收集并临时保留，以供后续收集。除此功能外，节点监控代理的 GitHub 存储库中还有一个 `kubectl` 插件，您可以安装该插件以便于交互和日志收集。有关更多信息，[请参阅 `kubectl ekslogs` 插件的文档](https://github.com/aws/eks-node-monitoring-agent/blob/main/tools/kubectl-ekslogs/README.md)。

## 示例用法
<a name="_example_usage"></a>

```
# Collect NodeDiagnostic logs from a single node
kubectl ekslogs <node-name>

# Collect NodeDiagnostic logs from multiple nodes
kubectl ekslogs <node-name-1> <node-name-2> <node-name-3>

# Collect NodeDiagnostic logs from all nodes with a specific label
kubectl ekslogs -l <key>=<value>
```

# Amazon EKS 混合节点功能概述
<a name="hybrid-nodes-overview"></a>

借助 *Amazon EKS 混合节点功能*，您可以将本地和边缘基础设施用作 Amazon EKS 集群中的节点。AWS 负责管理由 AWS 托管的 Amazon EKS 集群的 Kubernetes 控制面板，而您负责管理在本地或边缘环境中运行的混合节点。这样就实现了跨环境的统一 Kubernetes 管理，将本地和边缘应用程序的 Kubernetes 控制面板管理工作转移到 AWS。

Amazon EKS 混合节点功能可支持任何本地硬件或虚拟机，从而在任何需要运行应用程序的位置享受到 Amazon EKS 的效率、可扩展性和可用性。您可以将各种 Amazon EKS 功能与 Amazon EKS 混合节点功能结合使用，包括 Amazon EKS 附加组件、Amazon EKS 容器组身份、集群访问条目、集群及见解和 Kubernetes 版本延期支持。Amazon EKS 混合节点功能原生集成了多项 AWS 服务，包括 AWS Systems Manager、AWS IAM Roles Anywhere、Amazon Managed Service for Prometheus 和 Amazon CloudWatch，用于集中监控、日志记录和身份管理。

使用 Amazon EKS 混合节点功能时，无预付承诺或最低费用要求，并且在将混合节点挂载到 Amazon EKS 集群时，您只需按小时为混合节点的 vCPU 资源付费。有关详细定价信息，请参阅 [Amazon EKS 定价](https://aws.amazon.com/eks/pricing/)。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/tFn9IdlddBw?rel=0/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/tFn9IdlddBw?rel=0)


## 特征
<a name="hybrid-nodes-features"></a>

EKS 混合节点具有以下高级功能：
+  **托管式 Kubernetes 控制面板**：AWS 负责管理 EKS 集群中由 AWS 托管的 Kubernetes 控制面板，您负责管理在本地或边缘环境中运行的混合节点。这样就实现了跨环境的统一 Kubernetes 管理，将本地和边缘应用程序的 Kubernetes 控制面板管理工作转移到 AWS。通过将 Kubernetes 控制面板转移到 AWS，您可以将本地容量留给应用程序，并且 Kubernetes 控制平面会根据工作负载的需要而扩展。
+  **一致的 EKS 体验**：EKS 混合节点功能支持大多数 EKS 功能，可在本地和云环境中提供一致的 EKS 体验，包括 EKS 附加组件、EKS 容器组身份、集群访问条目、集群见解、扩展 Kubernetes 版本支持等。有关 EKS 混合节点功能支持的 EKS 附加组件的更多信息，请参阅[为混合节点配置附加组件](hybrid-nodes-add-ons.md)。
+  **集中式可观测性和身份管理**：EKS 混合节点功能可与多项 AWS 服务原生集成，包括 AWS Systems Manager、AWS IAM Roles Anywhere、Amazon Managed Service for Prometheus 和Amazon CloudWatch 等，从而满足集中监控、日志记录和身份管理等需求。
+  **通过云端满足突发需求或增加本地容量**：单个 EKS 集群可用于运行混合节点以及位于 AWS 区域、AWS Local Zones 或 AWS Outposts 中的节点，从而通过云端满足突发需求，也可为 EKS 集群添加本地容量。有关更多信息，请参阅[混合模式集群注意事项](hybrid-nodes-webhooks.md#hybrid-nodes-considerations-mixed-mode)。
+  **灵活基础设施**：EKS 混合节点功能遵循*自带基础设施*的方法，并且与您用于混合节点的基础设施无关。您可以在物理计算机或虚拟机上运行混合节点，可以使用 x86 和 ARM 架构，从而跨不同的基础设施类型迁移在混合节点上运行的本地工作负载。
+  **灵活联网**：使用 EKS 混合节点功能时，EKS 控制面板与混合节点之间的通信通过您在集群创建期间传递的 VPC 和子网进行路由，此方法基于 EKS 中控制面板用于节点联网的[现有机制](https://docs.aws.amazon.com/eks/latest/best-practices/subnets.html)。您可以灵活选择将本地网络连接到 AWS 中的 VPC 的首选方法。有多个[有文档记录的选项](https://docs.aws.amazon.com/whitepapers/latest/aws-vpc-connectivity-options/network-to-amazon-vpc-connectivity-options.html)可供选择，包括 AWS Site-to-Site VPN、AWS Direct Connect 或您自己的 VPN 解决方案，您可以根据自己的应用场景选择最适合的方法。

## 限制
<a name="hybrid-node-limits"></a>
+ 每个集群最多支持将 15 个 CIDR 用于远程节点网络，以及将 15 个 CIDR 用于远程容器组网络。

## 注意事项
<a name="hybrid-nodes-general"></a>
+ EKS 混合节点功能可与新的或现有的 EKS 集群结合使用。
+ 除 AWS GovCloud（美国）区域和 AWS 中国区域外，EKS 混合节点功能已在所有 AWS 区域开放。
+ 要使用 EKS 混合节点功能，必须在您的本地环境和 AWS 之间建立可靠的连接。EKS 混合节点功能不适合连接断开、中断、间歇性或受限（DDIL）的环境。如果在 DDIL 环境中运行，可以考虑使用 [Amazon EKS Anywhere](https://aws.amazon.com/eks/eks-anywhere/)。有关混合节点在网络断开连接情况下行为的信息，请参阅 [Best Practices for EKS Hybrid Nodes](https://docs.aws.amazon.com/eks/latest/best-practices/hybrid-nodes-network-disconnections.html)。
+ 不支持在云基础设施（包括 AWS 区域、AWS Local Zones、AWS Outposts 或其他云）中运行 EKS 混合节点功能。如果您在 Amazon EC2 实例上运行混合节点，则需要支付混合节点功能使用费。
+ 混合节点功能使用费从节点加入 EKS 集群时起开始计费，并在从集群中移除节点时停止计费。如果您不使用混合节点功能，请务必将其从 EKS 集群中移除。

## 其他资源
<a name="hybrid-nodes-resources"></a>
+  [https://www.eksworkshop.com/docs/networking/eks-hybrid-nodes/](https://www.eksworkshop.com/docs/networking/eks-hybrid-nodes/)：在演示环境中部署 EKS 混合节点的分步说明。
+  [https://www.youtube.com/watch?v=ZxC7SkemxvU](https://www.youtube.com/watch?v=ZxC7SkemxvU)：AWS re:Invent 会议介绍了 EKS 混合节点发布会，一位客户展示了其如何在自己的环境中使用 EKS 混合节点。
+  [https://repost.aws/articles/ARL44xuau6TG2t-JoJ3mJ5Mw/unpacking-the-cluster-networking-for-amazon-eks-hybrid-nodes](https://repost.aws/articles/ARL44xuau6TG2t-JoJ3mJ5Mw/unpacking-the-cluster-networking-for-amazon-eks-hybrid-nodes)：文章说明了为 EKS 混合节点设置网络的各种方法。
+  [https://aws.amazon.com/blogs/containers/run-genai-inference-across-environments-with-amazon-eks-hybrid-nodes/](https://aws.amazon.com/blogs/containers/run-genai-inference-across-environments-with-amazon-eks-hybrid-nodes/)：博客文章展示了如何使用 EKS 混合节点跨环境运行 GenAI 推理。

# 混合节点的先决条件设置
<a name="hybrid-nodes-prereqs"></a>

要使用 Amazon EKS 混合节点功能，您必须拥有在本地环境与 AWS、具有支持操作系统的裸机服务器或虚拟机之间往来传输的私有连接，并且配置了 AWS IAM Roles Anywhere 或 AWS Systems Manager（SSM）混合激活。您负责在整个混合节点生命周期中管理这些先决条件。
+ 在本地环境与 AWS 之间往来传输的混合网络连接 
+ 物理计算机或虚拟机形式的基础设施
+ 与混合节点功能兼容的操作系统
+ 已配置好本地 IAM 凭证提供者

![\[混合节点网络连接。\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-prereq-diagram.png)


## 混合网络连接
<a name="hybrid-nodes-prereqs-connect"></a>

Amazon EKS 控制面板和混合节点之间的通信通过您在集群创建期间传递的 VPC 和子网进行路由，此方法以 Amazon EKS 中控制面板到节点联网的[现有机制](https://aws.github.io/aws-eks-best-practices/networking/subnets/)为基础。有多个[有文档记录的选项](https://docs.aws.amazon.com/whitepapers/latest/aws-vpc-connectivity-options/network-to-amazon-vpc-connectivity-options.html)可供选择，以在本地环境与 VPC 之间建立连接，包括 AWS Site-to-Site VPN 和 AWS Direct Connect。有关如何使用这些解决方案实现混合网络连接的更多信息，请参阅 [AWS Site-to-Site VPN](https://docs.aws.amazon.com/vpn/latest/s2svpn/VPC_VPN.html) 和 [AWS Direct Connect](https://docs.aws.amazon.com/directconnect/latest/UserGuide/Welcome.html) 用户指南。

为确保最佳体验，我们建议您从混合节点到 AWS 区域的可靠网络连接至少达到 100 Mbps，并且往返延迟最大 200 毫秒。这是适用于大多数使用案例的一般指导，但并非严格要求。带宽和延迟要求可能因混合节点的数量和工作负载特征而异，例如应用程序映像大小，应用程序弹性、监控和日志记录配置，以及需要访问其他 AWS 服务中所存储数据的应用程序依赖项。我们建议在部署到生产环境之前使用自己的应用程序和环境进行测试，从而验证您的网络设置是否满足工作负载的要求。

## 本地网络配置
<a name="hybrid-nodes-prereqs-onprem"></a>

您必须启用从 Amazon EKS 控制面板到本地环境的入站网络访问权限，以允许 Amazon EKS 控制面板与在混合节点上运行的 `kubelet` 进行通信，此外也可以选择与在混合节点上运行的 Webhook 进行通信。此外，您必须为混合节点以及在其上运行的组件启用出站网络访问权限，确保其能与 Amazon EKS 控制面板进行通信。您可以将此通信配置为完全限定于您的 AWS Direct Connect、AWS Site-to-Site VPN 或您自己的 VPN 连接。

您用于本地节点和容器组（pod）网络的无类别域间路由范围必须使用 IPv4 RFC-1918 或 CGNAT 地址范围。本地路由器必须配置指向本地节点以及（可选）容器组的路由。请参阅[本地联网配置](hybrid-nodes-networking.md#hybrid-nodes-networking-on-prem)以了解有关本地网络要求的更多信息，包括防火墙和本地环境中必须启用的所需端口和协议的完整列表。

## EKS 集群配置
<a name="hybrid-nodes-prereqs-cluster"></a>

为尽可能减少延迟，我们建议您在距离本地或边缘环境最近的 AWS 区域创建 Amazon EKS 集群。您需要在创建 Amazon EKS 集群期间通过以下两个 API 字段来传递本地节点和容器组 CIDR：`RemoteNodeNetwork` 和 `RemotePodNetwork`。您可能需要与本地网络团队讨论，以确定本地节点和容器组 CIDR。节点 CIDR 是从本地网络分配的，如果您为 CNI 使用叠加网络，则容器组 CIDR 是从您使用的容器网络接口（CNI）分配的。默认情况下，Cilium 和 Calico 使用叠加网络。

您通过 `RemoteNodeNetwork` 和 `RemotePodNetwork` 字段配置的本地节点和容器组 CIDR 可用于配置 Amazon EKS 控制面板，以通过您的 VPC 将流量路由到 `kubelet` 以及在混合节点上运行的容器组。您的本地节点和容器组 CIDR 不能相互重叠，不能与您在创建集群时传递的 VPC CIDR 重叠，也不能与 Amazon EKS 集群的服务 IPv4 配置重叠。此外，每个 EKS 集群的容器组（pod）CIDR 必须是唯一的，这样本地路由器才能路由流量。

我们建议为 Amazon EKS Kubernetes API 服务器端点使用公有或私有端点访问权限。如果您选择“公有和私有”，Amazon EKS Kubernetes API 服务器端点将始终解析为在您的 VPC 之外运行的混合节点公有 IP，这可能会阻止您的混合节点加入集群。使用公有端点访问权限时，Kubernetes API 服务器端点将解析为公有 IP，并且从混合节点到 Amazon EKS 控制面板的通信将通过互联网路由。当您选择私有端点访问权限时，Kubernetes API 服务器端点将解析为私有 IP，并且从混合节点到 Amazon EKS 控制面板的通信将通过您的私有连接链路（大部分情况下为 AWS Direct Connect 或 AWS Site-to-Site VPN）进行路由。

## VPC 配置
<a name="hybrid-nodes-prereqs-vpc"></a>

您必须在创建 Amazon EKS 集群期间配置 VPC，并在其路由表中包含本地节点的路由，您还可以配置容器组网络，将您的虚拟专用网关（VGW）或中转网关（TGW）作为目标。下面显示了一个示例。将 `REMOTE_NODE_CIDR` 和 `REMOTE_POD_CIDR` 替换为本地网络的相应值。


| 目标位置 | Target | 说明 | 
| --- | --- | --- | 
|  10.226.0.0/16  |  本地  |  到 VPC 的流量将在 VPC 内部路由  | 
|  REMOTE\$1NODE\$1CIDR  |  tgw-abcdef123456  |  本地节点 CIDR，将流量路由到 TGW  | 
|  REMODE\$1POD\$1CIDR  |  tgw-abcdef123456  |  本地容器组 CIDR，将流量路由到 TGW  | 

## 安全组配置
<a name="hybrid-nodes-prereqs-sg"></a>

在创建集群时，Amazon EKS 将创建一个名为 `eks-cluster-sg-<cluster-name>-<uniqueID>` 的安全组。您无法更改此集群安全组的入站规则，但可以限制出站规则。您必须向集群添加一个额外的安全组，以确保在混合节点上运行的 kubelet 和（可选）Webhook 能够与 Amazon EKS 控制面板通信。对于此额外的安全组，必需的入站规则如下所示。将 `REMOTE_NODE_CIDR` 和 `REMOTE_POD_CIDR` 替换为本地网络的相应值。


| 名称 | 安全组规则 ID | IP 版本 | Type | 协议 | 端口范围 | 来源 | 
| --- | --- | --- | --- | --- | --- | --- | 
|  本地节点入站  |  sgr-abcdef123456  |  IPv4  |  HTTPS  |  TCP  |  443  |  REMOTE\$1NODE\$1CIDR  | 
|  本地容器组入站  |  sgr-abcdef654321  |  IPv4  |  HTTPS  |  TCP  |  443  |  REMOTE\$1POD\$1CIDR  | 

## Infrastructure
<a name="hybrid-nodes-prereqs-infra"></a>

您必须有可用作混合节点的裸机服务器或虚拟机可用。混合节点与底层基础设施无关，x86 和 ARM 架构均受支持。Amazon EKS 混合节点功能采用“自带基础设施”的方法，即您需要自行预置和管理用作混合节点的裸机服务器或虚拟机。虽然没有严格的最低资源要求，但对于混合节点，我们建议您使用至少具有 1 个 vCPU 和 1GiB RAM 的主机。

## 操作系统
<a name="hybrid-nodes-prereqs-os"></a>

Bottlerocket、Amazon Linux 2023（AL2023）、Ubuntu 和 RHEL 均已经过持续验证，可用作混合节点的节点操作系统。AWS 仅在 VMware vSphere 环境中支持 Bottlerocket。在 Amazon EC2 之外运行时，AL2023 不属于 AWS Support 计划的范围。AL2023 只能在本地虚拟化环境中使用；有关更多信息，请参阅《Amazon Linux 2023 User Guide》[https://docs.aws.amazon.com/linux/al2023/ug/outside-ec2.html](https://docs.aws.amazon.com/linux/al2023/ug/outside-ec2.html)。AWS 支持混合节点与 Ubuntu 和 RHEL 操作系统的集成，但不提供对操作系统本身的支持。

操作系统的预置和管理由您负责。首次测试混合节点时，最简单的方法是在一台已预置好的主机上运行 Amazon EKS 混合节点功能 CLI (`nodeadm`)。对于生产部署，建议在黄金操作系统映像中包含 `nodeadm` 并将其配置为作为 systemd 服务运行，从而在主机启动时自动将主机加入 Amazon EKS 集群。

## 本地 IAM 凭证提供者
<a name="hybrid-nodes-prereqs-iam"></a>

Amazon EKS 混合节点功能使用由 AWS SSM 混合激活或 AWS IAM Roles Anywhere 预置的临时 IAM 凭证，来进行 Amazon EKS 集群身份验证。您必须使用 AWS SSM 混合激活，或将 AWS IAM Roles Anywhere 与 Amazon EKS 混合节点功能 CLI (`nodeadm`) 配合使用。如果您没有具有证书颁发机构（CA）的现有公钥基础设施（PKI）和本地环境的证书，我们建议您使用 AWS SSM 混合激活。如果您在确实具有现有的 PKI 和本地证书，请使用 AWS IAM Roles Anywhere。

与适用于在 Amazon EC2 上运行的节点的 [Amazon EKS 节点 IAM 角色](create-node-role.md) 类似，您将创建一个混合节点 IAM 角色，具有将混合节点加入到 Amazon EKS 集群所需的权限。如果您使用 AWS IAM Roles Anywhere，请配置一个信任策略来允许 AWS IAM Roles Anywhere 代入该混合节点 IAM 角色，此外还需要配置您的 AWS IAM Roles Anywhere 配置文件，将该混合节点 IAM 角色作为假设角色。如果您使用 AWS SSM，请配置一个信任策略来允许 AWS SSM 代入混合节点 IAM 角色并使用混合节点 IAM 角色创建混合激活。有关如何创建具有必需权限的混合节点 IAM 角色的信息，请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)。

# 准备混合节点的联网
<a name="hybrid-nodes-networking"></a>

本主题概述创建 Amazon EKS 集群和挂载混合节点之前必须配置的联网设置。本指南假设您已满足使用 [AWS Site-to-Site VPN](https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html)、[AWS Direct Connect](https://docs.aws.amazon.com/directconnect/latest/UserGuide/Welcome.html) 或您自己的 VPN 解决方案进行混合网络连接的先决条件。

![\[混合节点网络连接。\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-prereq-diagram.png)


## 本地联网配置
<a name="hybrid-nodes-networking-on-prem"></a>

### 最低网络要求
<a name="hybrid-nodes-networking-min-reqs"></a>

为确保最佳体验，我们建议您从混合节点到 AWS 区域的可靠网络连接至少达到 100 Mbps，并且往返延迟最大 200 毫秒。这是适用于大多数使用案例的一般指导，但并非严格要求。带宽和延迟要求可能因混合节点的数量和工作负载特征而异，例如应用程序映像大小，应用程序弹性、监控和日志记录配置，以及需要访问其他 AWS 服务中所存储数据的应用程序依赖项。我们建议在部署到生产环境之前使用自己的应用程序和环境进行测试，从而验证您的网络设置是否满足工作负载的要求。

### 本地节点和容器组 CIDR
<a name="hybrid-nodes-networking-on-prem-cidrs"></a>

确定您将用于混合节点以及在其上运行的工作负载的节点和容器组 CIDR。节点 CIDR 是从本地网络分配的，如果您为 CNI 使用叠加网络，则容器组 CIDR 是从您的容器网络接口（CNI）分配的。创建 EKS 集群时，您可以使用 `RemoteNodeNetwork` 和 `RemotePodNetwork` 字段将本地节点 CIDR 和容器组 CIDR 作为输入传递。本地节点 CIDR 必须可在本地网络上路由。有关本地容器组 CIDR 可路由性的信息，请参阅以下一节。

本地节点和容器组 CIDR 块必须满足以下要求：

1. 位于以下 `IPv4` RFC-1918 范围之一：`10.0.0.0/8`、`172.16.0.0/12` 或 `192.168.0.0/16`，或位于 RFC 6598 定义的 CGNAT 范围：`100.64.0.0/10`。

1. 不相互重叠，也不与 EKS 集群的 VPC CIDR 或 Kubernetes 服务 `IPv4` CIDR 重叠。

### 本地容器组网络路由
<a name="hybrid-nodes-networking-on-prem-pod-routing"></a>

使用 EKS 混合节点时，我们通常建议您将本地容器组 CIDR 设置为在本地网络上可路由，以便在云和本地环境之间实现完整的集群通信和功能。

 **可路由的容器组网络** 

如果您能够将容器组网络设置为在本地网络上可路由，则请按照以下指导操作。

1. 使用本地容器 CIDR 配置 EKS 集群的 `RemotePodNetwork` 字段，使用本地容器 CIDR 配置您的 VPC 路由表，以及使用本地容器 CIDR 配置您的 EKS 集群安全组。

1. 您可以通过多种方法来使本地容器组 CIDR 可在本地网络上路由，包括边界网关协议（BGP）、静态路由或其他自定义路由解决方案。我们推荐使用 BGP 解决方案，因为与需要自定义或手动路由配置的备选解决方案相比，此方案具有更好的可扩展性并且更易于管理。AWS 支持使用 Cilium 和 Calico 的 BGP 功能来公开容器组 CIDR，有关更多信息，请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md)和[可路由的远程容器组（pod）CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)。

1. Webhook 可以在混合节点上运行，因为 EKS 控制面板能够与分配给 Webhook 的容器组 IP 地址进行通信。

1. 在云节点上运行的工作负载能够直接与同一 EKS 集群中混合节点上运行的工作负载进行通信。

1. 其他 AWS 服务（例如 AWS 应用程序负载均衡器和 Amazon Managed Service for Prometheus）能够与在混合节点上运行的工作负载进行通信，以平衡网络流量并抓取容器组指标。

 **不可路由的容器组网络** 

如果您*无法*将容器组网络设置为在本地网络上可路由，则请按照以下指导操作。

1. Webhook 无法在混合节点上运行，因为 Webhook 需要从 EKS 控制面板连接到分配给 Webhook 的容器组 IP 地址。在这种情况下，我们建议您在与混合节点位于同一 EKS 集群中的云节点上运行 Webhook；有关更多信息，请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

1. 对云节点使用 VPC CNI 并对混合节点使用 Cilium 或 Calico 时，在云节点上运行的工作负载无法直接与在混合节点上运行的工作负载进行通信。

1. 使用服务流量分布将流量保持在其源区域的本地。有关服务流量分布的更多信息，请参阅[配置服务流量分布](hybrid-nodes-webhooks.md#hybrid-nodes-mixed-service-traffic-distribution)。

1. 将 CNI 配置为在离开本地主机时对容器组流量使用出口伪装或网络地址转换（NAT）。此项在 Cilium 中默认为启用状态。Calico 需要将 `natOutgoing` 设置为 `true`。

1. 其他 AWS 服务（例如 AWS 应用程序负载均衡器和 Amazon Managed Service for Prometheus）能够与在混合节点上运行的工作负载进行通信。

### 混合节点安装和升级期间必需的访问权限
<a name="hybrid-nodes-networking-access-reqs"></a>

在安装过程中，您必须具有以下域的访问权限，以便在主机上安装混合节点依赖项。此过程可以在生成操作系统映像时一次执行，也可以在运行时中在每台主机上完成。这包括初始安装以及升级混合节点的 Kubernetes 版本时。

某些软件包使用操作系统的默认软件包管理器进行安装。对于 AL2023 和 RHEL，使用 `yum` 命令安装 `containerd`、`ca-certificates`、`iptables` 和 `amazon-ssm-agent`。对于 Ubuntu，使用 `apt` 安装 `containerd`、`ca-certificates` 和 `iptables`，并使用 `snap` 安装 `amazon-ssm-agent`。


| 组件 | URL | 协议 | 端口： | 
| --- | --- | --- | --- | 
|  EKS 节点构件（S3）  |  https://hybrid-assets.eks.amazonaws.com  |  HTTPS  |  443  | 
|   [EKS 服务端点](https://docs.aws.amazon.com/general/latest/gr/eks.html)   |  https://eks.*region*.amazonaws.com  |  HTTPS  |  443  | 
|   [ECR 服务端点](https://docs.aws.amazon.com/general/latest/gr/ecr.html)   |  https://api.ecr.*region*.amazonaws.com  |  HTTPS  |  443  | 
|  EKS ECR 端点  |  区域性端点请参阅[查看 Amazon EKS 附加组件的 Amazon 容器映像注册表](add-ons-images.md)。  |  HTTPS  |  443  | 
|  SSM 二进制端点 1   |  https://amazon-ssm-*region*.s3.*region*.amazonaws.com  |  HTTPS  |  443  | 
|   [SSM 服务端点](https://docs.aws.amazon.com/general/latest/gr/ssm.html) 1   |  https://ssm.*region*.amazonaws.com  |  HTTPS  |  443  | 
|  IAM Anywhere 二进制端点 2   |  https://rolesanywhere.amazonaws.com  |  HTTPS  |  443  | 
|   [IAM Anywhere 服务端点](https://docs.aws.amazon.com/general/latest/gr/rolesanywhere.html) 2   |  https://rolesanywhere.*region*.amazonaws.com  |  HTTPS  |  443  | 
|  操作系统软件包管理器端点  |  软件包存储库端点是特定于操作系统的端点，并且可能因地理区域而异。  |  HTTPS  |  443  | 

**注意**  
 1 仅在将 AWS SSM 混合激活用作本地 IAM 凭证提供者时，才需要 AWS SSM 端点访问权限。  
 2 仅在将 AWS IAM Roles Anywhere 用作本地 IAM 凭证提供者时，才需要 AWS IAM 端点访问权限。

### 正在进行的集群操作需要的访问权限
<a name="hybrid-nodes-networking-access-reqs-ongoing"></a>

正在进行的集群操作需要拥有本地防火墙的以下网络访问权限。

**重要**  
根据您选择的 CNI，您需要为 CNI 端口配置其他网络访问规则。有关详细信息，请参阅 [Cilium 文档](https://docs.cilium.io/en/stable/operations/system_requirements/#firewall-rules)和 [Calico 文档](https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements#network-requirements)。


| Type | 协议 | Direction | 端口： | 来源 | 目标 | 用法 | 
| --- | --- | --- | --- | --- | --- | --- | 
|  HTTPS  |  TCP  |  出站  |  443  |  远程节点 CIDR  |  EKS 集群 IP 1   |  Kubelet 到 Kubernetes API 服务器  | 
|  HTTPS  |  TCP  |  出站  |  443  |  远程容器组 CIDR  |  EKS 集群 IP 1   |  容器组（pod）到 Kubernetes API 服务器  | 
|  HTTPS  |  TCP  |  出站  |  443  |  远程节点 CIDR  |   [SSM 服务端点](https://docs.aws.amazon.com/general/latest/gr/ssm.html)   |  SSM 混合激活凭证刷新和 SSM 心跳信号发送每隔 5 分钟进行一次  | 
|  HTTPS  |  TCP  |  出站  |  443  |  远程节点 CIDR  |   [IAM Anywhere 服务端点](https://docs.aws.amazon.com/general/latest/gr/rolesanywhere.html)   |  IAM Roles Anywhere 凭证刷新  | 
|  HTTPS  |  TCP  |  出站  |  443  |  远程容器组 CIDR  |   [STS 区域性端点](https://docs.aws.amazon.com/general/latest/gr/sts.html)   |  容器组（pod）到 STS 端点，仅对 IRSA 为必需  | 
|  HTTPS  |  TCP  |  出站  |  443  |  远程节点 CIDR  |   [Amazon EKS 身份验证服务端点](https://docs.aws.amazon.com/general/latest/gr/eks.html)   |  节点到 Amazon EKS 身份验证端点，仅对 Amazon EKS 容器组身份为必需  | 
|  HTTPS  |  TCP  |  入站  |  10250  |  EKS 集群 IP 1   |  远程节点 CIDR  |  Kubernetes API 服务器到 kubelet  | 
|  HTTPS  |  TCP  |  入站  |  Webhook 端口  |  EKS 集群 IP 1   |  远程容器组 CIDR  |  Kubernetes API 服务器到 Webhook  | 
|  HTTPS  |  TCP、UDP  |  入站、出站  |  53  |  远程容器组 CIDR  |  远程容器组 CIDR  |  容器组（pod）到 CoreDNS。如果您在云端运行至少 1 个 CoreDNS 副本，则必须允许指向运行 CoreDNS 的 VPC 的 DNS 流量。  | 
|  用户定义  |  用户定义  |  入站、出站  |  应用程序端口  |  远程容器组 CIDR  |  远程容器组 CIDR  |  容器组（pod）到容器组（pod）  | 

**注意**  
 1 EKS 集群的 IP。请参阅以下有关 Amazon EKS 弹性网络接口的章节。

### Amazon EKS 网络接口
<a name="hybrid-nodes-networking-eks-network-interfaces"></a>

Amazon EKS 将网络接口附加到您在集群创建期间传递的 VPC 中的子网，从而实现 EKS 控制面板与您的 VPC 之间的通信。Amazon EKS 创建的网络接口可以在集群创建后通过 Amazon EC2 控制台查看，也可以通过 AWS CLI 查看。对 EKS 集群应用更改（例如 Kubernetes 版本升级）时，系统会删除原始网络接口并创建新的网络接口。您可以在集群创建期间传递子网时使用受限子网大小来限制 Amazon EKS 网络接口的 IP 范围，从而更轻松地配置本地防火墙，允许与已知受限 IP 集的入站/出站连接。要控制要在其中创建网络接口的子网，您可以在创建集群时限制指定的子网数，或者在创建集群后更新子网。

由 Amazon EKS 预置的网络接口的描述格式为 `Amazon EKS your-cluster-name `。有关可用于查找 Amazon EKS 所预置网络接口的 IP 地址的 AWS CLI 命令，请参阅以下示例。请将 `VPC_ID` 替换为您在创建集群时传递的 VPC 的 ID。

```
aws ec2 describe-network-interfaces \
--query 'NetworkInterfaces[?(VpcId == VPC_ID && contains(Description,Amazon EKS))].PrivateIpAddress'
```

## AWS VPC 和子网设置
<a name="hybrid-nodes-networking-vpc"></a>

Amazon EKS 的现有 [VPC 和子网要求](network-reqs.md)适用于使用混合节点的集群。此外，VPC CIDR 不能与本地节点和容器组 CIDR 重叠。必须在 VPC 路由表中为本地节点以及（可选）容器组 CIDR 配置路由。这些路由必须设置为将流量路由到用于混合网络连接的网关，这通常是虚拟专用网关（VGW）或中转网关（TGW）。如果您使用 TGW 或 VGW 来连接 VPC 和本地环境，则必须为您的 VPC 创建 TGW 或 VGW 连接。VPC 必须具有 DNS 主机名和 DNS 解析支持。

以下步骤会用到 AWS CLI。您还可以在 AWS 管理控制台中或使用其他接口（例如 AWS CloudFormation、AWS CDK 或 Terraform）创建这些资源。

### 第 1 步：创建 VPC
<a name="_step_1_create_vpc"></a>

1. 运行以下命令以创建一个 VPC。将 VPC\$1CIDR 替换为符合 RFC 1918（私有）、CGNAT（RFC 6598）或非 RFC 1918/非 CGNAT（公有）的 IPv4 CIDR 范围（例如 10.0.0.0/16）。注意：VPC 会默认启用 DNS 解析，这是 EKS 的一项要求。

   ```
   aws ec2 create-vpc --cidr-block VPC_CIDR
   ```

1. 为 VPC 启用 DNS 主机名。VPC 会默认启用 DNS 解析。请将 `VPC_ID` 替换为在上一步中创建的 VPC 的 ID。

   ```
   aws ec2 modify-vpc-attribute --vpc-id VPC_ID --enable-dns-hostnames
   ```

### 第 2 步：创建子网
<a name="_step_2_create_subnets"></a>

至少创建 2 个子网。Amazon EKS 会将这些子网作为集群网络接口。有关更多信息，请参阅[子网要求和注意事项](network-reqs.md#network-requirements-subnets)。

1. 您可以使用以下命令找到 AWS 区域的可用区。请将 `us-west-2` 替换为您的区域。

   ```
   aws ec2 describe-availability-zones \
        --query 'AvailabilityZones[?(RegionName == us-west-2)].ZoneName'
   ```

1. 创建子网。请将 `VPC_ID` 替换为 VPC 的 ID。请将 `SUBNET_CIDR` 替换为子网的 CIDR 块（例如 10.0.1.0/24）。请将 `AZ` 替换为将在其中创建子网的可用区（例如 us-west-2a）。您创建的子网必须至少位于 2 个不同的可用区。

   ```
   aws ec2 create-subnet \
       --vpc-id VPC_ID \
       --cidr-block SUBNET_CIDR \
       --availability-zone AZ
   ```

### （可选）第 3 步：使用 Amazon VPC Transit Gateway（TGW）或 AWS Direct Connect 虚拟专用网关（VGW）附加 VPC
<a name="optional_step_3_attach_vpc_with_amazon_vpc_transit_gateway_tgw_or_shared_aws_direct_connect_virtual_private_gateway_vgw"></a>

如果使用 TGW 或 VGW，请将您的 VPC 连接到该 TGW 或 VGW。有关更多信息，请参阅 [Amazon VPC attachments in Amazon VPC Transit Gateways](https://docs.aws.amazon.com/vpc/latest/tgw/tgw-vpc-attachments.html) 或 [AWS Direct Connect virtual private gateway associations](https://docs.aws.amazon.com/vpn/latest/s2svpn/how_it_works.html#VPNGateway)。

 **Transit Gateway** 

运行以下命令连接某个中转网关。请将 `VPC_ID` 替换为 VPC 的 ID。请将 `SUBNET_ID1` 和 `SUBNET_ID2` 替换为在上一步中创建的子网的 ID。请将 `TGW_ID` 替换为 TGW 的 ID。

```
aws ec2 create-transit-gateway-vpc-attachment \
    --vpc-id VPC_ID \
    --subnet-ids SUBNET_ID1 SUBNET_ID2 \
    --transit-gateway-id TGW_ID
```

 **虚拟专用网关** 

运行以下命令连接某个中转网关。请将 `VPN_ID` 替换为 VGW 的 ID。请将 `VPC_ID` 替换为 VPC 的 ID。

```
aws ec2 attach-vpn-gateway \
    --vpn-gateway-id VPN_ID \
    --vpc-id VPC_ID
```

### （可选）第 4 步：创建路由表
<a name="_optional_step_4_create_route_table"></a>

您可以修改 VPC 的主路由表，也可以创建自定义路由表。以下步骤将创建一个自定义路由表，其中包含本地节点和容器组 CIDR 的路由。有关更多信息，请参阅[子网路由表](https://docs.aws.amazon.com/vpc/latest/userguide/subnet-route-tables.html)。请将 `VPC_ID` 替换为 VPC 的 ID。

```
aws ec2 create-route-table --vpc-id VPC_ID
```

### 第 5 步：创建本地节点和容器组的路由
<a name="_step_5_create_routes_for_on_premises_nodes_and_pods"></a>

在路由表中创建每个本地远程节点的路由。您可以修改 VPC 的主路由表，也可以使用您在上一步中创建的自定义路由表。

以下示例展示了如何创建本地节点和容器组 CIDR 的路由。这些示例使用中转网关（TGW）将 VPC 连接到本地环境。如果您有多个本地节点和容器组 CIDR，请对每个 CIDR 重复这些步骤。
+ 如果您使用互联网网关或虚拟专用网关（VGW），请将 `--transit-gateway-id` 替换为 `--gateway-id`。
+ 请将 `RT_ID` 替换为在上一步中创建的路由表的 ID。
+ 请将 `REMOTE_NODE_CIDR` 替换为将用于混合节点的 CIDR 范围。
+ 请将 `REMOTE_POD_CIDR` 替换为将在混合节点上运行的容器组的 CIDR 范围。容器组 CIDR 范围对应于容器网络接口（CNI）配置，后者最常使用的是叠加本地网络。有关更多信息，请参阅 [为混合节点配置 CNI](hybrid-nodes-cni.md)。
+ 请将 `TGW_ID` 替换为 TGW 的 ID。

 **远程节点网络** 

```
aws ec2 create-route \
    --route-table-id RT_ID \
    --destination-cidr-block REMOTE_NODE_CIDR \
    --transit-gateway-id TGW_ID
```

 **远程容器组（pod）网络** 

```
aws ec2 create-route \
    --route-table-id RT_ID \
    --destination-cidr-block REMOTE_POD_CIDR \
    --transit-gateway-id TGW_ID
```

### （可选）第 6 步：将子网关联到路由表
<a name="_optional_step_6_associate_subnets_with_route_table"></a>

如果在上一步中创建了自定义路由表，请将您在上一步中创建的每个子网关联到您的自定义路由表。如果您选择修改 VPC 主路由表，则子网会自动关联到 VPC 的主路由表，因此可以跳过此步骤。

为您在之前步骤中创建的每个子网运行以下命令。请将 `RT_ID` 替换为在上一步中创建的路由表。请将 `SUBNET_ID` 替换为子网的 ID。

```
aws ec2 associate-route-table --route-table-id RT_ID --subnet-id SUBNET_ID
```

## 集群安全组配置
<a name="hybrid-nodes-networking-cluster-sg"></a>

EKS 集群安全组需要具有以下访问权限才能进行持续集群操作。当您创建或更新配置了远程节点和容器组（pod）网络的集群时，Amazon EKS 会自动为混合节点创建所需的**入站**安全组规则。默认情况下，安全组允许所有**出站**流量，因此 Amazon EKS 不会自动为混合节点修改集群安全组的**出站**规则。如果要自定义集群安全组，可将流量限制在下表中的规则范围内。


| Type | 协议 | Direction | 端口： | 来源 | 目标 | 用法 | 
| --- | --- | --- | --- | --- | --- | --- | 
|  HTTPS  |  TCP  |  入站  |  443  |  远程节点 CIDR  |  不适用  |  Kubelet 到 Kubernetes API 服务器  | 
|  HTTPS  |  TCP  |  入站  |  443  |  远程容器组 CIDR  |  不适用  |  当 CNI 未使用 NAT 来处理容器组流量时，容器组需要访问 K8s API 服务器的权限。  | 
|  HTTPS  |  TCP  |  出站  |  10250  |  不适用  |  远程节点 CIDR  |  Kubernetes API 服务器到 Kubelet  | 
|  HTTPS  |  TCP  |  出站  |  Webhook 端口  |  不适用  |  远程容器组 CIDR  |  Kubernetes API 服务器到 Webhook（如果在混合节点上运行 Webhook）  | 

**重要**  
 **安全组规则限制**：Amazon EC2 安全组默认最多有 60 条入站规则。如果集群安全组接近此限制，则安全组入站规则可能无法生效。在这种情况下，可能需要手动添加缺少的入站规则。  
 **CIDR 清理责任**：如果您从 EKS 集群中移除远程节点或容器组（pod）网络，EKS 不会自动移除相应的安全组规则。您负责从安全组规则中手动移除未使用的远程节点或容器组（pod）网络。

有关 Amazon EKS 创建的集群安全组的更多信息，请参阅 [查看集群的 Amazon EKS 安全组要求](sec-group-reqs.md)。

### （可选）手动安全组配置
<a name="_optional_manual_security_group_configuration"></a>

如果您需要创建其他安全组或修改自动创建的规则，可以参考以下命令。默认情况下，以下命令会创建一个允许所有出站访问的安全组。您可以将出站访问范围限定为仅包含上述规则。如果您考虑限制出站规则，我们建议您首先全面测试所有应用程序和容器组，然后再将更改后的规则应用于生产集群。
+ 请将第一个命令中的 `SG_NAME` 替换为安全组的名称
+ 请将第一个命令中的 `VPC_ID` 替换为在上一步中创建的 VPC 的 ID
+ 请将第二个命令中的 `SG_ID` 替换为您在第一个命令中创建的安全组的 ID
+ 请将第二个命令中的 `REMOTE_NODE_CIDR` 和 `REMOTE_POD_CIDR` 替换为混合节点和本地网络的相应值。

```
aws ec2 create-security-group \
    --group-name SG_NAME \
    --description "security group for hybrid nodes" \
    --vpc-id VPC_ID
```

```
aws ec2 authorize-security-group-ingress \
    --group-id SG_ID \
    --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 443, "ToPort": 443, "IpRanges": [{"CidrIp": "REMOTE_NODE_CIDR"}, {"CidrIp": "REMOTE_POD_CIDR"}]}]'
```

# 为混合节点准备操作系统
<a name="hybrid-nodes-os"></a>

Bottlerocket、Amazon Linux 2023（AL2023）、Ubuntu 和 RHEL 均已经过持续验证，可用作混合节点的节点操作系统。AWS 仅在 VMware vSphere 环境中支持 Bottlerocket。在 Amazon EC2 之外运行时，AL2023 不属于 AWS Support 计划的范围。AL2023 只能在本地虚拟化环境中使用；有关更多信息，请参阅《Amazon Linux 2023 User Guide》[https://docs.aws.amazon.com/linux/al2023/ug/outside-ec2.html](https://docs.aws.amazon.com/linux/al2023/ug/outside-ec2.html)。AWS 支持混合节点与 Ubuntu 和 RHEL 操作系统的集成，但不提供对操作系统本身的支持。

操作系统的预置和管理由您负责。首次测试混合节点时，最简单的方法是在一台已预置好的主机上运行 Amazon EKS 混合节点功能 CLI (`nodeadm`)。对于生产部署，建议在操作系统映像中包含 `nodeadm` 并将其配置为作为 systemd 服务运行，从而在主机启动时自动将主机加入 Amazon EKS 集群。如果在 vSphere 上将 Bottlerocket 作为节点操作系统使用，则无需使用 `nodeadm`，因为 Bottlerocket 已经包含混合节点功能所需的依赖项，并且会在主机启动时自动连接到您配置的集群。

## 版本兼容性
<a name="_version_compatibility"></a>

下表列举了经过验证可用作混合节点节点操作系统的兼容操作系统版本。如果使用此表中未包含的其他操作系统变体或版本，则混合节点与相关操作系统变体或版本的兼容性不属于 AWS Support 的范围。混合节点与底层基础设施无关，x86 和 ARM 架构均受支持。


| 操作系统 | 版本 | 
| --- | --- | 
|  Amazon Linux  |  Amazon Linux 2023（AL2023）  | 
|  Bottlerocket  |  运行 Kubernetes v1.28 及更高版本的 v1.37.0 及以上版本的 VMware 变体  | 
|  Ubuntu  |  Ubuntu 20.04、Ubuntu 22.04、Ubuntu 24.04  | 
|  Red Hat Enterprise Linux  |  RHEL 8、RHEL 9  | 

## 操作系统注意事项
<a name="_operating_system_considerations"></a>

### General
<a name="_general"></a>
+ Amazon EKS 混合节点功能 CLI (`nodeadm`) 可用于简化混合节点组件和依赖项的安装和配置。您可以在操作系统映像生成管道期间运行 `nodeadm install` 进程，也可以在每台本地主机的运行时中运行该进程。有关 `nodeadm` 将安装的组件的更多信息，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。
+ 如果您使用本地环境的代理来访问互联网，则安装和升级过程需要完成额外的操作系统配置，才能将软件包管理器配置为使用该代理。有关说明，请参阅[为混合节点功能配置代理](hybrid-nodes-proxy.md)：

### Bottlerocket
<a name="_bottlerocket"></a>
+ 连接 Bottlerocket 节点的步骤和工具与连接其他操作系统节点的步骤不同，将在[连接使用 Bottlerocket 的混合节点](hybrid-nodes-bottlerocket.md)中单独介绍，而不是使用[连接混合节点](hybrid-nodes-join.md)中的步骤。
+ 适用于 Bottlerocket 的步骤不使用混合节点 CLI 工具 `nodeadm`。
+ 仅支持将 Bottlerocket 版本 v1.37.0 及更高版本的 VMware 变体与 EKS 混合节点结合使用。Bottlerocket 的 VMware 变体支持 Kubernetes 版本 1.28 及更高版本。不支持将[其他 Bottlerocket 变体](https://bottlerocket.dev/en/os/1.36.x/concepts/variants)用作混合节点操作系统。注意：Bottlerocket 的 VMware 变体仅支持 x86\$164 架构。

### Containerd
<a name="_containerd"></a>
+ Containerd 是标准的 Kubernetes 容器运行时，也是混合节点以及所有 Amazon EKS 节点计算类型的一个依赖项。Amazon EKS 混合节点功能 CLI (`nodeadm`) 会尝试在 `nodeadm install` 进程中安装 containerd。您可以使用 `--containerd-source` 命令行选项在 `nodeadm install` 运行时中配置 containerd 安装。有效选项为 `none`、`distro`、和 `docker`。如果使用 RHEL，则 `distro` 不是有效选项，并且您可以将 `nodeadm` 配置为按照 Docker 存储库中的 containerd 版本，也可以手动安装 containerd。使用 AL2023 或 Ubuntu 时，`nodeadm` 默认为安装操作系统发行版中的 containerd。如果不希望 nodeadm 安装 containerd，请使用 `--containerd-source none` 选项。

### Ubuntu
<a name="_ubuntu"></a>
+ 如果您使用的是 Ubuntu 24.04，则可能需要更新 containerd 版本或更改 AppArmor 配置，以采用一个可让容器组（pod）正确终止的修复程序，请参阅 [Ubuntu \$12065423](https://bugs.launchpad.net/ubuntu/+source/containerd-app/\+bug/2065423)。需要重启后才能将更改应用于 AppArmor 配置文件。最新版本 Ubuntu 24.04 的包管理器中包含更新的 containerd 版本，其中具有该修复程序（containerd 版本 1.7.19\$1）。

### ARM
<a name="_arm"></a>
+ 如果使用的是 ARM 硬件，则需要带有加密扩展（ARMv8.2\$1crypto）的 ARMv8.2 兼容处理器，才能运行 1.31 版本及更高版本的 EKS kube-proxy 附加组件。Raspberry Pi 5 之前的所有 Raspberry Pi 系统以及基于 Cortex-A72 的处理器都不符合此要求。要解决此问题，可以继续使用 1.30 版本的 EKS kube-proxy 附加组件，直到其延期支持在 2026 年 7 月终止（请参阅 [Kubernetes 发布日历](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)）；也可以使用来自上游的自定义 kube-proxy 映像。
+ Kube-proxy 日志中的以下错误消息表明存在这样的不兼容性问题：

```
Fatal glibc error: This version of Amazon Linux requires a newer ARM64 processor compliant with at least ARM architecture 8.2-a with Cryptographic extensions. On EC2 this is Graviton 2 or later.
```

## 生成操作系统映像
<a name="_building_operating_system_images"></a>

Amazon EKS 提供了[示例 Packer 模板](https://github.com/aws/eks-hybrid/tree/main/example/packer)，您可以使用这些模板来创建包含 `nodeadm` 的操作系统映像，并将其配置为在主机启动时运行。建议使用此过程以避免在每台主机上分别拉取混合节点的依赖项，并自动完成混合节点的引导过程。您可以将示例 Packer 模板与 Ubuntu 22.04、Ubuntu 24.04、RHEL 8 或 RHEL 9 ISO 映像一起使用，并且可以输出以下格式的映像：OVA、Qcow2 或 Raw。

### 先决条件
<a name="_prerequisites"></a>

在使用示例 Packer 模板之前，必须在运行 Packer 的计算机上安装以下项目。
+ Packer 版本 1.11.0 或更高版本。有关安装 Packer 的说明，请参阅 Packer 文档中的 [Install Packer](https://developer.hashicorp.com/packer/tutorials/docker-get-started/get-started-install-cli)。
+ 如果生成 OVA，则必须已安装 VMware vSphere 插件 1.4.0 或更高版本
+ 如果生成 `Qcow2` 或原始映像，则必须已安装 QEMU 插件版本 1.x

### 设置环境变量
<a name="_set_environment_variables"></a>

在运行此 Packer 生成版本之前，请在运行 Packer 的计算机上设置以下环境变量。

 **General** 

要生成各种操作系统和输出格式的映像，必须设置以下环境变量。


| 环境变量 | 类型 | 说明 | 
| --- | --- | --- | 
|  PKR\$1SSH\$1PASSWORD  |  字符串  |  Packer 使用 `ssh_username` 和 `ssh_password` 变量以在预置时通过 SSH 连接到创建的计算机。这需要与在相应操作系统的 kickstart 文件或 user-data 文件中创建初始用户时使用的密码一致。默认设置为“builder器”或“ubuntu”，具体因操作系统而异。设置密码时，请务必在相应的 `ks.cfg` 或 `user-data` 文件中进行更改以确保一致。  | 
|  ISO\$1URL  |  字符串  |  要使用的 ISO URL。这可以是从服务器下载的 Web 链接，也可以是本地文件的绝对路径  | 
|  ISO\$1CHECKSUM  |  字符串  |  所提供 ISO 的相关校验和。  | 
|  CREDENTIAL\$1PROVIDER  |  字符串  |  混合节点的凭证提供者。SSM 混合激活的有效值为 `ssm`（默认），IAM Roles Anywhere 的有效值为 `iam`  | 
|  K8S\$1VERSION  |  字符串  |  适用于混合节点的 Kubernetes 版本（例如 `1.31`）。有关支持的 Kubernetes 版本，请参阅 [Amazon EKS 支持的版本](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)。  | 
|  NODEADM\$1ARCH  |  字符串  |  适用于 `nodeadm install` 的架构。选择 `amd` 或 `arm`。  | 

 **RHEL** 

如果使用 RHEL，则必须设置以下环境变量。


| 环境变量 | 类型 | 说明 | 
| --- | --- | --- | 
|  RH\$1USERNAME  |  字符串  |  RHEL 订阅管理员用户名  | 
|  RH\$1PASSWORD  |  字符串  |  RHEL 订阅管理器密码  | 
|  RHEL\$1VERSION  |  字符串  |  使用的 Rhel iso 版本。有效值为 `8` 或 `9`。  | 

 **Ubuntu** - 

没有特定于 Ubuntu 的环境变量。

 **vSphere** 

如果构建 VMware vSphere OVA，则必须设置以下环境变量。


| 环境变量 | 类型 | 说明 | 
| --- | --- | --- | 
|  VSPHERE\$1SERVER  |  字符串  |  vSphere 服务器地址  | 
|  VSPHERE\$1USER  |  字符串  |  vSphere 用户名  | 
|  VSPHERE\$1PASSWORD  |  字符串  |  vSphere 密码  | 
|  VSPHERE\$1DATACENTER  |  字符串  |  vSphere 数据中心名称  | 
|  VSPHERE\$1CLUSTER  |  字符串  |  vSphere 集群名称  | 
|  VSPHERE\$1DATASTORE  |  字符串  |  vSphere 数据存储名称  | 
|  VSPHERE\$1NETWORK  |  字符串  |  vSphere 网络名称  | 
|  VSPHERE\$1OUTPUT\$1FOLDER  |  字符串  |  模板的 vSphere 输出文件夹  | 

 **QEMU** 


| 环境变量 | 类型 | 说明 | 
| --- | --- | --- | 
|  PACKER\$1OUTPUT\$1FORMAT  |  字符串  |  QEMU 生成器的输出格式。有效值为 `qcow2` 和 `raw`。  | 

 **验证模版** 

在运行生成的版本之前，请在设置环境变量后使用以下命令验证模板。如果您的模板使用其他名称，请相应替换 `template.pkr.hcl`。

```
packer validate template.pkr.hcl
```

### 生成映像
<a name="_build_images"></a>

使用以下命令生成映像，并使用 `-only` 标志来指定映像的目标和操作系统。如果您的模板使用其他名称，请相应替换 `template.pkr.hcl`。

 **vSphere OVA** 

**注意**  
如果将 RHEL 与 vSphere 结合使用，则需要将 kickstart 文件转换为 OEMDRV 映像，然后将其传递为要用于启动的 ISO。有关更多信息，请参阅 EKS 混合节点 GitHub 存储库中的 [Packer Readme](https://github.com/aws/eks-hybrid/tree/main/example/packer#utilizing-rhel-with-vsphere)。

 **Ubuntu 22.04 OVA** 

```
packer build -only=general-build.vsphere-iso.ubuntu22 template.pkr.hcl
```

 **Ubuntu 24.04 OVA** 

```
packer build -only=general-build.vsphere-iso.ubuntu24 template.pkr.hcl
```

 **RHEL 8 OVA** 

```
packer build -only=general-build.vsphere-iso.rhel8 template.pkr.hcl
```

 **RHEL 9 OVA** 

```
packer build -only=general-build.vsphere-iso.rhel9 template.pkr.hcl
```

 **QEMU** 

**注意**  
如果要为其生成映像的特定主机 CPU 生成与生成器主机不匹配，请参阅 [QEMU](https://www.qemu.org/docs/master/system/qemu-cpu-models.html) 文档以获取与主机 CPU 匹配的名称，并在运行以下命令时将 `-cpu` 标志与该主机 CPU 的名称结合使用。

 **Ubuntu 22.04 Qcow2 / Raw** 

```
packer build -only=general-build.qemu.ubuntu22 template.pkr.hcl
```

 **Ubuntu 24.04 Qcow2 / Raw** 

```
packer build -only=general-build.qemu.ubuntu24 template.pkr.hcl
```

 **RHEL 8 Qcow2 / Raw** 

```
packer build -only=general-build.qemu.rhel8 template.pkr.hcl
```

 **RHEL 9 Qcow2 / Raw** 

```
packer build -only=general-build.qemu.rhel9 template.pkr.hcl
```

### 通过 user-data 传递 nodeadm 配置
<a name="_pass_nodeadm_configuration_through_user_data"></a>

您可以通过 cloud-init 在 user-data 中传递 `nodeadm` 的配置，从而配置混合节点并在主机启动时自动将其连接到 EKS 集群。以下示例演示了如何在将 VMware vSphere 作为混合节点的基础设施时实现这一点。

1. 按照 GitHub 上 [govc readme](https://github.com/vmware/govmomi/blob/main/govc/README.md) 中的说明安装 `govc` CLI。

1. 运行上一节中的 Packer 版本并预置模板后，您可以通过使用以下方法克隆模板来创建多个不同的节点。您必须为要创建的用于混合节点的每个新 VM 克隆该模板。请将以下命令中的变量替换为您的环境的相应值。当您通过 `metadata.yaml` 文件注入 VM 的名称时，以下命令中的 `VM_NAME` 将用作 `NODE_NAME`。

   ```
   govc vm.clone -vm "/PATH/TO/TEMPLATE" -ds="YOUR_DATASTORE" \
       -on=false -template=false -folder=/FOLDER/TO/SAVE/VM "VM_NAME"
   ```

1. 在为每个新 VM 克隆该模板后，为您的 VM 创建一个 `userdata.yaml` 和 `metadata.yaml`。VM 可以共享同一 `userdata.yaml` 和 `metadata.yaml`，并且您将在以下步骤中为每个 VM 填充这些参数。`nodeadm` 配置是在 `userdata.yaml` 的 `write_files` 部分中创建和定义的。以下示例将 AWS SSM 混合激活作为混合节点的本地凭证提供者。有关 `nodeadm` 配置的更多信息，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

    **userdata.yaml：**

   ```
   #cloud-config
   users:
     - name: # username for login. Use 'builder' for RHEL or 'ubuntu' for Ubuntu.
       passwd: # password to login. Default is 'builder' for RHEL.
       groups: [adm, cdrom, dip, plugdev, lxd, sudo]
       lock-passwd: false
       sudo: ALL=(ALL) NOPASSWD:ALL
       shell: /bin/bash
   
   write_files:
     - path: /usr/local/bin/nodeConfig.yaml
       permissions: '0644'
       content: |
         apiVersion: node.eks.aws/v1alpha1
         kind: NodeConfig
         spec:
             cluster:
                 name: # Cluster Name
                 region: # AWS region
             hybrid:
                 ssm:
                     activationCode: # Your ssm activation code
                     activationId: # Your ssm activation id
   
   runcmd:
     - /usr/local/bin/nodeadm init -c file:///usr/local/bin/nodeConfig.yaml >> /var/log/nodeadm-init.log 2>&1
   ```

    **metadata.yaml：**

   为您的环境创建一个 `metadata.yaml`。保留文件中的 `"$NODE_NAME"` 变量格式，因为这将使用后续步骤中的值填充。

   ```
   instance-id: "$NODE_NAME"
   local-hostname: "$NODE_NAME"
   network:
     version: 2
     ethernets:
       nics:
         match:
           name: ens*
         dhcp4: yes
   ```

1. 使用以下命令将 `userdata.yaml` 和 `metadata.yaml` 文件添加为 `gzip+base64` 字符串。应为要创建的每个 VM 运行以下命令。请将 `VM_NAME` 替换为要更新的 VM 的名称。

   ```
   export NODE_NAME="VM_NAME"
   export USER_DATA=$(gzip -c9 <userdata.yaml | base64)
   
   govc vm.change -dc="YOUR_DATASTORE" -vm "$NODE_NAME" -e guestinfo.userdata="${USER_DATA}"
   govc vm.change -dc="YOUR_DATASTORE" -vm "$NODE_NAME" -e guestinfo.userdata.encoding=gzip+base64
   
   envsubst '$NODE_NAME' < metadata.yaml > metadata.yaml.tmp
   export METADATA=$(gzip -c9 <metadata.yaml.tmp | base64)
   
   govc vm.change -dc="YOUR_DATASTORE" -vm "$NODE_NAME" -e guestinfo.metadata="${METADATA}"
   govc vm.change -dc="YOUR_DATASTORE" -vm "$NODE_NAME" -e guestinfo.metadata.encoding=gzip+base64
   ```

1. 将新 VM 开机，这时应会自动连接到您配置的 EKS 集群。

   ```
   govc vm.power -on "${NODE_NAME}"
   ```

# 准备用于混合节点的凭证
<a name="hybrid-nodes-creds"></a>

Amazon EKS 混合节点功能使用由 AWS SSM 混合激活或 AWS IAM Roles Anywhere 预置的临时 IAM 凭证，来进行 Amazon EKS 集群身份验证。您必须使用 AWS SSM 混合激活，或将 AWS IAM Roles Anywhere 与 Amazon EKS 混合节点功能 CLI (`nodeadm`) 配合使用。您不应同时使用 AWS SSM 混合激活和 AWS IAM Roles Anywhere。如果您没有具有证书颁发机构（CA）的现有公钥基础设施（PKI）和本地环境的证书，我们建议您使用 AWS SSM 混合激活。如果您在确实具有现有的 PKI 和本地证书，请使用 AWS IAM Roles Anywhere。

## 混合节点 IAM 角色
<a name="hybrid-nodes-role"></a>

您必须首先为您的混合节点凭证创建一个将与 AWS SSM 混合激活或 AWS IAM Roles Anywhere 结合使用的 IAM 角色，然后才能将混合节点连接到 Amazon EKS 集群。创建集群后，您将使用此角色和某个 Amazon EKS 访问条目或 `aws-auth` ConfigMap 条目，来将该 IAM 角色映射到 Kubernetes 基于角色的访问控制（RBAC）。有关将混合节点 IAM 角色与 Kubernetes RBAC 关联的更多信息，请参阅[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)。

混合节点 IAM 角色必须具有以下权限。
+ 需为 `nodeadm` 配置权限，使其能够调用 `eks:DescribeCluster` 操作，以获取待接入混合节点的目标集群相关信息。若未启用 `eks:DescribeCluster` 操作权限，则必须在传入 `nodeadm init` 命令的节点配置中，手动指定 Kubernetes API 端点、集群 CA 证书包以及服务 IPv4 CIDR。
+ 需为 `nodeadm` 配置权限，使其能够调用 `eks:ListAccessEntries` 操作，以列出待接入混合节点的目标集群中的访问条目。若未启用 `eks:ListAccessEntries` 操作权限，则在执行 `nodeadm init` 命令时，必须传入 `--skip cluster-access-validation` 标记。
+ 如 [AmazonEC2ContainerRegistryPullOnly](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonEC2ContainerRegistryPullOnly.html) 策略所定义，kubelet 使用来自 Amazon Elastic Container Registry（Amazon ECR）的容器映像的权限。
+ 如果使用 AWS SSM，则需要 `nodeadm init` 的权限以使用 [https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonSSMManagedInstanceCore.html](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonSSMManagedInstanceCore.html) 策略中定义的 AWS SSM 混合激活。
+ 如果使用 AWS SSM，则为使用 `nodeadm uninstall` 的 `ssm:DeregisterManagedInstance` 操作和 `ssm:DescribeInstanceInformation` 操作注销实例的权限。
+ （可选）Amazon EKS 容器组身份代理使用 `eks-auth:AssumeRoleForPodIdentity` 操作检索容器组凭证的权限。

## 设置 AWS SSM 混合激活
<a name="hybrid-nodes-ssm"></a>

必须首先创建并配置一个混合节点 IAM 角色，然后才能设置 AWS SSM 混合激活。有关更多信息，请参阅 [创建混合节点 IAM 角色](#hybrid-nodes-create-role)。按照《AWS Systems Manager 用户指南》中[创建混合激活以将节点注册到 Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/hybrid-activation-managed-nodes.html) 部分的说明，为您的混合节点创建一个 AWS SSM 混合激活。将主机作为混合节点注册到 Amazon EKS 集群时，您收到的激活码和 ID 将与 `nodeadm` 结合使用。在为混合节点创建并准备好了 Amazon EKS 集群后，您可以稍后再回到此步骤。

**重要**  
根据您创建激活的方式，Systems Manager 立即将激活码和 ID 返回到控制台或命令窗口。复制此信息并将其存储在安全位置。如果您离开该控制台或关闭命令窗口，可能会丢失此信息。如果您丢失对应信息，则必须创建一个新激活。

默认情况下，AWS SSM 混合激活会处于活动状态 24 小时。您也可以用时间戳格式（例如 `2024-08-01T00:00:00`）来指定 `--expiration-date` 何时创建混合激活。当凭证提供者为 AWS SSM 时，混合节点的节点名称将不可配置，而是由 AWS SSM 自动生成的。您可以在 AWS Systems Manager 控制台中的 Fleet Manager 下查看和管理 AWS SSM 托管式实例。每个账户在每个 AWS 区域最多可以免费注册 1000 个标准[混合激活节点](https://docs.aws.amazon.com/systems-manager/latest/userguide/activations.html)。但是，注册超过 1000 个混合节点需要激活高级实例套餐。使用高级实例套餐将会产生费用，并且该费用未包含在 [Amazon EKS 混合节点功能](https://aws.amazon.com/eks/pricing/)定价中。有关更多信息，请参阅 [AWS Systems Manager 定价](https://aws.amazon.com/systems-manager/pricing/)。

请参阅以下示例，了解如何使用混合节点 IAM 角色创建 AWS SSM 混合激活。将 AWS SSM 混合激活作为混合节点凭证使用时，混合节点名称的格式将为 `mi-012345678abcdefgh`，AWS SSM 预置的临时凭证有效期为 1 小时。当凭证提供者为 AWS SSM 时，您无法更改节点名称或凭证有效期。临时凭证将由 AWS SSM 自动轮换，但此轮换不会影响节点或应用程序的状态。

我们建议您为每个 EKS 集群使用一个 AWS SSM 混合激活来限制混合节点 IAM 角色的 AWS SSM `ssm:DeregisterManagedInstance` 权限，使其只能注销与您的 AWS SSM 混合激活关联的实例。本页中的示例使用了一个具有 EKS 集群 ARN 的标签，该标签可用于将您的 AWS SSM 混合激活映射到该 EKS 集群。您也可以根据自己的权限边界和要求，使用自己偏好的标签和方法来确定 AWS SSM 权限的范围。以下命令中的 `REGISTRATION_LIMIT` 选项是一个整型，用于限制可以使用 AWS SSM 混合激活的计算机数量（例如 `10`）

```
aws ssm create-activation \
     --region AWS_REGION \
     --default-instance-name eks-hybrid-nodes \
     --description "Activation for EKS hybrid nodes" \
     --iam-role AmazonEKSHybridNodesRole \
     --tags Key=EKSClusterARN,Value=arn:aws:eks:AWS_REGION:AWS_ACCOUNT_ID:cluster/CLUSTER_NAME \
     --registration-limit REGISTRATION_LIMIT
```

请参阅[创建混合激活以将节点注册到 Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/hybrid-activation-managed-nodes.html) 部分的说明，以详细了解有关 AWS SSM 混合激活的可用配置设置。

## 设置 AWS IAM Roles Anywhere
<a name="hybrid-nodes-iam-roles-anywhere"></a>

按照《IAM Roles Anywhere 用户指南》中 [Getting started with IAM Roles Anywhere](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/getting-started.html) 部分的说明，设置将用作混合节点 IAM 角色的临时 IAM 凭证的信任锚和配置文件。创建配置文件时，您可以仅创建配置文件而不添加任何角色。您可以首先创建此配置文件，然后返回这些步骤来创建混合节点 IAM 角色，最后再将创建的角色添加到您的配置文件。您也可以使用本页后面的 AWS CloudFormation 步骤来完成混合节点的 IAM Roles Anywhere 设置。

将混合节点 IAM 角色添加到配置文件时，请在 AWS IAM Roles Anywhere 控制台中**编辑配置文件**页面底部的**自定义角色**会话名称面板中，选择**接受自定义角色会话名称**。这对应于 `CreateProfile` API 的 [acceptRoleSessionName](https://docs.aws.amazon.com/rolesanywhere/latest/APIReference/API_CreateProfile.html#rolesanywhere-CreateProfile-request-acceptRoleSessionName) 字段。选择此选项后，您可以在引导阶段传递到 `nodeadm` 的配置中为混合节点提供自定义节点名称。在 `nodeadm init` 过程中必须传递一个自定义节点名称。创建配置文件后，您可以通过更新配置文件来接受自定义角色会话名称。

您可以通过 AWS IAM Roles Anywhere 配置文件的 [durationSeconds](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/authentication-create-session#credentials-object) 字段，来配置 AWS IAM Roles Anywhere 的凭证有效期。默认有效期为 1 小时，最长可为 12 小时。混合节点 IAM 角色的 `MaxSessionDuration` 设置必须大于 AWS IAM Roles Anywhere 配置文件中的 `durationSeconds` 设置。有关 `MaxSessionDuration` 的更多信息，请参阅 [UpdateRole API 文档](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_UpdateRole.html)。

您通过证书颁发机构（CA）为每台计算机生成的证书和密钥必须放置在每个混合节点的 `/etc/iam/pki` 目录中，并且证书的文件名必须为 `server.pem`，密钥的文件名必须为 `server.key`。

## 创建混合节点 IAM 角色
<a name="hybrid-nodes-create-role"></a>

要运行本节中的步骤，使用 AWS 控制台或 AWS CLI 的 IAM 主体必须具有以下权限。
+  `iam:CreatePolicy` 
+  `iam:CreateRole` 
+  `iam:AttachRolePolicy` 
+ 如果使用的是 AWS IAM Roles Anywhere
  +  `rolesanywhere:CreateTrustAnchor` 
  +  `rolesanywhere:CreateProfile` 
  +  `iam:PassRole` 

### AWS CloudFormation
<a name="hybrid-nodes-creds-cloudformation"></a>

安装并配置 AWS CLI（如果尚未执行此操作）。请参阅[安装或更新到最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

 **AWS SSM 混合激活的步骤** 

CloudFormation 堆栈将创建具有上述权限的混合节点 IAM 角色。CloudFormation 模板不会创建 AWS SSM 混合激活。

1. 下载适用于混合节点的 AWS SSM CloudFormation 模板：

   ```
   curl -OL 'https://raw.githubusercontent.com/aws/eks-hybrid/refs/heads/main/example/hybrid-ssm-cfn.yaml'
   ```

1. 使用以下选项创建 `cfn-ssm-parameters.json`：

   1. 将 `ROLE_NAME` 替换为混合节点 IAM 角色的名称。如果您未指定名称，则默认情况下 CloudFormation 模板将使用 `AmazonEKSHybridNodesRole` 作为其创建的角色的名称。

   1. 请将 `TAG_KEY` 替换为您在创建 AWS SSM 混合激活时使用的 AWS SSM 资源标签键。在条件中使用标签键和标签值组合，从而让 `ssm:DeregisterManagedInstance` 仅允许混合节点 IAM 角色注销与您的 AWS SSM 混合激活关联的 AWS SSM 托管式实例。在 CloudFormation 模板中，`TAG_KEY` 默认为 `EKSClusterARN`。

   1. 请将 `TAG_VALUE` 替换为您在创建 AWS SSM 混合激活时使用的 AWS SSM 资源标签值。在条件中使用标签键和标签值组合，从而让 `ssm:DeregisterManagedInstance` 仅允许混合节点 IAM 角色注销与您的 AWS SSM 混合激活关联的 AWS SSM 托管式实例。如果您使用 `EKSClusterARN` 的默认值 `TAG_KEY`，则请将 EKS 集群 ARN 传递为 `TAG_VALUE`。EKS 集群 ARN 的格式为 ` arn:aws:eks:AWS_REGION:AWS_ACCOUNT_ID:cluster/CLUSTER_NAME`。

      ```
      {
        "Parameters": {
          "RoleName": "ROLE_NAME",
          "SSMDeregisterConditionTagKey": "TAG_KEY",
          "SSMDeregisterConditionTagValue": "TAG_VALUE"
        }
      }
      ```

1. 部署 CloudFormation 堆栈。请将 `STACK_NAME` 替换 CloudFormation 堆栈的名称。

   ```
   aws cloudformation deploy \
       --stack-name STACK_NAME \
       --template-file hybrid-ssm-cfn.yaml \
       --parameter-overrides file://cfn-ssm-parameters.json \
       --capabilities CAPABILITY_NAMED_IAM
   ```

 **AWS IAM Roles Anywhere 的步骤** 

CloudFormation 堆栈会使用您配置的证书颁发机构（CA）来创建 AWS IAM Roles Anywhere 信任锚，创建 AWS IAM Roles Anywhere 配置文件，并创建具有前文所述权限的混合节点 IAM 角色。

1. 设置证书颁发机构（CA）

   1. 要使用 AWS 私有 CA 资源，请打开 [AWS Private Certificate Authority 控制台](https://console.aws.amazon.com/acm-pca/home)。按照 [AWS Private CA 用户指南](https://docs.aws.amazon.com/privateca/latest/userguide/PcaWelcome.html)中的说明进行操作。

   1. 要使用外部 CA，请按照相关 CA 提供的说明进行操作。您需要在后续步骤中提供证书正文。

   1. 公有 CA 颁发的证书不能用作信任锚。

1. 下载适用于混合节点的 AWS IAM Roles Anywhere CloudFormation 模板

   ```
   curl -OL 'https://raw.githubusercontent.com/aws/eks-hybrid/refs/heads/main/example/hybrid-ira-cfn.yaml'
   ```

1. 使用以下选项创建 `cfn-iamra-parameters.json`：

   1. 将 `ROLE_NAME` 替换为混合节点 IAM 角色的名称。如果您未指定名称，则默认情况下 CloudFormation 模板将使用 `AmazonEKSHybridNodesRole` 作为其创建的角色的名称。

   1. 请将 `CERT_ATTRIBUTE` 替换为用于唯一标识主机的每台计算机的证书属性。使用的证书属性必须与您在将混合节点连接到集群时用于 `nodeadm` 配置的 nodeName 一致。有关更多信息，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。默认情况下，CloudFormation 模板将 `${aws:PrincipalTag/x509Subject/CN}` 作为 `CERT_ATTRIBUTE`，这将对应于每台计算机的证书的 CN 字段。您也可以将 `$(aws:PrincipalTag/x509SAN/Name/CN}` 传递为您的 `CERT_ATTRIBUTE`。

   1. 请将 `CA_CERT_BODY` 替换为 CA 的证书正文，不带换行符。`CA_CERT_BODY` 必须采用隐私增强邮件（PEM）格式。如果您具有 PEM 格式的 CA 证书，请在将 CA 证书正文放入 `cfn-iamra-parameters.json` 文件之前移除换行符和 BEGIN CERTIFICATE 和 END CERTIFICATE 行。

      ```
      {
        "Parameters": {
          "RoleName": "ROLE_NAME",
          "CertAttributeTrustPolicy": "CERT_ATTRIBUTE",
          "CABundleCert": "CA_CERT_BODY"
        }
      }
      ```

1. 部署 CloudFormation 模板。请将 `STACK_NAME` 替换 CloudFormation 堆栈的名称。

   ```
   aws cloudformation deploy \
       --stack-name STACK_NAME \
       --template-file hybrid-ira-cfn.yaml \
       --parameter-overrides file://cfn-iamra-parameters.json
       --capabilities CAPABILITY_NAMED_IAM
   ```

### AWS CLI
<a name="hybrid-nodes-creds-awscli"></a>

安装并配置 AWS CLI（如果尚未执行此操作）。请参阅[安装或更新到最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

 **创建 EKS 描述集群策略** 

1. 使用以下内容创建名为 `eks-describe-cluster-policy.json` 的文件：

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "eks:DescribeCluster"
               ],
               "Resource": "*"
           }
       ]
   }
   ```

1. 使用以下命令创建此策略：

   ```
   aws iam create-policy \
       --policy-name EKSDescribeClusterPolicy \
       --policy-document file://eks-describe-cluster-policy.json
   ```

 **AWS SSM 混合激活的步骤** 

1. 使用以下内容创建名为 `eks-hybrid-ssm-policy.json` 的文件。此策略将授予对 `ssm:DescribeInstanceInformation` 和 `ssm:DeregisterManagedInstance` 这两个操作的权限。此策略将根据您在信任策略中指定的资源标签，将 `ssm:DeregisterManagedInstance` 权限范围限定为与您的 AWS SSM 混合激活关联的 AWS SSM 托管式实例。

   1. 请将 `AWS_REGION` 替换为您的 AWS SSM 混合激活的 AWS 区域。

   1. 将 `AWS_ACCOUNT_ID` 替换为您的AWS账户 ID。

   1. 请将 `TAG_KEY` 替换为您在创建 AWS SSM 混合激活时使用的 AWS SSM 资源标签键。在条件中使用标签键和标签值组合，从而让 `ssm:DeregisterManagedInstance` 仅允许混合节点 IAM 角色注销与您的 AWS SSM 混合激活关联的 AWS SSM 托管式实例。在 CloudFormation 模板中，`TAG_KEY` 默认为 `EKSClusterARN`。

   1. 请将 `TAG_VALUE` 替换为您在创建 AWS SSM 混合激活时使用的 AWS SSM 资源标签值。在条件中使用标签键和标签值组合，从而让 `ssm:DeregisterManagedInstance` 仅允许混合节点 IAM 角色注销与您的 AWS SSM 混合激活关联的 AWS SSM 托管式实例。如果您使用 `EKSClusterARN` 的默认值 `TAG_KEY`，则请将 EKS 集群 ARN 传递为 `TAG_VALUE`。EKS 集群 ARN 的格式为 ` arn:aws:eks:AWS_REGION:AWS_ACCOUNT_ID:cluster/CLUSTER_NAME`。

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "ssm:DescribeInstanceInformation",
                  "Resource": "*"
              },
              {
                  "Effect": "Allow",
                  "Action": "ssm:DeregisterManagedInstance",
                  "Resource": "arn:aws:ssm:us-east-1:123456789012:managed-instance/*",
                  "Condition": {
                      "StringEquals": {
                          "ssm:resourceTag/TAG_KEY": "TAG_VALUE"
                      }
                  }
              }
          ]
      }
      ```

1. 使用以下命令创建此策略

   ```
   aws iam create-policy \
       --policy-name EKSHybridSSMPolicy \
       --policy-document file://eks-hybrid-ssm-policy.json
   ```

1. 创建一个名为 `eks-hybrid-ssm-trust.json`的文件。请将 `AWS_REGION` 替换为您的 AWS SSM 混合激活所在的 AWS 区域，将 `AWS_ACCOUNT_ID` 替换为您的 AWS 账户 ID。

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement":[
         {
            "Sid":"",
            "Effect":"Allow",
            "Principal":{
               "Service":"ssm.amazonaws.com"
            },
            "Action":"sts:AssumeRole",
            "Condition":{
               "StringEquals":{
                  "aws:SourceAccount":"123456789012"
               },
               "ArnEquals":{
                  "aws:SourceArn":"arn:aws:ssm:us-east-1:123456789012:*"
               }
            }
         }
      ]
   }
   ```

1. 使用以下命令创建此角色。

   ```
   aws iam create-role \
       --role-name AmazonEKSHybridNodesRole \
       --assume-role-policy-document file://eks-hybrid-ssm-trust.json
   ```

1. 附加您在之前步骤中创建的 `EKSDescribeClusterPolicy` 和 `EKSHybridSSMPolicy`。将 `AWS_ACCOUNT_ID` 替换为您的AWS账户 ID。

   ```
   aws iam attach-role-policy \
       --role-name AmazonEKSHybridNodesRole \
       --policy-arn arn:aws:iam::AWS_ACCOUNT_ID:policy/EKSDescribeClusterPolicy
   ```

   ```
   aws iam attach-role-policy \
       --role-name AmazonEKSHybridNodesRole \
       --policy-arn arn:aws:iam::AWS_ACCOUNT_ID:policy/EKSHybridSSMPolicy
   ```

1. 附加 `AmazonEC2ContainerRegistryPullOnly` 和 `AmazonSSMManagedInstanceCore` AWS 托管式策略。

   ```
   aws iam attach-role-policy \
       --role-name AmazonEKSHybridNodesRole \
       --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly
   ```

   ```
   aws iam attach-role-policy \
       --role-name AmazonEKSHybridNodesRole \
       --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
   ```

 **AWS IAM Roles Anywhere 的步骤** 

要使用 AWS IAM Roles Anywhere，您必须在创建混合节点 IAM 角色之前设置 AWS IAM Roles Anywhere信任锚。有关说明，请参阅[设置 AWS IAM Roles Anywhere](#hybrid-nodes-iam-roles-anywhere)：

1. 创建一个名为 `eks-hybrid-iamra-trust.json`的文件。请将 `TRUST_ANCHOR ARN` 替换为您在“[设置 AWS IAM Roles Anywhere](#hybrid-nodes-iam-roles-anywhere)”步骤中创建的信任锚的 ARN。只有当角色会话名称与混合节点上安装的 x509 证书中的 CN 一致时，此信任策略中的条件才会将 AWS IAM Roles Anywhere 代入混合节点 IAM 角色的权限范围限定为仅交换临时 IAM 凭证。您也可以使用其他证书属性来唯一标识节点。您在信任策略中使用的证书属性必须与您在 `nodeadm` 配置中设置的 `nodeName` 对应。有关更多信息，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": {
                   "Service": "rolesanywhere.amazonaws.com"
               },
               "Action": [
                   "sts:TagSession",
                   "sts:SetSourceIdentity"
               ],
               "Condition": {
                   "StringEquals": {
                       "aws:PrincipalTag/x509Subject/CN": "${aws:PrincipalTag/x509Subject/CN}"
                   },
                   "ArnEquals": {
                       "aws:SourceArn": "arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/TA_ID"
                   }
               }
           },
           {
               "Effect": "Allow",
               "Principal": {
                   "Service": "rolesanywhere.amazonaws.com"
               },
               "Action": "sts:AssumeRole",
               "Condition": {
                   "StringEquals": {
                       "sts:RoleSessionName": "${aws:PrincipalTag/x509Subject/CN}",
                       "aws:PrincipalTag/x509Subject/CN": "${aws:PrincipalTag/x509Subject/CN}"
                   },
                   "ArnEquals": {
                       "aws:SourceArn": "arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/TA_ID"
                   }
               }
           }
       ]
   }
   ```

1. 使用以下命令创建此角色。

   ```
   aws iam create-role \
       --role-name AmazonEKSHybridNodesRole \
       --assume-role-policy-document file://eks-hybrid-iamra-trust.json
   ```

1. 附加您在之前步骤中创建的 `EKSDescribeClusterPolicy`。将 `AWS_ACCOUNT_ID` 替换为您的AWS账户 ID。

   ```
   aws iam attach-role-policy \
       --role-name AmazonEKSHybridNodesRole \
       --policy-arn arn:aws:iam::AWS_ACCOUNT_ID:policy/EKSDescribeClusterPolicy
   ```

1. 附加 `AmazonEC2ContainerRegistryPullOnly` AWS 托管式策略

   ```
   aws iam attach-role-policy \
       --role-name AmazonEKSHybridNodesRole \
       --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly
   ```

### AWS 管理控制台
<a name="hybrid-nodes-creds-console"></a>

 **创建 EKS 描述集群策略** 

1. 打开 [Amazon IAM 控制台](https://console.aws.amazon.com/iam/home) 

1. 在左侧导航窗格中，选择 **Policies（策略）**。

1. 在**策略**页面上，选择**创建策略**。

1. 在“指定权限”页面的“选择服务”面板中，选择 EKS。

   1. 筛选 **DescribeCluster** 的操作，然后选择 **DescribeCluster** 读取操作。

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

1. 在**检查并创建**页面上

   1. 输入策略的**策略名称**，如 `EKSDescribeClusterPolicy`。

   1. 选择**创建策略**。

 **AWS SSM 混合激活的步骤** 

1. 打开 [Amazon IAM 控制台](https://console.aws.amazon.com/iam/home) 

1. 在左侧导航窗格中，选择 **Policies（策略）**。

1. 在**策略**页面上，选择**创建策略**。

1. 在**指定权限**页面右上角的**策略编辑器**导航中，选择 **JSON**。粘贴以下代码段。请将 `AWS_REGION` 替换为您的 AWS SSM 混合激活所在的 AWS 区域，并将 `AWS_ACCOUNT_ID` 替换为您的 AWS 账户 ID。请将 `TAG_KEY` 和 `TAG_VALUE` 替换为您在创建 AWS SSM 混合激活时使用的 AWS SSM 资源标签键。

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "ssm:DescribeInstanceInformation",
               "Resource": "*"
           },
           {
               "Effect": "Allow",
               "Action": "ssm:DeregisterManagedInstance",
               "Resource": "arn:aws:ssm:us-east-1:123456789012:managed-instance/*",
               "Condition": {
                   "StringEquals": {
                       "ssm:resourceTag/TAG_KEY": "TAG_VALUE"
                   }
               }
           }
       ]
   }
   ```

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

1. 在**检查并创建**页面上，

   1. 输入策略的**策略**名称，如 `EKSHybridSSMPolicy` 

   1. 选择**创建策略**。

1. 在左侧导航窗格中，选择 **Roles**（角色）。

1. 在 **Roles**（角色）页面上，选择 **Create role**（创建角色）。

1. 在 **Select trusted entity**（选择受信任的实体）页面上，请执行以下操作：

   1. 在**可信实体类型**部分中，选择**自定义信任策略**。将以下策略复制粘贴到自定义信任策略编辑器中。请将 `AWS_REGION` 替换为您的 AWS SSM 混合激活所在的 AWS 区域，将 `AWS_ACCOUNT_ID` 替换为您的 AWS 账户 ID。

      ```
      {
         "Version":"2012-10-17",		 	 	 
         "Statement":[
            {
               "Sid":"",
               "Effect":"Allow",
               "Principal":{
                  "Service":"ssm.amazonaws.com"
               },
               "Action":"sts:AssumeRole",
               "Condition":{
                  "StringEquals":{
                     "aws:SourceAccount":"123456789012"
                  },
                  "ArnEquals":{
                     "aws:SourceArn":"arn:aws:ssm:us-east-1:123456789012:*"
                  }
               }
            }
         ]
      }
      ```

   1. 选择下一步。

1. 在**添加权限**页面上，附加自定义策略或执行以下操作：

   1. 在**筛选策略**对话框中，输入 `EKSDescribeClusterPolicy` 或您上面创建的策略的名称。选中搜索结果中您的策略左侧的复选框。

   1. 在**筛选策略**对话框中，输入 `EKSHybridSSMPolicy` 或您上面创建的策略的名称。选中搜索结果中您的策略左侧的复选框。

   1. 在 **Filter policies (筛选器策略)** 框中，输入 `AmazonEC2ContainerRegistryPullOnly`。选中搜索结果中 `AmazonEC2ContainerRegistryPullOnly` 左侧的复选框。

   1. 在 **Filter policies (筛选器策略)** 框中，输入 `AmazonSSMManagedInstanceCore`。选中搜索结果中 `AmazonSSMManagedInstanceCore` 左侧的复选框。

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

1. 在 **Name, review, and create**（命名、查看和创建）页面中，请执行以下操作：

   1. 对于 **Role name**（角色名称），请为角色输入唯一名称，例如 `AmazonEKSHybridNodesRole`。

   1. 对于 **Description**（说明），请将当前文本替换为描述性文本，例如 `Amazon EKS - Hybrid Nodes role`。

   1. 选择**创建角色**。

 **AWS IAM Roles Anywhere 的步骤** 

要使用 AWS IAM Roles Anywhere，您必须在创建混合节点 IAM 角色之前设置 AWS IAM Roles Anywhere信任锚。有关说明，请参阅[设置 AWS IAM Roles Anywhere](#hybrid-nodes-iam-roles-anywhere)：

1. 打开 [Amazon IAM 控制台](https://console.aws.amazon.com/iam/home) 

1. 在左侧导航窗格中，选择 **Roles**（角色）。

1. 在 **Roles**（角色）页面上，选择 **Create role**（创建角色）。

1. 在 **Select trusted entity**（选择受信任的实体）页面上，请执行以下操作：

   1. 在**可信实体类型**部分中，选择**自定义信任策略**。将以下策略复制粘贴到自定义信任策略编辑器中。请将 `TRUST_ANCHOR ARN` 替换为您在“[设置 AWS IAM Roles Anywhere](#hybrid-nodes-iam-roles-anywhere)”步骤中创建的信任锚的 ARN。只有当角色会话名称与混合节点上安装的 x509 证书中的 CN 一致时，此信任策略中的条件才会将 AWS IAM Roles Anywhere 代入混合节点 IAM 角色的权限范围限定为仅交换临时 IAM 凭证。您也可以使用其他证书属性来唯一标识节点。您在信任策略中使用的证书属性必须与您在 nodeadm 配置中设置的 nodeName 对应。有关更多信息，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Principal": {
                      "Service": "rolesanywhere.amazonaws.com"
                  },
                  "Action": [
                      "sts:TagSession",
                      "sts:SetSourceIdentity"
                  ],
                  "Condition": {
                      "StringEquals": {
                          "aws:PrincipalTag/x509Subject/CN": "${aws:PrincipalTag/x509Subject/CN}"
                      },
                      "ArnEquals": {
                          "aws:SourceArn": "arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/TA_ID"
                      }
                  }
              },
              {
                  "Effect": "Allow",
                  "Principal": {
                      "Service": "rolesanywhere.amazonaws.com"
                  },
                  "Action": "sts:AssumeRole",
                  "Condition": {
                      "StringEquals": {
                          "sts:RoleSessionName": "${aws:PrincipalTag/x509Subject/CN}",
                          "aws:PrincipalTag/x509Subject/CN": "${aws:PrincipalTag/x509Subject/CN}"
                      },
                      "ArnEquals": {
                          "aws:SourceArn": "arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/TA_ID"
                      }
                  }
              }
          ]
      }
      ```

   1. 选择下一步。

1. 在**添加权限**页面上，附加自定义策略或执行以下操作：

   1. 在**筛选策略**对话框中，输入 `EKSDescribeClusterPolicy` 或您上面创建的策略的名称。选中搜索结果中您的策略左侧的复选框。

   1. 在 **Filter policies (筛选器策略)** 框中，输入 `AmazonEC2ContainerRegistryPullOnly`。选中搜索结果中 `AmazonEC2ContainerRegistryPullOnly` 左侧的复选框。

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

1. 在 **Name, review, and create**（命名、查看和创建）页面中，请执行以下操作：

   1. 对于 **Role name**（角色名称），请为角色输入唯一名称，例如 `AmazonEKSHybridNodesRole`。

   1. 对于 **Description**（说明），请将当前文本替换为描述性文本，例如 `Amazon EKS - Hybrid Nodes role`。

   1. 选择**创建角色**。

# 创建具有混合节点的 Amazon EKS 集群
<a name="hybrid-nodes-cluster-create"></a>

本主题概述了创建启用混合节点功能的 Amazon EKS 集群时可用的选项，并介绍了相关注意事项。EKS 混合节点功能提供的 [Kubernetes 版本支持](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)与具有云端节点的 Amazon EKS 集群相同，包括标准和扩展支持。

如果您不计划使用 EKS 混合节点功能，请参阅有关 Amazon EKS 创建集群的主文档：[创建一个 Amazon EKS 集群。](create-cluster.md)。

## 先决条件
<a name="hybrid-nodes-cluster-create-prep"></a>
+ 已完成[混合节点的先决条件设置](hybrid-nodes-prereqs.md)。在创建启用混合节点功能的集群之前，必须确定本地节点和可选的容器组 CIDR，根据 EKS 要求和混合节点要求创建 VPC 和子网，并且具有包含本地入站规则和（可选）容器组 CIDR 的安全组。有关这些先决条件的更多信息，请参阅[准备混合节点的联网](hybrid-nodes-networking.md)。
+ 已在您的设备上安装并配置了最新版本的 AWS 命令行界面（AWS CLI）。要查看当前版本，请使用 `aws --version`。yum、apt-get 或适用于 macOS 的 Homebrew 等软件包管理器通常比 AWS CLI 的最新版本落后几个版本。要安装最新版本，请参阅《AWS 命令行界面用户指南》中的[安装或更新到最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 和[配置 AWS CLI 设置](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。
+ 一个具有创建 IAM 角色和附加策略以及创建和描述 EKS 集群的权限的 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles#iam-term-principal)

## 注意事项
<a name="hybrid-nodes-cluster-create-consider"></a>
+ 集群的集群身份验证模式必须为 `API` 或 `API_AND_CONFIG_MAP`。
+ 集群必须使用 IPv4 地址系列。
+ 集群必须使用公有或私有集群端点连接。集群不能使用“公有和私有”集群端点连接，因为 Amazon EKS Kubernetes API 服务器端点将解析为在您的 VPC 之外运行的混合节点公有 IP。
+ 具有混合节点的 Amazon EKS 集群支持 OIDC 身份验证。
+ 您可以从现有集群中添加、更改或移除混合节点配置。有关更多信息，请参阅 [在现有 Amazon EKS 集群上启用混合节点或修改配置](hybrid-nodes-cluster-update.md)。

## 第 1 步：创建集群 IAM 角色
<a name="hybrid-nodes-cluster-create-iam"></a>

如果您已经拥有集群 IAM 角色，或者您将使用 `eksctl` 或AWS CloudFormation 创建集群，则可以跳过此步骤。默认情况下，`eksctl` 和 AWS CloudFormation 模板会为您创建集群 IAM 角色。

1. 运行以下命令以创建 IAM 信任策略 JSON 文件。

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "eks.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

1. 创建 Amazon EKS 集群 IAM 角色。如有必要，使用您在上一步中将文件写入到的计算机上的路径为 eks-cluster-role-trust-policy.json 添加前言。该命令将您在上一步中创建的信任策略与角色关联。要创建 IAM 角色，必须为正在创建角色的 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles#iam-term-principal)分配 `iam:CreateRole` 操作（权限）。

   ```
   aws iam create-role \
       --role-name myAmazonEKSClusterRole \
       --assume-role-policy-document file://"eks-cluster-role-trust-policy.json"
   ```

1. 您可以分配 Amazon EKS 托管策略或创建自己的自定义策略。有关必须在自定义策略中使用的最低权限，请参阅 [Amazon EKS 节点 IAM 角色](create-node-role.md)。将名为 `AmazonEKSClusterPolicy` 的 Amazon EKS 托管 IAM 策略附加到角色。要将 IAM 策略附加到某个 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles#iam-term-principal)，必须为附加该策略的主体分配以下 IAM 操作（权限）之一：`iam:AttachUserPolicy` 或 `iam:AttachRolePolicy`。

   ```
   aws iam attach-role-policy \
       --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy \
       --role-name myAmazonEKSClusterRole
   ```

## 第 2 步：创建启用混合节点功能的集群
<a name="hybrid-nodes-cluster-create-cluster"></a>

您可以使用以下工具来创建集群：
+  [eksctl](#hybrid-nodes-cluster-create-eksctl) 
+  [AWS CloudFormation](#hybrid-nodes-cluster-create-cfn) 
+  [AWS CLI](#hybrid-nodes-cluster-create-cli) 
+  [AWS 管理控制台](#hybrid-nodes-cluster-create-console) 

### 创建启用混合节点功能的集群 – eksctl
<a name="hybrid-nodes-cluster-create-eksctl"></a>

您需要安装最新版本的 `eksctl` 命令行工具。要安装或更新 `eksctl`，请参阅 `eksctl` 文档中的 [Installation](https://eksctl.io/installation)。

1. 创建 `cluster-config.yaml` 以定义启用混合节点功能的 Amazon EKS IPv4 集群。在 `cluster-config.yaml` 中进行以下替换。有关完整的设置列表，请参阅 [eksctl 文档](https://eksctl.io/getting-started/)。

   1. 将 `CLUSTER_NAME` 替换为您的集群名称。名称只能包含字母数字字符（区分大小写）和连字符。该名称必须以字母数字字符开头，且不得超过 100 个字符。对于您在其中创建集群的 AWS 区域和 AWS 账户，该名称必须在其内具有唯一性。

   1. 请将 `AWS_REGION` 替换为要在其中创建集群的 AWS 区域。

   1. 将 `K8S_VERSION` 替换为 [Amazon EKS 支持的版本](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)。

   1. 请根据您在 [准备用于混合节点的凭证](hybrid-nodes-creds.md) 步骤中配置的凭证提供者，将 `CREDS_PROVIDER` 替换为 `ssm` 或 `ira`。

   1. 如果凭证提供者设置为 `ira`，请替换 `CA_BUNDLE_CERT`，这会将 AWS IAM Roles Anywhere 作为凭证提供者。CA\$1BUNDLE\$1CERT 是证书颁发机构（CA）的证书正文，具体取决于您选择的 CA。该证书必须采用隐私增强邮件（PEM）格式。

   1. 请将 `GATEWAY_ID` 替换为要连接到 VPC 的虚拟专用网关或中转网关的 ID。

   1. 请将 `REMOTE_NODE_CIDRS` 替换为混合节点的本地节点 CIDR。

   1. 对于在混合节点上运行的工作负载，请将 `REMOTE_POD_CIDRS` 替换为本地容器组 CIDR；如果您不在混合节点上运行 Webhook，则请从配置中移除该行。如果您的 CNI 在容器组流量离开本地主机时不使用网络地址转换（NATI）或容器组 IP 地址伪装，则必须配置 `REMOTE_POD_CIDRS`。如果在混合节点上运行 Webhook，则必须配置 `REMOTE_POD_CIDRS`，更多信息请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

   1. 本地节点和容器组 CIDR 块必须满足以下要求：

      1. 位于 IPv4 RFC–1918 范围之一：`10.0.0.0/8`、`172.16.0.0/12` 或 `192.168.0.0/16`，或者在 RFC 6598 定义的 CGNAT 范围内：`100.64.0.0/10`。

      1. 不相互重叠，也不与集群的 `VPC CIDR` 或 Kubernetes 服务 IPv4 CIDR 重叠

         ```
         apiVersion: eksctl.io/v1alpha5
         kind: ClusterConfig
         
         metadata:
           name: CLUSTER_NAME
           region: AWS_REGION
           version: "K8S_VERSION"
         
         remoteNetworkConfig:
           iam:
             provider: CREDS_PROVIDER # default SSM, can also be set to IRA
             # caBundleCert: CA_BUNDLE_CERT
           vpcGatewayID: GATEWAY_ID
           remoteNodeNetworks:
           - cidrs: ["REMOTE_NODE_CIDRS"]
           remotePodNetworks:
           - cidrs: ["REMOTE_POD_CIDRS"]
         ```

1. 运行如下命令：

   ```
   eksctl create cluster -f cluster-config.yaml
   ```

   集群预配置需要几分钟时间。在创建集群时，将显示几行输出。输出的最后一行类似于以下示例行。

   ```
   [✓]  EKS cluster "CLUSTER_NAME" in "REGION" region is ready
   ```

1. 继续[第 3 步：更新 kubeconfig](#hybrid-nodes-cluster-create-kubeconfig)。

### 创建启用混合节点功能的集群 – AWS CloudFormation
<a name="hybrid-nodes-cluster-create-cfn"></a>

CloudFormation 堆栈使用您指定的 `RemoteNodeNetwork` 和 `RemotePodNetwork` 来创建 EKS 集群 IAM 角色和 EKS 集群。如果您需要自定义未在 CloudFormation 模板中公开的 EKS 集群设置，请修改 CloudFormation 模板。

1. 下载 CloudFormation 模板文件。

   ```
   curl -OL 'https://raw.githubusercontent.com/aws/eks-hybrid/refs/heads/main/example/hybrid-eks-cfn.yaml'
   ```

1. 创建 `cfn-eks-parameters.json` 并指定每个值的配置。

   1.  `CLUSTER_NAME`：要创建的 EKS 集群的名称

   1.  `CLUSTER_ROLE_NAME`：要创建的 EKS 集群 IAM 角色的名称。模板中的默认值为“EKSClusterRole”。

   1.  `SUBNET1_ID`：您在先决条件步骤中创建的第一个子网的 ID

   1.  `SUBNET2_ID`：您在先决条件步骤中创建的第二个子网的 ID

   1.  `SG_ID`：您在先决条件步骤中创建的安全组 ID

   1.  `REMOTE_NODE_CIDRS`：混合节点的本地节点 CIDR

   1.  `REMOTE_POD_CIDRS`：在混合节点上运行的工作负载的本地容器组 CIDR。如果您的 CNI 在容器组流量离开本地主机时不使用网络地址转换（NATI）或容器组 IP 地址伪装，则必须配置 `REMOTE_POD_CIDRS`。如果在混合节点上运行 Webhook，则必须配置 `REMOTE_POD_CIDRS`，更多信息请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

   1. 本地节点和容器组 CIDR 块必须满足以下要求：

      1. 位于 IPv4 RFC–1918 范围之一：`10.0.0.0/8`、`172.16.0.0/12` 或 `192.168.0.0/16`，或者在 RFC 6598 定义的 CGNAT 范围内：`100.64.0.0/10`。

      1. 不相互重叠，也不与集群的 `VPC CIDR` 或 Kubernetes 服务 IPv4 CIDR 重叠。

   1.  `CLUSTER_AUTH`：集群的集群身份验证模式。有效值为 `API` 和 `API_AND_CONFIG_MAP`。模版中的默认值为 `API_AND_CONFIG_MAP`。

   1.  `CLUSTER_ENDPOINT`：集群的集群端点连接。有效值为“公有”或“私有”。模板中的默认值为“私有”，因此只能从 VPC 内连接到 Kubernetes API 端点。

   1.  `K8S_VERSION`：要用于集群的 Kubernetes 版本。请参阅 [Amazon EKS 支持的版本](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)。

      ```
      {
        "Parameters": {
          "ClusterName": "CLUSTER_NAME",
          "ClusterRoleName": "CLUSTER_ROLE_NAME",
          "SubnetId1": "SUBNET1_ID",
          "SubnetId2": "SUBNET2_ID",
          "SecurityGroupId" "SG_ID",
          "RemoteNodeCIDR": "REMOTE_NODE_CIDRS",
          "RemotePodCIDR": "REMOTE_POD_CIDRS",
          "ClusterAuthMode": "CLUSTER_AUTH",
          "ClusterEndpointConnectivity": "CLUSTER_ENDPOINT",
          "K8sVersion": "K8S_VERSION"
        }
       }
      ```

1. 部署 CloudFormation 堆栈。请将 `STACK_NAME` 替换为 CloudFormation 堆栈的名称，并将 `AWS_REGION` 替换为将会创建集群的 AWS 区域。

   ```
   aws cloudformation deploy \
       --stack-name STACK_NAME \
       --region AWS_REGION \
       --template-file hybrid-eks-cfn.yaml \
       --parameter-overrides file://cfn-eks-parameters.json \
       --capabilities CAPABILITY_NAMED_IAM
   ```

   集群预配置需要几分钟时间。您可以使用以下命令检查堆栈的状态。请将 `STACK_NAME` 替换为 CloudFormation 堆栈的名称，并将 `AWS_REGION` 替换为将会创建集群的 AWS 区域。

   ```
   aws cloudformation describe-stacks \
       --stack-name STACK_NAME \
       --region AWS_REGION \
       --query 'Stacks[].StackStatus'
   ```

1. 继续[第 3 步：更新 kubeconfig](#hybrid-nodes-cluster-create-kubeconfig)。

### 创建启用混合节点功能的集群 – AWS CLI
<a name="hybrid-nodes-cluster-create-cli"></a>

1. 运行以下命令创建启用混合节点功能的 EKS 集群。在运行此命令之前，请将以下参数替换为相应的设置。有关完整的设置列表，请参阅[创建一个 Amazon EKS 集群。](create-cluster.md)文档。

   1.  `CLUSTER_NAME`：要创建的 EKS 集群的名称

   1.  `AWS_REGION`：将创建集群的 AWS 区域。

   1.  `K8S_VERSION`：要用于集群的 Kubernetes 版本。请参阅“Amazon EKS 支持的版本”。

   1.  `ROLE_ARN`：您为集群配置的 Amazon EKS 集群角色。有关更多信息，请参阅“Amazon EKS 集群 IAM 角色”。

   1.  `SUBNET1_ID`：您在先决条件步骤中创建的第一个子网的 ID

   1.  `SUBNET2_ID`：您在先决条件步骤中创建的第二个子网的 ID

   1.  `SG_ID`：您在先决条件步骤中创建的安全组 ID

   1. 您可以将 `API` 和 `API_AND_CONFIG_MAP` 作为集群访问身份验证模式。在下面的命令中，集群访问身份验证模式设置为 `API_AND_CONFIG_MAP`。

   1. 您可以使用 `endpointPublicAccess` 和 `endpointPrivateAccess` 参数来启用或禁用对集群 Kubernetes API 服务器端点的公有和私有访问。在下面的命令中，`endpointPublicAccess` 设置为 false，`endpointPrivateAccess` 设置为 true。

   1.  `REMOTE_NODE_CIDRS`：混合节点的本地节点 CIDR。

   1.  `REMOTE_POD_CIDRS`（可选）：在混合节点上运行的工作负载的本地容器组 CIDR。

   1. 本地节点和容器组 CIDR 块必须满足以下要求：

      1. 位于 IPv4 RFC–1918 范围之一：`10.0.0.0/8`、`172.16.0.0/12` 或 `192.168.0.0/16`，或者在 RFC 6598 定义的 CGNAT 范围内：`100.64.0.0/10`。

      1. 不相互重叠，也不与 Amazon EKS 集群的 `VPC CIDR` 或 Kubernetes 服务 IPv4 CIDR 重叠。

         ```
         aws eks create-cluster \
             --name CLUSTER_NAME \
             --region AWS_REGION \
             --kubernetes-version K8S_VERSION \
             --role-arn ROLE_ARN \
             --resources-vpc-config subnetIds=SUBNET1_ID,SUBNET2_ID,securityGroupIds=SG_ID,endpointPrivateAccess=true,endpointPublicAccess=false \
             --access-config authenticationMode=API_AND_CONFIG_MAP \
             --remote-network-config '{"remoteNodeNetworks":[{"cidrs":["REMOTE_NODE_CIDRS"]}],"remotePodNetworks":[{"cidrs":["REMOTE_POD_CIDRS"]}]}'
         ```

1. 预置集群需要几分钟时间。可使用以下命令查询集群的状态。请将 `CLUSTER_NAME` 替换为要创建的集群的名称，并将 `AWS_REGION` 替换为要创建集群的 AWS 区域。在返回的输出为 `ACTIVE` 之前，请勿继续执行下一步。

   ```
   aws eks describe-cluster \
       --name CLUSTER_NAME \
       --region AWS_REGION \
       --query "cluster.status"
   ```

1. 继续[第 3 步：更新 kubeconfig](#hybrid-nodes-cluster-create-kubeconfig)。

### 创建启用混合节点功能的集群 – AWS 管理控制台
<a name="hybrid-nodes-cluster-create-console"></a>

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

1. 请选择 Add cluster（添加集群），然后选择 Create（创建）。

1. 在 Configure cluster（配置集群）页面上，输入以下字段：

   1.  **Name**（名称）– 集群的名称。名称只能包含字母数字字符（区分大小写）、连字符和下划线。该名称必须以字母数字字符开头，且不得超过 100 个字符。对于您在其中创建集群的 AWS 区域和 AWS 账户，该名称必须在其内具有唯一性。

   1.  **集群 IAM 角色** – 选择您创建的 Amazon EKS 集群 IAM 角色，以允许 Kubernetes 控制面板来代表您管理 AWS 资源。

   1.  **Kubernetes version（Kubernetes 版本）**– 要用于集群的 Kubernetes 的版本。建议选择最新版本，除非您需要早期版本。

   1.  **升级策略** – 选择“扩展”或“标准”。

      1.  **扩展：**选中此选项后，将从发布之日起为 Kubernetes 版本提供 26 个月的支持。扩展支持期会额外按小时收取费用，从标准支持期结束后开始计算。扩展支持终止时，集群将自动升级到下一个版本。

      1.  **标准：**选中此选项后，将从发布之日起为 Kubernetes 版本提供 14 个月的支持。此选项不会产生额外的成本。标准支持终止时，集群将自动升级到下一个版本。

   1.  **集群访问权限** – 选择允许还是禁止集群管理员访问权限并选择身份验证模式。启用混合节点功能的集群支持以下身份验证模式。

      1.  **EKS API**：集群将仅从 EKS 访问条目 API 中获取已通过身份验证的 IAM 主体。

      1.  **EKS API 和 ConfigMap**：集群将从 EKS 访问条目 API 和 `aws-auth` ConfigMap 中获取已通过身份验证的 IAM 主体。

   1.  **Secrets encryption**（密钥加密）–（可选）选择此选项以使用 KMS 密钥启用 Kubernetes 密钥的密钥加密。您也可以在创建集群后启用此功能。在启用此功能之前，请确保您熟悉[在现有集群上使用 KMS 加密 Kubernetes 密钥](enable-kms.md)中的信息。

   1.  **ARC 可用区转移**：若启用该功能，EKS 会将集群注册到 ARC 可用区转移服务，使您能够借助可用区流量转移能力，将应用流量从某一可用区（AZ）中迁出。

   1.  **Tags（标签）**– （可选）向集群添加任何标签。有关更多信息，请参阅 [使用标签整理 Amazon EKS 资源](eks-using-tags.md)。

   1. 完成此页面后，请选择**下一步**。

1. 在 **Specify networking (指定联网)** 页面上，为以下字段选择值：

   1.  **VPC** – 选择符合[查看 Amazon EKS 对 VPC 和子网的联网要求](network-reqs.md)和 [Amazon EKS 混合节点功能要求](hybrid-nodes-prereqs.md)的现有 VPC。在选择 VPC 之前，我们建议您熟悉“查看有关 VPC、子网和混合节点的 Amazon EKS 联网要求”中的所有要求和注意事项。集群创建后，您无法更改要使用的 VPC。如果没有列出任何 VPC，则需要先创建一个。有关更多信息，请参阅[为您的 Amazon EKS 集群创建 Amazon VPC](creating-a-vpc.md)和 [Amazon EKS 混合节点功能联网要求](hybrid-nodes-prereqs.md)。

   1.  **Subnets**（子网）– 预设情况下，已预先选中在之前字段中指定的 VPC 中的所有可用子网。您必须至少选择两个子网。

   1.  **Security groups**（安全组）–（可选）指定您希望 Amazon EKS 将之与其创建的网络接口关联的一个或多个安全组。您指定的安全组中必须至少有一个含有本地节点和（可选）容器组 CIDR 的入站规则。有关更多信息，请参阅 [Amazon EKS 混合节点功能联网要求](hybrid-nodes-networking.md)。无论您是否选择任何安全组，Amazon EKS 都会创建一个安全组，以实现集群和 VPC 之间的通信。Amazon EKS 将此安全组以及您选择的任何安全组与它创建的网络接口关联起来。要详细了解 Amazon EKS 创建的集群安全组，请参阅[查看集群的 Amazon EKS 安全组要求](sec-group-reqs.md)。您可以修改 Amazon EKS 创建的集群安全组中的规则。

   1.  **选择集群 IP 地址系列** – 对于启用混合节点功能的集群必须选择 IPv4。

   1. （可选）选择**配置 Kubernetes 服务 IP 地址范围**，然后指定一个**服务 IPv4 范围**。

   1.  选择**配置远程网络以启用混合节点**，并为混合节点指定本地节点和容器组 CIDR。

   1. 如果您的 CNI 在容器组流量离开本地主机时不使用网络地址转换（NATI）或容器组 IP 地址伪装，则必须配置远程容器组 CIDR。如果在混合节点上运行 Webhook，则必须配置远程容器组 CIDR。

   1. 本地节点和容器组 CIDR 块必须满足以下要求：

      1. 位于 IPv4 RFC–1918 范围之一：`10.0.0.0/8`、`172.16.0.0/12` 或 `192.168.0.0/16`，或者在 RFC 6598 定义的 CGNAT 范围内：`100.64.0.0/10`。

      1. 不相互重叠，也不与集群的 `VPC CIDR` 或 Kubernetes 服务 IPv4 CIDR 重叠

   1. 对于**集群端点访问**中，选择一个选项。创建集群后，您可以更改此选项。对于启用混合节点功能的集群，您必须选择“公有”或“私有”。在选择非默认选项之前，请务必熟悉这些选项及其影响。有关更多信息，请参阅 [集群 API 服务器端点](cluster-endpoint.md)。

   1. 完成此页面后，请选择**下一步**。

1. （可选）在**配置**可观测性页面上，选择要开启的指标和控制面板日志记录选项。默认情况下，每种日志类型都处于关闭状态。

   1. 有关 Prometheus 指标选项的更多信息，请参阅[使用 Prometheus 监控集群指标](prometheus.md)。

   1. 有关 EKS 控制面板日志记录选项的更多信息，请参阅[将控制面板日志发送到 CloudWatch Logs](control-plane-logs.md)。

   1. 完成此页面后，请选择**下一步**。

1. 在 **Select add-ons**（选择附加组件）页面上，选择要添加到集群的附加组件。

   1. 您可以根据需要选择任意数量的 **Amazon EKS 附加组件**和 **AWS Marketplace 附加组件**。与混合节点功能不兼容的 Amazon EKS 附加组件带有“与混合节点功能不兼容”标志，并且此类附加组件使用反亲和性规则来防止其在混合节点上运行。有关更多信息，请参阅“为混合节点配置附加组件”。如果未列出要安装的 **AWS Marketplace 附加组件**，则可以通过在搜索框中输入文本来搜索可用的 **AWS Marketplace 附加组件**。您也可以按 **category**（类别）、**vendor**（供应商）或 **pricing model**（定价模式）进行搜索，然后从搜索结果中选择附加组件。

   1. CoreDNS 和 kube-proxy 等附加组件会默认安装。如果您禁用任何默认插件，则可能会影响您运行 Kubernetes 应用程序的能力。

   1. 完成此页中步骤后，请选择 `Next`。

1. 在**配置选定插件设置**页面上，选择要安装的版本。

   1. 创建集群后，您可以随时更新到更高版本。创建集群后，您可以更新每个附加组件的配置。有关配置附加组件的更多信息，请参阅[更新 Amazon EKS 附加组件](updating-an-add-on.md)。有关兼容混合节点功能的附加组件版本，请参阅[为混合节点配置附加组件](hybrid-nodes-add-ons.md)。

   1. 完成此页面后，请选择下一步。

1. 在 **Review and create (审核和创建)** 页面上，审核您在之前页面输入或选择的信息。如果需要进行更改，请选择 **Edit**（编辑）。在您感到满意后，选择**创建**。**Status**（状态）字段在预置集群时显示 **CREATING**（正在创建）。集群预配置需要几分钟时间。

1. 继续[第 3 步：更新 kubeconfig](#hybrid-nodes-cluster-create-kubeconfig)。

## 第 3 步：更新 kubeconfig
<a name="hybrid-nodes-cluster-create-kubeconfig"></a>

如果您使用 `eksctl` 创建了集群，则可以跳过此步骤。这是因为 `eksctl` 已经为您完成了此步骤。通过向 `kubectl` 文件添加新上下文，从而启用 `kubectl` 与集群之间的通信。有关如何创建和更新文件的更多信息，请参阅 [通过创建 kubeconfig 文件将 kubectl 连接到 EKS 集群](create-kubeconfig.md)。

```
aws eks update-kubeconfig --name CLUSTER_NAME --region AWS_REGION
```

示例输出如下。

```
Added new context arn:aws:eks:AWS_REGION:111122223333:cluster/CLUSTER_NAME to /home/username/.kube/config
```

通过运行以下命令以确认与集群的通信。

```
kubectl get svc
```

示例输出如下。

```
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   28h
```

## 第 4 步：集群设置
<a name="_step_4_cluster_setup"></a>

然后请参阅[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)以启用让混合节点能够加入集群的访问权限。

# 在现有 Amazon EKS 集群上启用混合节点或修改配置
<a name="hybrid-nodes-cluster-update"></a>

本主题概述了添加、更改或移除 Amazon EKS 集群的混合节点配置时可用的选项，并介绍了相关注意事项。

要让 Amazon EKS 集群能够使用混合节点，请在 `RemoteNetworkConfig` 配置中添加本地节点的 IP 地址 CIDR 范围以及可选的容器组（pod）网络。EKS 使用此 CIDR 列表来实现集群与本地网络之间的连接。有关更新集群配置时选项的完整列表，请参阅《Amazon EKS API Reference**》中的 [UpdateClusterConfig](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html)。

您可以对集群中的 EKS 混合节点网络配置执行以下任一操作：
+  [添加远程网络配置，以在现有集群中启用 EKS 混合节点。](#hybrid-nodes-cluster-enable-existing)
+  [在现有集群中添加、更改或移除远程节点网络或远程容器组（pod）网络。](#hybrid-nodes-cluster-update-config)
+  [移除所有远程节点网络 CIDR 范围，以在现有集群中禁用 EKS 混合节点。](#hybrid-nodes-cluster-disable)

## 先决条件
<a name="hybrid-nodes-cluster-enable-prep"></a>
+ 在为混合节点启用 Amazon EKS 集群之前，请确保您的环境满足 [混合节点的先决条件设置](hybrid-nodes-prereqs.md) 中概述的要求以及 [准备混合节点的联网](hybrid-nodes-networking.md)、[为混合节点准备操作系统](hybrid-nodes-os.md) 和 [准备用于混合节点的凭证](hybrid-nodes-creds.md) 中详细介绍的要求。
+ 集群必须使用 IPv4 地址系列。
+ 集群的集群身份验证模式必须为 `API` 或 `API_AND_CONFIG_MAP`。[更改身份验证模式以使用访问条目](setting-up-access-entries.md) 中介绍了修改集群身份验证模式的流程。
+ 我们建议为 Amazon EKS Kubernetes API 服务器端点使用公有或私有端点访问权限，但不要同时启用这两者。如果您选择“公有和私有”，Amazon EKS Kubernetes API 服务器端点将始终解析为在您的 VPC 之外运行的混合节点公有 IP，这可能会阻止您的混合节点加入集群。[集群 API 服务器端点](cluster-endpoint.md) 中介绍了修改集群网络访问权限的流程。
+ 已在您的设备上安装并配置了最新版本的 AWS 命令行界面（AWS CLI）。要查看当前版本，请使用 `aws --version`。yum、apt-get 或适用于 macOS 的 Homebrew 等软件包管理器通常比 AWS CLI 的最新版本落后几个版本。要安装最新版本，请参阅《AWS 命令行界面用户指南》中的[安装或更新到最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 和[配置 AWS CLI 设置](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)。
+ 有权限在您的 Amazon EKS 集群上调用 [UpdateClusterConfig](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html) 的 [IAM 主体](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles#iam-term-principal)。
+ 将附加组件更新到兼容混合节点的版本。有关兼容混合节点功能的附加组件版本，请参阅[为混合节点配置附加组件](hybrid-nodes-add-ons.md)。
+ 如果您正在运行与混合节点不兼容的附加组件，请确保附加组件 [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) 或 [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) 具有以下亲和性规则来防止部署到混合节点。如果以下亲和性规则尚不存在，请添加该规则。

  ```
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: NotIn
            values:
            - hybrid
  ```

## 注意事项
<a name="hybrid-nodes-cluster-enable-consider"></a>

`remoteNetworkConfig` JSON 对象在更新期间具有以下行为：
+ 您未指定的任何现有配置部分均保持不变。如果您未指定 `remoteNodeNetworks` 或 `remotePodNetworks` 中的任何一个，则该部分将保持不变。
+ 如果要修改 CIDR 的 `remoteNodeNetworks` 或 `remotePodNetworks` 列表，则必须在最终配置中指定所需的 CIDR 的完整列表。如果您指定了对 `remoteNodeNetworks` 或 `remotePodNetworks` CIDR 列表的更改，EKS 将在更新期间替换原始列表。
+ 本地节点和容器组 CIDR 块必须满足以下要求：

  1. 位于 IPv4 RFC–1918 范围之一：10.0.0.0/8、172.16.0.0/12 或 192.168.0.0/16，或者在 RFC 6598 定义的 CGNAT 范围内：`100.64.0.0/10`

  1. 不相互重叠，也不与 Amazon EKS 集群的所有 VPC CIDR 或 Kubernetes 服务 IPv4 CIDR 重叠。

## 在现有集群上启用混合节点
<a name="hybrid-nodes-cluster-enable-existing"></a>

您可以使用以下方法在现有集群中启用 EKS 混合节点：
+  [AWS CloudFormation](#hybrid-nodes-cluster-enable-cfn) 
+  [AWS CLI](#hybrid-nodes-cluster-enable-cli) 
+  [AWS 管理控制台](#hybrid-nodes-cluster-enable-console) 

### 在现有集群中启用 EKS 混合节点 – AWS CloudFormation
<a name="hybrid-nodes-cluster-enable-cfn"></a>

1. 要在集群中启用 EKS 混合节点，请将 `RemoteNodeNetwork` 和（可选）`RemotePodNetwork` 添加到您的 CloudFormation 模板并更新堆栈。请注意，`RemoteNodeNetwork` 列表最多包含一个 `Cidrs` 项目，而 `Cidrs` 列表可包含多个 IP CIDR 范围。

   ```
   RemoteNetworkConfig:
     RemoteNodeNetworks:
       - Cidrs: [RemoteNodeCIDR]
     RemotePodNetworks:
       - Cidrs: [RemotePodCIDR]
   ```

1. 继续[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)。

### 在现有集群中启用 EKS 混合节点 – AWS CLI
<a name="hybrid-nodes-cluster-enable-cli"></a>

1. 运行以下命令，为 EKS 集群启用 EKS 混合节点的 `RemoteNetworkConfig`。在运行此命令之前，请将以下参数替换为相应的设置。有关设置的完整列表，请参阅《Amazon EKS API Reference》**中的 [UpdateClusterConfig](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html)。

   1.  `CLUSTER_NAME`：要更新的 EKS 集群的名称。

   1.  `AWS_REGION`：EKS 集群正在运行的 AWS 区域。

   1.  `REMOTE_NODE_CIDRS`：混合节点的本地节点 CIDR。

   1.  `REMOTE_POD_CIDRS`（可选）：在混合节点上运行的工作负载的本地容器组 CIDR。

      ```
      aws eks update-cluster-config \
          --name CLUSTER_NAME \
          --region AWS_REGION \
          --remote-network-config '{"remoteNodeNetworks":[{"cidrs":["REMOTE_NODE_CIDRS"]}],"remotePodNetworks":[{"cidrs":["REMOTE_POD_CIDRS"]}]}'
      ```

1. 更新集群需要几分钟时间。可使用以下命令查询集群的状态。请将 `CLUSTER_NAME` 替换为要修改的集群的名称，并将 `AWS_REGION` 替换为运行集群的 AWS 区域。在返回的输出为 `ACTIVE` 之前，请勿继续执行下一步。

   ```
   aws eks describe-cluster \
       --name CLUSTER_NAME \
       --region AWS_REGION \
       --query "cluster.status"
   ```

1. 继续[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)。

### 在现有集群中启用 EKS 混合节点 – AWS 管理控制台
<a name="hybrid-nodes-cluster-enable-console"></a>

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

1. 选择集群的名称可以显示集群信息。

1. 选择**联网**选项卡，然后选择**更新**。

1. 在下拉列表中，选择**远程网络**。

1.  选择**配置远程网络以启用混合节点**，并为混合节点指定本地节点和容器组 CIDR。

1. 选择 **Save changes（保存更改）**以完成操作。等待集群状态恢复为**活动**。

1. 继续[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)。

## 更新现有集群中的混合节点配置
<a name="hybrid-nodes-cluster-update-config"></a>

您可以使用以下任何一种方法修改现有混合集群中的 `remoteNetworkConfig`：
+  [AWS CloudFormation](#hybrid-nodes-cluster-update-cfn) 
+  [AWS CLI](#hybrid-nodes-cluster-update-cli) 
+  [AWS 管理控制台](#hybrid-nodes-cluster-update-console) 

### 更新现有集群中的混合配置 – AWS CloudFormation
<a name="hybrid-nodes-cluster-update-cfn"></a>

1. 使用新的网络 CIDR 值更新您的 CloudFormation 模板。

   ```
   RemoteNetworkConfig:
     RemoteNodeNetworks:
       - Cidrs: [NEW_REMOTE_NODE_CIDRS]
     RemotePodNetworks:
       - Cidrs: [NEW_REMOTE_POD_CIDRS]
   ```
**注意**  
更新 `RemoteNodeNetworks` 或 `RemotePodNetworks` CIDR 列表时，请包含全部 CIDR（新的和现有的）。更新期间，EKS 会替换整个列表。在更新请求中省略这些字段会保留其现有配置。

1. 使用修改后的模板更新您的 CloudFormation 堆栈，然后等待堆栈更新完成。

### 更新现有集群中的混合配置 – AWS CLI
<a name="hybrid-nodes-cluster-update-cli"></a>

1. 要修改远程网络 CIDR，请运行以下命令。将这些值替换为相应的设置：

   ```
   aws eks update-cluster-config
   --name CLUSTER_NAME
   --region AWS_REGION
   --remote-network-config '{"remoteNodeNetworks":[{"cidrs":["NEW_REMOTE_NODE_CIDRS"]}],"remotePodNetworks":[{"cidrs":["NEW_REMOTE_POD_CIDRS"]}]}'
   ```
**注意**  
更新 `remoteNodeNetworks` 或 `remotePodNetworks` CIDR 列表时，请包含全部 CIDR（新的和现有的）。更新期间，EKS 会替换整个列表。在更新请求中省略这些字段会保留其现有配置。

1. 等待集群状态恢复为“ACTIVE”，然后再继续。

### 更新现有集群中的混合配置 – AWS 管理控制台
<a name="hybrid-nodes-cluster-update-console"></a>

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

1. 选择集群的名称可以显示集群信息。

1. 选择**联网**选项卡，然后选择**更新**。

1. 在下拉列表中，选择**远程网络**。

1. 根据需要更新 `Remote node networks` 和 `Remote pod networks - Optional` 下方的 CIDR。

1. 选择**保存更改**，然后等待集群状态恢复为**活动**。

## 在现有集群中禁用混合节点
<a name="hybrid-nodes-cluster-disable"></a>

您可以使用以下方法在现有集群中禁用 EKS 混合节点：
+  [AWS CloudFormation](#hybrid-nodes-cluster-disable-cfn) 
+  [AWS CLI](#hybrid-nodes-cluster-disable-cli) 
+  [AWS 管理控制台](#hybrid-nodes-cluster-disable-console) 

### 在现有集群中禁用 EKS 混合节点 – AWS CloudFormation
<a name="hybrid-nodes-cluster-disable-cfn"></a>

1. 要在集群中禁用 EKS 混合节点，请在 CloudFormation 模板中将 `RemoteNodeNetworks` 和 `RemotePodNetworks` 设置为空数组，然后更新堆栈。

   ```
   RemoteNetworkConfig:
     RemoteNodeNetworks: []
     RemotePodNetworks: []
   ```

### 在现有集群中禁用 EKS 混合节点 – AWS CLI
<a name="hybrid-nodes-cluster-disable-cli"></a>

1. 运行以下命令，从 EKS 集群中移除 `RemoteNetworkConfig`。在运行此命令之前，请将以下参数替换为相应的设置。有关设置的完整列表，请参阅《Amazon EKS API Reference》**中的 [UpdateClusterConfig](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html)。

   1.  `CLUSTER_NAME`：要更新的 EKS 集群的名称。

   1.  `AWS_REGION`：EKS 集群正在运行的 AWS 区域。

      ```
      aws eks update-cluster-config \
          --name CLUSTER_NAME \
          --region AWS_REGION \
          --remote-network-config '{"remoteNodeNetworks":[],"remotePodNetworks":[]}'
      ```

1. 更新集群需要几分钟时间。可使用以下命令查询集群的状态。请将 `CLUSTER_NAME` 替换为要修改的集群的名称，并将 `AWS_REGION` 替换为运行集群的 AWS 区域。在返回的输出为 `ACTIVE` 之前，请勿继续执行下一步。

   ```
   aws eks describe-cluster \
       --name CLUSTER_NAME \
       --region AWS_REGION \
       --query "cluster.status"
   ```

### 在现有集群中禁用 EKS 混合节点 – AWS 管理控制台
<a name="hybrid-nodes-cluster-disable-console"></a>

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

1. 选择集群的名称可以显示集群信息。

1. 选择**联网**选项卡，然后选择**更新**。

1. 在下拉列表中，选择**远程网络**。

1. 选择**配置远程网络以启用混合节点**，然后移除 `Remote node networks` 和 `Remote pod networks - Optional` 下的所有 CIDR。

1. 选择 **Save changes（保存更改）**以完成操作。等待集群状态恢复为**活动**。

# 准备混合节点的集群访问权限
<a name="hybrid-nodes-cluster-prep"></a>

在将混合节点连接到 Amazon EKS 集群之前，您必须为混合节点 IAM 角色授予加入集群的 Kubernetes 权限。有关如何创建混合节点 IAM 角色的信息，请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)。Amazon EKS 支持通过两种方式将 IAM 主体关联到 Kubernetes 基于角色的访问控制（RBAC）、Amazon EKS 访问条目和 `aws-auth` ConfigMap。有关 Amazon EKS 访问权限管理的更多信息，请参阅[向 IAM 用户和角色授予对 Kubernetes API 的访问权限](grant-k8s-access.md)。

按照以下过程将混合节点 IAM 角色与 Kubernetes 权限关联起来。要使用 Amazon EKS 访问条目，集群必须是使用 `API` 或 `API_AND_CONFIG_MAP` 身份验证模式创建的。要使用 `aws-auth` ConfigMap，集群必须是使用 `API_AND_CONFIG_MAP` 身份验证模式创建的。启用混合节点功能的 Amazon EKS 集群不支持仅 `CONFIG_MAP` 身份验证模式。

## 将 Amazon EKS 访问条目用于混合节点 IAM 角色
<a name="_using_amazon_eks_access_entries_for_hybrid_nodes_iam_role"></a>

一种名为 HYBRID\$1LINUX 的混合节点 Amazon EKS 访问条目类型可以与 IAM 角色一起使用。使用此访问条目类型，用户名将被自动设置为 system:node:\$1\$1SessionName\$1\$1。有关创建访问条目的更多信息，请参阅[创建访问条目](creating-access-entries.md)。

### AWS CLI
<a name="shared_aws_cli"></a>

1. 您必须已在设备上安装和配置最新版本的 AWS CLI。要查看当前版本，请使用 `aws --version`。yum、apt-get 或适用于 macOS 的 Homebrew 等软件包管理器通常比 AWS CLI 的最新版本落后几个版本。要安装最新版本，请参阅《AWS 命令行界面用户指南》中的“安装”和“使用 aws configure 快速配置”。

1. 使用以下命令创建访问条目。请将 CLUSTER\$1NAME 替换为集群的名称，将 HYBRID\$1NODES\$1ROLE\$1ARN 替换为您在[准备用于混合节点的凭证](hybrid-nodes-creds.md)步骤中创建的角色的 ARN。

   ```
   aws eks create-access-entry --cluster-name CLUSTER_NAME \
       --principal-arn HYBRID_NODES_ROLE_ARN \
       --type HYBRID_LINUX
   ```

### AWS 管理控制台
<a name="hybrid-nodes-cluster-prep-console"></a>

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

1. 选择已启用混合节点功能的集群的名称。

1. 选择**访问**选项卡。

1. 选择**创建访问条目**。

1. 对于 **IAM 主体**，请选择您在[准备用于混合节点的凭证](hybrid-nodes-creds.md)步骤中创建的混合节点 IAM 角色。

1. 对于**类型**，选择 **Hybrid Linux**。

1. （可选）对于**标签**，为访问条目分配标签。例如，为了更轻松地查找所有具有相同标签的资源。

1. 选择**跳过以检查并创建**。不能向 Hybrid Linux 访问条目添加策略或更改其访问权限范围。

1. 查看访问条目的配置。如果有任何内容看起来不正确，请选择**上一步**以返回步骤并更正错误。如果配置正确，请选择**创建**。

## 将 aws-auth ConfigMap 用于混合节点 IAM 角色
<a name="_using_aws_auth_configmap_for_hybrid_nodes_iam_role"></a>

在以下步骤中，您将使用您在[准备用于混合节点的凭证](hybrid-nodes-creds.md)步骤中创建的混合节点 IAM 角色的 ARN 来创建或更新 `aws-auth` ConfigMap。

1. 检查您的集群是否已有现有的 `aws-auth` ConfigMap。请注意如果您使用特定的 `kubeconfig` 文件，请使用 `--kubeconfig` 标志。

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

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

   1. 打开该 ConfigMap 进行编辑。

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

   1. 根据需要添加新的 `mapRoles` 条目。将 `HYBRID_NODES_ROLE_ARN` 替换为混合节点 IAM 角色的 ARN。注意，`{{SessionName}}` 是保存在 ConfigMap 中的正确模板格式。请勿将其替换为其他值。

      ```
      data:
        mapRoles: |
        - groups:
          - system:bootstrappers
          - system:nodes
          rolearn: HYBRID_NODES_ROLE_ARN
          username: system:node:{{SessionName}}
      ```

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

1. 如果集群没有现有的 `aws-auth` ConfigMap，请使用以下命令创建一个。将 `HYBRID_NODES_ROLE_ARN` 替换为混合节点 IAM 角色的 ARN。注意，`{{SessionName}}` 是保存在 ConfigMap 中的正确模板格式。请勿将其替换为其他值。

   ```
   kubectl apply -f=/dev/stdin <<-EOF
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: aws-auth
     namespace: kube-system
   data:
     mapRoles: |
     - groups:
       - system:bootstrappers
       - system:nodes
       rolearn: HYBRID_NODES_ROLE_ARN
       username: system:node:{{SessionName}}
   EOF
   ```

# 在混合节点上运行本地工作负载
<a name="hybrid-nodes-tutorial"></a>

在启用了混合节点功能的 EKS 集群中，您可以使用与 AWS 云端相同的 Amazon EKS 集群、功能和工具，在自己的基础设施上运行本地和边缘应用程序。

以下章节包含有关使用混合节点的分步指导。

**Topics**
+ [连接混合节点](hybrid-nodes-join.md)
+ [连接使用 Bottlerocket 的混合节点](hybrid-nodes-bottlerocket.md)
+ [升级混合节点](hybrid-nodes-upgrade.md)
+ [修补混合节点](hybrid-nodes-security.md)
+ [删除混合节点](hybrid-nodes-remove.md)

# 连接混合节点
<a name="hybrid-nodes-join"></a>

**注意**  
以下步骤适用于运行除 Bottlerocket 以外的兼容操作系统的混合节点。有关连接运行 Bottlerocket 的混合节点的步骤，请参阅[连接使用 Bottlerocket 的混合节点](hybrid-nodes-bottlerocket.md)。

本主题介绍如何将混合节点连接到 Amazon EKS 集群。混合节点加入集群后，将在 Amazon EKS 控制台和兼容 Kubernetes 的工具（例如 kubectl）中显示并且状态为“未就绪”。完成本页介绍的步骤后，[为混合节点配置 CNI](hybrid-nodes-cni.md) 以确保混合节点可以随时用于运行应用程序。

## 先决条件
<a name="_prerequisites"></a>

在将混合节点连接到 Amazon EKS 集群之前，请确保您已完成先决步骤。
+ 您已建立从本地环境到托管 Amazon EKS 集群的 AWS 区域的连接。请参阅[准备混合节点的联网](hybrid-nodes-networking.md)了解更多信息。
+ 您已在本地主机上安装了适用于混合节点的兼容操作系统。请参阅[为混合节点准备操作系统](hybrid-nodes-os.md)了解更多信息。
+ 您已经创建了混合节点 IAM 角色并设置了本地凭证提供者（AWS Systems Manager 混合激活或 AWS IAM Roles Anywhere）。请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)了解更多信息。
+ 您已经创建启用了混合节点的 Amazon EKS 集群。请参阅[创建具有混合节点的 Amazon EKS 集群](hybrid-nodes-cluster-create.md)了解更多信息。
+ 您已为您的混合节点 IAM 角色关联了 Kubernetes 基于角色的访问控制（RBAC）权限。请参阅[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)了解更多信息。

## 第 1 步：在每台本地主机上安装混合节点 CLI (`nodeadm`)
<a name="_step_1_install_the_hybrid_nodes_cli_nodeadm_on_each_on_premises_host"></a>

如果您预构建的操作系统映像已经包含 Amazon EKS 混合节点功能 CLI (`nodeadm`)，则可以跳过此步骤。有关 `nodeadm` 混合节点版本的更多信息，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

`nodeadm` 的混合节点版本在 Amazon S3 中托管，由 Amazon CloudFront 分发。要在每台本地主机上安装 `nodeadm`，您可以在本地主机上运行以下命令。

 **x86\$164 主机：**

```
curl -OL 'https://hybrid-assets.eks.amazonaws.com/releases/latest/bin/linux/amd64/nodeadm'
```

 **ARM 主机** 

```
curl -OL 'https://hybrid-assets.eks.amazonaws.com/releases/latest/bin/linux/arm64/nodeadm'
```

将可执行文件权限添加到每台主机上下载的二进制文件。

```
chmod +x nodeadm
```

## 第 2 步：使用 `nodeadm` 安装混合节点依赖项
<a name="_step_2_install_the_hybrid_nodes_dependencies_with_nodeadm"></a>

如果在预构建的操作系统映像中安装混合节点依赖项，则可以跳过此步骤。`nodeadm install` 命令可用于安装混合节点必需的所有依赖项。混合节点依赖项包括 containerd、kubelet、kubectl 以及 AWS SSM 或 AWS IAM Roles Anywhere 组件。要详细了解 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md) 安装的组件和文件位置，请参阅`nodeadm install`。要详细了解必须在本地防火墙中为 `nodeadm install` 进程允许的域，请参阅[准备混合节点的联网](hybrid-nodes-networking.md)。

运行以下命令，从而在本地主机上安装混合节点依赖项。运行以下命令的用户必须具有您主机上的 sudo/root 访问权限。

**重要**  
运行混合节点 CLI (`nodeadm`) 的用户必须具有您主机上的 sudo/root 访问权限。
+ 请 `K8S_VERSION` 替换为 Amazon EKS 集群的 Kubernetes 次要版本，例如 `1.31`。有关支持的 Kubernetes 版本的列表，请参阅 [Amazon EKS 支持的版本](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)。
+ 请将 `CREDS_PROVIDER` 替换为您使用的本地凭证提供者。AWS SSM 的有效值为 `ssm`，AWS IAM Roles Anywhere 的有效值为 `iam-ra`。

```
nodeadm install K8S_VERSION --credential-provider CREDS_PROVIDER
```

## 第 3 步：将混合节点连接到集群
<a name="_step_3_connect_hybrid_nodes_to_your_cluster"></a>

在将混合节点连接到集群之前，请确保您的本地防火墙和集群安全组中已经允许在 Amazon EKS 控制面板与混合节点之间进行通信所必需的权限。此步骤中出现的大多数问题都与防火墙配置、安全组配置或混合节点 IAM 角色配置有关。

**重要**  
运行混合节点 CLI (`nodeadm`) 的用户必须具有您主机上的 sudo/root 访问权限。

1. 在每台主机上创建一个包含适用于部署的值的 `nodeConfig.yaml` 文件。有关可用配置设置的完整说明，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。如果混合节点 IAM 角色没有执行 `eks:DescribeCluster` 操作的权限，则必须在 `nodeConfig.yaml` 的集群部分中传递 Kubernetes API 端点、集群 CA 捆绑和 Kubernetes 服务 IPv4 CIDR。

   1. 如果您的本地凭证提供者为 AWS SSM 混合激活，请使用以下 `nodeConfig.yaml` 示例。

      1. 将 `CLUSTER_NAME` 替换为您的集群名称。

      1. 请将 AWS 替换为集群所在的 `AWS_REGION` 区域。例如 `us-west-2`。

      1. 请将 `ACTIVATION_CODE` 替换为创建 AWS SSM 混合激活时收到的激活码。请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)了解更多信息。

      1. 请将 `ACTIVATION_ID` 替换为创建 AWS SSM 混合激活时收到的激活 ID。您可以通过 AWS Systems Manager 控制台或 AWS CLI `aws ssm describe-activations` 命令查看此信息。

         ```
         apiVersion: node.eks.aws/v1alpha1
         kind: NodeConfig
         spec:
           cluster:
             name: CLUSTER_NAME
             region: AWS_REGION
           hybrid:
             ssm:
               activationCode: ACTIVATION_CODE
               activationId: ACTIVATION_ID
         ```

   1. 如果您的本地凭证提供者为 AWS IAM Roles Anywhere，请使用以下 `nodeConfig.yaml` 示例。

      1. 将 `CLUSTER_NAME` 替换为您的集群名称。

      1. 请将 AWS 替换为集群所在的 `AWS_REGION` 区域。例如 `us-west-2`。

      1. 请将 `NODE_NAME` 替换为节点的名称。如果您为混合节点 IAM 角色配置的信任策略使用 `"sts:RoleSessionName": "${aws:PrincipalTag/x509Subject/CN}"` 资源条件，则节点名称必须与主机上证书的 CN 一致。您使用的 `nodeName` 长度不得超过 64 个字符。

      1. 请将 `TRUST_ANCHOR_ARN` 替换为您在“准备用于混合节点的凭证”步骤中配置的信任锚的 ARN。

      1. 请将 `PROFILE_ARN` 替换为您在“[准备用于混合节点的凭证](hybrid-nodes-creds.md)”步骤中配置的信任锚的 ARN。

      1. 将 `ROLE_ARN` 替换为混合节点 IAM 角色的 ARN。

      1. 请将 `CERTIFICATE_PATH` 替换为磁盘中指向节点证书的路径。如果不指定此参数，则默认值为 `/etc/iam/pki/server.pem`。

      1. 请将 `KEY_PATH` 替换为磁盘中指向证书私有密钥的路径。如果不指定此参数，则默认值为 `/etc/iam/pki/server.key`。

         ```
         apiVersion: node.eks.aws/v1alpha1
         kind: NodeConfig
         spec:
           cluster:
             name: CLUSTER_NAME
             region: AWS_REGION
           hybrid:
             iamRolesAnywhere:
               nodeName: NODE_NAME
               trustAnchorArn: TRUST_ANCHOR_ARN
               profileArn: PROFILE_ARN
               roleArn: ROLE_ARN
               certificatePath: CERTIFICATE_PATH
               privateKeyPath: KEY_PATH
         ```

1. 使用您的 `nodeConfig.yaml` 运行 `nodeadm init` 命令，从而将混合节点连接到 Amazon EKS 集群。

   ```
   nodeadm init -c file://nodeConfig.yaml
   ```

如果上述命令成功完成，则表示混合节点已加入您的 Amazon EKS 集群。您可以在 Amazon EKS 控制台中导航到集群的“计算”选项卡（[确保 IAM 主体具有查看权限](view-kubernetes-resources.md#view-kubernetes-resources-permissions)）或使用 `kubectl get nodes` 来验证此信息。

**重要**  
您的节点将处于 `Not Ready` 状态，此状态符合预期，是因混合节点上缺少正在运行的 CNI 所致。如果节点未加入集群，请参阅[混合节点故障排除](hybrid-nodes-troubleshooting.md)。

## 第 4 步：为混合节点配置 CNI
<a name="_step_4_configure_a_cni_for_hybrid_nodes"></a>

要使混合节点能够随时运行应用程序，请继续完成[为混合节点配置 CNI](hybrid-nodes-cni.md)中的步骤。

# 连接使用 Bottlerocket 的混合节点
<a name="hybrid-nodes-bottlerocket"></a>

本主题介绍如何将运行 Bottlerocket 的混合节点连接到 Amazon EKS 集群。[Bottlerocket](https://aws.amazon.com/bottlerocket/) 是由 AWS 赞助并提供支持的开源 Linux 发行版。Bottlerocket 专为托管容器工作负载而构建。您可以借助 Bottlerocket 实现容器基础设施自动更新，由此提高容器化部署的可用性，降低运营成本。Bottlerocket 仅包含运行容器所需的必备软件，可提高资源利用率、减少安全威胁并降低管理开销。

仅支持将 Bottlerocket 版本 v1.37.0 及更高版本的 VMware 变体与 EKS 混合节点结合使用。Bottlerocket 的 VMware 变体支持 Kubernetes 版本 1.28 及更高版本。这些变体的操作系统映像包括 kubelet、containerd、aws-iam-authenticator 以及适用于 EKS 混合节点功能的其他软件先决条件。您可以使用 Bottlerocket [设置](https://github.com/bottlerocket-os/bottlerocket#settings)文件来配置这些组件，该文件包含用于 Bottlerocket 引导容器和管理容器的 base64 编码用户数据。通过配置这些设置，可让 Bottlerocket 使用您的混合节点凭证提供程序来完成集群对混合节点的身份验证。混合节点加入集群后，将在 Amazon EKS 控制台以及 `kubectl` 等兼容 Kubernetes 的工具中显示并且状态为 `Not Ready`。完成本页介绍的步骤后，[为混合节点配置 CNI](hybrid-nodes-cni.md) 以确保混合节点可以随时用于运行应用程序。

## 先决条件
<a name="_prerequisites"></a>

在将混合节点连接到 Amazon EKS 集群之前，请确保您已完成先决步骤。
+ 您已建立从本地环境到托管 Amazon EKS 集群的 AWS 区域的连接。请参阅[准备混合节点的联网](hybrid-nodes-networking.md)了解更多信息。
+ 您已经创建了混合节点 IAM 角色并设置了本地凭证提供者（AWS Systems Manager 混合激活或 AWS IAM Roles Anywhere）。请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)了解更多信息。
+ 您已经创建启用了混合节点的 Amazon EKS 集群。请参阅[创建具有混合节点的 Amazon EKS 集群](hybrid-nodes-cluster-create.md)了解更多信息。
+ 您已为您的混合节点 IAM 角色关联了 Kubernetes 基于角色的访问控制（RBAC）权限。请参阅[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)了解更多信息。

## 第 1 步：创建 Bottlerocket 设置 TOML 文件
<a name="_step_1_create_the_bottlerocket_settings_toml_file"></a>

要为混合节点配置 Bottlerocket，您需要创建一个包含必要配置的 `settings.toml` 文件。TOML 文件的内容因您使用的凭证提供程序（SSM 或 IAM Roles Anywhere）而异。在预置 Bottlerocket 实例时，此文件将作为用户数据传递。

**注意**  
下方提供的 TOML 文件仅包含将 Bottlerocket VMWare 机器初始化为 EKS 集群节点所需的最低配置项。Bottlerocket 提供了丰富的配置项，可满足多种不同的使用案例。因此，若需配置混合节点初始化之外的更多功能，请查阅 [Bottlerocket 文档](https://bottlerocket.dev/en)，获取所使用版本的完整配置项列表（例如，[此处](https://bottlerocket.dev/en/os/1.51.x/api/settings-index)列出了 Bottlerocket 1.51.x 版本的全部可用配置项）。

### SSM
<a name="_ssm"></a>

如果将 AWS Systems Manager 作为凭证提供程序，请创建一个包含以下内容的 `settings.toml` 文件：

```
[settings.kubernetes]
cluster-name = "<cluster-name>"
api-server = "<api-server-endpoint>"
cluster-certificate = "<cluster-certificate-authority>"
hostname-override = "<hostname>"
provider-id = "eks-hybrid:///<region>/<cluster-name>/<hostname>"
authentication-mode = "aws"
cloud-provider = ""
server-tls-bootstrap = true

[settings.network]
hostname = "<hostname>"

[settings.aws]
region = "<region>"

[settings.kubernetes.credential-providers.ecr-credential-provider]
enabled = true
cache-duration = "12h"
image-patterns = [
    "*.dkr.ecr.*.amazonaws.com",
    "*.dkr.ecr.*.amazonaws.com.rproxy.goskope.com.cn",
    "*.dkr.ecr.*.amazonaws.eu",
    "*.dkr.ecr-fips.*.amazonaws.com",
    "*.dkr.ecr-fips.*.amazonaws.eu",
    "public.ecr.aws"
]

[settings.kubernetes.node-labels]
"eks.amazonaws.com/compute-type" = "hybrid"
"eks.amazonaws.com/hybrid-credential-provider" = "ssm"

[settings.host-containers.admin]
enabled = true
user-data = "<base64-encoded-admin-container-userdata>"

[settings.bootstrap-containers.eks-hybrid-setup]
mode = "always"
user-data = "<base64-encoded-bootstrap-container-userdata>"

[settings.host-containers.control]
enabled = true
```

将占位符替换为以下值：
+  `<cluster-name>`：Amazon EKS 集群的名称。
+  `<api-server-endpoint>`：集群的 API 服务器端点。
+  `<cluster-certificate-authority>`：集群的 base64 编码 CA 捆绑包。
+  `<region>`：托管集群的 AWS 区域，例如“us-east-1”。
+  `<hostname>`：Bottlerocket 实例的主机名，这也将被配置为节点名称。这可以是您选择的任何唯一值，但必须符合 [Kubernetes 对象命名惯例](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)。此外，使用的主机名称长度不能超过 64 个字符。注意：使用 SSM 提供程序时，在将实例注册到 SSM 后，该主机名和节点名称将替换为托管实例 ID（例如，`mi-*` ID）。
+  `<base64-encoded-admin-container-userdata>`：Bottlerocket 管理容器配置的 base64 编码内容。启用管理容器后，您将能够通过 SSH 连接到 Bottlerocket 实例，以便进行系统探索和调试。虽然这不是必需设置，但为了便于故障排除，我们建议将其启用。有关使用管理容器进行身份验证的更多信息，请参阅 [Bottlerocket 管理容器文档](https://github.com/bottlerocket-os/bottlerocket-admin-container#authenticating-with-the-admin-container)。例如，管理容器接受 JSON 格式的 SSH 用户和密钥输入。

```
{
  "user": "<ssh-user>",
  "ssh": {
    "authorized-keys": [
      "<ssh-authorized-key>"
    ]
  }
}
```
+  `<base64-encoded-bootstrap-container-userdata>`：Bottlerocket 引导容器配置的 base64 编码内容。有关其配置的更多信息，请参阅 [Bottlerocket 引导容器文档](https://github.com/bottlerocket-os/bottlerocket-bootstrap-container)。引导容器负责将实例注册为 AWS SSM 托管式实例，并将其作为 Kubernetes 节点加入 Amazon EKS 集群。传递到引导容器的用户数据采用命令调用的形式，这会将您之前创建的 SSM 混合激活码和 ID 作为输入接受：

```
eks-hybrid-ssm-setup --activation-id=<activation-id> --activation-code=<activation-code> --region=<region>
```

### IAM Roles Anywhere
<a name="_iam_roles_anywhere"></a>

如果将 AWS IAM Roles Anywhere 作为凭证提供程序，请创建一个包含以下内容的 `settings.toml` 文件：

```
[settings.kubernetes]
cluster-name = "<cluster-name>"
api-server = "<api-server-endpoint>"
cluster-certificate = "<cluster-certificate-authority>"
hostname-override = "<hostname>"
provider-id = "eks-hybrid:///<region>/<cluster-name>/<hostname>"
authentication-mode = "aws"
cloud-provider = ""
server-tls-bootstrap = true

[settings.network]
hostname = "<hostname>"

[settings.aws]
region = "<region>"
config = "<base64-encoded-aws-config-file>"

[settings.kubernetes.credential-providers.ecr-credential-provider]
enabled = true
cache-duration = "12h"
image-patterns = [
    "*.dkr.ecr.*.amazonaws.com",
    "*.dkr.ecr.*.amazonaws.com.rproxy.goskope.com.cn",
    "*.dkr.ecr.*.amazonaws.eu",
    "*.dkr.ecr-fips.*.amazonaws.com",
    "*.dkr.ecr-fips.*.amazonaws.eu",
    "public.ecr.aws"
]

[settings.kubernetes.node-labels]
"eks.amazonaws.com/compute-type" = "hybrid"
"eks.amazonaws.com/hybrid-credential-provider" = "iam-ra"

[settings.host-containers.admin]
enabled = true
user-data = "<base64-encoded-admin-container-userdata>"

[settings.bootstrap-containers.eks-hybrid-setup]
mode = "always"
user-data = "<base64-encoded-bootstrap-container-userdata>"
```

将占位符替换为以下值：
+  `<cluster-name>`：Amazon EKS 集群的名称。
+  `<api-server-endpoint>`：集群的 API 服务器端点。
+  `<cluster-certificate-authority>`：集群的 base64 编码 CA 捆绑包。
+  `<region>`：托管集群的 AWS 区域，例如“us-east-1”
+  `<hostname>`：Bottlerocket 实例的主机名，这也将被配置为节点名称。这可以是您选择的任何唯一值，但必须符合 [Kubernetes 对象命名惯例](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)。此外，使用的主机名称长度不能超过 64 个字符。注意：使用 IAM-RA 提供程序时，如果您为混合节点 IAM 角色配置的信任策略使用 `"sts:RoleSessionName": "${aws:PrincipalTag/x509Subject/CN}"` 资源条件，则节点名称必须与主机上证书的 CN 一致。
+  `<base64-encoded-aws-config-file>`：AWS 配置文件的 Base64 编码内容。该文件的内容应会如下所示：

```
[default]
credential_process = aws_signing_helper credential-process --certificate /root/.aws/node.crt --private-key /root/.aws/node.key --profile-arn <profile-arn> --role-arn <role-arn> --trust-anchor-arn <trust-anchor-arn> --role-session-name <role-session-name>
```
+  `<base64-encoded-admin-container-userdata>`：Bottlerocket 管理容器配置的 base64 编码内容。启用管理容器后，您将能够通过 SSH 连接到 Bottlerocket 实例，以便进行系统探索和调试。虽然这不是必需设置，但为了便于故障排除，我们建议将其启用。有关使用管理容器进行身份验证的更多信息，请参阅 [Bottlerocket 管理容器文档](https://github.com/bottlerocket-os/bottlerocket-admin-container#authenticating-with-the-admin-container)。例如，管理容器接受 JSON 格式的 SSH 用户和密钥输入。

```
{
  "user": "<ssh-user>",
  "ssh": {
    "authorized-keys": [
      "<ssh-authorized-key>"
    ]
  }
}
```
+  `<base64-encoded-bootstrap-container-userdata>`：Bottlerocket 引导容器配置的 base64 编码内容。有关其配置的更多信息，请参阅 [Bottlerocket 引导容器文档](https://github.com/bottlerocket-os/bottlerocket-bootstrap-container)。引导容器负责在实例上创建 IAM Roles Anywhere 主机证书和证书私有密钥文件。然后，`aws_signing_helper` 将会使用这些证书和文件来获取临时证书，以用于 Amazon EKS 集群身份验证。传递到引导容器的用户数据采用命令调用的形式，这会将您之前创建的证书和私有密钥内容作为输入接受：

```
eks-hybrid-iam-ra-setup --certificate=<certificate> --key=<private-key>
```

## 第 2 步：预置 Bottlerocket vSphere 虚拟机及用户数据
<a name="_step_2_provision_the_bottlerocket_vsphere_vm_with_user_data"></a>

构造 TOML 文件后，在创建 vSphere 虚拟机期间将其传递为用户数据。请注意，在虚拟机首次开机之前，必须配置用户数据。因此，您需要在创建实例时提供用户数据；如果您希望先行创建虚拟机，则在您为其配置用户数据前，虚拟机必须处于关机状态。例如，假设使用 `govc` CLI：

### 首次创建虚拟机
<a name="_creating_vm_for_the_first_time"></a>

```
govc vm.create \
  -on=true \
  -c=2 \
  -m=4096 \
  -net.adapter=<network-adapter> \
  -net=<network-name> \
  -e guestinfo.userdata.encoding="base64" \
  -e guestinfo.userdata="$(base64 -w0 settings.toml)" \
  -template=<template-name> \
  <vm-name>
```

### 更新现有虚拟机的用户数据
<a name="_updating_user_data_for_an_existing_vm"></a>

```
govc vm.create \
    -on=false \
    -c=2 \
    -m=4096 \
    -net.adapter=<network-adapter> \
    -net=<network-name> \
    -template=<template-name> \
    <vm-name>

govc vm.change
    -vm <vm-name> \
    -e guestinfo.userdata="$(base64 -w0 settings.toml)" \
    -e guestinfo.userdata.encoding="base64"

govc vm.power -on <vm-name>
```

在以上章节中，`-e guestinfo.userdata.encoding="base64"` 选项用于指定用户数据采用 base64 编码。`-e guestinfo.userdata` 选项将 `settings.toml` 文件的 base64 编码内容作为用户数据传递给 Bottlerocket 实例。将占位符替换为您的具体值，例如 Bottlerocket OVA 模板和联网详细信息。

## 第 3 步：验证混合节点连接
<a name="_step_3_verify_the_hybrid_node_connection"></a>

Bottlerocket 实例启动后，将会尝试加入您的 Amazon EKS 集群。您可以在 Amazon EKS 控制台中导航到集群的“计算”选项卡或运行以下命令，从而验证连接：

```
kubectl get nodes
```

**重要**  
您的节点将处于 `Not Ready` 状态，此状态符合预期，是因混合节点上缺少正在运行的 CNI 所致。如果节点未加入集群，请参阅[混合节点故障排除](hybrid-nodes-troubleshooting.md)。

## 第 4 步：为混合节点配置 CNI
<a name="_step_4_configure_a_cni_for_hybrid_nodes"></a>

要使混合节点能够随时运行应用程序，请继续完成[为混合节点配置 CNI](hybrid-nodes-cni.md)中的步骤。

# 升级集群的混合节点
<a name="hybrid-nodes-upgrade"></a>

升级混合节点的指南与在 Amazon EC2 中运行的自主管理型 Amazon EKS 节点类似。我们建议您在目标 Kubernetes 版本上创建新的混合节点，从容地将现有应用程序迁移到新 Kubernetes 版本上的混合节点，然后再从集群中移除旧 Kubernetes 版本上的混合节点。在开始升级之前，请务必检查 [Amazon EKS 升级最佳实践](https://docs.aws.amazon.com/eks/latest/best-practices/cluster-upgrades.html)。Amazon EKS 混合节点功能[支持的 Kubernetes 版本](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)与具有云节点的 Amazon EKS 集群相同，包括标准和扩展支持。

Amazon EKS 混合节点功能使用的节点[版本偏斜策略](https://kubernetes.io/releases/version-skew-policy/#supported-version-skew)与上游 Kubernetes 相同。Amazon EKS 混合节点功能不能使用比 Amazon EKS 控制面板更高的版本，混合节点的 Kubernetes 次要版本最多可比 Amazon EKS 控制面板早三个次要版本。

如果您没有剩余容量可用来创建具有目标 Kubernetes 版本的新混合节点，以满足割接迁移升级策略的需要，则可以使用 Amazon EKS 混合节点 CLI (`nodeadm`) 就地升级混合节点的 Kubernetes 版本。

**重要**  
如果您使用 `nodeadm` 就地升级混合节点，则在关闭旧版本的 Kubernetes 组件以及安装和启动新的 Kubernetes 版本组件的过程中，节点会有停机时间。

## 先决条件
<a name="_prerequisites"></a>

在升级之前，请确保您已满足以下先决条件。
+ 升级混合节点的目标 Kubernetes 版本必须等于或早于 Amazon EKS 控制面板的版本。
+ 如果您遵循割接迁移升级策略，则在目标 Kubernetes 版本上安装的新混合节点必须满足[混合节点的先决条件设置](hybrid-nodes-prereqs.md)要求。这包括拥有在创建 Amazon EKS 集群期间传递的远程节点网络 CIDR 中的 IP 地址。
+ 无论是割接迁移升级还是就地升级，混合节点必须有权访问[所需的域](hybrid-nodes-networking.md#hybrid-nodes-networking-on-prem)才能拉取混合节点依赖项的新版本。
+ 您必须已在本地计算机或用于与 Amazon EKS Kubernetes API 端点进行交互的实例上安装 kubectl。
+ 您的 CNI 版本必须支持要升级到的 Kubernetes 版本。如果不支持，请在升级混合节点之前先升级 CNI 版本。请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md)了解更多信息。

## 割接迁移（蓝绿迁移）升级
<a name="hybrid-nodes-upgrade-cutover"></a>

 *割接迁移升级*是指首先在新主机上创建具有目标 Kubernetes 版本的新混合节点，从容地将现有应用程序迁移到目标 Kubernetes 版本的新混合节点，然后再从集群中移除旧 Kubernetes 版本的混合节点的过程。这种策略也称为蓝绿迁移。

1. 按照 [连接混合节点](hybrid-nodes-join.md) 步骤将新主机作为混合节点连接。运行 `nodeadm install` 命令时，请使用目标 Kubernetes 版本。

1. 启用目标 Kubernetes 版本的新混合节点与旧 Kubernetes 版本的混合节点之间的通信。此配置让容器组可在将工作负载迁移到目标 Kubernetes 版本的混合节点后进行相互通信。

1. 确认目标 Kubernetes 版本的混合节点已成功加入集群并处于“就绪”状态。

1. 使用以下命令，将要移除的每个节点标记为不可调度。这样可确保新容器组不会在要替换的节点上调度或重新调度。有关更多信息，请参阅 Kubernetes 文档中的 [kubectl cordon](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_cordon/)。请将 `NODE_NAME` 替换为旧 Kubernetes 版本混合节点的名称。

   ```
   kubectl cordon NODE_NAME
   ```

   您可以使用以下代码段标识并封锁使用特定 Kubernetes 版本（此示例中为版本 `1.28`）的所有节点。

   ```
   K8S_VERSION=1.28
   for node in $(kubectl get nodes -o json | jq --arg K8S_VERSION "$K8S_VERSION" -r '.items[] | select(.status.nodeInfo.kubeletVersion | match("\($K8S_VERSION)")).metadata.name')
   do
       echo "Cordoning $node"
       kubectl cordon $node
   done
   ```

1. 如果混合节点上当前部署运行的 CoreDNS 副本少于 2 个，请将部署横向扩展到至少 2 个副本。我们建议您在混合节点上运行至少两个 CoreDNS 副本，以确保正常运行期间的恢复能力。

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

1. 使用以下命令清空要从集群中删除的每个使用旧版本 Kubernetes 的混合节点。有关清空节点的更多信息，请参阅 Kubernetes 文档中的[安全地清空一个节点](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/)。请将 `NODE_NAME` 替换为旧 Kubernetes 版本混合节点的名称。

   ```
   kubectl drain NODE_NAME --ignore-daemonsets --delete-emptydir-data
   ```

   您可以使用以下代码段标识并清空特定 Kubernetes 版本（此示例中为版本 `1.28`）的所有节点。

   ```
   K8S_VERSION=1.28
   for node in $(kubectl get nodes -o json | jq --arg K8S_VERSION "$K8S_VERSION" -r '.items[] | select(.status.nodeInfo.kubeletVersion | match("\($K8S_VERSION)")).metadata.name')
   do
       echo "Draining $node"
       kubectl drain $node --ignore-daemonsets --delete-emptydir-data
   done
   ```

1. 您可以使用 `nodeadm` 停止混合节点构件并将其从主机中移除。您必须使用具有 root/sudo 权限的用户运行 `nodeadm`。默认情况下，如果节点上还有容器组，则 `nodeadm uninstall` 不会执行。有关更多信息，请参阅 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

   ```
   nodeadm uninstall
   ```

1. 停止并卸载混合节点构件后，从集群中移除节点资源。

   ```
   kubectl delete node node-name
   ```

   您可以使用以下代码段标识并删除特定 Kubernetes 版本（此示例中为版本 `1.28`）的所有节点。

   ```
   K8S_VERSION=1.28
   for node in $(kubectl get nodes -o json | jq --arg K8S_VERSION "$K8S_VERSION" -r '.items[] | select(.status.nodeInfo.kubeletVersion | match("\($K8S_VERSION)")).metadata.name')
   do
       echo "Deleting $node"
       kubectl delete node $node
   done
   ```

1. 运行上述步骤后，您的混合节点上可能会剩下一些构件，具体取决于您选择的 CNI。请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md)了解更多信息。

## 就地升级
<a name="hybrid-nodes-upgrade-inplace"></a>

就地升级过程是指使用 `nodeadm upgrade` 升级混合节点的 Kubernetes 版本，而不使用新的物理或虚拟主机和割接迁移策略。`nodeadm upgrade` 进程会关闭在混合节点上运行的现有较早版本的 Kubernetes 组件，卸载现有较早版本的 Kubernetes 组件，安装新的目标 Kubernetes 组件，然后启动新的目标 Kubernetes 组件。强烈建议一次升级一个节点，以尽可能减少对混合节点上运行的应用程序的影响。此过程的持续时间取决于网络带宽和延迟。

1. 使用以下命令将要升级的节点标记为不可调度。这样可确保新容器组不会在要升级的节点上调度或重新调度。有关更多信息，请参阅 Kubernetes 文档中的 [kubectl cordon](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_cordon/)。请将 `NODE_NAME` 替换为要升级的混合节点的名称

   ```
   kubectl cordon NODE_NAME
   ```

1. 使用以下命令清空您要升级的节点。有关清空节点的更多信息，请参阅 Kubernetes 文档中的[安全地清空一个节点](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/)。请将 `NODE_NAME` 替换为要升级的混合节点的名称。

   ```
   kubectl drain NODE_NAME --ignore-daemonsets --delete-emptydir-data
   ```

1. 在要升级的混合节点上运行 `nodeadm upgrade`。您必须使用具有 root/sudo 权限的用户运行 `nodeadm`。无论是使用 AWS SSM 还是 AWS IAM Roles Anywhere 凭证提供者，节点名称都会通过升级保留。在升级过程中，您无法更改凭证提供者。有关 `nodeConfig.yaml` 的配置值，请参阅 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。请将 `K8S_VERSION` 替换为要升级到的目标 Kubernetes 版本。

   ```
   nodeadm upgrade K8S_VERSION -c file://nodeConfig.yaml
   ```

1. 要允许在升级后在节点上调度容器组（pod），请键入以下内容。请将 `NODE_NAME` 替换为节点的名称。

   ```
   kubectl uncordon NODE_NAME
   ```

1. 观察混合节点的状态，等待节点关闭并在新的 Kubernetes 版本上重新启动并进入“就绪”状态。

   ```
   kubectl get nodes -o wide -w
   ```

# 混合节点的安全更新修补
<a name="hybrid-nodes-security"></a>

本主题介绍为在混合节点上运行的特定程序包和依赖项执行就地安全更新修补的过程。作为一项最佳实践，我们建议您定期更新混合节点以获取 CVE 和安全补丁。

有关升级 Kubernetes 版本的步骤，请参阅[升级集群的混合节点](hybrid-nodes-upgrade.md)。

可能需要安装安全补丁的软件的一个例子是 `containerd`。

## `Containerd`
<a name="_containerd"></a>

 `containerd` 是适用于 EKS 混合节点功能的标准 Kubernetes 容器运行时和核心依赖项，用于管理容器生命周期，包括提取映像和管理容器执行等。在混合节点上，您可以通过 [nodeadm CLI](https://docs.aws.amazon.com/eks/latest/userguide/hybrid-nodes-nodeadm.html) 来安装 `containerd`，也可以手动安装。`nodeadm` 将从操作系统分发的程序包或 Docker 程序包安装 `containerd`，具体取决于节点使用的操作系统。

`containerd` 中的 CVE 发布后，您可以使用以下方案，在混合节点上升级到 `containerd` 的修补版本。

## 第 1 步：检查补丁是否已发布
<a name="_step_1_check_if_the_patch_published_to_package_managers"></a>

您可以参考相应的安全公告，检查 `containerd` CVE 补丁是否已发布到相应的各个操作系统程序包管理器：
+  [Amazon Linux 2023](https://alas.aws.amazon.com/alas2023.html) 
+  [RHEL](https://access.redhat.com/security/security-updates/security-advisories) 
+  [Ubuntu 20.04](https://ubuntu.com/security/notices?order=newest&release=focal) 
+  [Ubuntu 22.04](https://ubuntu.com/security/notices?order=newest&release=jammy) 
+  [Ubuntu 24.04](https://ubuntu.com/security/notices?order=newest&release=noble) 

如果将该 Docker 存储库作为 `containerd` 的来源，您可以检查 [Docker 安全公告](https://docs.docker.com/security/security-announcements/)，来确定已修补版本是否在 Docker 存储库中可用。

## 第 2 步：选择安装补丁的方法
<a name="_step_2_choose_the_method_to_install_the_patch"></a>

在节点上就地修补和安装安全升级的方法有三种。具体可以使用的方法，取决于程序包管理器中的操作系统是否提供补丁：

1. 使用 `nodeadm upgrade` 发布到程序包管理器的安装补丁，详情请参阅[第 2 a 步](#hybrid-nodes-security-nodeadm)。

1. 直接使用程序包管理器安装补丁，详情请参见[第 2 b 步](#hybrid-nodes-security-package)。

1. 安装未在程序包管理器中发布的自定义补丁。对于[第 2 c 步](#hybrid-nodes-security-manual) 中 `containerd` 的自定义补丁，有一些特殊注意事项需要注意。

## 第 2 a 步：使用 `nodeadm upgrade` 修补
<a name="hybrid-nodes-security-nodeadm"></a>

确认 `containerd` CVE 补丁已发布到操作系统或 Docker 存储库（Apt 或 RPM）后，您可以使用 `nodeadm upgrade` 命令升级到最新版本的 `containerd`。由于这不属于 Kubernetes 版本升级，因此您必须将当前的 Kubernetes 版本传递给 `nodeadm` 升级命令。

```
nodeadm upgrade K8S_VERSION --config-source file:///root/nodeConfig.yaml
```

## 第 2 b 步：使用操作系统程序包管理器修补
<a name="hybrid-nodes-security-package"></a>

您也可以通过相应的程序包管理器来获取更新，并使用该更新来升级 `containerd` 程序包，如下所示。

 **Amazon Linux 2023** 

```
sudo yum update -y
sudo yum install -y containerd
```

 **RHEL** 

```
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo yum update -y
sudo yum install -y containerd
```

 **Ubuntu** 

```
sudo mkdir -p /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update -y
sudo apt install -y --only-upgrade containerd.io
```

## 第 2 c 步：`Containerd` CVE 补丁未在程序包管理器中发布
<a name="hybrid-nodes-security-manual"></a>

如果修补后的 `containerd` 版本只能通过其他方式获取，而未在程序包管理器中提供，例如对于 GitHub 发行版，可以从 GitHub 官方网站安装 `containerd`。

1. 如果计算机已作为混合节点加入集群，则需要运行 `nodeadm uninstall` 命令。

1. 安装官方 `containerd` 二进制文件。您可以使用 GitHub 上的[官方安装步骤](https://github.com/containerd/containerd/blob/main/docs/getting-started.md#option-1-from-the-official-binaries)。

1. 运行 `nodeadm install` 命令并将 `--containerd-source` 参数设置为 `none`，这将跳过通过 `nodeadm` 安装 `containerd` 的过程。对于节点运行的任何操作系统，您可以在 `containerd` 来源中使用 `none` 的值。

   ```
   nodeadm install K8S_VERSION --credential-provider CREDS_PROVIDER --containerd-source none
   ```

# 移除混合节点
<a name="hybrid-nodes-remove"></a>

本主题介绍如何删除 Amazon EKS 集群中的混合节点。必须使用您选择的兼容 Kubernetes 的工具（例如 [kubectl](https://kubernetes.io/docs/reference/kubectl/)）来删除混合节点。从 Amazon EKS 集群中移除节点对象后，将停止收取混合节点的费用。有关混合节点定价的更多信息，请参阅 [Amazon EKS 定价](https://aws.amazon.com/eks/pricing/)。

**重要**  
移除节点对于在节点上运行的工作负载而言是破坏性的。在删除混合节点之前，我们建议您首先清空节点以将容器组转移到其他活动节点。有关清空节点的更多信息，请参阅 Kubernetes 文档中的[安全地清空一个节点](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/)。

在用于与 Amazon EKS 集群的 Kubernetes API 端点进行交互的本地计算机或实例上运行以下 kubectl 步骤。如果您使用特定的 `kubeconfig` 文件，请使用 `--kubeconfig` 标志。

## 第 1 步：列出节点
<a name="_step_1_list_your_nodes"></a>

```
kubectl get nodes
```

## 第 2 步：清空节点
<a name="_step_2_drain_your_node"></a>

有关 `kubectl drain` 命令的更多信息，请参阅 Kubernetes 文档中的 [kubectl drain](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_drain/)。

```
kubectl drain --ignore-daemonsets <node-name>
```

## 第 3 步：停止并卸载混合节点构件
<a name="_step_3_stop_and_uninstall_hybrid_nodes_artifacts"></a>

您可以使用 Amazon EKS 混合节点功能 CLI (`nodeadm`) 来停止混合节点构件并将其从主机中移除。您必须使用具有 root/sudo 权限的用户运行 `nodeadm`。默认情况下，如果节点上还有容器组，则 `nodeadm uninstall` 不会执行。如果您将 AWS Systems Manager（SSM）作为凭证提供者，则 `nodeadm uninstall` 命令会将主机从 AWS SSM 托管式实例中注销。有关更多信息，请参阅 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

```
nodeadm uninstall
```

## 第 4 步：删除集群中的节点
<a name="_step_4_delete_your_node_from_the_cluster"></a>

停止并卸载混合节点构件后，从集群中移除节点资源。

```
kubectl delete node <node-name>
```

## 第 5 步：检查剩余的构件
<a name="_step_5_check_for_remaining_artifacts"></a>

运行上述步骤后，您的混合节点上可能会剩下一些构件，具体取决于您选择的 CNI。参阅 [为混合节点配置 CNI](hybrid-nodes-cni.md) 了解更多信息。

# 为混合节点配置应用程序联网、附加组件和 Webhook
<a name="hybrid-nodes-configure"></a>

为混合节点创建 EKS 集群后，请为应用程序联网（CNI、BGP、入口、负载均衡、网络策略）、附加组件、Webhook 和代理设置配置附加功能。有关兼容混合节点功能的 EKS 和社区附加组件的完整列表，请参阅[为混合节点配置附加组件](hybrid-nodes-add-ons.md)。

 **EKS 集群见解** EKS 包括见解检查，可检查混合节点设置中可能损害集群或工作负载功能的错误配置。有关集群见解的更多信息，请参阅[利用集群见解为 Kubernetes 版本升级做好准备并对错误配置进行问题排查](cluster-insights.md)。

以下列出了可用于混合节点的常用功能和附加组件：
+  **容器网络接口（CNI）**：AWS 支持 [Cilium](https://docs.cilium.io/en/stable/index.html) 作为混合节点的 CNI。有关更多信息，请参阅 [为混合节点配置 CNI](hybrid-nodes-cni.md)。注意：AWS VPC CNI 不能用于混合节点。
+  混合节点加入 EKS 集群时会自动安装 **CoreDNS 以及 `kube-proxy` **: CoreDNS 和 `kube-proxy`。这些附加组件可以在集群创建后作为 EKS 附加组件进行管理。
+  **入口和负载均衡**：您可以将 AWS 负载均衡器控制器和应用程序负载均衡器（ALB）或目标类型为 `ip` 的网络负载均衡器（NLB）用于在混合节点上运行的工作负载。对于在混合节点上运行的工作负载，AWS 支持 Cilium 的内置入口、网关和 Kubernetes 服务负载均衡功能。有关更多信息，请参阅[为混合节点配置 Kubernetes 入口](hybrid-nodes-ingress.md)和[为混合节点配置 LoadBalancer 类型服务](hybrid-nodes-load-balancing.md)。
+  **指标**：您可以将 Amazon Managed Service for Prometheus（AMP）无代理抓取程序、AWS Distro for Open Telemetry（ADOT）以及 Amazon CloudWatch 可观测性代理与混合节点结合使用。要将 AMP 无代理抓取程序用于混合节点的容器组（pod）指标，相关容器组必须可以从您用于 EKS 集群的 VPC 进行访问。
+  **日志**：您可以为启用混合节点功能的集群启用 EKS 控制面板日志记录。您可以将 ADOT EKS 附加组件和 Amazon CloudWatch 可观测性代理 EKS 附加组件用于混合节点和容器组（pod）日志记录。
+  **容器组身份和 IRSA**：您可以将 Amazon EKS 容器组身份和服务账户 IAM 角色（IRSA）与在混合节点上运行的应用程序配合使用，从而为使用其他 AWS 服务在混合节点上运行的容器组（pod）实现精细访问控制。
+  **Webhook**：如果运行 Webhook，请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)，以了解在无法将本地容器组网络设置为可路由时，选择在云节点上运行 Webhook 的注意事项和步骤。
+  **代理**：如果在本地环境中使用代理服务器来处理离开数据中心或边缘环境的流量，则需要将混合节点和集群配置为使用您的代理服务器。有关更多信息，请参阅 [为混合节点功能配置代理](hybrid-nodes-proxy.md)。

**Topics**
+ [为混合节点配置 CNI](hybrid-nodes-cni.md)
+ [为混合节点配置附加组件](hybrid-nodes-add-ons.md)
+ [为混合节点配置 Webhook](hybrid-nodes-webhooks.md)
+ [为混合节点功能配置代理](hybrid-nodes-proxy.md)
+ [为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md)
+ [为混合节点配置 Kubernetes 入口](hybrid-nodes-ingress.md)
+ [为混合节点配置 LoadBalancer 类型服务](hybrid-nodes-load-balancing.md)
+ [为混合节点配置 Kubernetes 网络策略](hybrid-nodes-network-policies.md)

# 为混合节点配置 CNI
<a name="hybrid-nodes-cni"></a>

Cilium 是 AWS 支持的 Amazon EKS 混合节点功能容器网络接口（CNI）。您必须为混合节点安装 CNI 才能使其做好服务工作负载的准备。在 CNI 开始运行之前，混合节点的状态会显示为 `Not Ready`。您可以使用自己选择的工具（例如 Helm）来管理该 CNI。本页上的说明涵盖了 Cilium 生命周期管理（安装、升级、删除）。有关如何配置 Cilium 的入口、负载均衡和网络策略的信息，请参阅[Cilium 入口和 Cilium 网关概述](hybrid-nodes-ingress.md#hybrid-nodes-ingress-cilium)、[服务类型 LoadBalancer](hybrid-nodes-ingress.md#hybrid-nodes-ingress-cilium-loadbalancer)和[为混合节点配置 Kubernetes 网络策略](hybrid-nodes-network-policies.md)。

在 AWS 云中的节点上运行时，AWS 不支持 Cilium。Amazon VPC CNI 与混合节点功能不兼容，并且 VPC CNI 使用 `eks.amazonaws.com/compute-type: hybrid` 标签配置了反亲和性。

本页之前的 Calico 文档已移至 [EKS Hybrid Examples Repository](https://github.com/aws-samples/eks-hybrid-examples)。

## 版本兼容性
<a name="hybrid-nodes-cilium-version-compatibility"></a>

对于 Amazon EKS 所支持的全部 Kubernetes 版本，其 EKS 混合节点均兼容 Cilium `v1.17.x` 与 `v1.18.x` 版本。

**注意**  
 **Cilium v1.18.3 内核版本要求**：由于该版本存在内核版本限制（要求 Linux 内核版本 ≥ 5.10），因此 Cilium v1.18.3 无法在以下节点上使用：
+ Ubuntu 20.04
+ Red Hat Enterprise Linux (RHEL) 8

有关系统要求，请参阅 [Cilium 系统要求](https://docs.cilium.io/en/stable/operations/system_requirements/)。

有关 Amazon EKS 支持的 Kubernetes 版本，请参阅 [Kubernetes 版本支持](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)。EKS 混合节点功能提供的 Kubernetes 版本支持与具有云端节点的 Amazon EKS 集群相同。

## 支持的功能
<a name="hybrid-nodes-cilium-support"></a>

 AWS 维护基于开源 [Cilium 项目](https://github.com/cilium/cilium)的适用于 EKS 混合节点的 Cilium 构建版本。要获得 AWS 对 Cilium 的支持，您必须使用由 AWS 维护的 Cilium 构建版本和支持的 Cilium 版本。

 AWS 为 Cilium 以下功能的默认配置提供技术支持，以用于 EKS 混合节点。如果您计划使用不属于 AWS 支持范围的功能，建议您获得 Cilium 的替代商业支持，或者利用内部专业知识对 Cilium 项目进行问题排查并提供修复。


| Cilium 功能 | 由 AWS 支持  | 
| --- | --- | 
|  Kubernetes 网络合规性  |  是  | 
|  核心集群连接性  |  是  | 
|  IP 系列  |  IPv4  | 
|  生命周期管理  |  Helm  | 
|  联网模式  |  VXLAN 封装  | 
|  IP 地址管理（IPAM）  |  Cilium IPAM 集群范围  | 
|  网络策略  |  Kubernetes 网络策略  | 
|  边界网关协议（BGP）  |  Cilium BGP 控制面板  | 
|  Kubernetes 入口  |  Cilium 入口、Cilium 网关  | 
|  服务 LoadBalancer IP 分配  |  Cilium 负载均衡器 IPAM  | 
|  服务 LoadBalancer IP 地址通告  |  Cilium BGP 控制面板  | 
|  kube-proxy 替换  |  是  | 

## Cilium 注意事项
<a name="hybrid-nodes-cilium-considerations"></a>
+  **Helm 存储库**：AWS 在 [Amazon EKS Cilium/Cilium](https://gallery.ecr.aws/eks/cilium/cilium) 的 Amazon Elastic Container Registry Public（Amazon ECR Public）中托管 Cilium Helm 图表。可用版本包括：
  + Cilium v1.17.9：`oci://public.ecr.aws/eks/cilium/cilium:1.17.9-0`
  + Cilium v1.18.3：`oci://public.ecr.aws/eks/cilium/cilium:1.18.3-0`

    本主题中的命令使用此存储库。请注意，某些 `helm repo` 命令对于 Amazon ECR Public 中的 Helm 存储库无效，因此您无法从本地 Helm 存储库名称中引用此存储库。因此请在大多数命令中使用完整的 URI。
+ [默认情况下，Cilium 配置为在覆盖/隧道模式下运行，并以 VXLAN 为封装方法](https://docs.cilium.io/en/stable/network/concepts/routing/#encapsulation)。此模式对底层物理网络的要求最低。
+ 默认情况下，对于离开集群的所有容器组流量，Cilium 会将其源 IP 地址[伪装](https://docs.cilium.io/en/stable/network/concepts/masquerading/)为该节点的 IP 地址。如果禁用伪装功能，则您的容器组（pod）CIDR 必须可在本地网络上路由。
+ 如果在混合节点上运行 Webhook，则您的容器组（pod）CIDR 必须可在本地网络上路由。如果容器组 CIDR 无法在本地网络上路由，则建议在同一集群中的云端节点上运行 Webhook。有关更多信息，请参阅 [为混合节点配置 Webhook](hybrid-nodes-webhooks.md) 和 [准备混合节点的联网](hybrid-nodes-networking.md)。
+  AWS 建议使用 Cilium 的内置 BGP 功能，使您的容器组（pod）CIDR 可在本地网络上路由。有关如何为 Cilium BGP 配置混合节点的更多信息，请参阅[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md)。
+ Cilium 中的默认 IP 地址管理（IPAM）称为[集群范围](https://docs.cilium.io/en/stable/network/concepts/ipam/cluster-pool/)，其中 Cilium 管理器根据用户配置的容器组（pod）CIDR 为每个节点分配 IP 地址。

## 在混合节点上安装 Cilium
<a name="hybrid-nodes-cilium-install"></a>

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

1. 创建一个名为 `cilium-values.yaml` 的 YAML 文件。以下示例通过设置 Cilium 代理和管理器的 `eks.amazonaws.com/compute-type: hybrid` 标签的亲和性，将 Cilium 配置为仅在混合节点上运行。
   + 使用为 EKS 集群的*远程容器组（pod）网络*配置的相同 容器组（pod）CIDR，对 `clusterPoolIpv4PodCIDRList` 进行配置。例如 `10.100.0.0/24`。Cilium 管理器从配置的 `clusterPoolIpv4PodCIDRList` IP 空间内分配 IP 地址切片。容器组（pod）CIDR 不得与本地节点 CIDR、VPC CIDR 或 Kubernetes 服务 CIDR 重叠。
   + 根据每个节点所需的容器组数量配置 `clusterPoolIpv4MaskSize`。例如，`25` 对应于分段大小 /25，每个节点 128 个容器组。
   + 在集群上部署 Cilium 之后，请勿更改 `clusterPoolIpv4PodCIDRList` 或 `clusterPoolIpv4MaskSize`，请参阅 [Expanding the cluster pool](https://docs.cilium.io/en/stable/network/concepts/ipam/cluster-pool/#expanding-the-cluster-pool) 了解更多信息。
   + 如果在 kube-proxy 替换模式下运行 Cilium，请在 Helm 值中设置 `kubeProxyReplacement: "true"`，并确保在与 Cilium 相同的节点上没有运行现有的 kube-proxy 部署。
   + 以下示例禁用了 Cilium 用于 L7 网络策略和入口的 Envoy 第 7 层（L7）代理。有关更多信息，请参阅[为混合节点配置 Kubernetes 网络策略](hybrid-nodes-network-policies.md)和[Cilium 入口和 Cilium 网关概述](hybrid-nodes-ingress.md#hybrid-nodes-ingress-cilium)。
   + 以下示例配置 `loadBalancer.serviceTopology`: `true`，以便在您为服务配置了服务流量分发功能的情况下，该功能可以正常运行。有关更多信息，请参阅 [配置服务流量分布](hybrid-nodes-webhooks.md#hybrid-nodes-mixed-service-traffic-distribution)。
   + 有关适用于 Cilium 的完整 Helm 值列表，请参阅 Cilium 文档中的 [Helm reference](https://docs.cilium.io/en/stable/helm-reference/)。

     ```
     affinity:
       nodeAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: eks.amazonaws.com/compute-type
               operator: In
               values:
               - hybrid
     ipam:
       mode: cluster-pool
       operator:
         clusterPoolIPv4MaskSize: 25
         clusterPoolIPv4PodCIDRList:
         - POD_CIDR
     loadBalancer:
       serviceTopology: true
     operator:
       affinity:
         nodeAffinity:
           requiredDuringSchedulingIgnoredDuringExecution:
             nodeSelectorTerms:
             - matchExpressions:
               - key: eks.amazonaws.com/compute-type
                 operator: In
                 values:
                   - hybrid
       unmanagedPodWatcher:
         restart: false
     loadBalancer:
       serviceTopology: true
     envoy:
       enabled: false
     kubeProxyReplacement: "false"
     ```

1. 在集群上安装 Cilium。
   + 将 `CILIUM_VERSION` 替换为某个 Cilium 版本（例如 `1.17.9-0` 或 `1.18.3-0`）。建议使用 Cilium 次要版本的最新补丁版本。
   + 确保节点符合所选版本的内核版本要求。Cilium v1.18.3 要求 Linux 内核版本 ≥ 5.10。
   + 如果使用特定的 kubeconfig 文件，请在 Helm install 命令中使用 `--kubeconfig` 标志。

     ```
     helm install cilium oci://public.ecr.aws/eks/cilium/cilium \
         --version CILIUM_VERSION \
         --namespace kube-system \
         --values cilium-values.yaml
     ```

1. 使用以下命令确认 Cilium 安装是否成功。您应会看到 `cilium-operator` 部署以及在每个混合节点上运行的 `cilium-agent`。此外，混合节点现在的状态应为 `Ready`。有关如何配置 Cilium BGP 以向本地网络通告您的容器组（pod）CIDR 的信息，请转到[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md)。

   ```
   kubectl get pods -n kube-system
   ```

   ```
   NAME                              READY   STATUS    RESTARTS   AGE
   cilium-jjjn8                      1/1     Running   0          11m
   cilium-operator-d4f4d7fcb-sc5xn   1/1     Running   0          11m
   ```

   ```
   kubectl get nodes
   ```

   ```
   NAME                   STATUS   ROLES    AGE   VERSION
   mi-04a2cf999b7112233   Ready    <none>   19m   v1.31.0-eks-a737599
   ```

## 在混合节点上升级 Cilium
<a name="hybrid-nodes-cilium-upgrade"></a>

在升级 Cilium 部署之前，请仔细查看 [Cilium 升级文档](https://docs.cilium.io/en/v1.17/operations/upgrade/)和升级说明，以了解目标 Cilium 版本中的更改。

1. 确保已在命令行环境中安装了 `helm` CLI。有关安装说明，请参阅 [Helm 文档](https://helm.sh/docs/intro/quickstart/)。

1. 运行 Cilium 升级预检。请将 `CILIUM_VERSION` 替换为您的目标 Cilium 版本。建议运行 Cilium 次要版本的最新补丁版本。您可以在 Cilium 文档的 [Stable Releases section](https://github.com/cilium/cilium#stable-releases) 部分找到给定次要 Cilium 版本的最新补丁版本。

   ```
   helm install cilium-preflight oci://public.ecr.aws/eks/cilium/cilium --version CILIUM_VERSION \
     --namespace=kube-system \
     --set preflight.enabled=true \
     --set agent=false \
     --set operator.enabled=false
   ```

1. 应用 `cilium-preflight.yaml` 后，请确保状态为 `READY` 的容器组（pod）数量与正在运行的 Cilium 容器组（pod）数量相同。

   ```
   kubectl get ds -n kube-system | sed -n '1p;/cilium/p'
   ```

   ```
   NAME                      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
   cilium                    2         2         2       2            2           <none>          1h20m
   cilium-pre-flight-check   2         2         2       2            2           <none>          7m15s
   ```

1. 一旦状态为 READY 的容器组数量相等，请确保 Cilium 执行前部署也标记为 READY 1/1。如果显示为 READY 0/1，请先查阅 [CNP Validation](https://docs.cilium.io/en/v1.17/operations/upgrade/#cnp-validation) 部分并解决部署问题，然后再继续升级。

   ```
   kubectl get deployment -n kube-system cilium-pre-flight-check -w
   ```

   ```
   NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
   cilium-pre-flight-check   1/1     1            0           12s
   ```

1. 删除预检

   ```
   helm uninstall cilium-preflight --namespace kube-system
   ```

1. 在运行 `helm upgrade` 命令之前，请将部署值保留在 `existing-cilium-values.yaml` 中，或在运行升级命令时为您的设置使用 `--set` 命令行选项。升级操作会覆盖 Cilium ConfigMap，因此在升级时传递配置值至关重要。

   ```
   helm get values cilium --namespace kube-system -o yaml > existing-cilium-values.yaml
   ```

1. 在正常的集群操作期间，所有 Cilium 组件都应运行相同的版本。以下步骤介绍了如何将所有组件从一个稳定版本升级到更高的稳定版本。从一个次要版本升级到另一个次要版本时，建议先升级到现有 Cilium 次要版本的最新补丁版本。为尽可能减少中断，请将 `upgradeCompatibility` 选项设置为此集群中安装的初始 Cilium 版本。

   ```
   helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium --version CILIUM_VERSION \
     --namespace kube-system \
     --set upgradeCompatibility=1.X \
     -f existing-cilium-values.yaml
   ```

1. （可选）如果由于问题出现需要回滚升级，请运行以下命令。

   ```
   helm history cilium --namespace kube-system
   helm rollback cilium [REVISION] --namespace kube-system
   ```

## 从混合节点中删除 Cilium
<a name="hybrid-nodes-cilium-delete"></a>

1. 运行以下命令从集群中卸载所有 Cilium 组件。请注意，卸载 CNI 可能会影响节点和容器组（pod）的运行状况，因此不应在生产集群上执行卸载。

   ```
   helm uninstall cilium --namespace kube-system
   ```

   从集群中移除 CNI 时，Cilium 配置的接口和路由默认不会移除，有关更多信息，请参阅 [GitHub issue](https://github.com/cilium/cilium/issues/34289)。

1. 要清理磁盘上的配置文件和资源，如果使用的是标准配置目录，则可以移除 GitHub Cilium 存储库中 [`cni-uninstall.sh` 脚本](https://github.com/cilium/cilium/blob/main/plugins/cilium-cni/cni-uninstall.sh)所显示的文件。

1. 要从集群中移除 Cilium 自定义资源定义（CRD），可以运行以下命令。

   ```
   kubectl get crds -oname | grep "cilium" | xargs kubectl delete
   ```

# 为混合节点配置附加组件
<a name="hybrid-nodes-add-ons"></a>

本页介绍通过 Amazon EKS 混合节点功能运行 AWS 附加组件和社区附加组件的注意事项。要详细了解 Amazon EKS 附加组件以及在集群中创建、升级和移除附加组件的过程，请参阅 [Amazon EKS 附加组件](eks-add-ons.md)。除本页中另有说明的外，对于具有混合节点的 Amazon EKS 集群，创建、升级和删除 Amazon EKS 附加组件的过程与使用在 AWS 云端运行的节点的 Amazon EKS 集群相同。仅本页包含的组件已通过 Amazon EKS 混合节点功能兼容性验证。

下列 AWS 附加组件与 Amazon EKS 混合节点功能兼容。


|  AWS 附加组件 | 兼容的附加组件版本 | 
| --- | --- | 
|  kube-proxy  |  v1.25.14-eksbuild.2 及更高版本  | 
|  CoreDNS  |  v1.9.3-eksbuild.7 及更高版本  | 
|   AWS Distro for OpenTelemetry (ADOT)  |  v0.102.1-eksbuild.2 及更高版本  | 
|  CloudWatch 可观测性代理  |  v2.2.1-eksbuild.1 及更高版本  | 
|  EKS 容器组身份代理  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/hybrid-nodes-add-ons.html)  | 
|  节点监控代理  |  v1.2.0-eksbuild.1 及更高版本  | 
|  CSI 快照控制器  |  v8.1.0-eksbuild.1 及更高版本  | 
|   适用于 Kubernetes 的 AWS Private CA Connector  |  v1.6.0-eksbuild.1 及更高版本  | 
|  Amazon FSx CSI 驱动程序  |  v1.7.0-eksbuild.1 及更高版本  | 
|   AWS Secrets Store CSI Driver 提供程序  |  v2.1.1-eksbuild.1 及更高版本  | 

下列社区附加组件与 Amazon EKS 混合节点功能兼容。要了解有关社区组件的更多信息，请参阅[社区附加组件](community-addons.md)。


| 社区附加组件 | 兼容的附加组件版本 | 
| --- | --- | 
|  Kubernetes Metrics Server  |  v0.7.2-eksbuild.1 及更高版本  | 
|  cert-manager  |  v1.17.2-eksbuild.1 及更高版本  | 
|  Prometheus Node Exporter  |  v1.9.1-eksbuild.2 及更高版本  | 
|  kube-state-metrics  |  v2.15.0-eksbuild.4 及更高版本  | 
|  External DNS  |  v0.19.0-eksbuild.1 及更高版本  | 

除以上表格所列的 Amazon EKS 附加组件外，[Amazon Managed Service for Prometheus Collector](prometheus.md)，以及用于[应用程序入口](alb-ingress.md)（HTTP）和[负载均衡](network-load-balancing.md)（TCP/UDP）的 [AWS 负载均衡器控制器](aws-load-balancer-controller.md)也与混合节点功能兼容。

有些 AWS 附加组件和社区附加组件与 Amazon EKS 混合节点功能不兼容。这些附加组件的最新版本存在针对混合节点所应用默认 `eks.amazonaws.com/compute-type: hybrid` 标签的反亲和性规则。这会在集群中部署有混合节点时阻止这些附加组件在混合节点上运行。如果集群既有混合节点又有在 AWS 云端运行的节点，则可以在集群中将这些附加组件部署到在 AWS 云端运行的节点。Amazon VPC CNI 与混合节点功能不兼容，Amazon EKS 混合节点功能支持将 Cilium 和 Calico 作为容器网络接口（CNI）。请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md)了解更多信息。

## AWS 附加组件
<a name="hybrid-nodes-add-ons-aws-add-ons"></a>

后续章节介绍了与其他 Amazon EKS 计算类型相比，在混合节点上运行兼容的 AWS 附加组件的区别。

## kube-proxy 和 CoreDNS
<a name="hybrid-nodes-add-ons-core"></a>

使用 AWS API 和 AWS SDK（包括通过 AWS CLI）创建 EKS 集群时，EKS 会默认将 kube-proxy 和 CoreDNS 安装为自主管理型附加组件。您可以在集群创建后使用 Amazon EKS 附加组件覆盖这些附加组件。有关[在 Amazon EKS 集群中管理 `kube-proxy`](managing-kube-proxy.md)和[在 Amazon EKS 集群中管理 DNS 的 CoreDNS](managing-coredns.md)的详细信息，请参阅 EKS 文档。如果您运行混合模式集群，既有混合节点，也有位于 AWS 云的节点，则 AWS 建议混合节点上至少有一个 CoreDNS 副本，在 AWS 云的节点上也至少有一个 CoreDNS 副本。有关配置步骤，请参阅[配置 CoreDNS 副本](hybrid-nodes-webhooks.md#hybrid-nodes-mixed-coredns)。

## CloudWatch 可观测性代理
<a name="hybrid-nodes-add-ons-cw"></a>

CloudWatch 可观测性代理操作符使用 [Webhook](https://kubernetes.io/docs/reference/access-authn-authz/webhook/)。如果在混合节点上运行此操作符，则本地容器组 CIDR 必须可在本地网络上路由，并且必须为您的 EKS 集群配置远程容器组网络。有关更多信息，请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

混合节点不提供节点级别指标，因为 [CloudWatch Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html) 仅在[实例元数据服务](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)（IMDS）可用的情况下才能提供节点级别指标。混合节点提供集群、工作负载、容器组和容器级别的指标。

按照[使用 Amazon CloudWatch Observability 安装 CloudWatch 代理](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Observability-EKS-addon.html)中描述的步骤安装附加组件后，必须先更新附加组件清单，然后才能在混合节点上成功运行代理。编辑集群上的 `amazoncloudwatchagents` 资源以添加 `RUN_WITH_IRSA` 环境变量，如下所示。

```
kubectl edit amazoncloudwatchagents -n amazon-cloudwatch cloudwatch-agent
```

```
apiVersion: v1
items:
- apiVersion: cloudwatch.aws.amazon.com/v1alpha1
  kind: AmazonCloudWatchAgent
  metadata:
    ...
    name: cloudwatch-agent
    namespace: amazon-cloudwatch
    ...
  spec:
    ...
    env:
    - name: RUN_WITH_IRSA # <-- Add this
      value: "True" # <-- Add this
    - name: K8S_NODE_NAME
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName
          ...
```

## 适用于混合节点的 Amazon Managed Prometheus 托管式收集器
<a name="hybrid-nodes-add-ons-amp"></a>

Amazon Managed Service for Prometheus（AMP）托管式收集器由一个抓取程序组成，用于发现和收集 Amazon EKS 集群中资源的指标。AMP 负责为您管理抓取程序，无需您自行管理任何实例、代理或抓取程序。

您可以在不提供任何混合节点特定附加配置的情况下使用 AMP 托管式收集器。不过对于混合节点上的应用程序，指标端点必须可以从 VPC 访问，包括从 VPC 到远程容器组网络 CIDR 的路由以及本地防火墙中打开的端口。此外，集群必须具有[私有集群端点访问权限](cluster-endpoint.md)。

按照《Amazon Managed Service for Prometheus 用户指南》中 [Using an AWS managed collector](https://docs.aws.amazon.com/prometheus/latest/userguide/AMP-collector-how-to.html) 部分说明的步骤进行操作。

## AWS Distro for OpenTelemetry (ADOT)
<a name="hybrid-nodes-add-ons-adot"></a>

您可以使用 AWS Distro for OpenTelemetry（ADOT）附加组件，来收集在混合节点上运行的应用程序的指标、日志和跟踪数据。ADOT 使用准入 [Webhook](https://kubernetes.io/docs/reference/access-authn-authz/webhook/) 更改和验证收集器自定义资源请求。如果在混合节点上运行 ADOT 操作符，则本地容器组 CIDR 必须可在本地网络上路由，并且必须为您的 EKS 集群配置远程容器组网络。有关更多信息，请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

按照《AWS Distro for OpenTelemetry》文档中 [Getting Started with AWS Distro for OpenTelemetry using EKS Add-Ons](https://aws-otel.github.io/docs/getting-started/adot-eks-add-on) **部分说明的步骤进行操作。

## AWS Load Balancer Controller
<a name="hybrid-nodes-add-ons-lbc"></a>

您可以将 [AWS 负载均衡器控制器](aws-load-balancer-controller.md)和应用程序负载均衡器（ALB）或目标类型为 `ip` 的网络负载均衡器（NLB）用于混合节点上的工作负载。与 ALB 或 NLB 一起使用的 IP 目标必须可从 AWS 路由。AWS 负载均衡器控制器也使用 [Webhook](https://kubernetes.io/docs/reference/access-authn-authz/webhook/)。如果在混合节点上运行 AWS 负载均衡器控制器操作符，则本地容器组 CIDR 必须可在本地网络上路由，并且必须为您的 EKS 集群配置远程容器组网络。有关更多信息，请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

要安装 AWS 负载均衡器控制器，请按照[AWS 应用程序负载均衡器](hybrid-nodes-ingress.md#hybrid-nodes-ingress-alb)或[AWS 网络负载均衡器](hybrid-nodes-load-balancing.md#hybrid-nodes-service-lb-nlb)部分说明的步骤操作。

对于使用 ALB 的 Ingress，您必须指定下面的注释。请参阅[使用应用程序负载均衡器路由应用程序和 HTTP 流量](alb-ingress.md)了解更多信息。

```
alb.ingress.kubernetes.io/target-type: ip
```

对于使用 NLB 的负载均衡，您必须指定下面的注释。请参阅[使用网络负载均衡器路由 TCP 和 UDP 流量](network-load-balancing.md)了解更多信息。

```
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
```

## EKS 容器组身份代理
<a name="hybrid-nodes-add-ons-pod-id"></a>

**注意**  
要在运行 Bottlerocket 的混合节点上成功部署 EKS 容器组身份代理附加组件，请确保您的 Bottlerocket 版本至少为 v1.39.0。混合节点环境中较早的 Bottlerocket 版本不支持容器组身份代理。

原始 Amazon EKS 容器组身份代理 DaemonSet 仅在节点上的 EC2 IMDS 可用时才能获取必需的 AWS 凭证。由于 IMDS 在混合节点上不可用，因此从版本 1.3.3-eksbuild.1 开始，容器组身份代理附加组件可以选择部署挂载所需凭证的 DaemonSet。运行 Bottlerocket 的混合节点需要不同的方法来挂载凭证，从 1.3.7-eksbuild.2 版本开始，容器组身份代理附加组件可以选择部署特别以 Bottlerocket 混合节点为目标的 DaemonSet。以下各节介绍启用可选 DaemonSet 的过程。

### Ubuntu/RHEL/AL2023
<a name="_ubunturhelal2023"></a>

1. 要在 Ubuntu/RHEL/Al2023 混合节点上使用容器组身份代理，请按如下所示，在 `nodeadm` 配置的混合部分设置 `enableCredentialsFile: true`：

   ```
   apiVersion: node.eks.aws/v1alpha1
   kind: NodeConfig
   spec:
       hybrid:
           enableCredentialsFile: true # <-- Add this
   ```

   这将配置 `nodeadm` 以创建一个将在 `/eks-hybrid/.aws/credentials` 下的节点上配置的凭证文件，以供 `eks-pod-identity-agent` 容器组使用。此凭证文件包含将会定期刷新的临时 AWS 凭证。

1. 在*每个*节点上更新 `nodeadm` 配置后，使用您的 `nodeConfig.yaml` 运行以下 `nodeadm init` 命令，从而将混合节点加入 Amazon EKS 集群。如果节点之前已经加入集群，仍可再次运行 `nodeadm init` 命令。

   ```
   nodeadm init -c file://nodeConfig.yaml
   ```

1. 使用 AWS CLI 或 AWS 管理控制台安装 `eks-pod-identity-agent`，并启用混合节点支持。

   1.  AWS CLI：在您用于管理集群的计算机上，运行以下命令安装 `eks-pod-identity-agent` 并启用混合节点支持。将 `my-cluster` 替换为您的集群名称。

      ```
      aws eks create-addon \
          --cluster-name my-cluster \
          --addon-name eks-pod-identity-agent \
          --configuration-values '{"daemonsets":{"hybrid":{"create": true}}}'
      ```

   1.  AWS 管理控制台：如果您要通过 AWS 控制台安装容器组身份代理附加组件，请在可选配置中添加以下内容，以部署将混合节点作为目标的 DaemonSet。

      ```
      {"daemonsets":{"hybrid":{"create": true}}}
      ```

### Bottlerocket
<a name="_bottlerocket"></a>

1. 要在 Bottlerocket 混合节点上使用容器组身份代理，请在用于 Bottlerocket 引导容器用户数据的命令中添加 `--enable-credentials-file=true` 标志，如 [连接使用 Bottlerocket 的混合节点](hybrid-nodes-bottlerocket.md) 中所述。

   1. 如果您使用的是 SSM 凭证提供程序，则命令应如下所示：

      ```
      eks-hybrid-ssm-setup --activation-id=<activation-id> --activation-code=<activation-code> --region=<region> --enable-credentials-file=true
      ```

   1. 如果您使用的是 IAM Roles Anywhere 凭证提供商，则命令应如下所示：

      ```
      eks-hybrid-iam-ra-setup --certificate=<certificate> --key=<private-key> --enable-credentials-file=true
      ```

      这将配置引导脚本，以便在 `/var/eks-hybrid/.aws/credentials` 下在节点上创建凭证文件，以供 `eks-pod-identity-agent` 容器组（pod）使用。此凭证文件包含将会定期刷新的临时 AWS 凭证。

1. 使用 AWS CLI 或 AWS 管理控制台安装 `eks-pod-identity-agent` 并启用 Bottlerocket 混合节点支持。

   1.  AWS CLI：在您用于管理集群的计算机上，运行以下命令安装 `eks-pod-identity-agent` 并启用 Bottlerocket 混合节点支持。将 `my-cluster` 替换为您的集群名称。

      ```
      aws eks create-addon \
          --cluster-name my-cluster \
          --addon-name eks-pod-identity-agent \
          --configuration-values '{"daemonsets":{"hybrid-bottlerocket":{"create": true}}}'
      ```

   1.  AWS 管理控制台：如果您要通过 AWS 控制台安装容器组身份代理附加组件，请在可选配置中添加以下内容，以部署将 Bottlerocket 混合节点作为目标的 DaemonSet。

      ```
      {"daemonsets":{"hybrid-bottlerocket":{"create": true}}}
      ```

## CSI 快照控制器
<a name="hybrid-nodes-add-ons-csi-snapshotter"></a>

从版本 `v8.1.0-eksbuild.2` 起，[CSI 快照控制器附加组件](csi-snapshot-controller.md)执行针对混合节点的软反亲和性规则，偏向让控制器 `deployment` 在与 Amazon EKS 控制面板相同的 AWS 区域中的 EC2 上运行。将 `deployment` 与 Amazon EKS 控制面板托管在同一 AWS 区域有助于减少延迟。

## 社区附加组件
<a name="hybrid-nodes-add-ons-community"></a>

后续章节介绍了与其他 Amazon EKS 计算类型相比，在混合节点上运行兼容的社区附加组件的区别。

## Kubernetes Metrics Server
<a name="hybrid-nodes-add-ons-metrics-server"></a>

控制面板需要能够连接到 Metrics Server 的容器组 IP（如果启用了 hostNetwork，则需要能够连接到节点 IP）。因此，除非在 hostNetwork 模式下运行 Metrics Server，否则在创建 Amazon EKS 集群时必须配置远程容器组网络，并且必须确保您的容器 IP 地址可路由。要使容器组 IP 地址可路由，一种常用的方法是使用 CNI 实现边界网关协议（BGP）。

## cert-manager
<a name="hybrid-nodes-add-ons-cert-manager"></a>

 `cert-manager` 可使用 [Webhook](https://kubernetes.io/docs/reference/access-authn-authz/webhook/)。如果在混合节点上运行 `cert-manager`，则本地容器组 CIDR 必须可在本地网络上路由，并且必须为您的 EKS 集群配置远程容器组网络。有关更多信息，请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

# 为混合节点配置 Webhook
<a name="hybrid-nodes-webhooks"></a>

本页详细介绍了使用混合节点运行 Webhook 的注意事项。在 Kubernetes 应用程序和开源项目（例如 AWS 负载均衡器控制器和 CloudWatch 可观测性代理）中，Webhook 用于执行运行时更改和验证功能。

 **可路由的容器组网络** 

如果您能够在本地网络上路由本地容器组 CIDR，则可以在混合节点上运行 Webhook。您可以通过多种方法来使本地容器组 CIDR 可在本地网络上路由，包括边界网关协议（BGP）、静态路由或其他自定义路由解决方案。我们推荐使用 BGP 解决方案，因为与需要自定义或手动路由配置的备选解决方案相比，此方案具有更好的可扩展性并且更易于管理。AWS 支持使用 Cilium 和 Calico 的 BGP 功能来公开容器组 CIDR，有关更多信息，请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md)和[可路由的远程容器组（pod）CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)。

 **不可路由的容器组网络** 

如果*无法*在本地网络上路由本地容器组 CIDR，但又需要运行 Webhook，我们建议您在与混合节点位于同一 EKS 集群中的云节点上运行所有 Webhook。

## 混合模式集群的注意事项
<a name="hybrid-nodes-considerations-mixed-mode"></a>

 *混合模式集群*是指为既有混合节点又有在 AWS 云端运行的节点的 EKS 集群。运行混合模式集群时应注意以下建议：
+ 在 AWS 云端节点上运行 VPC CNI，在混合节点上运行 Cilium 或 Calico。在 AWS 云端节点上运行时，AWS 不支持 Cilium 和 Calico。
+ 配置要在 AWS 云端节点上运行的 Webhook。请参阅[为附加组件配置 Webhook](#hybrid-nodes-webhooks-add-ons)，了解如何为 AWS 和社区附加组件配置 webhook。
+ 如果应用程序要求在 AWS Cloud 节点上运行的容器组直接与在混合节点上运行的容器组通信（“东西向通信”），并且您在 AWS Cloud 节点上使用 VPC CNI，在混合节点上使用 Cilium 或 Calico，则必须使本地容器组 CIDR 可在本地网络上路由。
+ 在 AWS Cloud 中的节点上运行至少一个 CoreDNS 副本，在混合节点上运行至少一个 CoreDNS 副本。
+ 配置服务流量分布，使服务流量保持在其源区域的本地。有关服务流量分布的更多信息，请参阅[配置服务流量分布](#hybrid-nodes-mixed-service-traffic-distribution)。
+ 如果使用 AWS 应用程序负载均衡器（ALB）或网络负载均衡器（NLB）来处理在混合节点上运行的工作负载流量，则用于 ALB 或 NLB 的 IP 目标必须可以从 AWS 路由。
+ Metrics Server 附加组件需要能够从 EKS 控制面板连接到 Metrics Server 容器组 IP 地址。如果在混合节点上运行 Metrics Server 附加组件，则本地容器组 CIDR 必须可在本地网络上路由。
+ 要使用 Amazon Managed Service for Prometheus（AMP）托管式收集器来收集混合节点的指标，本地容器组 CIDR 必须可在本地网络上路由。您也可以将 AMP 托管式收集器用于 EKS 控制面板指标和在 AWS Cloud 中运行的资源，以及使用 AWS Distro for OpenTelemetry（ADOT）附加组件来收集混合节点的指标。

## 配置混合模式集群
<a name="hybrid-nodes-mixed-mode"></a>

要查看集群上运行的更改和验证 Webhook，可以通过集群的 EKS 控制台的**资源**面板查看**扩展**资源类型，也可以使用以下命令。EKS 还会在集群可观测性控制面板中报告 Webhook 指标，有关更多信息，请参阅[使用可观测性仪表板监控您的集群](observability-dashboard.md)。

```
kubectl get mutatingwebhookconfigurations
```

```
kubectl get validatingwebhookconfigurations
```

### 配置服务流量分布
<a name="hybrid-nodes-mixed-service-traffic-distribution"></a>

运行混合模式集群时，我们建议您使用[https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution](https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution)将服务流量保持在其源区域的本地。推荐解决方案是服务流量分配功能（在 Kubernetes 1.31 及更高版本的 EKS 中提供此功能），而不建议使用[拓扑感知路由](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/)功能，因为前者的可预测性更好。使用服务流量分配功能时，分区中运行正常的端点将会接收指向该分区的所有流量。使用拓扑感知路由功能时，每项服务必须满足该分区中的多个条件才能应用自定义路由，否则会将流量平均路由到所有端点。

如果将 Cilium 作为 CNI，则必须在运行该 CNI 时将 `enable-service-topology` 设置为 `true`，才能启用服务流量分配功能。您可以使用 Helm 安装标志 `--set loadBalancer.serviceTopology=true` 传递此配置，也可以使用 Cilium CLI 命令 `cilium config set enable-service-topology true` 更新现有安装。更新现有安装的配置后，必须重新启动在每个节点上运行的 Cilium 代理。

以下部分显示如何为 CoreDNS 服务配置服务流量分布的示例，我们建议您为集群中的所有服务启用相同的配置，以避免意外的跨环境流量。

### 配置 CoreDNS 副本
<a name="hybrid-nodes-mixed-coredns"></a>

如果运行混合模式集群，既有混合节点，也有位于 AWS 云端的节点，则建议混合节点上至少有一个 CoreDNS 副本，在 AWS 云端的节点上也至少有一个 CoreDNS 副本。为防止混合模式集群设置中的延迟和网络问题，可以使用[服务流量分配](https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution)功能，将 CoreDNS 服务配置为首选距离最近的 CoreDNS 副本。

 推荐解决方案是*服务流量分配*功能（在 Kubernetes 1.31 及更高版本的 EKS 中提供此功能），而不建议使用[拓扑感知路由](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/)功能，因为前者的可预测性更好。使用服务流量分配功能时，分区中运行正常的端点将会接收指向该分区的所有流量。而使用拓扑感知路由功能时，每项服务必须满足该分区中的多个条件才能应用自定义路由，否则会将流量平均路由到所有端点。以下是配置服务流量分配功能的步骤。

如果将 Cilium 作为 CNI，则必须在运行该 CNI 时将 `enable-service-topology` 设置为 `true`，才能启用服务流量分配功能。您可以使用 Helm 安装标志 `--set loadBalancer.serviceTopology=true` 传递此配置，也可以使用 Cilium CLI 命令 `cilium config set enable-service-topology true` 更新现有安装。更新现有安装的配置后，必须重新启动在每个节点上运行的 Cilium 代理。

1. 为每个混合节点添加一个拓扑分区标签，例如 `topology.kubernetes.io/zone: onprem`。您也可以通过在 `nodeadm` 配置中指定标签，从而在 `nodeadm init` 阶段设置该标签，具体请参阅[自定义 kubelet 的节点配置（可选）](hybrid-nodes-nodeadm.md#hybrid-nodes-nodeadm-kubelet)。请注意，在 AWS 云端运行的节点会自动应用一个拓扑分区标签，与节点的可用区（AZ）相对应。

   ```
   kubectl label node hybrid-node-name topology.kubernetes.io/zone=zone
   ```

1. 使用拓扑分区键将 `podAntiAffinity` 添加到 CoreDNS 部署。您也可以在安装过程中使用 EKS 附加组件配置 CoreDNS 部署。

   ```
   kubectl edit deployment coredns -n kube-system
   ```

   ```
   spec:
     template:
       spec:
         affinity:
          ...
           podAntiAffinity:
             preferredDuringSchedulingIgnoredDuringExecution:
             - podAffinityTerm:
                 labelSelector:
                   matchExpressions:
                   - key: k8s-app
                     operator: In
                     values:
                     - kube-dns
                 topologyKey: kubernetes.io/hostname
               weight: 100
             - podAffinityTerm:
                 labelSelector:
                   matchExpressions:
                   - key: k8s-app
                     operator: In
                     values:
                     - kube-dns
                 topologyKey: topology.kubernetes.io/zone
               weight: 50
         ...
   ```

1. 将设置 `trafficDistribution: PreferClose` 添加到 `kube-dns` 服务配置以启用服务流量分布。

   ```
   kubectl patch svc kube-dns -n kube-system --type=merge -p '{
     "spec": {
       "trafficDistribution": "PreferClose"
     }
   }'
   ```

1. 您可以通过查看 `kube-dns` 服务的端点切片来确认已启用服务流量功能。端点切片必须显示拓扑分区标签为 `hints`，从而确认服务流量分配功能已启用。如果没有看到每个端点地址为 `hints`，则说明服务流量分配功能尚未启用。

   ```
   kubectl get endpointslice -A | grep "kube-dns"
   ```

   ```
   kubectl get endpointslice [.replaceable]`kube-dns-<id>`  -n kube-system -o yaml
   ```

   ```
   addressType: IPv4
   apiVersion: discovery.k8s.io/v1
   endpoints:
   - addresses:
     - <your-hybrid-node-pod-ip>
     hints:
       forZones:
       - name: onprem
     nodeName: <your-hybrid-node-name>
     zone: onprem
   - addresses:
     - <your-cloud-node-pod-ip>
     hints:
       forZones:
       - name: us-west-2a
     nodeName: <your-cloud-node-name>
     zone: us-west-2a
   ```

### 为附加组件配置 Webhook
<a name="hybrid-nodes-webhooks-add-ons"></a>

以下附加组件使用 Webhook，并支持将 Webhook 用于混合节点。
+  AWS Load Balancer Controller
+ CloudWatch 可观测性代理
+  AWS Distro for OpenTelemetry (ADOT)
+  `cert-manager` 

请参阅以下章节，了解如何配置这些附加组件使用的 Webhook，使其在 AWS 云端的节点上运行。

#### AWS Load Balancer Controller
<a name="hybrid-nodes-mixed-lbc"></a>

要在混合模式集群设置中使用 AWS 负载均衡器控制器，您必须在 AWS 云端的节点上运行控制器。为此，请将以下内容添加到 Helm 值配置中，或者使用 EKS 附加组件配置来指定值。

```
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: eks.amazonaws.com/compute-type
          operator: NotIn
          values:
          - hybrid
```

#### CloudWatch 可观测性代理
<a name="hybrid-nodes-mixed-cwagent"></a>

CloudWatch 可观测性代理附加组件有一个使用 Webhook 的 Kubernetes 操作符。要在混合模式集群设置下在 AWS 云端节点上运行此操作符，请编辑 CloudWatch 可观测性代理操作符配置。无法在安装过程中使用 Helm 和 EKS 附加组件配置操作符亲和性（请参阅 [containers-roadmap 问题 \$12431](https://github.com/aws/containers-roadmap/issues/2431)）。

```
kubectl edit -n amazon-cloudwatch deployment amazon-cloudwatch-observability-controller-manager
```

```
spec:
  ...
  template:
    ...
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: eks.amazonaws.com/compute-type
                operator: NotIn
                values:
                - hybrid
```

#### AWS Distro for OpenTelemetry (ADOT)
<a name="hybrid-nodes-mixed-adot"></a>

AWS Distro for OpenTelemetry（ADOT）附加组件有一个使用 Webhook 的 Kubernetes 操作符。要在混合模式集群设置中的 AWS 云端节点上运行此操作符，请将以下内容添加到 Helm 值配置中，或者使用 EKS 附加组件配置来指定值。

```
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: eks.amazonaws.com/compute-type
          operator: NotIn
          values:
          - hybrid
```

如果容器组 CIDR 无法在本地网络上路由，则 ADOT 收集器必须在混合节点上运行，以便可以从混合节点以及在其上运行的工作负载中抓取指标。为此，请编辑自定义资源定义（CRD）。

```
kubectl -n opentelemetry-operator-system edit opentelemetrycollectors.opentelemetry.io adot-col-prom-metrics
```

```
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: In
            values:
            - hybrid
```

您可以通过在 ADOT 收集器 CRD 配置中将以下 `relabel_configs` 添加到每个 `scrape_configs` 中，从而将 ADOT 收集器配置为仅从混合节点以及在混合节点上运行的资源中抓取指标。

```
relabel_configs:
  - action: keep
    regex: hybrid
    source_labels:
    - __meta_kubernetes_node_label_eks_amazonaws_com_compute_type
```

ADOT 附加组件的一个先决条件是为 ADOT 操作符使用的 TLS 证书安装 `cert-manager`。`cert-manager` 也会运行 Webhook，并且您可以使用以下 Helm 值配置将其配置为在 AWS 云端的节点上运行。

```
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: eks.amazonaws.com/compute-type
          operator: NotIn
          values:
          - hybrid
webhook:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: NotIn
            values:
            - hybrid
cainjector:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: NotIn
            values:
            - hybrid
startupapicheck:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: NotIn
            values:
            - hybrid
```

#### `cert-manager`
<a name="hybrid-nodes-mixed-cert-manager"></a>

`cert-manager` 附加组件会运行 Webhook，并且您可以使用以下 Helm 值配置将其配置为在 AWS 云端的节点上运行。

```
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: eks.amazonaws.com/compute-type
          operator: NotIn
          values:
          - hybrid
webhook:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: NotIn
            values:
            - hybrid
cainjector:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: NotIn
            values:
            - hybrid
startupapicheck:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/compute-type
            operator: NotIn
            values:
            - hybrid
```

# 为混合节点功能配置代理
<a name="hybrid-nodes-proxy"></a>

如果在本地环境中使用代理服务器来处理离开数据中心或边缘环境的流量，则需要单独将节点和集群配置为使用您的代理服务器。

集群  
在集群上，您需要将 `kube-proxy` 配置为使用您的代理服务器。创建 Amazon EKS 集群后，您必须配置 `kube-proxy`。

Nodes  
在节点上，您必须将操作系统、`containerd`、`kubelet` 和 Amazon SSM Agent 配置为使用您的代理服务器。您可以在操作系统映像构建过程中进行这些更改，也可在每个混合节点上运行 `nodeadm init` 之前进行这些更改。

## 节点级别配置
<a name="_node_level_configuration"></a>

您必须在操作系统映像中或在每个混合节点上运行 `nodeadm init` 之前应用以下配置。

### `containerd` 代理配置
<a name="_containerd_proxy_configuration"></a>

 `containerd` 是 Kubernetes 的默认容器管理运行时。如果使用代理来访问互联网，则必须配置 `containerd`，以确保其能够提取 Kubernetes 和 Amazon EKS 所需的容器镜像。

在每个混合节点的 `/etc/systemd/system/containerd.service.d` 目录中，创建一个名为 `http-proxy.conf` 的文件，其中应包含以下内容。请将 `proxy-domain` 和 `port` 替换为环境的相应值。

```
[Service]
Environment="HTTP_PROXY=http://proxy-domain:port"
Environment="HTTPS_PROXY=http://proxy-domain:port"
Environment="NO_PROXY=localhost"
```

#### 来自用户数据的 `containerd` 配置
<a name="_containerd_configuration_from_user_data"></a>

需要为此文件创建 `containerd.service.d` 目录。您要重新加载 systemd，才能在不重新启动的情况下获取配置文件。在 AL2023 中，该服务在脚本执行时可能已经在运行，因此还需要重新启动服务。

```
mkdir -p /etc/systemd/system/containerd.service.d
echo '[Service]' > /etc/systemd/system/containerd.service.d/http-proxy.conf
echo 'Environment="HTTP_PROXY=http://proxy-domain:port"' >> /etc/systemd/system/containerd.service.d/http-proxy.conf
echo 'Environment="HTTPS_PROXY=http://proxy-domain:port"' >> /etc/systemd/system/containerd.service.d/http-proxy.conf
echo 'Environment="NO_PROXY=localhost"' >> /etc/systemd/system/containerd.service.d/http-proxy.conf
systemctl daemon-reload
systemctl restart containerd
```

### `kubelet` 代理配置
<a name="_kubelet_proxy_configuration"></a>

 `kubelet` 是在每个 Kubernetes 节点上运行的 Kubernetes 节点代理，负责管理该节点以及在该节点上运行的容器组（pod）。如果在本地环境中使用代理，则必须配置 `kubelet`，以确保其能够与 Amazon EKS 集群的公共或私有端点通信。

在每个混合节点的 `/etc/systemd/system/kubelet.service.d/` 目录中，创建一个名为 `http-proxy.conf` 的文件，其中应包含以下内容。请将 `proxy-domain` 和 `port` 替换为环境的相应值。

```
[Service]
Environment="HTTP_PROXY=http://proxy-domain:port"
Environment="HTTPS_PROXY=http://proxy-domain:port"
Environment="NO_PROXY=localhost"
```

#### 来自用户数据的 `kubelet` 配置
<a name="_kubelet_configuration_from_user_data"></a>

必须为此文件创建 `kubelet.service.d` 目录。您要重新加载 systemd，才能在不重新启动的情况下获取配置文件。在 AL2023 中，该服务在脚本执行时可能已经在运行，因此还需要重新启动服务。

```
mkdir -p /etc/systemd/system/kubelet.service.d
echo '[Service]' > /etc/systemd/system/kubelet.service.d/http-proxy.conf
echo 'Environment="HTTP_PROXY=http://proxy-domain:port"' >> /etc/systemd/system/kubelet.service.d/http-proxy.conf
echo 'Environment="HTTPS_PROXY=http://proxy-domain:port"' >> /etc/systemd/system/kubelet.service.d/http-proxy.conf
echo 'Environment="NO_PROXY=localhost"' >> /etc/systemd/system/kubelet.service.d/http-proxy.conf
systemctl daemon-reload
systemctl restart kubelet
```

### `ssm` 代理配置
<a name="_ssm_proxy_configuration"></a>

 `ssm` 是可用于初始化混合节点的凭证提供程序之一。`ssm` 负责完成 AWS 身份验证并生成将由 `kubelet` 使用的临时凭证。如果在本地环境中使用代理，并在节点上将 `ssm` 作为凭证提供程序，则必须配置 `ssm`，以确保其能够与 Amazon SSM 服务端点通信。

在每个混合节点的以下路径中创建一个名为 `http-proxy.conf` 文件，具体取决于操作系统
+ Ubuntu - `/etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service.d/http-proxy.conf` 
+ Amazon Linux 2023 和 Red Hat Enterprise Linux – `/etc/systemd/system/amazon-ssm-agent.service.d/http-proxy.conf` 

使用以下内容填充该文件。请将 `proxy-domain` 和 `port` 替换为环境的相应值。

```
[Service]
Environment="HTTP_PROXY=http://proxy-domain:port"
Environment="HTTPS_PROXY=http://proxy-domain:port"
Environment="NO_PROXY=localhost"
```

#### 来自用户数据的 `ssm` 配置
<a name="_ssm_configuration_from_user_data"></a>

必须为该文件创建 `ssm` systemd 服务文件目录。目录路径取决于节点上使用的操作系统。
+ Ubuntu - `/etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service.d` 
+ Amazon Linux 2023 和 Red Hat Enterprise Linux – `/etc/systemd/system/amazon-ssm-agent.service.d` 

请替换以下重启命令中的 systemd 服务名称，具体取决于节点上使用的操作系统
+ Ubuntu - `snap.amazon-ssm-agent.amazon-ssm-agent` 
+ Amazon Linux 2023 和 Red Hat Enterprise Linux – `amazon-ssm-agent` 

```
mkdir -p systemd-service-file-directory
echo '[Service]' > [.replaceable]#systemd-service-file-directory/http-proxy.conf
echo 'Environment="HTTP_PROXY=http://[.replaceable]#proxy-domain:port"' >> systemd-service-file-directory/http-proxy.conf
echo 'Environment="HTTPS_PROXY=http://[.replaceable]#proxy-domain:port"' >> [.replaceable]#systemd-service-file-directory/http-proxy.conf
echo 'Environment="NO_PROXY=localhost"' >> [.replaceable]#systemd-service-file-directory/http-proxy.conf
systemctl daemon-reload
systemctl restart [.replaceable]#systemd-service-name
```

### 操作系统代理配置
<a name="_operating_system_proxy_configuration"></a>

如果使用代理来访问互联网，则必须对操作系统进行配置，以确保能够从操作系统的软件包管理器中提取混合节点依赖项。

 **Ubuntu** 

1. 通过以下命令配置 `snap` 以使用代理：

   ```
   sudo snap set system proxy.https=http://proxy-domain:port
   sudo snap set system proxy.http=http://proxy-domain:port
   ```

1. 要为 `apt` 启用代理，请在 `/etc/apt/` 目录中创建一个名为 `apt.conf` 的文件。请将代理域和端口替换为环境的相应值。

   ```
   Acquire::http::Proxy "http://proxy-domain:port";
   Acquire::https::Proxy "http://proxy-domain:port";
   ```

 **Amazon Linux 2023** 

1. 配置 `dnf` 以使用代理。创建一个具有环境的代理域和端口值的文件 `/etc/dnf/dnf.conf`。

   ```
   proxy=http://proxy-domain:port
   ```

 **Red Hat Enterprise Linux** 

1. 配置 `yum` 以使用代理。创建一个具有环境的代理域和端口值的文件 `/etc/yum.conf`。

   ```
   proxy=http://proxy-domain:port
   ```

### IAM Roles Anywhere 代理配置
<a name="_iam_roles_anywhere_proxy_configuration"></a>

在使用带有 `enableCredentialsFile` 标志的 IAM Roles Anywhere 时，IAM Roles Anywhere 凭证提供商服务负责刷新凭证（请参阅[EKS 容器组身份代理](hybrid-nodes-add-ons.md#hybrid-nodes-add-ons-pod-id)）。如果在本地环境中使用代理，则必须配置该服务，以确保其能够与 IAM Roles Anywhere 端点通信。

在 `/etc/systemd/system/aws_signing_helper_update.service.d/` 目录中，创建一个名为 `http-proxy.conf` 的包含以下内容的文件。请将 `proxy-domain` 和 `port` 替换为环境的相应值。

```
[Service]
Environment="HTTP_PROXY=http://proxy-domain:port"
Environment="HTTPS_PROXY=http://proxy-domain:port"
Environment="NO_PROXY=localhost"
```

## 集群范围配置
<a name="_cluster_wide_configuration"></a>

本节中的配置必须在创建 Amazon EKS 集群之后并且在每个混合节点上运行 `nodeadm init` 之前应用。

### kube-proxy 代理配置
<a name="_kube_proxy_proxy_configuration"></a>

当混合节点加入集群时，Amazon EKS 会自动在每个混合节点上将 `kube-proxy` 作为 DaemonSet 安装。`kube-proxy` 支持在 Amazon EKS 集群上跨容器组支持的服务进行路由。要配置每台主机，`kube-proxy` 需要对 Amazon EKS 集群端点进行 DNS 解析。

1. 使用以下命令编辑 `kube-proxy` DaemonSet

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

   这将在您配置的编辑器中打开 `kube-proxy` DaemonSet 定义。

1. 添加 `HTTP_PROXY` 和 `HTTPS_PROXY` 的环境变量。请注意，您的配置中应该已经存在 `NODE_NAME` 环境变量。请将 `proxy-domain` 和 `port` 替换为环境的相应值。

   ```
   containers:
     - command:
       - kube-proxy
       - --v=2
       - --config=/var/lib/kube-proxy-config/config - --hostname-override=$(NODE_NAME)
       env:
       - name: HTTP_PROXY
         value: http://proxy-domain:port
       - name: HTTPS_PROXY
         value: http://proxy-domain:port
       - name: NODE_NAME
         valueFrom:
           fieldRef:
             apiVersion: v1
             fieldPath: spec.nodeName
   ```

# 为混合节点配置 Cilium BGP
<a name="hybrid-nodes-cilium-bgp"></a>

本主题介绍如何为 Amazon EKS 混合节点功能配置 Cilium 边界网关协议（BGP）。Cilium 的 BGP 功能称为 [Cilium BGP 控制面板](https://docs.cilium.io/en/stable/network/bgp-control-plane/bgp-control-plane/)，可用于向本地网络通告容器组（pod）和服务地址。有关将容器组（pod）CIDR 设置为可在本地网络上路由的替代方法，请参阅[可路由的远程容器组（pod）CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)。

## 配置 Cilium BGP
<a name="hybrid-nodes-cilium-bgp-configure"></a>

### 先决条件
<a name="_prerequisites"></a>
+ 按照[为混合节点配置 CNI](hybrid-nodes-cni.md)中的说明安装 Cilium。

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

1. 要将 BGP 与 Cilium 结合使用，以向本地网络通告容器组（pod）或服务地址，必须已经安装了 Cilium 并配置了 `bgpControlPlane.enabled: true`。如果要为现有 Cilium 部署启用 BGP，则如果之前未启用 BGP，则必须重新启动 Cilium 管理器才能应用 BGP 配置。可以在 Helm 值中将 `operator.rollOutPods` 设置为 `true`，以便在 Helm 安装/升级过程中重新启动 Cilium 管理器。

   ```
   helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \
     --namespace kube-system \
     --reuse-values \
     --set operator.rollOutPods=true \
     --set bgpControlPlane.enabled=true
   ```

1. 确认 Cilium 管理器和代理已重启并正在运行。

   ```
   kubectl -n kube-system get pods --selector=app.kubernetes.io/part-of=cilium
   ```

   ```
   NAME                               READY   STATUS    RESTARTS   AGE
   cilium-grwlc                       1/1     Running   0          4m12s
   cilium-operator-68f7766967-5nnbl   1/1     Running   0          4m20s
   cilium-operator-68f7766967-7spfz   1/1     Running   0          4m20s
   cilium-pnxcv                       1/1     Running   0          6m29s
   cilium-r7qkj                       1/1     Running   0          4m12s
   cilium-wxhfn                       1/1     Running   0          4m1s
   cilium-z7hlb                       1/1     Running   0          6m30s
   ```

1. 创建带有 `CiliumBGPClusterConfig` 定义的名为 `cilium-bgp-cluster.yaml` 的文件。您可能需要从网络管理员获取以下信息：
   + 使用 ASN 为运行 Cilium 的节点配置 `localASN`。
   + 使用 ASN 为本地路由器配置 `peerASN`。
   + 使用运行 Cilium 的每个节点将与之对等的本地路由器 IP 对 `peerAddress` 进行配置。

     ```
     apiVersion: cilium.io/v2alpha1
     kind: CiliumBGPClusterConfig
     metadata:
       name: cilium-bgp
     spec:
       nodeSelector:
         matchExpressions:
         - key: eks.amazonaws.com/compute-type
           operator: In
           values:
           - hybrid
       bgpInstances:
       - name: "rack0"
         localASN: NODES_ASN
         peers:
         - name: "onprem-router"
           peerASN: ONPREM_ROUTER_ASN
           peerAddress: ONPREM_ROUTER_IP
           peerConfigRef:
             name: "cilium-peer"
     ```

1. 将 Cilium BGP 集群配置应用于集群。

   ```
   kubectl apply -f cilium-bgp-cluster.yaml
   ```

1. 使用定义 BGP 对等配置的 `CiliumBGPPeerConfig` 资源创建名为 `cilium-bgp-peer.yaml` 的文件。多个对等体可以共享相同的配置并引用共同的 `CiliumBGPPeerConfig` 资源。有关配置选项的完整列表，请参阅 Cilium 文档中的 [BGP Peer Configuration](https://docs.cilium.io/en/latest/network/bgp-control-plane/bgp-control-plane-v2/#bgp-peer-configuration)。

   以下 Cilium 对等设置的值必须与您正在与之对等的本地路由器的值相匹配。
   + 配置 `holdTimeSeconds`，其决定了 BGP 对等体在宣布会话关闭之前等待保持连接或更新消息的时间。默认值为 90 秒。
   + 配置 `keepAliveTimeSeconds`，其决定了 BGP 对等体是否仍可访问以及 BGP 会话是否处于活动状态。默认值为 30 秒。
   + 配置 `restartTimeSeconds`，其决定了 Cilium 的 BGP 控制面板在重启后预计重新建立 BGP 会话的时间。默认值为 120 秒。

     ```
     apiVersion: cilium.io/v2alpha1
     kind: CiliumBGPPeerConfig
     metadata:
       name: cilium-peer
     spec:
       timers:
         holdTimeSeconds: 90
         keepAliveTimeSeconds: 30
       gracefulRestart:
         enabled: true
         restartTimeSeconds: 120
       families:
         - afi: ipv4
           safi: unicast
           advertisements:
             matchLabels:
               advertise: "bgp"
     ```

1. 将 Cilium BGP 对等体配置应用于集群。

   ```
   kubectl apply -f cilium-bgp-peer.yaml
   ```

1. 使用 `CiliumBGPAdvertisement` 资源创建名为 `cilium-bgp-advertisement-pods.yaml` 的文件，用于向本地网络通告容器组（pod）CIDR。
   + `CiliumBGPAdvertisement` 资源用于定义各种通告类型以及与之相关的属性。以下示例将 Cilium 配置为仅通告容器组（pod）CIDR。有关配置 Cilium 以通告服务地址的更多信息，请参阅[服务类型 LoadBalancer](hybrid-nodes-ingress.md#hybrid-nodes-ingress-cilium-loadbalancer)和[Cilium 集群内负载均衡](hybrid-nodes-load-balancing.md#hybrid-nodes-service-lb-cilium)中的示例。
   + 每个运行 Cilium 代理的混合节点都与启用了 BGP 的上游路由器对等。如下方示例所示，当 Cilium 的 `advertisementType` 设置为 `PodCIDR` 时，每个节点都会通告其拥有的容器组（pod）CIDR 范围。有关更多信息，请参阅 Cilium 文档中的 [BGP Advertisements configuration](https://docs.cilium.io/en/stable/network/bgp-control-plane/bgp-control-plane-v2/#bgp-advertisements)。

     ```
     apiVersion: cilium.io/v2alpha1
     kind: CiliumBGPAdvertisement
     metadata:
       name: bgp-advertisement-pods
       labels:
         advertise: bgp
     spec:
       advertisements:
         - advertisementType: "PodCIDR"
     ```

1. 将 Cilium BGP 广播配置应用到集群。

   ```
   kubectl apply -f cilium-bgp-advertisement-pods.yaml
   ```

1. 您可以通过 [Cilium CLI](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/#install-the-cilium-cli)，使用 `cilium bgp peers` 命令来确认 BGP 对等连接是否有效。您应会在输出中看到您环境的正确值，会话状态为 `established`。有关故障排除的更多信息，请参阅 Cilium 文档中的 [Troubleshooting and Operations Guide](https://docs.cilium.io/en/latest/network/bgp-control-plane/bgp-control-plane/#troubleshooting-and-operation-guide)。

   在下面的示例中，有五个混合节点在运行 Cilium 代理，每个节点都会通告其拥有的容器组（pod）CIDR 范围。

   ```
   cilium bgp peers
   ```

   ```
   Node                   Local AS    Peer AS               Peer Address        Session State   Uptime     Family         Received   Advertised
   mi-026d6a261e355fba7   NODES_ASN
                     ONPREM_ROUTER_ASN
                     ONPREM_ROUTER_IP    established     1h18m58s   ipv4/unicast   1          2
   mi-082f73826a163626e   NODES_ASN
                     ONPREM_ROUTER_ASN
                     ONPREM_ROUTER_IP    established     1h19m12s   ipv4/unicast   1          2
   mi-09183e8a3d755abf6   NODES_ASN
                     ONPREM_ROUTER_ASN
                     ONPREM_ROUTER_IP    established     1h18m47s   ipv4/unicast   1          2
   mi-0d78d815980ed202d   NODES_ASN
                     ONPREM_ROUTER_ASN
                     ONPREM_ROUTER_IP    established     1h19m12s   ipv4/unicast   1          2
   mi-0daa253999fe92daa   NODES_ASN
                     ONPREM_ROUTER_ASN
                     ONPREM_ROUTER_IP    established     1h18m58s   ipv4/unicast   1          2
   ```

   ```
   cilium bgp routes
   ```

   ```
   Node                   VRouter       Prefix           NextHop   Age         Attrs
   mi-026d6a261e355fba7   NODES_ASN     10.86.2.0/26     0.0.0.0   1h16m46s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-082f73826a163626e   NODES_ASN     10.86.2.192/26   0.0.0.0   1h16m46s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-09183e8a3d755abf6   NODES_ASN     10.86.2.64/26    0.0.0.0   1h16m46s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-0d78d815980ed202d   NODES_ASN     10.86.2.128/26   0.0.0.0   1h16m46s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-0daa253999fe92daa   NODES_ASN     10.86.3.0/26     0.0.0.0   1h16m46s   [{Origin: i} {Nexthop: 0.0.0.0}]
   ```

# 为混合节点配置 Kubernetes 入口
<a name="hybrid-nodes-ingress"></a>

本主题介绍如何为在 Amazon EKS 混合节点上运行的工作负载配置 Kubernetes 入口。[Kubernetes 入口](https://kubernetes.io/docs/concepts/services-networking/ingress/)向集群内的服务公开来自集群外部的 HTTP 和 HTTPS 路由。要使用入口资源，需要使用 Kubernetes 入口控制器来设置联网基础设施以及为网络流量提供服务的组件。

 AWS 支持 AWS 应用程序负载均衡器（ALB）和适用于 Kubernetes 入口的 Cilium，可用于在 EKS 混合节点上运行的工作负载。使用 ALB 还是适用于入口的 Cilium，取决于应用程序流量的来源。如果应用程序流量来自某个 AWS 区域，AWS 建议使用 AWS ALB 和 AWS 负载均衡器控制器。如果应用程序流量来自本地或边缘环境，AWS 建议使用 Cilium 的内置入口功能，无论是否在环境中使用负载均衡器基础设施，均可使用该功能。

![\[EKS 混合节点入口\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-ingress.png)


## AWS 应用程序负载均衡器
<a name="hybrid-nodes-ingress-alb"></a>

您可以将 [AWS 负载均衡器控制器](aws-load-balancer-controller.md)和目标类型为 `ip` 的应用程序负载均衡器（ALB）用于在混合节点上运行的工作负载。使用目标类型 `ip` 时，ALB 会绕过服务层网络路径，直接将流量转发到容器组（pod）。为了让 ALB 到达混合节点上的容器组（pod）IP 目标，本地容器组（pod）CIDR 必须可在本地网络中路由。此外，AWS 负载均衡器控制器使用 Webhook，需要来自 EKS 控制面板的直接通信。有关更多信息，请参阅 [为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

### 注意事项
<a name="_considerations"></a>
+ 有关 AWS 应用程序负载均衡器和 AWS 负载均衡器控制器的更多信息，请参阅[使用应用程序负载均衡器路由应用程序和 HTTP 流量](alb-ingress.md)和[使用 Helm 安装 AWS 负载均衡器控制器](lbc-helm.md)。
+ 有关如何在 AWS 应用程序负载均衡器和 AWS 网络负载均衡器之间做出选择的信息，请参阅 [Best Practices for Load Balancing](https://docs.aws.amazon.com/eks/latest/best-practices/load-balacing.html)。
+ 有关可以使用 AWS 应用程序负载均衡器为入口资源配置的注释列表，请参阅 [AWS Load Balancer Controller Ingress annotations](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/ingress/annotations/)。

### 先决条件
<a name="_prerequisites"></a>
+ 按照[为混合节点配置 CNI](hybrid-nodes-cni.md)中的说明安装 Cilium。
+ 按照[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md) 中的说明启用 Cilium BGP 控制面板。如果您不想使用 BGP，则必须使用其他方法，使本地容器组（pod）CIDR 可在本地网络中路由。如果您不将本地容器组（pod）CIDR 设置为可路由，ALB 将无法注册或联系您的容器组（pod）IP 目标。
+ 在命令行环境中安装 Helm，有关更多信息，请参阅[安装 Helm 说明](helm.md)。
+ 在命令行环境中安装 eksctl，有关更多信息，请参阅 [eksctl 安装说明](install-kubectl.md#eksctl-install-update)。

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

1. 下载AWS负载均衡器控制器的 IAM 策略，该策略允许负载均衡器代表您调用 AWS API。

   ```
   curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json
   ```

1. 使用上一步中下载的策略创建一个 IAM 策略。

   ```
   aws iam create-policy \
       --policy-name AWSLoadBalancerControllerIAMPolicy \
       --policy-document file://iam_policy.json
   ```

1. 将集群名称 (`CLUSTER_NAME`)、AWS 区域 (`AWS_REGION`) 和 AWS 账户 ID (`AWS_ACCOUNT_ID`) 的值替换为您的设置，然后运行以下命令。

   ```
   eksctl create iamserviceaccount \
       --cluster=CLUSTER_NAME \
       --namespace=kube-system \
       --name=aws-load-balancer-controller \
       --attach-policy-arn=arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
       --override-existing-serviceaccounts \
       --region AWS_REGION \
       --approve
   ```

1. 添加 eks-charts Helm 图表存储库并更新您的本地 Helm 存储库，确保您拥有最新的图表。

   ```
   helm repo add eks https://aws.github.io/eks-charts
   ```

   ```
   helm repo update eks
   ```

1. 安装AWS负载均衡器控制器。将集群名称 (`CLUSTER_NAME`)、AWS 区域 (`AWS_REGION`)、VPC ID (`VPC_ID`) 和 AWS 负载均衡器控制器 Helm 图表版本 (`AWS_LBC_HELM_VERSION`) 的值替换为您的设置，并运行下列命令。如果您运行的混合模式集群同时包含混合节点和 AWS 云中的节点，则可以按照[AWS Load Balancer Controller](hybrid-nodes-webhooks.md#hybrid-nodes-mixed-lbc) 中的说明，在云端节点上运行 AWS 负载均衡器控制器。
   + 您可以通过运行 `helm search repo eks/aws-load-balancer-controller --versions` 找到最新版本的 Helm 图表。

     ```
     helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
       -n kube-system \
       --version AWS_LBC_HELM_VERSION \
       --set clusterName=CLUSTER_NAME \
       --set region=AWS_REGION \
       --set vpcId=VPC_ID \
       --set serviceAccount.create=false \
       --set serviceAccount.name=aws-load-balancer-controller
     ```

1. 验证 AWS 负载均衡器控制器是否成功安装。

   ```
   kubectl get -n kube-system deployment aws-load-balancer-controller
   ```

   ```
   NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
   aws-load-balancer-controller   2/2     2            2           84s
   ```

1. 创建示例应用程序。以下示例使用 [Istio Bookinfo](https://istio.io/latest/docs/examples/bookinfo/) 示例微服务应用程序。

   ```
   kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml
   ```

1. 使用以下内容创建名为 `my-ingress-alb.yaml` 的文件。

   ```
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: my-ingress
     namespace: default
     annotations:
       alb.ingress.kubernetes.io/load-balancer-name: "my-ingress-alb"
       alb.ingress.kubernetes.io/target-type: "ip"
       alb.ingress.kubernetes.io/scheme: "internet-facing"
       alb.ingress.kubernetes.io/healthcheck-path: "/details/1"
   spec:
     ingressClassName: alb
     rules:
     - http:
         paths:
         - backend:
             service:
               name: details
               port:
                 number: 9080
           path: /details
           pathType: Prefix
   ```

1. 将入口配置应用于集群。

   ```
   kubectl apply -f my-ingress-alb.yaml
   ```

1. 为您的入口资源预置 ALB 可能需要几分钟时间。预置 NLB 后，将为您的入口资源分配一个与 ALB 部署的 DNS 名称相对应的地址。该地址将采用以下格式：`<alb-name>-<random-string>.<region>.elb.amazonaws.com`。

   ```
   kubectl get ingress my-ingress
   ```

   ```
   NAME         CLASS   HOSTS   ADDRESS                                                     PORTS   AGE
   my-ingress   alb     *       my-ingress-alb-<random-string>.<region>.elb.amazonaws.com   80      23m
   ```

1. 使用 ALB 的地址访问服务。

   ```
   curl -s http//my-ingress-alb-<random-string>.<region>.elb.amazonaws.com:80/details/1 | jq
   ```

   ```
   {
     "id": 1,
     "author": "William Shakespeare",
     "year": 1595,
     "type": "paperback",
     "pages": 200,
     "publisher": "PublisherA",
     "language": "English",
     "ISBN-10": "1234567890",
     "ISBN-13": "123-1234567890"
     "details": "This is the details page"
   }
   ```

## Cilium 入口和 Cilium 网关概述
<a name="hybrid-nodes-ingress-cilium"></a>

Cilium 的入口功能内置在 Cilium 的架构中，可以使用 Kubernetes 入口 API 或网关 API 进行管理。如果您没有现有的入口资源，AWS 建议您从网关 API 开始，因为它是定义和管理 Kubernetes 联网资源的一种更具表现力和灵活性的方式。[Kubernetes 网关 API](https://gateway-api.sigs.k8s.io/) 旨在标准化在 Kubernetes 集群中定义和管理入口、负载均衡和服务网格的联网资源的方式。

启用 Cilium 的入口或网关功能时，Cilium 管理器会协调集群中的入口/网关对象，每个节点上的 Envoy 代理负责处理第 7 层（L7）网络流量。Cilium 不直接预置入口/网关基础设施，例如负载均衡器。如果您计划将 Cilium 入口/网关与负载均衡器一起使用，则必须使用负载均衡器的工具（通常是入口或网关控制器）来部署和管理负载均衡器的基础设施。

对于入口/网关流量，Cilium 会处理核心网络流量和 L3/L4 策略执行，集成的 Envoy 代理负责处理第 7 层网络流量。借助 Cilium 入口/网关，Envoy 负责应用 L7 路由规则、策略和请求操作、高级流量管理（例如流量拆分和镜像）以及 TLS 终止和发起。默认情况下，Cilium 的 Envoy 代理作为单独的 DaemonSet (`cilium-envoy`) 部署，这使得可以单独对 Envoy 和 Cilium 代理进行更新、扩展和管理。

有关 Cilium 入口和 Cilium 网关如何工作的更多信息，请参阅 Cilium 文档中的 [Cilium Ingress](https://docs.cilium.io/en/stable/network/servicemesh/ingress/) 和 [Cilium Gateway](https://docs.cilium.io/en/stable/network/servicemesh/gateway-api/gateway-api/) 页面。

## Cilium 入口和网关比较
<a name="hybrid-nodes-ingress-cilium-comparison"></a>

下表汇总了截至 **Cilium 1.17.x 版本**的 Cilium 入口和 Cilium 网关功能。


| 功能 | 入口 | Gateway | 
| --- | --- | --- | 
|  服务类型 LoadBalancer  |  支持  |  是  | 
|  服务类型 NodePort  |  是  |  否1   | 
|  主机网络  |  支持  |  是  | 
|  共享负载均衡器  |  支持  |  是  | 
|  专用负载均衡器  |  是  |  否2   | 
|  网络策略  |  支持  |  是  | 
|  协议  |  第 7 层 [HTTP（S）、gRPC]  |  第 7 层 [HTTP（S）、gRPC]3   | 
|  TLS 传递  |  支持  |  是  | 
|  流量管理  |  路径和主机路由  |  路径和主机路由、URL 重定向和重写、流量拆分、标头修改  | 

 1 Cilium 1.18.x 版本计划提供 NodePort 服务的 Cilium 网关支持（[\$127273](https://github.com/cilium/cilium/pull/27273)）

 2 针对专用负载均衡器的 Cilium 网关支持（[\$125567](https://github.com/cilium/cilium/issues/25567)）

 3 针对 TCP/UDP 的 Cilium 网关支持（[\$121929](https://github.com/cilium/cilium/issues/21929)）

## 安装 Cilim 网关
<a name="hybrid-nodes-ingress-cilium-gateway-install"></a>

### 注意事项
<a name="_considerations_2"></a>
+ 配置 Cilium 时，必须将 `nodePort.enabled` 设置为 `true`，如下列示例所示。如果您使用的是 Cilium 的 kube-proxy 替换功能，则无需将 `nodePort.enabled` 设置为 `true`。
+ 配置 Cilium 时，必须将 `envoy.enabled` 设置为 `true`，如下列示例所示。
+ Cilium 网关可以在负载均衡器（默认）或主机网络模式下部署。
+ 在负载均衡器模式下使用 Cilium 网关时，必须在网关资源上设置 `service.beta.kubernetes.io/aws-load-balancer-type: "external"` 注释，以防止传统 AWS 云提供商为 Cilium 为网关资源创建的 LoadBalancer 类型服务创建经典负载均衡器。
+ 在主机网络模式下使用 Cilium 网关时，将禁用 LoadBalancer 模式类型的服务。主机网络模式对于没有负载均衡器基础设施的环境非常有用，有关更多信息，请参阅[主机网络](#hybrid-nodes-ingress-cilium-host-network)。

### 先决条件
<a name="_prerequisites_2"></a>

1. 在命令行环境中安装 Helm，请参阅[安装 Helm 说明](helm.md)。

1. 按照[为混合节点配置 CNI](hybrid-nodes-cni.md)中的说明安装 Cilium。

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

1. 安装 Kubernetes 网关 API 自定义资源定义（CRD）。

   ```
   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml
   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_gateways.yaml
   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml
   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml
   kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml
   ```

1. 创建以下内容的名为 `cilium-gateway-values.yaml` 的文件。以下示例将 Cilium 网关配置为使用默认负载均衡器模式，并为配置为仅在混合节点上运行的 Envoy 代理使用单独的 `cilium-envoy` DaemonSet。

   ```
   gatewayAPI:
     enabled: true
     # uncomment to use host network mode
     # hostNetwork:
     #   enabled: true
   nodePort:
     enabled: true
   envoy:
     enabled: true
     affinity:
       nodeAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: eks.amazonaws.com/compute-type
               operator: In
               values:
               - hybrid
   ```

1. 将 Helm 值文件应用于集群。

   ```
   helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \
     --namespace kube-system \
     --reuse-values \
     --set operator.rollOutPods=true \
     --values cilium-gateway-values.yaml
   ```

1. 确认 Cilium 管理器、代理和 Envoy 容器组（pod）正在运行。

   ```
   kubectl -n kube-system get pods --selector=app.kubernetes.io/part-of=cilium
   ```

   ```
   NAME                               READY   STATUS    RESTARTS   AGE
   cilium-envoy-5pgnd                 1/1     Running   0          6m31s
   cilium-envoy-6fhg4                 1/1     Running   0          6m30s
   cilium-envoy-jskrk                 1/1     Running   0          6m30s
   cilium-envoy-k2xtb                 1/1     Running   0          6m31s
   cilium-envoy-w5s9j                 1/1     Running   0          6m31s
   cilium-grwlc                       1/1     Running   0          4m12s
   cilium-operator-68f7766967-5nnbl   1/1     Running   0          4m20s
   cilium-operator-68f7766967-7spfz   1/1     Running   0          4m20s
   cilium-pnxcv                       1/1     Running   0          6m29s
   cilium-r7qkj                       1/1     Running   0          4m12s
   cilium-wxhfn                       1/1     Running   0          4m1s
   cilium-z7hlb                       1/1     Running   0          6m30s
   ```

## 配置 Cilim 网关
<a name="hybrid-nodes-ingress-cilium-gateway-configure"></a>

通过将 `gatewayClassName` 设置为 `cilium`，可以在网关对象上启用 Cilium 网关。Cilium 为网关资源创建的服务可以使用网关对象上的字段进行配置。可以使用网关对象的 `infrastructure` 字段，配置网关控制器用于配置负载均衡器基础设施的常用注释。使用 Cilium 的 LoadBalancer IPAM（请参阅[服务类型 LoadBalancer](#hybrid-nodes-ingress-cilium-loadbalancer)中的示例）时，可以在网关对象的 `addresses` 字段上配置用于 LoadBalancer 类型服务的 IP 地址。有关网关配置的更多信息，请参阅 [Kubernetes Gateway API specification](https://gateway-api.sigs.k8s.io/reference/spec/#gateway)。

```
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
spec:
  gatewayClassName: cilium
  infrastructure:
    annotations:
      service.beta.kubernetes.io/...
      service.kuberentes.io/...
  addresses:
  - type: IPAddress
    value: <LoadBalancer IP address>
  listeners:
  ...
```

Cilium 和 Kubernetes 网关规范支持 GatewayClass、网关、httpRoute、grpcRoute 和 ReferenceGrant 资源。
+ 有关可用字段的列表，请参阅 [HTTPRoute](https://gateway-api.sigs.k8s.io/api-types/httproute/HTTPRoute) 和 [GRPCRoute](https://gateway-api.sigs.k8s.io/api-types/grpcroute/GRPCRoute) 规范。
+ 有关如何使用和配置这些资源，请参阅以下[部署 Cilium 网关](#hybrid-nodes-ingress-cilium-gateway-deploy)部分中的示例和 [Cilium 文档](https://docs.cilium.io/en/stable/network/servicemesh/gateway-api/gateway-api/#examples)中的示例。

## 部署 Cilium 网关
<a name="hybrid-nodes-ingress-cilium-gateway-deploy"></a>

1. 创建示例应用程序。以下示例使用 [Istio Bookinfo](https://istio.io/latest/docs/examples/bookinfo/) 示例微服务应用程序。

   ```
   kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml
   ```

1. 确认应用程序在成功运行。

   ```
   kubectl get pods
   ```

   ```
   NAME                              READY   STATUS    RESTARTS   AGE
   details-v1-766844796b-9965p       1/1     Running   0          81s
   productpage-v1-54bb874995-jmc8j   1/1     Running   0          80s
   ratings-v1-5dc79b6bcd-smzxz       1/1     Running   0          80s
   reviews-v1-598b896c9d-vj7gb       1/1     Running   0          80s
   reviews-v2-556d6457d-xbt8v        1/1     Running   0          80s
   reviews-v3-564544b4d6-cpmvq       1/1     Running   0          80s
   ```

1. 使用以下内容创建名为 `my-gateway.yaml` 的文件。以下示例使用 `service.beta.kubernetes.io/aws-load-balancer-type: "external"` 注释，防止传统 AWS 云提供商为 Cilium 为网关资源创建的 LoadBalancer 类型服务创建经典负载均衡器。

   ```
   ---
   apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
   metadata:
     name: my-gateway
   spec:
     gatewayClassName: cilium
     infrastructure:
       annotations:
         service.beta.kubernetes.io/aws-load-balancer-type: "external"
     listeners:
     - protocol: HTTP
       port: 80
       name: web-gw
       allowedRoutes:
         namespaces:
           from: Same
   ---
   apiVersion: gateway.networking.k8s.io/v1
   kind: HTTPRoute
   metadata:
     name: http-app-1
   spec:
     parentRefs:
     - name: my-gateway
       namespace: default
     rules:
     - matches:
       - path:
           type: PathPrefix
           value: /details
       backendRefs:
       - name: details
         port: 9080
   ```

1. 将网关资源应用于集群。

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

1. 确认网关资源和相应的服务已创建。在此阶段，预计网关资源的 `ADDRESS` 字段中没有填充 IP 地址或主机名，网关资源的 LoadBalancer 类型服务同样没有分配 IP 地址或主机名。

   ```
   kubectl get gateway my-gateway
   ```

   ```
   NAME         CLASS    ADDRESS   PROGRAMMED   AGE
   my-gateway   cilium             True         10s
   ```

   ```
   kubectl get svc cilium-gateway-my-gateway
   ```

   ```
   NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
   cilium-gateway-my-gateway   LoadBalancer   172.16.227.247   <pending>     80:30912/TCP   24s
   ```

1. 继续执行[服务类型 LoadBalancer](#hybrid-nodes-ingress-cilium-loadbalancer)，将网关资源配置为使用 Cilium 负载均衡器 IPAM 分配的 IP 地址，并执行[服务类型 NodePort](#hybrid-nodes-ingress-cilium-nodeport)或[主机网络](#hybrid-nodes-ingress-cilium-host-network)，将网关资源配置为使用 NodePort 或主机网络地址。

## 安装 Cilium 入口
<a name="hybrid-nodes-ingress-cilium-ingress-install"></a>

### 注意事项
<a name="_considerations_3"></a>
+ 配置 Cilium 时，必须将 `nodePort.enabled` 设置为 `true`，如下列示例所示。如果您使用的是 Cilium 的 kube-proxy 替换功能，则无需将 `nodePort.enabled` 设置为 `true`。
+ 配置 Cilium 时，必须将 `envoy.enabled` 设置为 `true`，如下列示例所示。
+ 将 `ingressController.loadbalancerMode` 设置为 `dedicated` 后，Cilium 会为每个入口资源创建专用服务。将 `ingressController.loadbalancerMode` 设置为 `shared` 后，Cilium 会为集群中的所有入口资源创建 LoadBalancer 类型的共享服务。使用 `shared` 负载均衡器模式时，共享服务的设置（例如 `labels`、`annotations`、`type` 和 `loadBalancerIP`）在 Helm 值的 `ingressController.service` 部分中进行配置。有关更多信息，请参阅 [Cilium Helm values reference](https://github.com/cilium/cilium/blob/v1.17.6/install/kubernetes/cilium/values.yaml#L887)。
+ 将 `ingressController.default` 设置为 `true` 后，Cilium 将被配置为集群的默认入口控制器并会创建入口条目（即使未在入口资源上指定 `ingressClassName`，也是如此）。
+ Cilium 入口可以在负载均衡器（默认）、节点端口或主机网络模式下部署。在主机网络模式下安装 Cilium 时，将禁用 LoadBalancer 类型服务和 NodePort 类型服务的模式。请参阅[主机网络](#hybrid-nodes-ingress-cilium-host-network)了解更多信息。
+ 在 Helm 值中，始终将 `ingressController.service.annotations` 设置为 `service.beta.kubernetes.io/aws-load-balancer-type: "external"`，以防止传统 AWS 云提供商为 [Cilium Helm 图表](https://github.com/cilium/cilium/blob/main/install/kubernetes/cilium/templates/cilium-ingress-service.yaml)创建的默认 `cilium-ingress` 服务创建经典负载均衡器。

### 先决条件
<a name="_prerequisites_3"></a>

1. 在命令行环境中安装 Helm，请参阅[安装 Helm 说明](helm.md)。

1. 按照[为混合节点配置 CNI](hybrid-nodes-cni.md)中的说明安装 Cilium。

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

1. 创建以下内容的名为 `cilium-ingress-values.yaml` 的文件。以下示例将 Cilium 入口配置为使用默认负载均衡器 `dedicated` 模式，并对配置为仅在混合节点上运行的 Envoy 代理使用单独的 `cilium-envoy` DaemonSet。

   ```
   ingressController:
     enabled: true
     loadbalancerMode: dedicated
     service:
       annotations:
         service.beta.kubernetes.io/aws-load-balancer-type: "external"
   nodePort:
     enabled: true
   envoy:
     enabled: true
     affinity:
       nodeAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: eks.amazonaws.com/compute-type
               operator: In
               values:
               - hybrid
   ```

1. 将 Helm 值文件应用于集群。

   ```
   helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \
     --namespace kube-system \
     --reuse-values \
     --set operator.rollOutPods=true \
     --values cilium-ingress-values.yaml
   ```

1. 确认 Cilium 管理器、代理和 Envoy 容器组（pod）正在运行。

   ```
   kubectl -n kube-system get pods --selector=app.kubernetes.io/part-of=cilium
   ```

   ```
   NAME                               READY   STATUS    RESTARTS   AGE
   cilium-envoy-5pgnd                 1/1     Running   0          6m31s
   cilium-envoy-6fhg4                 1/1     Running   0          6m30s
   cilium-envoy-jskrk                 1/1     Running   0          6m30s
   cilium-envoy-k2xtb                 1/1     Running   0          6m31s
   cilium-envoy-w5s9j                 1/1     Running   0          6m31s
   cilium-grwlc                       1/1     Running   0          4m12s
   cilium-operator-68f7766967-5nnbl   1/1     Running   0          4m20s
   cilium-operator-68f7766967-7spfz   1/1     Running   0          4m20s
   cilium-pnxcv                       1/1     Running   0          6m29s
   cilium-r7qkj                       1/1     Running   0          4m12s
   cilium-wxhfn                       1/1     Running   0          4m1s
   cilium-z7hlb                       1/1     Running   0          6m30s
   ```

## 配置 Cilium 入口
<a name="hybrid-nodes-ingress-cilium-ingress-configure"></a>

通过将 `ingressClassName` 设置为 `cilium`，可以在入口对象上启用 Cilium 入口。Cilium 为入口资源创建的服务在使用 `dedicated` 负载均衡器模式时可以在入口对象上使用注释进行配置，在使用 `shared` 负载均衡器模式时可以在 Cilium/Helm 配置中进行配置。入口控制器通常使用这些注释来配置负载均衡器基础设施或服务的其他属性，例如服务类型、负载均衡器模式、端口和 TLS 传递。下面介绍了关键注释。有关支持的注释的完整列表，请参阅 Cilium 文档中的 [Cilium Ingress annotations](https://docs.cilium.io/en/stable/network/servicemesh/ingress/#supported-ingress-annotations)。


| 注释 | 描述 | 
| --- | --- | 
|   `ingress.cilium.io/loadbalancer-mode`   |   `dedicated`：每个入口资源的 LoadBalancer 类型的专用服务（默认）。  `shared`：所有入口资源的 LoadBalancer 类型的单一服务。  | 
|   `ingress.cilium.io/service-type`   |   `LoadBalancer`：该服务将为 LoadBalancer 类型（默认）  `NodePort`：该服务将为 NodePort 类型。  | 
|   `service.beta.kubernetes.io/aws-load-balancer-type`   |   `"external"`：防止传统 AWS 云提供商为 LoadBalancer 类型服务预置经典负载均衡器。  | 
|   `lbipam.cilium.io/ips`   |  要从 Cilium LoadBalancer IPAM 分配的 IP 地址列表  | 

Cilium 和 Kubernetes 入口规范支持入口路径的精确、前缀和特定于实现的匹配规则。Cilium 支持正则表达式作为其特定于实现的匹配规则。有关更多信息，请参阅 Cilium 文档中的 [Ingress path types and precedence](https://docs.cilium.io/en/stable/network/servicemesh/ingress/#ingress-path-types-and-precedence) 和 [Path types examples](https://docs.cilium.io/en/stable/network/servicemesh/path-types/)，以及本页[部署 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-deploy)部分中的示例。

以下显示了示例 Cilium 入口对象。

```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    service.beta.kuberentes.io/...
    service.kuberentes.io/...
spec:
  ingressClassName: cilium
  rules:
  ...
```

## 部署 Cilium 入口
<a name="hybrid-nodes-ingress-cilium-ingress-deploy"></a>

1. 创建示例应用程序。以下示例使用 [Istio Bookinfo](https://istio.io/latest/docs/examples/bookinfo/) 示例微服务应用程序。

   ```
   kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml
   ```

1. 确认应用程序在成功运行。

   ```
   kubectl get pods
   ```

   ```
   NAME                              READY   STATUS    RESTARTS   AGE
   details-v1-766844796b-9965p       1/1     Running   0          81s
   productpage-v1-54bb874995-jmc8j   1/1     Running   0          80s
   ratings-v1-5dc79b6bcd-smzxz       1/1     Running   0          80s
   reviews-v1-598b896c9d-vj7gb       1/1     Running   0          80s
   reviews-v2-556d6457d-xbt8v        1/1     Running   0          80s
   reviews-v3-564544b4d6-cpmvq       1/1     Running   0          80s
   ```

1. 使用以下内容创建名为 `my-ingress.yaml` 的文件。以下示例使用 `service.beta.kubernetes.io/aws-load-balancer-type: "external"` 注释，防止传统 AWS 云提供商为 Cilium 为入口资源创建的 LoadBalancer 类型服务创建经典负载均衡器。

   ```
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: my-ingress
     namespace: default
     annotations:
       service.beta.kubernetes.io/aws-load-balancer-type: "external"
   spec:
     ingressClassName: cilium
     rules:
     - http:
         paths:
         - backend:
             service:
               name: details
               port:
                 number: 9080
           path: /details
           pathType: Prefix
   ```

1. 将入口资源应用于集群。

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

1. 确认入口资源和相应的服务已创建。在此阶段，预计入口资源的 `ADDRESS` 字段中没有填充 IP 地址或主机名，同样，入口资源的 LoadBalancer 类型的共享或专用服务也没有分配 IP 地址或主机名。

   ```
   kubectl get ingress my-ingress
   ```

   ```
   NAME         CLASS    HOSTS   ADDRESS   PORTS   AGE
   my-ingress   cilium   *                 80      8s
   ```

   适用于负载均衡器模式 `shared` 

   ```
   kubectl -n kube-system get svc cilium-ingress
   ```

   ```
   NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
   cilium-ingress   LoadBalancer   172.16.217.48   <pending>     80:32359/TCP,443:31090/TCP   10m
   ```

   适用于负载均衡器模式 `dedicated` 

   ```
   kubectl -n default get svc cilium-ingress-my-ingress
   ```

   ```
   NAME                        TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
   cilium-ingress-my-ingress   LoadBalancer   172.16.193.15   <pending>     80:32088/TCP,443:30332/TCP   25s
   ```

1. 继续执行[服务类型 LoadBalancer](#hybrid-nodes-ingress-cilium-loadbalancer)，将入口资源配置为使用 Cilium 负载均衡器 IPAM 分配的 IP 地址，并执行[服务类型 NodePort](#hybrid-nodes-ingress-cilium-nodeport)或[主机网络](#hybrid-nodes-ingress-cilium-host-network)，将入口资源配置为使用 NodePort 或主机网络地址。

## 服务类型 LoadBalancer
<a name="hybrid-nodes-ingress-cilium-loadbalancer"></a>

### 现有的负载均衡器基础设施
<a name="_existing_load_balancer_infrastructure"></a>

默认情况下，对于 Cilium 入口和 Cilium 网关，Cilium 会为入口/网关资源创建 LoadBalancer 类型的 Kubernetes 服务。Cilium 创建的服务的属性可以通过入口和网关资源进行配置。在创建入口或网关资源时，入口或网关的对外部公开的 IP 地址或主机名是从负载均衡器基础设施进行分配，而负载均衡器基础设施通常由入口或网关控制器预置。

许多入口和网关控制器都使用注释来检测和配置负载均衡器基础设施。这些入口和网关控制器的注释是在入口或网关资源上配置，如上面的示例所示。请参阅入口或网关控制器的文档，了解其支持的注释，并参阅 [Kubernetes 入口文档](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)和 [Kubernetes 网关文档](https://gateway-api.sigs.k8s.io/implementations/)，获取常用控制器列表。

**重要**  
在具有 EKS 混合节点的情况下，Cilium 入口和网关不能与 AWS 负载均衡器控制器和 AWS 网络负载均衡器（NLB）一起使用。尝试将它们一起使用会导致目标未注册，因为当 NLB 的 `target-type` 设置为 `ip` 时（在 EKS 混合节点上运行工作负载时使用 NLB 的要求），NLB 会尝试直接连接到支持 LoadBalancer 类型服务的容器组（pod）IP。

### 没有负载均衡器基础设施
<a name="_no_load_balancer_infrastructure"></a>

如果您的环境中没有负载均衡器基础设施和相应的入口/网关控制器，则可以将入口/网关资源和相应的 LoadBalancer 类型服务配置为使用 Cilium 的 [负载均衡器 IP 地址管理](https://docs.cilium.io/en/stable/network/lb-ipam/)（LB IPAM）分配的 IP 地址。Cilium LB IPAM 可以使用本地环境中的已知 IP 地址范围进行配置，并且可以使用 Cilium 的内置边界网关协议（BGP）支持或 L2 通告向您的本地网络通告 LoadBalancer IP 地址。

以下示例说明如何使用用于入口/网关资源的 IP 地址配置 Cilium 的 LB IPAM，以及如何配置 Cilium BGP 控制面板以向本地网络通告 LoadBalancer IP 地址。默认情况下，Cilium 的 LB IPAM 功能处于启用状态，但在创建 `CiliumLoadBalancerIPPool` 资源后才会激活。

#### 先决条件
<a name="_prerequisites_4"></a>
+ 按照[安装 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-install)或[安装 Cilim 网关](#hybrid-nodes-ingress-cilium-gateway-install)中的说明安装 Cilium 入口或网关。
+ 按照[部署 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-deploy)或[部署 Cilium 网关](#hybrid-nodes-ingress-cilium-gateway-deploy)中的说明部署带有示例应用程序的 Cilium 入口或网关资源。
+ 按照[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md) 中的说明启用 Cilium BGP 控制面板。如果您不想使用 BGP，则可以跳过此先决条件，但是在 Cilium LB IPAM 分配的 LoadBalancer IP 地址可在本地网络上路由之前，您无法访问您的入口或网关资源。

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

1. 可选择修补入口或网关资源，以请求用于 LoadBalancer 类型服务的特定 IP 地址。如果您不请求特定 IP 地址，Cilium 将在后续步骤中从 `CiliumLoadBalancerIPPool` 资源中配置的 IP 地址范围分配一个 IP 地址。在下面的命令中，将 `LB_IP_ADDRESS` 替换为请求 LoadBalancer 类型服务的 IP 地址。

    **网关** 

   ```
   kubectl patch gateway -n default my-gateway --type=merge -p '{
     "spec": {
       "addresses": [{"type": "IPAddress", "value": "LB_IP_ADDRESS"}]
     }
   }'
   ```

    **入口** 

   ```
   kubectl patch ingress my-ingress --type=merge -p '{
     "metadata": {"annotations": {"lbipam.cilium.io/ips": "LB_IP_ADDRESS"}}
   }'
   ```

1. 使用 `CiliumLoadBalancerIPPool` 资源创建一个名为 `cilium-lbip-pool-ingress.yaml` 的文件，用于为您的入口/网关资源配置负载均衡器 IP 地址范围。
   + 如果使用的是 Cilium 入口，Cilium 会自动将 `cilium.io/ingress: "true"` 标签应用于它为入口资源创建的服务。您可以在 `CiliumLoadBalancerIPPool` 资源定义的 `serviceSelector` 字段中使用此标签来选择符合 LB IPAM 条件的服务。
   + 如果您使用的是 Cilium 网关，则可以使用 `CiliumLoadBalancerIPPool` 资源定义 `serviceSelector` 字段中的 `gateway.networking.k8s.io/gateway-name` 标签来选择符合 LB IPAM 条件的网关资源。
   + 将 `LB_IP_CIDR` 替换为用于负载均衡器 IP 地址的 IP 地址范围。要选择单个 IP 地址，请使用 `/32` CIDR。有关更多信息，请参阅 Cilium 文档中的 [LoadBalancer IP Address Management](https://docs.cilium.io/en/stable/network/lb-ipam/)。

     ```
     apiVersion: cilium.io/v2alpha1
     kind: CiliumLoadBalancerIPPool
     metadata:
       name: bookinfo-pool
     spec:
       blocks:
       - cidr: "LB_IP_CIDR"
       serviceSelector:
         # if using Cilium Gateway
         matchExpressions:
           - { key: gateway.networking.k8s.io/gateway-name, operator: In, values: [ my-gateway ] }
         # if using Cilium Ingress
         matchLabels:
           cilium.io/ingress: "true"
     ```

1. 将 `CiliumLoadBalancerIPPool` 资源应用于集群。

   ```
   kubectl apply -f cilium-lbip-pool-ingress.yaml
   ```

1. 确认已从 Cilium LB IPAM 为入口/网关资源分配了 IP 地址。

    **网关** 

   ```
   kubectl get gateway my-gateway
   ```

   ```
   NAME         CLASS    ADDRESS        PROGRAMMED   AGE
   my-gateway   cilium   LB_IP_ADDRESS    True         6m41s
   ```

    **入口** 

   ```
   kubectl get ingress my-ingress
   ```

   ```
   NAME         CLASS    HOSTS   ADDRESS        PORTS   AGE
   my-ingress   cilium   *       LB_IP_ADDRESS   80      10m
   ```

1. 使用 `CiliumBGPAdvertisement` 资源创建一个名为 `cilium-bgp-advertisement-ingress.yaml` 的文件，用于通告入口/网关资源的 LoadBalancer IP 地址。如果您不使用 Cilium BGP，则可跳过此步骤。用于入口/网关资源的 LoadBalancer IP 地址必须可在本地网络上路由，这样您才能在下一步中查询该服务。

   ```
   apiVersion: cilium.io/v2alpha1
   kind: CiliumBGPAdvertisement
   metadata:
     name: bgp-advertisement-lb-ip
     labels:
       advertise: bgp
   spec:
     advertisements:
       - advertisementType: "Service"
         service:
           addresses:
             - LoadBalancerIP
         selector:
           # if using Cilium Gateway
           matchExpressions:
             - { key: gateway.networking.k8s.io/gateway-name, operator: In, values: [ my-gateway ] }
           # if using Cilium Ingress
           matchLabels:
             cilium.io/ingress: "true"
   ```

1. 将 `CiliumBGPAdvertisement` 资源应用于集群。

   ```
   kubectl apply -f cilium-bgp-advertisement-ingress.yaml
   ```

1. 使用从 Cilium LB IPAM 分配的 IP 地址访问该服务。

   ```
   curl -s http://LB_IP_ADDRESS:80/details/1 | jq
   ```

   ```
   {
     "id": 1,
     "author": "William Shakespeare",
     "year": 1595,
     "type": "paperback",
     "pages": 200,
     "publisher": "PublisherA",
     "language": "English",
     "ISBN-10": "1234567890",
     "ISBN-13": "123-1234567890"
   }
   ```

## 服务类型 NodePort
<a name="hybrid-nodes-ingress-cilium-nodeport"></a>

如果您的环境中没有负载均衡器基础设施和相应的入口控制器，或者您要自行管理负载均衡器基础设施或使用基于 DNS 的负载均衡，则可以将 Cilium 入口配置成为入口资源创建 NodePort 类型服务。将 NodePort 与 Cilium 入口配合使用时，NodePort 类型服务会在端口范围为 30000-32767 的每个节点的端口上公开。在此模式下，当流量到达 NodePort 上集群中的任何节点时，它会被转发到支持该服务的容器组（pod），而该容器组可能位于同一节点或不同节点上。

**注意**  
Cilium 1.18.x 版本计划提供 NodePort 服务的 Cilium 网关支持（[\$127273](https://github.com/cilium/cilium/pull/27273)）

### 先决条件
<a name="_prerequisites_5"></a>
+ 按照[安装 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-install)中的说明安装Cilium 入口。
+ 按照[部署 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-deploy)中的说明部署带有示例应用程序的 Cilium 入口资源。

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

1. 修补现有入口资源 `my-ingress`，将其从 LoadBalancer 类型服务更改为 NodePort 类型服务。

   ```
   kubectl patch ingress my-ingress --type=merge -p '{
       "metadata": {"annotations": {"ingress.cilium.io/service-type": "NodePort"}}
   }'
   ```

   如果您尚未创建入口资源，则可以通过将以下入口定义应用于集群来创建它。请注意，下面的入口定义使用了[部署 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-deploy)中所述的 Istio Bookinfo 示例应用程序。

   ```
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: my-ingress
     namespace: default
     annotations:
       service.beta.kubernetes.io/aws-load-balancer-type: "external"
       "ingress.cilium.io/service-type": "NodePort"
   spec:
     ingressClassName: cilium
     rules:
     - http:
         paths:
         - backend:
             service:
               name: details
               port:
                 number: 9080
           path: /details
           pathType: Prefix
   ```

1. 确认入口资源的服务已更新为使用 NodePort 类型服务。记下输出中 HTTP 协议的端口。在下面的示例中，此 HTTP 端口为 `32353`，将在后续步骤中使用它来查询服务。将 Cilium 入口与 NodePort 类型服务配合使用的好处是，您可以为入口流量应用基于路径和主机的路由，以及网络策略，而对于没有入口的 NodePort 类型的标准服务，则无法做到这一点。

   ```
   kubectl -n default get svc cilium-ingress-my-ingress
   ```

   ```
   NAME                        TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
   cilium-ingress-my-ingress   NodePort   172.16.47.153   <none>        80:32353/TCP,443:30253/TCP   27m
   ```

1. 获取集群节点的 IP 地址。

   ```
   kubectl get nodes -o wide
   ```

   ```
   NAME                   STATUS   ROLES    AGE   VERSION               INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
   mi-026d6a261e355fba7   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.150   <none>        Ubuntu 22.04.5 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-082f73826a163626e   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.32    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-09183e8a3d755abf6   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.33    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-0d78d815980ed202d   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.97    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-0daa253999fe92daa   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.100   <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   ```

1. 使用您的节点的 IP 地址和上面捕获的 NodePort 访问 NodePort 类型服务。在下面的示例中，使用的节点 IP 地址是 `10.80.146.32`，NodePort 是 `32353`。请将这些值替换为您环境的相应值。

   ```
   curl -s http://10.80.146.32:32353/details/1 | jq
   ```

   ```
   {
     "id": 1,
     "author": "William Shakespeare",
     "year": 1595,
     "type": "paperback",
     "pages": 200,
     "publisher": "PublisherA",
     "language": "English",
     "ISBN-10": "1234567890",
     "ISBN-13": "123-1234567890"
   }
   ```

## 主机网络
<a name="hybrid-nodes-ingress-cilium-host-network"></a>

与 NodePort 类型服务类似，如果您没有负载均衡器基础设施和入口或网关控制器，或者您要使用外部负载均衡器自行管理负载均衡，则可以将 Cilium 入口和 Cilium 网关配置为直接在主机网络上公开入口和网关资源。当为入口或网关资源启用主机网络模式时，会自动禁用 LoadBalancer 类型服务和 NodePort 类型服务的模式，主机网络模式与每个入口或网关资源的这些替代模式相互排斥。与 NodePort 类型服务模式相比，主机网络模式为可使用的端口范围提供了更大灵活性（不限于 30000-32767 NodePort 范围），您可以配置 Envoy 代理在主机网络上运行的节点子集。

### 先决条件
<a name="_prerequisites_6"></a>
+ 按照[安装 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-install)或[安装 Cilim 网关](#hybrid-nodes-ingress-cilium-gateway-install)中的说明安装 Cilium 入口或网关。

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

#### Gateway
<a name="_gateway"></a>

1. 使用以下内容创建名为 `cilium-gateway-host-network.yaml` 的文件。

   ```
   gatewayAPI:
     enabled: true
     hostNetwork:
       enabled: true
       # uncomment to restrict nodes where Envoy proxies run on the host network
       # nodes:
       #   matchLabels:
       #     role: gateway
   ```

1. 将主机网络 Cilium 网关配置应用于集群。

   ```
   helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \
     --namespace kube-system \
     --reuse-values \
     --set operator.rollOutPods=true \
     -f cilium-gateway-host-network.yaml
   ```

   如果您尚未创建网关资源，则可以通过将以下网关定义应用于集群来创建它。下面的网关定义使用了[部署 Cilium 网关](#hybrid-nodes-ingress-cilium-gateway-deploy)中所述的 Istio Bookinfo 示例应用程序。在下面的示例中，网关资源配置为使用 HTTP 侦听器的 `8111` 端口，该端口是在主机网络上运行的 Envoy 代理的共享侦听器端口。如果您将特权端口（低于 1023）用于网关资源，请参阅 [Cilium 文档](https://docs.cilium.io/en/stable/network/servicemesh/gateway-api/gateway-api/#bind-to-privileged-port)获取相关说明。

   ```
   ---
   apiVersion: gateway.networking.k8s.io/v1
   kind: Gateway
   metadata:
     name: my-gateway
   spec:
     gatewayClassName: cilium
     listeners:
     - protocol: HTTP
       port: 8111
       name: web-gw
       allowedRoutes:
         namespaces:
           from: Same
   ---
   apiVersion: gateway.networking.k8s.io/v1
   kind: HTTPRoute
   metadata:
     name: http-app-1
   spec:
     parentRefs:
     - name: my-gateway
       namespace: default
     rules:
     - matches:
       - path:
           type: PathPrefix
           value: /details
       backendRefs:
       - name: details
         port: 9080
   ```

   您可以使用以下命令观察应用的 Cilium Envoy 配置。

   ```
   kubectl get cec cilium-gateway-my-gateway -o yaml
   ```

   您可以使用以下命令获取 `cilium-gateway-my-gateway` 服务的 Envoy 侦听器端口。在此示例中，共享侦听器端口为 `8111`。

   ```
   kubectl get cec cilium-gateway-my-gateway -o jsonpath={.spec.services[0].ports[0]}
   ```

1. 获取集群节点的 IP 地址。

   ```
   kubectl get nodes -o wide
   ```

   ```
   NAME                   STATUS   ROLES    AGE   VERSION               INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
   mi-026d6a261e355fba7   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.150   <none>        Ubuntu 22.04.5 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-082f73826a163626e   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.32    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-09183e8a3d755abf6   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.33    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-0d78d815980ed202d   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.97    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-0daa253999fe92daa   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.100   <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   ```

1. 使用节点的 IP 地址和 `cilium-gateway-my-gateway` 资源的侦听器端口访问服务。在下面的示例中，使用的节点 IP 地址是 `10.80.146.32`，侦听器端口是 `8111`。请将这些值替换为您环境的相应值。

   ```
   curl -s http://10.80.146.32:8111/details/1 | jq
   ```

   ```
   {
     "id": 1,
     "author": "William Shakespeare",
     "year": 1595,
     "type": "paperback",
     "pages": 200,
     "publisher": "PublisherA",
     "language": "English",
     "ISBN-10": "1234567890",
     "ISBN-13": "123-1234567890"
   }
   ```

#### 入口
<a name="_ingress"></a>

由于上游 Cilium 问题（[\$134028](https://github.com/cilium/cilium/issues/34028)），主机网络模式下的 Cilium 入口需要使用 `loadbalancerMode: shared`，这会为集群中的所有入口资源创建 ClusterIP 类型的单一服务。如果您将特权端口（低于 1023）用于入口资源，请参阅 [Cilium 文档](https://docs.cilium.io/en/stable/network/servicemesh/ingress/#bind-to-privileged-port)获取相关说明。

1. 使用以下内容创建名为 `cilium-ingress-host-network.yaml` 的文件。

   ```
   ingressController:
     enabled: true
     loadbalancerMode: shared
     # This is a workaround for the upstream Cilium issue
     service:
       externalTrafficPolicy: null
       type: ClusterIP
     hostNetwork:
       enabled: true
       # ensure the port does not conflict with other services on the node
       sharedListenerPort: 8111
       # uncomment to restrict nodes where Envoy proxies run on the host network
       # nodes:
       #   matchLabels:
       #     role: ingress
   ```

1. 将主机网络 Cilium 入口配置应用于集群。

   ```
   helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \
     --namespace kube-system \
     --reuse-values \
     --set operator.rollOutPods=true \
     -f cilium-ingress-host-network.yaml
   ```

   如果您尚未创建入口资源，则可以通过将以下入口定义应用于集群来创建它。下面的入口定义使用了[部署 Cilium 入口](#hybrid-nodes-ingress-cilium-ingress-deploy)中所述的 Istio Bookinfo 示例应用程序。

   ```
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: my-ingress
     namespace: default
   spec:
     ingressClassName: cilium
     rules:
     - http:
         paths:
         - backend:
             service:
               name: details
               port:
                 number: 9080
           path: /details
           pathType: Prefix
   ```

   您可以使用以下命令观察应用的 Cilium Envoy 配置。

   ```
   kubectl get cec -n kube-system cilium-ingress -o yaml
   ```

   您可以使用以下命令获取 `cilium-ingress` 服务的 Envoy 侦听器端口。在此示例中，共享侦听器端口为 `8111`。

   ```
   kubectl get cec -n kube-system cilium-ingress -o jsonpath={.spec.services[0].ports[0]}
   ```

1. 获取集群节点的 IP 地址。

   ```
   kubectl get nodes -o wide
   ```

   ```
   NAME                   STATUS   ROLES    AGE   VERSION               INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
   mi-026d6a261e355fba7   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.150   <none>        Ubuntu 22.04.5 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-082f73826a163626e   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.32    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-09183e8a3d755abf6   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.33    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-0d78d815980ed202d   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.97    <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   mi-0daa253999fe92daa   Ready    <none>   23h   v1.32.3-eks-473151a   10.80.146.100   <none>        Ubuntu 22.04.4 LTS   5.15.0-142-generic   containerd://1.7.27
   ```

1. 使用节点的 IP 地址和 `cilium-ingress` 资源的 `sharedListenerPort` 访问服务。在下面的示例中，使用的节点 IP 地址是 `10.80.146.32`，侦听器端口是 `8111`。请将这些值替换为您环境的相应值。

   ```
   curl -s http://10.80.146.32:8111/details/1 | jq
   ```

   ```
   {
     "id": 1,
     "author": "William Shakespeare",
     "year": 1595,
     "type": "paperback",
     "pages": 200,
     "publisher": "PublisherA",
     "language": "English",
     "ISBN-10": "1234567890",
     "ISBN-13": "123-1234567890"
   }
   ```

# 为混合节点配置 LoadBalancer 类型服务
<a name="hybrid-nodes-load-balancing"></a>

本主题介绍了如何为在 Amazon EKS 混合节点上运行的应用程序配置第 4 层（L4）负载均衡。LoadBalancer 类型的 Kubernetes 服务用于向集群外部公开 Kubernetes 应用程序。LoadBalancer 类型服务通常与云或本地环境中的物理负载均衡器基础设施结合使用，以处理工作负载的流量。这种负载均衡器基础设施通常通过特定于环境的控制器进行预置。

 对于在 EKS 混合节点上运行的 LoadBalancer 类型服务，AWS 支持使用 AWS 网络负载均衡器（NLB）和 Cilium。使用 NLB 还是 Cilium 取决于应用程序流量的来源。如果应用程序流量来自某个 AWS 区域，AWS 建议使用 AWS NLB 和 AWS 负载均衡器控制器。如果应用程序流量来自本地或边缘环境，AWS 建议使用 Cilium 的内置负载均衡功能，无论是否在环境中使用负载均衡器基础设施，均可使用该功能。

有关第 7 层（L7）应用程序流量负载均衡的信息，请参阅[为混合节点配置 Kubernetes 入口](hybrid-nodes-ingress.md)。有关使用 EKS 实现负载均衡的一般信息，请参阅 [Best Practices for Load Balancing](https://docs.aws.amazon.com/eks/latest/best-practices/load-balancing.html)。

## AWS 网络负载均衡器
<a name="hybrid-nodes-service-lb-nlb"></a>

您可以将 [AWS 负载均衡器控制器](aws-load-balancer-controller.md)和目标类型为 `ip` 的 NLB 用于在混合节点上运行的工作负载。使用目标类型 `ip` 时，NLB 会绕过服务层网络路径，直接将流量转发到容器组（pod）。为了让 NLB 到达混合节点上的容器组（pod）IP 目标，本地容器组（pod）CIDR 必须可在本地网络中路由。此外，AWS 负载均衡器控制器使用 Webhook，需要来自 EKS 控制面板的直接通信。有关更多信息，请参阅 [为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。
+ 有关子网配置要求，请参阅[使用网络负载均衡器路由 TCP 和 UDP 流量](network-load-balancing.md)；有关 AWS 网络负载均衡器及 AWS 负载均衡器控制器的其他信息，请参阅[使用 Helm 安装 AWS 负载均衡器控制器](lbc-helm.md) 和 [Best Practices for Load Balancing](https://docs.aws.amazon.com/eks/latest/best-practices/load-balancing.html)。
+ 有关可应用于使用 AWS 网络负载均衡器的 `LoadBalancer` 类型服务的配置，请参阅 [AWS Load Balancer Controller NLB configurations](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/service/nlb/)。

### 先决条件
<a name="_prerequisites"></a>
+ 按照[为混合节点配置 CNI](hybrid-nodes-cni.md)中的说明安装 Cilium。
+ 按照[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md) 中的说明启用 Cilium BGP 控制面板。如果您不想使用 BGP，则必须使用其他方法，使本地容器组（pod）CIDR 可在本地网络中路由，有关更多信息，请参阅[可路由的远程容器组（pod）CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)。
+ 在命令行环境中安装 Helm，请参阅[安装 Helm 说明](helm.md)。
+ 在命令行环境中安装 eksctl，请参阅[安装 eksctl 说明](install-kubectl.md#eksctl-install-update)。

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

1. 下载AWS负载均衡器控制器的 IAM 策略，该策略允许负载均衡器代表您调用 AWS API。

   ```
   curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json
   ```

1. 使用上一步中下载的策略创建一个 IAM 策略。

   ```
   aws iam create-policy \
       --policy-name AWSLoadBalancerControllerIAMPolicy \
       --policy-document file://iam_policy.json
   ```

1. 将集群名称 (`CLUSTER_NAME`)、AWS 区域 (`AWS_REGION`) 和 AWS 账户 ID (`AWS_ACCOUNT_ID`) 的值替换为您的设置，然后运行以下命令。

   ```
   eksctl create iamserviceaccount \
       --cluster=CLUSTER_NAME \
       --namespace=kube-system \
       --name=aws-load-balancer-controller \
       --attach-policy-arn=arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
       --override-existing-serviceaccounts \
       --region AWS_REGION \
       --approve
   ```

1. 添加 eks-charts Helm 图表存储库。AWS 会在 GitHub 上维护此存储库。

   ```
   helm repo add eks https://aws.github.io/eks-charts
   ```

1. 更新本地 Helm 存储库，确保拥有最新的图表。

   ```
   helm repo update eks
   ```

1. 安装AWS负载均衡器控制器。将集群名称 (`CLUSTER_NAME`)、AWS 区域 (`AWS_REGION`)、VPC ID (`VPC_ID`) 和 AWS 负载均衡器控制器 Helm 图表版本 (`AWS_LBC_HELM_VERSION`) 的值替换为您的设置。您可以通过运行 `helm search repo eks/aws-load-balancer-controller --versions` 找到最新版本的 Helm 图表。如果您运行的混合模式集群同时包含混合节点和 AWS 云中的节点，则可以按照[AWS Load Balancer Controller](hybrid-nodes-webhooks.md#hybrid-nodes-mixed-lbc) 中的说明，在云端节点上运行 AWS 负载均衡器控制器。

   ```
   helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
     -n kube-system \
     --version AWS_LBC_HELM_VERSION \
     --set clusterName=CLUSTER_NAME \
     --set region=AWS_REGION \
     --set vpcId=VPC_ID \
     --set serviceAccount.create=false \
     --set serviceAccount.name=aws-load-balancer-controller
   ```

1. 验证 AWS 负载均衡器控制器是否成功安装。

   ```
   kubectl get -n kube-system deployment aws-load-balancer-controller
   ```

   ```
   NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
   aws-load-balancer-controller   2/2     2            2           84s
   ```

1. 在名为 `tcp-sample-app.yaml` 的文件中定义示例应用程序。以下示例使用带有 TCP 端口的简单 NGINX 部署。

   ```
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: tcp-sample-app
     namespace: default
   spec:
     replicas: 3
     selector:
       matchLabels:
         app: nginx
     template:
       metadata:
         labels:
           app: nginx
       spec:
         containers:
           - name: nginx
             image: public.ecr.aws/nginx/nginx:1.23
             ports:
               - name: tcp
                 containerPort: 80
   ```

1. 将部署应用于集群。

   ```
   kubectl apply -f tcp-sample-app.yaml
   ```

1. 在名为 `tcp-sample-service.yaml` 的文件中为部署定义 LoadBalancer 类型服务。

   ```
   apiVersion: v1
   kind: Service
   metadata:
     name: tcp-sample-service
     namespace: default
     annotations:
       service.beta.kubernetes.io/aws-load-balancer-type: external
       service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
       service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
   spec:
     ports:
       - port: 80
         targetPort: 80
         protocol: TCP
     type: LoadBalancer
     selector:
       app: nginx
   ```

1. 将服务配置应用于集群。

   ```
   kubectl apply -f tcp-sample-service.yaml
   ```

1. 为服务预置 NLB 可能需要几分钟时间。预置 NLB 后，将为服务分配一个与 NLB 部署的 DNS 名称相对应的地址。

   ```
   kubectl get svc tcp-sample-service
   ```

   ```
   NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP                                                                    PORT(S)        AGE
   tcp-sample-service   LoadBalancer   172.16.115.212   k8s-default-tcpsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.<region>.amazonaws.com   80:30396/TCP   8s
   ```

1. 使用 NLB 的地址访问服务。

   ```
   curl k8s-default-tcpsampl-xxxxxxxxxx-xxxxxxxxxxxxxxxx.elb.<region>.amazonaws.com
   ```

   输出示例如下。

   ```
   <!DOCTYPE html>
   <html>
   <head>
   <title>Welcome to nginx!</title>
   [...]
   ```

1. 清理您创建的 资源。

   ```
   kubectl delete -f tcp-sample-service.yaml
   kubectl delete -f tcp-sample-app.yaml
   ```

## Cilium 集群内负载均衡
<a name="hybrid-nodes-service-lb-cilium"></a>

Cilium 可用作在 EKS 混合节点上运行的工作负载的集群内负载均衡器，这对于没有负载均衡器基础设施的环境非常有用。Cilium 的负载均衡功能基于多种 Cilium 功能构建而成，包括 kube-proxy 替换、负载均衡器 IP 地址管理（IPAM）和 BGP 控制面板。这些功能的职责详述如下：
+  **Cilium kube-proxy 替换**：负责将服务流量路由到后端容器组（pod）。
+  **Cilium 负载均衡器 IPAM**：管理可分配给 `LoadBalancer` 类型服务的 IP 地址。
+  **Cilium BGP 控制面板**：向本地网络通告负载均衡器 IPAM 分配的 IP 地址。

如果不使用 Cilium 的 kube-proxy 替换，您仍然可以使用 Cilium 负载均衡器 IPAM 和 BGP 控制面板为 LoadBalancer 类型服务分配和指定 IP 地址。如果不使用 Cilium 的 kube-proxy 替换，则在默认情况下，服务到后端容器组（pod）的负载均衡将由 EKS 中的 kube-proxy 和 iptables 规则处理。

### 先决条件
<a name="_prerequisites_2"></a>
+ 无论是否启用 kube-proxy 替换，都已按照[为混合节点配置 CNI](hybrid-nodes-cni.md) 中的说明安装 Cilium。Cilium 的 kube-proxy 替换需要运行 Linux 内核至少为 v4.19.57、v5.1.16 或 v5.2.0 的最新操作系统。除 Red Hat Enterprise Linux（RHEL）8.x 外，所有支持用于混合节点的操作系统的最新版本都符合此标准。
+ 按照[为混合节点配置 Cilium BGP](hybrid-nodes-cilium-bgp.md) 中的说明启用 Cilium BGP 控制面板。如果您不想使用 BGP，则必须使用其他方法，使本地容器组（pod）CIDR 可在本地网络中路由，有关更多信息，请参阅[可路由的远程容器组（pod）CIDR](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-pod-cidrs)。
+ 在命令行环境中安装 Helm，请参阅[安装 Helm 说明](helm.md)。

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

1. 创建一个名为 `cilium-lbip-pool-loadbalancer.yaml` 的文件，其中包含 `CiliumLoadBalancerIPPool` 资源，用于为 LoadBalancer 类型服务配置负载均衡器 IP 地址范围。
   + 将 `LB_IP_CIDR` 替换为用于负载均衡器 IP 地址的 IP 地址范围。要选择单个 IP 地址，请使用 `/32` CIDR。有关更多信息，请参阅 Cilium 文档中的 [LoadBalancer IP Address Management](https://docs.cilium.io/en/stable/network/lb-ipam/)。
   + 配置 `serviceSelector` 字段，使其与将在后续步骤中创建的服务名称相匹配。此配置完成后，此池中的 IP 将仅分配给名为 `tcp-sample-service` 的服务。

     ```
     apiVersion: cilium.io/v2alpha1
     kind: CiliumLoadBalancerIPPool
     metadata:
       name: tcp-service-pool
     spec:
       blocks:
       - cidr: "LB_IP_CIDR"
       serviceSelector:
         matchLabels:
           io.kubernetes.service.name: tcp-sample-service
     ```

1. 将 `CiliumLoadBalancerIPPool` 资源应用于集群。

   ```
   kubectl apply -f cilium-lbip-pool-loadbalancer.yaml
   ```

1. 确认池中至少有一个可用的 IP 地址。

   ```
   kubectl get ciliumloadbalancerippools.cilium.io
   ```

   ```
   NAME               DISABLED   CONFLICTING   IPS AVAILABLE   AGE
   tcp-service-pool   false      False         1               24m
   ```

1. 创建一个名为 `cilium-bgp-advertisement-loadbalancer.yaml` 的文件，其中包含 `CiliumBGPAdvertisement` 资源，用于通告将在下一步中创建的服务的负载均衡器 IP 地址。如果您不使用 Cilium BGP，则可跳过此步骤。用于服务的负载均衡器 IP 地址必须可在本地网络中路由，以便您可以在最后一步中查询服务。
   + 将 `advertisementType` 字段设置为 `Service`，`service.addresses` 设置为 `LoadBalancerIP`，以仅通告 `LoadBalancer` 类型服务的 `LoadBalancerIP`。
   + 配置 `selector` 字段，使其与将在后续步骤中创建的服务名称相匹配。此配置完成后，仅会通告名为 `tcp-sample-service` 的服务的 `LoadBalancerIP`。

     ```
     apiVersion: cilium.io/v2alpha1
     kind: CiliumBGPAdvertisement
     metadata:
       name: bgp-advertisement-tcp-service
       labels:
         advertise: bgp
     spec:
       advertisements:
         - advertisementType: "Service"
           service:
             addresses:
               - LoadBalancerIP
           selector:
             matchLabels:
               io.kubernetes.service.name: tcp-sample-service
     ```

1. 将 `CiliumBGPAdvertisement` 资源应用于集群。如果您不使用 Cilium BGP，则可跳过此步骤。

   ```
   kubectl apply -f cilium-bgp-advertisement-loadbalancer.yaml
   ```

1. 在名为 `tcp-sample-app.yaml` 的文件中定义示例应用程序。以下示例使用带有 TCP 端口的简单 NGINX 部署。

   ```
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: tcp-sample-app
     namespace: default
   spec:
     replicas: 3
     selector:
       matchLabels:
         app: nginx
     template:
       metadata:
         labels:
           app: nginx
       spec:
         containers:
           - name: nginx
             image: public.ecr.aws/nginx/nginx:1.23
             ports:
               - name: tcp
                 containerPort: 80
   ```

1. 将部署应用于集群。

   ```
   kubectl apply -f tcp-sample-app.yaml
   ```

1. 在名为 `tcp-sample-service.yaml` 的文件中为部署定义 LoadBalancer 类型服务。
   + 您可以使用服务对象上的 `lbipam.cilium.io/ips` 注释，从负载均衡器 IP 池请求特定 IP 地址。如果您不想为服务请求特定 IP 地址，可以删除此注释。
   + `loadBalancerClass` 规范字段为必填字段，用于防止传统 AWS 云提供商为服务创建经典负载均衡器。在以下示例中，将此字段配置为 `io.cilium/bgp-control-plane`，以将 Cilium 的 BGP 控制面板用作负载均衡器类。也可将此字段配置为 `io.cilium/l2-announcer`，以使用 Cilium 的 [L2 通告功能](https://docs.cilium.io/en/latest/network/l2-announcements/)（目前处于测试阶段，尚未得到 AWS 正式支持）。

     ```
     apiVersion: v1
     kind: Service
     metadata:
       name: tcp-sample-service
       namespace: default
       annotations:
         lbipam.cilium.io/ips: "LB_IP_ADDRESS"
     spec:
       loadBalancerClass: io.cilium/bgp-control-plane
       ports:
         - port: 80
           targetPort: 80
           protocol: TCP
       type: LoadBalancer
       selector:
         app: nginx
     ```

1. 将服务应用于集群。服务将使用外部 IP 地址创建，您可以使用该地址访问应用程序。

   ```
   kubectl apply -f tcp-sample-service.yaml
   ```

1. 确认服务是否已成功创建，是否为其分配了来自上一步创建的 `CiliumLoadBalancerIPPool` 的 IP。

   ```
   kubectl get svc tcp-sample-service
   ```

   ```
   NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
   tcp-sample-service   LoadBalancer   172.16.117.76   LB_IP_ADDRESS   80:31129/TCP   14m
   ```

1. 如果您在 kube-proxy 替换模式下使用 Cilium，则可通过运行以下命令来确认 Cilium 是否正在处理服务的负载均衡。在以下输出中，`10.86.2.x` 地址是服务后端容器组（pod）的容器组（pod）IP 地址。

   ```
   kubectl -n kube-system exec ds/cilium -- cilium-dbg service list
   ```

   ```
   ID   Frontend               Service Type   Backend
   ...
   41   LB_IP_ADDRESS:80/TCP   LoadBalancer   1 => 10.86.2.76:80/TCP (active)
                                              2 => 10.86.2.130:80/TCP (active)
                                              3 => 10.86.2.141:80/TCP (active)
   ```

1. 确认 Cilium 正在通过 BGP 向本地网络通告 IP 地址。在以下示例中，有五个混合节点，每个节点都将向本地网络通告 `tcp-sample-service` 服务的 `LB_IP_ADDRESS`。

   ```
   Node                   VRouter      Prefix             NextHop   Age     Attrs
   mi-026d6a261e355fba7   NODES_ASN
                     LB_IP_ADDRESS/32   0.0.0.0   12m3s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-082f73826a163626e   NODES_ASN
                     LB_IP_ADDRESS/32   0.0.0.0   12m3s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-09183e8a3d755abf6   NODES_ASN
                     LB_IP_ADDRESS/32   0.0.0.0   12m3s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-0d78d815980ed202d   NODES_ASN
                     LB_IP_ADDRESS/32   0.0.0.0   12m3s   [{Origin: i} {Nexthop: 0.0.0.0}]
   mi-0daa253999fe92daa   NODES_ASN
                     LB_IP_ADDRESS/32   0.0.0.0   12m3s   [{Origin: i} {Nexthop: 0.0.0.0}]
   ```

1. 使用分配的负载均衡器 IP 地址访问服务。

   ```
   curl LB_IP_ADDRESS
   ```

   输出示例如下。

   ```
   <!DOCTYPE html>
   <html>
   <head>
   <title>Welcome to nginx!</title>
   [...]
   ```

1. 清理您创建的 资源。

   ```
   kubectl delete -f tcp-sample-service.yaml
   kubectl delete -f tcp-sample-app.yaml
   kubectl delete -f cilium-lb-ip-pool.yaml
   kubectl delete -f cilium-bgp-advertisement.yaml
   ```

# 为混合节点配置 Kubernetes 网络策略
<a name="hybrid-nodes-network-policies"></a>

 如果将 Cilium 用作 EKS 混合节点的 CNI，则 AWS 支持通过 Kubernetes 网络策略（第 3 层/第 4 层）来控制容器组（pod）的入口和出口流量。如果运行的 EKS 集群包含 AWS 云中的节点，则 AWS 支持[使用 Amazon VPC CNI 来实现 Kubernetes 网络策略](cni-network-policy.md)。

本主题介绍如何通过 EKS 混合节点配置 Cilium 和 Kubernetes 网络策略。有关 Kubernetes 网络策略的详细信息，请参阅 Kubernetes 文档中的 [Kubernetes Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/)。

## 配置网络策略
<a name="hybrid-nodes-configure-network-policies"></a>

### 注意事项
<a name="_considerations"></a>
+  AWS 支持通过上游 Kubernetes 网络策略及其规范，控制容器组（pod）的入口和出口流量，但 AWS 目前不支持 `CiliumNetworkPolicy` 或 `CiliumClusterwideNetworkPolicy`。
+ `policyEnforcementMode` Helm 可用于控制 Cilium 的默认策略执行行为。默认行为允许所有出口和入口流量。如果一个端点被某个网络策略选中，则会转换为默认拒绝状态，仅允许明确允许的流量。有关[默认策略模式](https://docs.cilium.io/en/stable/security/policy/intro/#policy-mode-default)和[策略执行模式](https://docs.cilium.io/en/stable/security/policy/intro/#policy-enforcement-modes)的更多信息，请参阅 Cilium 文档。
+ 如果要为现有的 Cilium 安装更改 `policyEnforcementMode`，则必须重启 Cilium 代理 DaemonSet，这样才能应用新的策略执行模式。
+ 使用 `namespaceSelector` 和 `podSelector` 以允许或拒绝进出带有匹配标签的命名空间和容器组（pod）的流量。`namespaceSelector` 和 `podSelector` 可与 `matchLabels` 或 `matchExpressions` 结合使用，以根据标签选择命名空间和容器组（pod）。
+ 使用 `ingress.ports` 和 `egress.ports` 以允许或拒绝进出端口和协议的流量。
+ `ipBlock` 字段不能用于选择性地允许或拒绝进出容器组（pod）IP 地址的流量（[\$19209](https://github.com/cilium/cilium/issues/9209)）。对节点 IP 使用 `ipBlock` 选择器是 Cilium 中的一项测试功能，不受 AWS 支持。
+ 有关 Kubernetes 网络策略可用字段的信息，请参阅 Kubernetes 文档中的 [NetworkPolicy resource](https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource)。

### 先决条件
<a name="_prerequisites"></a>
+ 按照[为混合节点配置 CNI](hybrid-nodes-cni.md)中的说明安装 Cilium。
+ 在命令行环境中安装 Helm，请参阅[安装 Helm 说明](helm.md)。

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

以下过程为示例微服务应用程序设置了网络策略，使得各个组件只能与应用程序正常运行所需的其他组件通信。该过程使用 [Istio Bookinfo](https://istio.io/latest/docs/examples/bookinfo/) 示例微服务应用程序。

Bookinfo 应用程序由四项独立的微服务组成，它们具有以下关系：
+  **productpage**。productpage 微服务会调用 details 和 reviews 微服务来填充页面。
+  **details**。details 微服务包含包含书籍信息。
+  **reviews**。reviews 微服务包含书评，还会调用 ratings 微服务。
+  **ratings**。ratings 微服务包含随书评附带的书籍排名信息。

  1. 创建示例应用程序。

     ```
     kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml
     ```

  1. 确认应用程序成功运行，并记下 productpage 微服务的容器组（pod）IP 地址。您将在后续步骤中使用此容器组（pod）IP 地址查询每项微服务。

     ```
     kubectl get pods -o wide
     ```

     ```
     NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE
     details-v1-766844796b-9wff2       1/1     Running   0          7s    10.86.3.7     mi-0daa253999fe92daa
     productpage-v1-54bb874995-lwfgg   1/1     Running   0          7s    10.86.2.193   mi-082f73826a163626e
     ratings-v1-5dc79b6bcd-59njm       1/1     Running   0          7s    10.86.2.232   mi-082f73826a163626e
     reviews-v1-598b896c9d-p2289       1/1     Running   0          7s    10.86.2.47    mi-026d6a261e355fba7
     reviews-v2-556d6457d-djktc        1/1     Running   0          7s    10.86.3.58    mi-0daa253999fe92daa
     reviews-v3-564544b4d6-g8hh4       1/1     Running   0          7s    10.86.2.69    mi-09183e8a3d755abf6
     ```

  1. 创建一个容器组（pod），用于全程测试网络策略。请注意，该容器组（pod）是在 `default` 命名空间中创建，带有 `access: true` 标签。

     ```
     kubectl run curl-pod --image=curlimages/curl -i --tty --labels=access=true --namespace=default --overrides='{"spec": { "nodeSelector": {"eks.amazonaws.com/compute-type": "hybrid"}}}' -- /bin/sh
     ```

  1. 测试对 productpage 微服务的访问权限。在以下示例中，我们使用 productpage 容器组（pod）的容器组（pod）IP 地址 (`10.86.2.193`) 查询该微服务。请将其替换为环境中 productpage 容器组（pod）的容器组（pod）IP 地址。

     ```
     curl -s http://10.86.2.193:9080/productpage | grep -o "<title>.*</title>"
     ```

     ```
     <title>Simple Bookstore App</title>
     ```

  1. 您可以通过输入 `exit` 来退出测试 curl 容器组（pod），也可以通过运行以下命令重新附加到该容器组（pod）。

     ```
     kubectl attach curl-pod -c curl-pod -i -t
     ```

  1. 为演示后续步骤中网络策略的效果，我们首先创建了一个拒绝所有流向 BookInfo 微服务之流量的网络策略。创建一个名为 `network-policy-deny-bookinfo.yaml` 的文件，用于定义拒绝网络策略。

     ```
     apiVersion: networking.k8s.io/v1
     kind: NetworkPolicy
     metadata:
       name: deny-bookinfo
       namespace: default
     spec:
       podSelector:
         matchExpressions:
         - key: app
           operator: In
           values: ["productpage", "details", "reviews", "ratings"]
       policyTypes:
       - Ingress
       - Egress
     ```

  1. 将拒绝网络策略应用于集群。

     ```
     kubectl apply -f network-policy-default-deny-bookinfo.yaml
     ```

  1. 测试对 BookInfo 应用程序的访问权限。在以下示例中，我们使用 productpage 容器组（pod）的容器组（pod）IP 地址 (`10.86.2.193`) 查询该微服务。请将其替换为环境中 productpage 容器组（pod）的容器组（pod）IP 地址。

     ```
     curl http://10.86.2.193:9080/productpage --max-time 10
     ```

     ```
     curl: (28) Connection timed out after 10001 milliseconds
     ```

  1. 创建一个名为 `network-policy-productpage.yaml` 的文件，用于定义 productpage 网络策略。该策略具有以下规则：
     + 允许来自带有 `access: true` 标签的容器组（pod）[即上一步中创建的 curl 容器组（pod）] 的入口流量
     + 允许端口 `9080` 上的出口 TCP 流量流向 details、reviews 和 ratings 微服务
     + 允许端口 `53` 上的出口 TCP/UDP 流量流向在 `kube-system` 命名空间中运行的 CoreDNS

       ```
       apiVersion: networking.k8s.io/v1
       kind: NetworkPolicy
       metadata:
         name: productpage-policy
         namespace: default
       spec:
         podSelector:
           matchLabels:
             app: productpage
         policyTypes:
         - Ingress
         - Egress
         ingress:
         - from:
           - podSelector:
               matchLabels:
                 access: "true"
         egress:
         - to:
           - podSelector:
               matchExpressions:
               - key: app
                 operator: In
                 values: ["details", "reviews", "ratings"]
           ports:
           - port: 9080
             protocol: TCP
         - to:
           - namespaceSelector:
               matchLabels:
                 kubernetes.io/metadata.name: kube-system
             podSelector:
               matchLabels:
                 k8s-app: kube-dns
           ports:
           - port: 53
             protocol: UDP
           - port: 53
             protocol: TCP
       ```

  1. 将 productpage 网络策略应用于集群。

     ```
     kubectl apply -f network-policy-productpage.yaml
     ```

  1. 连接到 curl 容器组（pod）并测试对 Bookinfo 应用程序的访问权限。现在允许访问 productpage 微服务，但其他微服务仍被拒绝，因为它们仍然受到拒绝网络策略的约束。在以下示例中，我们使用 productpage 容器组（pod）的容器组（pod）IP 地址 (`10.86.2.193`) 查询该微服务。请将其替换为环境中 productpage 容器组（pod）的容器组（pod）IP 地址。

     ```
     kubectl attach curl-pod -c curl-pod -i -t
     ```

     ```
     curl -s http://10.86.2.193:9080/productpage | grep -o "<title>.*</title>"
     <title>Simple Bookstore App</title>
     ```

     ```
     curl -s http://10.86.2.193:9080/api/v1/products/1
     {"error": "Sorry, product details are currently unavailable for this book."}
     ```

     ```
     curl -s http://10.86.2.193:9080/api/v1/products/1/reviews
     {"error": "Sorry, product reviews are currently unavailable for this book."}
     ```

     ```
     curl -s http://10.86.2.193:9080/api/v1/products/1/ratings
     {"error": "Sorry, product ratings are currently unavailable for this book."}
     ```

  1. 创建一个名为 `network-policy-details.yaml` 的文件，用于定义 details 网络策略。该策略仅允许来自 productpage 微服务的入口流量。

     ```
     apiVersion: networking.k8s.io/v1
     kind: NetworkPolicy
     metadata:
       name: details-policy
       namespace: default
     spec:
       podSelector:
         matchLabels:
           app: details
       policyTypes:
       - Ingress
       ingress:
       - from:
         - podSelector:
             matchLabels:
               app: productpage
     ```

  1. 创建一个名为 `network-policy-reviews.yaml` 的文件，用于定义 reviews 网络策略。该策略仅允许来自 productpage 微服务的入口流量，并且仅允许流向 ratings 微服务和 CoreDNS 的出口流量。

     ```
     apiVersion: networking.k8s.io/v1
     kind: NetworkPolicy
     metadata:
       name: reviews-policy
       namespace: default
     spec:
       podSelector:
         matchLabels:
           app: reviews
       policyTypes:
       - Ingress
       - Egress
       ingress:
       - from:
         - podSelector:
             matchLabels:
               app: productpage
       egress:
       - to:
         - podSelector:
             matchLabels:
               app: ratings
       - to:
         - namespaceSelector:
             matchLabels:
               kubernetes.io/metadata.name: kube-system
           podSelector:
             matchLabels:
               k8s-app: kube-dns
         ports:
         - port: 53
           protocol: UDP
         - port: 53
           protocol: TCP
     ```

  1. 创建一个名为 `network-policy-ratings.yaml` 的文件，用于定义 ratings 网络策略。该策略仅允许来自 productpage 和 reviews 微服务的入口流量。

     ```
     apiVersion: networking.k8s.io/v1
     kind: NetworkPolicy
     metadata:
       name: ratings-policy
       namespace: default
     spec:
       podSelector:
         matchLabels:
           app: ratings
       policyTypes:
       - Ingress
       ingress:
       - from:
         - podSelector:
             matchExpressions:
             - key: app
               operator: In
               values: ["productpage", "reviews"]
     ```

  1. 将 details、reviews 和 ratings 网络策略应用于集群。

     ```
     kubectl apply -f network-policy-details.yaml
     kubectl apply -f network-policy-reviews.yaml
     kubectl apply -f network-policy-ratings.yaml
     ```

  1. 连接到 curl 容器组（pod）并测试对 Bookinfo 应用程序的访问权限。在以下示例中，我们使用 productpage 容器组（pod）的容器组（pod）IP 地址 (`10.86.2.193`) 查询该微服务。请将其替换为环境中 productpage 容器组（pod）的容器组（pod）IP 地址。

     ```
     kubectl attach curl-pod -c curl-pod -i -t
     ```

     测试 details 微服务。

     ```
     curl -s http://10.86.2.193:9080/api/v1/products/1
     ```

     ```
     {"id": 1, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890"}
     ```

     测试 reviews 微服务。

     ```
     curl -s http://10.86.2.193:9080/api/v1/products/1/reviews
     ```

     ```
     {"id": "1", "podname": "reviews-v1-598b896c9d-p2289", "clustername": "null", "reviews": [{"reviewer": "Reviewer1", "text": "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!"}, {"reviewer": "Reviewer2", "text": "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare."}]}
     ```

     测试 ratings 微服务。

     ```
     curl -s http://10.86.2.193:9080/api/v1/products/1/ratings
     ```

     ```
     {"id": 1, "ratings": {"Reviewer1": 5, "Reviewer2": 4}}
     ```

  1. 清理您在此过程中创建的资源。

     ```
     kubectl delete -f network-policy-deny-bookinfo.yaml
     kubectl delete -f network-policy-productpage.yaml
     kubectl delete -f network-policy-details.yaml
     kubectl delete -f network-policy-reviews.yaml
     kubectl delete -f network-policy-ratings.yaml
     kubectl delete -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml
     kubectl delete pod curl-pod
     ```

# 混合节点的概念
<a name="hybrid-nodes-concepts"></a>

借助 *Amazon EKS 混合节点功能*，您可以将在本地或边缘环境中运行的物理计算机或虚拟机加入到在 AWS Cloud 中运行的 Amazon EKS 集群。这种方法提供了诸多优势，同时也为熟悉在单一网络环境中运行 Kubernetes 集群的用户引入了新的网络概念和架构。

以下各节将深入探讨 Kubernetes 和 EKS 混合节点的网络概念，并详细介绍流量如何流经混合架构。这些章节要求您熟悉基本的 Kubernetes 网络知识，例如容器组（pod）、节点、服务、Kubernetes 控制面板、kubelet 以及 kube-proxy 的概念。

建议按顺序阅读这些页面，从 [混合节点的联网概念](hybrid-nodes-concepts-networking.md) 开始，然后是 [混合节点的 Kubernetes 概念](hybrid-nodes-concepts-kubernetes.md)，最后是 [混合节点的网络流量](hybrid-nodes-concepts-traffic-flows.md)。

**Topics**
+ [混合节点的联网概念](hybrid-nodes-concepts-networking.md)
+ [混合节点的 Kubernetes 概念](hybrid-nodes-concepts-kubernetes.md)
+ [混合节点的网络流量](hybrid-nodes-concepts-traffic-flows.md)

# 混合节点的联网概念
<a name="hybrid-nodes-concepts-networking"></a>

本节详细介绍了核心联网概念以及在为 EKS 混合节点设计网络拓扑时必须考虑的限制。

## EKS 混合节点的联网概念
<a name="_networking_concepts_for_eks_hybrid_nodes"></a>

![\[高级混合节点网络图\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-highlevel-network.png)


 **作为网络中心的 VPC** 

所有穿过云边界的流量都会通过您的 VPC 进行路由。这包括从 EKS 控制面板或 AWS 中运行的容器组（pod）流向混合节点或这些节点上运行的容器组（pod）的流量。您可以将集群的 VPC 视为混合节点和集群其余部分之间的网络中心。此架构让您可以完全控制流量及其路由，但您因此也有责任为 VPC 正确配置路由、安全组和防火墙。

 **EKS 控制面板到 VPC** 

EKS 控制面板将**弹性网络接口（ENI）**附加到您的 VPC 中。这些 ENI 处理流入和流出 EKS API 服务器的流量。在配置集群时，您可以控制 EKS 控制面板 ENI 的位置，因为 EKS 会将 ENI 附加到您在集群创建期间传递的子网。

EKS 将安全组与 EKS 附加到子网的 ENI 相关联。这些安全组允许通过 ENI 流入和流出 EKS 控制面板的流量。这对 EKS 混合节点很重要，因为您必须允许混合节点及其上运行的容器组（pod）的流量流向 EKS 控制面板 ENI。

 **远程节点网络** 

远程节点网络，特别是远程节点 CIDR，是分配给作为混合节点使用的计算机的 IP 范围。您预置混合节点时，它们位于您的本地数据中心或边缘站点，这与 EKS 控制面板和 VPC 属于不同的网络域。每个混合节点都有一个或多个来自远程节点 CIDR 的 IP 地址，该地址与 VPC 中的子网不同。

您可以使用这些远程节点 CIDR 配置 EKS 集群，这样 EKS 就会通过集群 VPC 路由所有发往混合节点 IP 的流量，例如对 kubelet API 的请求。与 `kubelet` API 的连接用于 `kubectl attach`、`kubectl cp`、`kubectl exec`、`kubectl logs` 和 `kubectl port-forward` 命令中。

 **远程容器组（pod）网络** 

远程容器组（pod）网络是分配给在混合节点上运行的容器组（pod）的 IP 范围。通常，您可以使用这些范围来配置 CNI，而 CNI 的 IP 地址管理（IPAM）功能负责将这些范围的切片分配给每个混合节点。您创建容器组（pod）时，CNI 会从分配给节点 [容器组（pod）在其中计划] 的切片中为该容器组分配 IP。

您可以使用这些远程容器组（pod）CIDR 配置 EKS 集群，这样 EKS 控制面板就会通过集群的 VPC 来路由所有发往混合节点上运行的容器组（pod）的流量，例如与 Webhook 的通信。

![\[远程容器组（pod）网络\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-remote-pod-cidrs.png)


 **本地到 VPC** 

用于混合节点的本地网络必须路由到用于 EKS 集群的 VPC。有多种[网络到 Amazon VPC 的连接选项](https://docs.aws.amazon.com/whitepapers/latest/aws-vpc-connectivity-options/network-to-amazon-vpc-connectivity-options.html)可用来将本地网络连接到 VPC。您还可以使用自己的 VPN 解决方案。

务必在 VPC 和本地网络中的 AWS 云端正确配置路由，这样两个网络便会通过各自的连接路由正确的流量。

在 VPC 中，所有流向远程节点和远程容器组（pod）网络的流量都必须通过连接路由到本地网络（称为“网关”）。如果您的某些子网具有不同的路由表，则必须使用混合节点的路由和在这些节点上运行的容器组（pod）来配置每个路由表。这适用于 ENI 附加到 EKS 控制面板的子网，以及包含必须与混合节点通信的 EC2 节点或容器组（pod）的子网。

在您的本地网络中，您必须将网络配置为允许流入和流出 EKS 集群 VPC 以及混合节点所需的其他 AWS 服务的流量。EKS 集群的流量会双向穿过网关。

## 网络限制
<a name="_networking_constraints"></a>

 **完全路由的网络** 

主要限制在于 EKS 控制面板和所有节点，无论是云节点还是混合节点，都需要形成一个**完全路由的**网络。这意味着所有节点都必须能够通过 IP 地址在第三层相互访问。

EKS 控制面板和云节点已经可以相互访问，因为它们位于扁平化网络（VPC）中。但是，混合节点位于不同的网络域中。因此，您需要在 VPC 和本地网络中配置其他路由，以便在混合节点和集群的其余部分之间路由流量。如果混合节点可以相互访问并可从 VPC 访问，则您的混合节点可以位于一个扁平化网络中，也可以位于多个分段网络中。

 **可路由的远程容器组（pod）CIDR** 

为了让 EKS 控制面板与在混合节点（例如 Webhook 或 Metrics Server）上运行的容器组（pod）通信，或者让在云节点上运行的容器组（pod）与在混合节点上运行的容器组（pod）通信（工作负载东西向通信），远程容器组（pod）CIDR 必须可以从 VPC 路由。这意味着 VPC 必须能够通过网关将流量路由到容器组（pod）CIDR 再到本地网络，并且本地网络必须能够将容器组（pod）的流量路由到正确的节点。

请务必注意 VPC 和本地容器组（pod）路由要求之间的区别。VPC 只需要知道任何流向远程容器组（pod）的流量都应通过网关即可。如果您只有一个远程容器组（pod）CIDR，则只需要一条路由。

此要求适用于本地网络中的所有跃点，包括与混合节点位于同一子网中的本地路由器。这是唯一需要知道分配给每个节点的 pod CIDR 切片的路由器，这能确保特定容器组（pod）的流量传送到计划了容器组（pod）的节点。

您可以选择将本地容器组（pod）CIDR 的这些路由从本地路由器传播到 VPC 路由表，但这不是必需的。如果您的本地容器组（pod）CIDR 频繁更改，并且需要更新 VPC 路由表以反映不断变化的容器组（pod）CIDR，我们建议您将本地容器组（pod）CIDR 传播到 VPC 路由表，但这种情况并不常见。

注意，本地容器组（pod）CIDR 可路由的限制条件是可选的。如果您不需要在混合节点上运行 Webhook，也不需要让云节点上的容器组（pod）与混合节点上的容器组（pod）通信，则无需在本地网络上为容器组（pod）CIDR 配置路由。

 *为何本地容器组（pod）CIDR 需要可通过混合节点进行路由？* 

在云节点上使用 EKS 和 VPC CNI 时，VPC CNI 会直接从 VPC 向容器组（pod）分配 IP。这意味着无需任何特殊路由，因为云容器组（pod）和 EKS 控制面板都可以直接访问 Pod IP。

在本地运行（以及使用云中的其他 CNI 运行）时，容器组（pod）通常在隔离的覆盖网络中运行，CNI 负责在容器组之间传送流量。这通常通过封装来完成：CNI 将容器组（pod）到容器组（pod）的流量转换为节点到节点的流量，同时负责两端的封装和解封工作。这样一来，就无需在节点和路由器上进行额外配置。

与混合节点的联网是独一无二的，因为它结合了两种拓扑：EKS 控制面板和云节点（使用 VPC CNI）需要一个包含节点和容器组（pod）的扁平化网络，而在混合节点上运行的容器组（pod）则使用 VXLAN 进行封装（默认情况下在 Cilium 中），以处于叠加网络中。假设本地网络可以路由到 VPC，则在混合节点上运行的容器组（pod）可以访问 EKS 控制面板以及在云节点上运行的容器组（pod）。但是，如果本地网络上的容器组（pod）CIDR 没有路由，若网络不知道如何访问叠加网络并路由到正确的节点，则返回本地容器组（pod）IP 的任何流量最终都将被丢弃。

# 混合节点的 Kubernetes 概念
<a name="hybrid-nodes-concepts-kubernetes"></a>

本页面详细介绍了支持 EKS 混合节点系统架构的关键 Kubernetes 概念。

## VPC 中的 EKS 控制面板
<a name="hybrid-nodes-concepts-k8s-api"></a>

EKS 控制面板 ENI 的 IP 存储在 `default` 命名空间的 `kubernetes` `Endpoints` 对象中。EKS 创建新的 ENI 或移除较旧的 ENI 时，EKS 会更新此对象，因此 IP 列表始终是最新的。

您可以通过 `kubernetes` 服务使用这些端点，也可以在 `default` 命名空间中使用。`ClusterIP` 类型的这种服务总是会获分配集群服务 CIDR 的第一个 IP。例如，对于服务 CIDR `172.16.0.0/16`，服务 IP 将为 `172.16.0.1`。

通常，这就是容器组（pod）（无论是在云端还是混合节点中运行）访问 EKS Kubernetes API 服务器的方式。容器组（pod）使用服务 IP 作为目标 IP，然后将其转换为其中一个 EKS 控制面板 ENI 的实际 IP。主要例外是 `kube-proxy`，因为它设置了转换。

## EKS API 服务器端点
<a name="hybrid-nodes-concepts-k8s-eks-api"></a>

`kubernetes` 服务 IP 并不是访问 EKS API 服务器的唯一途径。您创建集群时，EKS 还会创建一个 Route53 DNS 名称。这是调用 EKS `DescribeCluster` API 操作时您的 EKS 集群的 `endpoint` 字段。

```
{
    "cluster": {
        "endpoint": "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.gr7.us-west-2.eks.amazonaws.com",
        "name": "my-cluster",
        "status": "ACTIVE"
    }
}
```

在公有端点访问或公有和私有端点访问集群中，您的混合节点默认会将此 DNS 名称解析为可通过互联网路由的公有 IP。在私有端点访问集群中，DNS 名称解析为 EKS 控制面板 ENI 的私有 IP。

这就是 `kubelet` 和 `kube-proxy` 访问 Kubernetes API 服务器的方式。如果您希望所有 Kubernetes 集群流量都通过 VPC，则需要在私有访问模式下配置集群，或者修改本地 DNS 服务器，将 EKS 集群端点解析为 EKS 控制面板 ENI 的私有 IP。

## `kubelet` 端点
<a name="hybrid-nodes-concepts-k8s-kubelet-api"></a>

`kubelet` 公开了多个 REST 端点，允许系统的其他部分与每个节点交互并从每个节点收集信息。在大多数集群中，流向 `kubelet` 服务器的大部分流量来自控制面板，但某些监控代理也可能与该服务器交互。

通过此接口，`kubelet` 可以处理各种请求：获取日志 (`kubectl logs`)、在容器内执行命令 (`kubectl exec`) 以及端口转发流量 (`kubectl port-forward`)。这些请求中的每一个都通过 `kubelet` 与底层容器运行时进行交互，在集群管理员和开发人员看来，这是一个无缝的过程。

此 API 最常见的使用器是 Kubernetes API 服务器。您使用前面提到的任何 `kubectl` 命令时，`kubectl` 会向 API 服务器发出 API 请求，然后服务器调用运行容器组（pod）的节点的 `kubelet` API。这就是需要从 EKS 控制面板访问节点 IP 的主要原因，也解释了为什么即使您的容器组（pod）正在运行，但如果节点路由配置错误，您也无法访问它们的日志或 `exec`。

 **节点 IP** 

EKS 控制面板与节点通信时，它会使用 `Node` 对象状态 (`status.addresses`) 中报告的地址之一。

对于 EKS 云节点，kubelet 通常会在节点注册期间将 EC2 实例的私有 IP 报告为 `InternalIP`。然后，云控制器管理器（CCM）会验证此 IP，确保它属于 EC2 实例。此外，CCM 通常会将实例的公有 IP（作为 `ExternalIP`）和 DNS 名称（`InternalDNS` 和 `ExternalDNS`）添加到节点状态。

但是，没有适用于混合节点的 CCM。您向 EKS 混合节点 CLI (`nodeadm`) 注册混合节点时，它会将 kubelet 配置为直接以节点状态报告计算机的 IP，而不使用 CCM。

```
apiVersion: v1
kind: Node
metadata:
  name: my-node-1
spec:
  providerID: eks-hybrid:///us-west-2/my-cluster/my-node-1
status:
  addresses:
  - address: 10.1.1.236
    type: InternalIP
  - address: my-node-1
    type: Hostname
```

如果您的计算机有多个 IP，kubelet 会按照自己的逻辑选择其中一个 IP。您可以使用 `--node-ip` 标志控制选定的 IP，并且可以在 `spec.kubelet.flags` 的 `nodeadm` 配置中传入该标志。只有 `Node` 对象中报告的 IP 需要来自 VPC 的路由。您的计算机可能有无法从云端访问的其他 IP。

## `kube-proxy`
<a name="hybrid-nodes-concepts-k8s-kube-proxy"></a>

 `kube-proxy` 负责在每个节点的网络层实现服务抽象。它充当流向 Kubernetes 服务的流量的网络代理和负载均衡器。通过持续监控 Kubernetes API 服务器中与服务和端点相关的更改，`kube-proxy` 会动态更新底层主机的网络规则，确保流量得到正确引导。

在 `iptables` 模式下，`kube-proxy` 会对多个 `netfilter` 链进行编程以处理服务流量。这些规则构成以下层次结构：

1.  **KUBE-SERVICES 链**：所有服务流量的入口点。它具有与每项 `ClusterIP` 服务和端口匹配的规则。

1.  **KUBE-SVC-XXX 链**：特定于服务的链对每项服务都有负载均衡规则。

1.  **KUBE-SEP-XXX 链**：特定于端点的链具有实际的 `DNAT` 规则。

让我们来看看 `default` 命名空间中的 `test-server` 服务会发生什么：\$1 服务 ClusterIP：`172.16.31.14` \$1 服务端口：`80` \$1 支持性容器组（pod）：`10.2.0.110`、`10.2.1.39` 和 `10.2.2.254` 

检查 `iptables` 规则（使用 `iptables-save 0 grep -A10 KUBE-SERVICES`）时：

1. 在 **KUBE-SERVICES** 链中，我们找到了一条与该服务匹配的规则：

   ```
   -A KUBE-SERVICES -d 172.16.31.14/32 -p tcp -m comment --comment "default/test-server cluster IP" -m tcp --dport 80 -j KUBE-SVC-XYZABC123456
   ```
   + 此规则与发往 172.16.31.14:80 的数据包匹配
   + 注释指出了此规则的用途：`default/test-server cluster IP`
   + 匹配的数据包跳转到 `KUBE-SVC-XYZABC123456` 链

1. **KUBE-SVC-XYZABC123456** 链具有基于概率的负载均衡规则：

   ```
   -A KUBE-SVC-XYZABC123456 -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-POD1XYZABC
   -A KUBE-SVC-XYZABC123456 -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-POD2XYZABC
   -A KUBE-SVC-XYZABC123456 -j KUBE-SEP-POD3XYZABC
   ```
   + 第一条规则：有 33.3% 的概率跳转到 `KUBE-SEP-POD1XYZABC` 
   + 第二条规则：剩余流量（占总流量的 33.3%）有 50% 的概率跳转到 `KUBE-SEP-POD2XYZABC` 
   + 最后一条规则：所有剩余流量（占总流量的 33.3%）都将跳转到 `KUBE-SEP-POD3XYZABC` 

1. 各个 **KUBE-SEP-XXX** 链都执行 DNAT（目标 NAT）：

   ```
   -A KUBE-SEP-POD1XYZABC -p tcp -m tcp -j DNAT --to-destination 10.2.0.110:80
   -A KUBE-SEP-POD2XYZABC -p tcp -m tcp -j DNAT --to-destination 10.2.1.39:80
   -A KUBE-SEP-POD3XYZABC -p tcp -m tcp -j DNAT --to-destination 10.2.2.254:80
   ```
   + 这些 DNAT 规则会重写目标 IP 和端口，将流量引导至特定容器组（pod）。
   + 每条规则处理大约 33.3% 的流量，从而在 `10.2.0.110`、`10.2.1.39` 和 `10.2.2.254` 之间提供均衡的负载均衡。

这种多级链结构让 `kube-proxy` 能够通过内核级别的数据包操作高效地实现服务负载均衡和重定向，而无需在数据路径中使用代理进程。

### 对 Kubernetes 操作的影响
<a name="hybrid-nodes-concepts-k8s-operations"></a>

节点上损坏的 `kube-proxy` 会阻止该节点正确路由服务流量，导致依赖集群服务的容器组（pod）超时或连接失败。首次注册节点时，这可能会造成特别大的干扰。CNI 需要先与 Kubernetes API 服务器通信以获取信息，例如节点的容器组（pod）CIDR，然后才能配置任何容器组（pod）网络。为此，它使用 `kubernetes` 服务 IP。但是，如果 `kube-proxy` 无法启动或未能设置正确的 `iptables` 规则，则发往 `kubernetes` 服务 IP 的请求不会转换为 EKS 控制面板 ENI 的实际 IP。因此，CNI 将进入崩溃循环，所有的容器组（pod）都无法正常运行。

我们知道容器组（pod）使用 `kubernetes` 服务 IP 与 Kubernetes API 服务器通信，但 `kube-proxy` 需要先设置 `iptables` 规则才能使其正常工作。

`kube-proxy` 如何与 API 服务器通信？

`kube-proxy` 必须配置为使用 Kubernetes API 服务器的实际 IP 或解析为它们的 DNS 名称。对于 EKS，EKS 将默认 `kube-proxy` 配置为指向您在创建集群时 EKS 创建的 Route53 DNS 名称。您可以在 `kube-system` 命名空间的 `kube-proxy` ConfigMap 中看到此值。此 ConfigMap 的内容是注入到 `kube-proxy` 容器组（pod）中的 `kubeconfig`，因此请寻找 `clusters0.cluster.server` 字段。此值将与 EKS 集群的 `endpoint` 字段匹配（在调用 EKS `DescribeCluster` API 时）。

```
apiVersion: v1
data:
  kubeconfig: |-
    kind: Config
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        server: https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.gr7.us-west-2.eks.amazonaws.com
      name: default
    contexts:
    - context:
        cluster: default
        namespace: default
        user: default
      name: default
    current-context: default
    users:
    - name: default
      user:
        tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
```

## 可路由的远程容器组（pod）CIDR
<a name="hybrid-nodes-concepts-k8s-pod-cidrs"></a>

[混合节点的联网概念](hybrid-nodes-concepts-networking.md) 页面详细说明了在混合节点上运行 Webhook 或让在云节点上运行的容器组（pod）与在混合节点上运行的容器组（pod）通信的要求。关键要求是，本地路由器需要知道哪个节点负责特定容器组（pod）IP。有多种方法可以实现这一点，包括边界网关协议（BGP）、静态路由和地址解析协议（ARP）代理。以下部分将介绍这些方法。

 **边界网关协议（BGP）** 

如果您的 CNI 支持这种协议（例如 Cilium 和 Calico），您可以使用 CNI 的 BGP 模式，将每节点容器组（pod）CIDR 的路由从节点传播到本地路由器。使用 CNI 的 BGP 模式时，您的 CNI 充当虚拟路由器，因此本地路由器认为容器组（pod）CIDR 属于不同的子网，而您的节点是该子网的网关。

![\[混合节点 BGP 路由\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-bgp.png)


 **静态路由** 

您也可以在本地路由器中配置静态路由。这是将本地容器组（pod）CIDR 路由到您的 VPC 的最简单方法，但这也是最容易出错且最难维护的方法。您需要确保现有节点及其分配的容器组（pod）CIDR 的路由始终是最新的。如果您的节点数量很少且基础设施是静态的，那么这是一个可行的选择，并且无需在路由器中支持 BGP。如果您选择这样做，建议使用要分配给每个节点的容器组（pod）CIDR 切片来配置 CNI，而不是让其 IPAM 决定。

![\[混合节点静态路由\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-static-routes.png)


 **地址解析协议（ARP）代理** 

ARP 代理是使本地容器组（pod）IP 可路由的另一种方法，当混合节点与本地路由器位于同一个第 2 层网络上时，这种方法特别有用。启用 ARP 代理后，节点会响应其托管的容器组（pod）IP 的 ARP 请求，即使这些 IP 属于不同的子网，也会如此。

本地网络上的设备尝试访问容器组（pod）IP 时，它会首先发送 ARP 请求，询问“谁拥有此 IP？”。托管该容器组（pod）的混合节点将使用自己的 MAC 地址进行响应，表示“我可以处理该 IP 的流量。” 这无需配置路由器，即可在本地网络上的设备和容器组（pod）之间创建直接路径。

要使此方法起作用，您的 CNI 必须支持代理 ARP 功能。Cilium 内置了对代理 ARP 的支持，您可以通过配置启用该功能。关键考虑因素是容器组（pod）CIDR 不得与环境中的任何其他网络重叠，因为这可能会导致路由冲突。

这种方法有几个优点：\$1 无需为路由器配置 BGP，也无需维护静态路由 \$1 在路由器配置不由您控制的环境中效果良好

![\[混合节点 ARP 代理\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-arp-proxy.png)


## 容器组（pod）到容器组（pod）封装
<a name="hybrid-nodes-concepts-k8s-pod-encapsulation"></a>

在本地环境中，CNI 通常使用封装协议来创建叠加网络，这种网络无需重新配置即可在物理网络之上运行。此部分介绍了这种封装的工作原理。请注意，根据您使用的 CNI，某些细节可能会有所不同。

封装将原始容器组（pod）网络数据包包装在另一个网络数据包中，该数据包可以通过底层物理网络路由。这允许容器组（pod）在运行相同 CNI 的节点之间进行通信，物理网络不必理解如何路由这些容器组（pod）CIDR。

Kubernetes 中最常用的封装协议是虚拟可扩展局域网（VXLAN），但也可使用其他封装协议（例如 `Geneve`），具体取决于您的 CNI。

### VXLAN 封装
<a name="_vxlan_encapsulation"></a>

VXLAN 将第 2 层以太网帧封装在 UDP 数据包中。当一个容器组（pod）向不同节点上的另一个容器组（pod）发送流量时，CNI 会执行以下操作：

1. CNI 拦截来自容器组（pod）A 的数据包

1. CNI 将原始数据包封装在 VXLAN 标头中

1. 然后，这个封装后的数据包通过节点的常规网络堆栈发送到目标节点

1. 目标节点上的 CNI 解开数据包并将其传送到容器组（pod）B

以下是 VXLAN 封装期间，数据包结构的情况：

容器组（pod）到容器组（pod）的原始数据包：

```
+-----------------+---------------+-------------+-----------------+
| Ethernet Header | IP Header     | TCP/UDP     | Payload         |
| Src: Pod A MAC  | Src: Pod A IP | Src Port    |                 |
| Dst: Pod B MAC  | Dst: Pod B IP | Dst Port    |                 |
+-----------------+---------------+-------------+-----------------+
```

VXLAN 封装后：

```
+-----------------+-------------+--------------+------------+---------------------------+
| Outer Ethernet  | Outer IP    | Outer UDP    | VXLAN      | Original Pod-to-Pod       |
| Src: Node A MAC | Src: Node A | Src: Random  | VNI: xx    | Packet (unchanged         |
| Dst: Node B MAC | Dst: Node B | Dst: 4789    |            | from above)               |
+-----------------+-------------+--------------+------------+---------------------------+
```

VXLAN 网络标识符（VNI）用于区分不同的叠加网络。

### 容器组（pod）通信场景
<a name="_pod_communication_scenarios"></a>

 **同一个混合节点上的容器组（pod）** 

同一个混合节点上的容器组（pod）通信时，通常不需要封装。CNI 设置本地路由，通过节点的内部虚拟接口引导容器组（pod）之间的流量：

```
Pod A -> veth0 -> node's bridge/routing table -> veth1 -> Pod B
```

数据包永远不会离开节点，也不需要封装。

 **不同混合节点上的容器组（pod）** 

不同混合节点上的容器组（pod）之间的通信需要封装：

```
Pod A -> CNI -> [VXLAN encapsulation] -> Node A network -> router or gateway -> Node B network -> [VXLAN decapsulation] -> CNI -> Pod B
```

这样，容器组（pod）流量就可以遍历物理网络基础架构，而物理网络不必理解容器组（pod）IP 路由。

# 混合节点的网络流量
<a name="hybrid-nodes-concepts-traffic-flows"></a>

本页面详细介绍了 EKS 混合节点的网络流量，其中的图表显示了不同流量类型的端到端网络路径。

涵盖以下流量：
+  [混合节点 `kubelet` 到 EKS 控制面板](#hybrid-nodes-concepts-traffic-flows-kubelet-to-cp) 
+  [EKS 控制面板到混合节点（`kubelet` 服务器）](#hybrid-nodes-concepts-traffic-flows-cp-to-kubelet) 
+  [混合节点上运行的容器组（pod）到 EKS 控制面板](#hybrid-nodes-concepts-traffic-flows-pods-to-cp) 
+  [EKS 控制面板到混合节点上运行的容器组（pod）（Webhook）](#hybrid-nodes-concepts-traffic-flows-cp-to-pod) 
+  [在混合节点上运行的容器组（pod）到容器组（pod）](#hybrid-nodes-concepts-traffic-flows-pod-to-pod) 
+  [云节点上的容器组（pod）到混合节点上的容器组（pod）（东西向流量）](#hybrid-nodes-concepts-traffic-flows-east-west) 

## 混合节点 `kubelet` 到 EKS 控制面板
<a name="hybrid-nodes-concepts-traffic-flows-kubelet-to-cp"></a>

![\[混合节点 kubelet 到 EKS 控制面板\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-kubelet-to-cp-public.png)


### 请求
<a name="_request"></a>

 **1`kubelet`. 发起请求** 

混合节点上的 `kubelet` 需要与 EKS 控制面板通信 [例如，报告节点状态或获取容器组（pod）规格] 时，它将使用节点注册期间提供的 `kubeconfig` 文件。此 `kubeconfig` 具有 API 服务器端点 URL（Route53 DNS 名称），而非直接 IP 地址。

`kubelet` 对端点执行 DNS 查找（例如 `https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.gr7.us-west-2.eks.amazonaws.com`）。在公有访问集群中，这会解析为属于 AWS 中运行的 EKS 服务的某个公有 IP 地址（如 `54.239.118.52`）。然后，`kubelet` 创建针对此端点的安全 HTTPS 请求。初始数据包类似于以下示例：

```
+--------------------+---------------------+-----------------+
| IP Header          | TCP Header          | Payload         |
| Src: 10.80.0.2     | Src: 52390 (random) |                 |
| Dst: 54.239.118.52 | Dst: 443            |                 |
+--------------------+---------------------+-----------------+
```

 **2. 本地路由器路由** 

目标 IP 是公有 IP 地址而不是本地网络的一部分，因此 `kubelet` 会将此数据包发送到其默认网关（本地路由器）。路由器检查目标 IP 并确定它是公有 IP 地址。

对于公共流量，路由器通常会将数据包转发到处理互联网出站流量的互联网网关或边界路由器。图表中省略了这一点，并且这取决于您的本地网络设置方式。数据包会穿过您的本地网络基础设施，最终到达互联网服务提供商的网络。

 **3. 分发到 EKS 控制面板** 

数据包通过公共互联网和传输网络进行传输，直至到达 AWS 网络。AWS 网络将数据包路由到相应区域的 EKS 服务端点。数据包到达 EKS 服务时，它会被转发到集群的实际 EKS 控制面板。

这种通过公共互联网进行的路由不同于我们在其他流量流中看到的私有 VPC 路由路径。主要区别在于，在使用公共访问模式时，从本地 `kubelet` [尽管不是从容器组（pod）] 到 EKS 控制面板的流量不会通过您的 VPC，而是使用全球互联网基础设施。

### 响应
<a name="_response"></a>

在 EKS 控制面板处理 `kubelet` 请求后，它会发送回响应：

 **3. EKS 控制面板发送响应** 

EKS 控制面板创建响应数据包。此数据包以该公有 IP 为源，并以混合节点的 IP 为目标：

```
+--------------------+---------------------+-----------------+
| IP Header          | TCP Header          | Payload         |
| Src: 54.239.118.52 | Src: 443            |                 |
| Dst: 10.80.0.2     | Dst: 52390          |                 |
+--------------------+---------------------+-----------------+
```

 **2. 互联网路由** 

响应数据包沿着互联网服务提供商确定的路由路径，通过互联网返回，直至到达本地网络边缘路由器。

 **1。本地分发** 

本地路由器会收到数据包并将目标 IP (`10.80.0.2`) 识别为属于本地网络。它通过本地网络基础设施转发数据包，直至到达目标混合节点，`kubelet` 在该节点接收和处理响应。

## 混合节点 `kube-proxy` 到 EKS 控制面板
<a name="_hybrid_node_kube_proxy_to_eks_control_plane"></a>

如果为集群启用了公有端点访问权限，则返回流量会使用公共互联网。此流量从混合节点上的 `kube-proxy` 出发流向 EKS 控制面板，其路径与从 `kubelet` 流向 EKS 控制面板的流量相同。

## EKS 控制面板到混合节点（`kubelet` 服务器）
<a name="hybrid-nodes-concepts-traffic-flows-cp-to-kubelet"></a>

![\[EKS 控制面板到混合节点\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-cp-to-kubelet.png)


### 请求
<a name="_request_2"></a>

 **1。EKS Kubernetes API 服务器启动请求** 

EKS Kubernetes API 服务器从节点对象的状态中检索节点的 IP 地址 (`10.80.0.2`)。然后通过 VPC 中的 ENI 路由此请求，因为目标 IP 属于配置的远程节点 CIDR (`10.80.0.0/16`)。初始数据包类似于以下示例：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 67493 (random) |                 |
| Dst: 10.80.0.2  | Dst: 10250          |                 |
+-----------------+---------------------+-----------------+
```

 **2. VPC 网络处理** 

数据包离开 ENI 并进入 VPC 网络层，在此处它会被引导到子网的网关进行进一步路由。

 **3. VPC 路由表查找** 

包含 EKS 控制面板 ENI 的子网的 VPC 路由表具有远程节点 CIDR 的专用路由（图中的第二条路由）。根据此路由规则，数据包将被引导至“VPC 到本地”网关。

 **4. 跨边界传输** 

网关通过您建立的连接（例如 Direct Connect 或 VPN）将数据包跨云边界传输到本地网络。

 **5. 本地网络接收** 

数据包到达本地路由器，该路由器处理混合节点所在子网的流量。

 **6. 最终分发** 

本地路由器确定目标 IP (`10.80.0.2`) 地址属于其直连网络，并将数据包直接转发到目标混合节点，而 `kubelet` 在该节点接收和处理请求。

### 响应
<a name="_response_2"></a>

在混合节点的 `kubelet` 处理请求后，它会按照相同的路径反向发送响应：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.80.0.2  | Src: 10250          |                 |
| Dst: 10.0.0.132 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

 **6. `kubelet` 发送响应** 

混合节点 (`10.80.0.2`) 上的 `kubelet` 创建以原始源 IP 为目标的响应数据包。该目标不属于本地网络，因此它会发送到主机的默认网关，即本地路由器。

 **5. 本地路由器路由** 

路由器确定目标 IP (`10.0.0.132`) 属于 `10.0.0.0/16`，其中具有指向连接到 AWS 的网关的路由。

 **4. 跨边界返回** 

数据包通过同一个本地与 VPC 的连接（例如 Direct Connect 或 VPN）返回，朝相反的方向穿过云边界。

 **3. VPC 路由** 

数据包到达 VPC 时，路由表确定目标 IP 属于某个 VPC CIDR。数据包将在该 VPC 内路由。

 **2. VPC 网络分发** 

VPC 网络层使用 EKS 控制面板 ENI (`10.0.0.132`) 将数据包转发到子网。

 **1。ENI 接收** 

数据包到达附加到 Kubernetes API 服务器的 EKS 控制面板 ENI，从而完成往返行程。

## 混合节点上运行的容器组（pod）到 EKS 控制面板
<a name="hybrid-nodes-concepts-traffic-flows-pods-to-cp"></a>

![\[混合节点上运行的容器组（pod）到 EKS 控制面板\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-pod-to-cp.png)


### 不使用 CNI NAT
<a name="_without_cni_nat"></a>

### 请求
<a name="_request_3"></a>

容器组（pod）通常通过 `kubernetes` 服务与 Kubernetes API 服务器通信。服务 IP 是集群的服务 CIDR 的第一个 IP。此惯例允许需要在 CoreDNS 可用之前运行的容器组（pod）访问 API 服务器，例如 CNI。请求离开以服务 IP 为目标的容器组（pod）。例如，如果服务 CIDR 是 `172.16.0.0/16`，则服务 IP 将为 `172.16.0.1`。

 **1。容器组（pod）发起请求** 

容器组（pod）从随机源端口向 API 服务器端口（443）上的 `kubernetes` 服务 IP（`172.16.0.1`）发送请求。数据包类似于以下示例：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 67493 (random) |                 |
| Dst: 172.16.0.1 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

 **2. CNI 处理** 

CNI 检测到目标 IP 不属于其管理的任何容器组（pod）CIDR。由于**传出 NAT 已禁用**，CNI 会将数据包传递到主机网络堆栈，而不会对其进行修改。

 **3. 节点网络处理** 

数据包进入节点的网络堆栈，`netfilter` 钩子在该堆栈中触发 kube-proxy 设置的 `iptables` 规则。有多条规则按以下顺序适用：

1. 数据包首先到达 `KUBE-SERVICES` 链，链中包含与每项服务的 ClusterIP 和端口匹配的规则。

1. 匹配的规则跳转到包含负载均衡规则的 `kubernetes` 服务（发往 `172.16.0.1:443` 的数据包）的 `KUBE-SVC-XXX` 链。

1. 负载均衡规则会为控制面板 ENI IP（`10.0.0.132` 或 `10.0.1.23`）随机选择一条 `KUBE-SEP-XXX` 链。

1. 所选 `KUBE-SEP-XXX` 链具有将目标 IP 从服务 IP 更改为所选 IP 的实际规则。这称为目标网络地址转换（DNAT）。

应用这些规则后，假设所选 EKS 控制面板 ENI 的 IP 是 `10.0.0.132`，则数据包如下所示：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 67493 (random) |                 |
| Dst: 10.0.0.132 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

由于目标 IP 不在本地网络中，节点会将数据包转发到其默认网关。

 **4. 本地路由器路由** 

本地路由器确定目标 IP (`10.0.0.132`) 属于 VPC CIDR (`10.0.0.0/16`)，并将其转发到连接至 AWS 的网关。

 **5. 跨边界传输** 

数据包通过您建立的连接（例如 Direct Connect 或 VPN）跨云边界传输到 VPC。

 **6. VPC 网络分发** 

VPC 网络层将数据包路由到 EKS 控制面板 ENI (`10.0.0.132`) 所在的正确子网。

 **7. ENI 接收** 

数据包到达附加到 Kubernetes API 服务器的 EKS 控制面板 ENI。

### 响应
<a name="_response_3"></a>

在 EKS 控制面板处理请求后，它会将响应发送回容器组（pod）：

 **7. API 服务器发送响应** 

EKS Kubernetes API 服务器会创建以原始源 IP 为目标的响应数据包。数据包类似于以下示例：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 443            |                 |
| Dst: 10.85.1.56 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

由于目标 IP 属于配置的远程容器组 CIDR (`10.85.0.0/16`)，它通过 VPC 中的 ENI 将其发送，并将子网的路由器作为下一个跃点。

 **6. VPC 路由** 

VPC 路由表包含远程容器组 CIDR (`10.85.0.0/16`) 的条目，该条目将此流量引导至“VPC 到本地”网关。

 **5. 跨边界传输** 

网关通过您建立的连接（例如 Direct Connect 或 VPN）将数据包跨云边界传输到本地网络。

 **4. 本地网络接收** 

数据包到达您的本地路由器。

 **3. 分发到节点** 

路由器的表中有一个将 `10.80.0.2` 作为下一个跃点的 `10.85.1.0/24` 条目，该条目将数据包分发到我们的节点。

 **2. 节点网络处理** 

当数据包由节点的网络堆栈处理时，`conntrack`（`netfilter` 的一部分）会将数据包与容器组最初建立的连接进行比对。由于最初应用了 DNAT，因此 `conntrack` 会通过将源 IP 从 EKS 控制面板 ENI 的 IP 重写为 `kubernetes` 服务 IP，从而逆转 DNAT：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 172.16.0.1 | Src: 443            |                 |
| Dst: 10.85.1.56 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

 **1。CNI 处理** 

CNI 确定目标 IP 属于其网络中的某个容器组（pod），并将数据包分发到正确的容器组（pod）网络命名空间。

此流程展示了为何远程容器组（pod）CIDR 必须能够从 VPC 正确路由到托管每个容器组（pod）的特定节点 – 整个返回路径取决于云和本地网络中容器组（pod）IP 的正确路由。

### 使用 CNI NAT
<a name="_with_cni_nat"></a>

此流程与*不使用 CNI NAT* 的流程非常相似，但有一个主要区别：CNI 会在将数据包发送到节点的网络堆栈之前对数据包应用源 NAT（SNAT）。这会将数据包的源 IP 更改为节点的 IP，从而无需进行额外的路由配置即可将数据包路由回节点。

### 请求
<a name="_request_4"></a>

 **1。容器组（pod）发起请求** 

容器组（pod）从随机源端口向 EKS Kubernetes API 服务器端口（443）上的 `kubernetes` 服务 IP（`172.16.0.1`）发送请求。数据包类似于以下示例：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 67493 (random) |                 |
| Dst: 172.16.0.1 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

 **2. CNI 处理** 

CNI 检测到目标 IP 不属于其管理的任何容器组（pod）CIDR。由于**传出 NAT 已启用**，CNI 会对数据包应用 SNAT，将源 IP 更改为节点的 IP，然后再将其传递到节点的网络堆栈：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.80.0.2  | Src: 67493 (random) |                 |
| Dst: 172.16.0.1 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

注意：为清楚起见，CNI 和 `iptables` 在示例中显示为单独的块，但实际上，某些 CNI 可能使用 `iptables` 来应用 NAT。

 **3. 节点网络处理** 

在这里，由 `kube-proxy` 设置的 `iptables` 规则的行为与之前的示例相同，即将数据包负载均衡到其中一个 EKS 控制面板 ENI。现在的数据包如下所示：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.80.0.2  | Src: 67493 (random) |                 |
| Dst: 10.0.0.132 | Dst: 443            |                 |
+-----------------+---------------------+-----------------+
```

由于目标 IP 不在本地网络中，节点会将数据包转发到其默认网关。

 **4. 本地路由器路由** 

本地路由器确定目标 IP (`10.0.0.132`) 属于 VPC CIDR (`10.0.0.0/16`)，并将其转发到连接至 AWS 的网关。

 **5. 跨边界传输** 

数据包通过您建立的连接（例如 Direct Connect 或 VPN）跨云边界传输到 VPC。

 **6. VPC 网络分发** 

VPC 网络层将数据包路由到 EKS 控制面板 ENI (`10.0.0.132`) 所在的正确子网。

 **7. ENI 接收** 

数据包到达附加到 Kubernetes API 服务器的 EKS 控制面板 ENI。

### 响应
<a name="_response_4"></a>

在 EKS 控制面板处理请求后，它会将响应发送回容器组（pod）：

 **7. API 服务器发送响应** 

EKS Kubernetes API 服务器会创建以原始源 IP 为目标的响应数据包。数据包类似于以下示例：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 443            |                 |
| Dst: 10.80.0.2  | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

由于目标 IP 属于配置的远程节点 CIDR (`10.80.0.0/16`)，它通过 VPC 中的 ENI 将其发送，并将子网的路由器作为下一个跃点。

 **6. VPC 路由** 

VPC 路由表包含远程节点 CIDR (`10.80.0.0/16`) 的条目，该条目将此流量引导至“VPC 到本地”网关。

 **5. 跨边界传输** 

网关通过您建立的连接（例如 Direct Connect 或 VPN）将数据包跨云边界传输到本地网络。

 **4. 本地网络接收** 

数据包到达您的本地路由器。

 **3. 分发到节点** 

本地路由器确定目标 IP (`10.80.0.2`) 地址属于其直连网络，并将数据包直接转发到目标混合节点。

 **2. 节点网络处理** 

当数据包由节点的网络堆栈处理时，`conntrack`（`netfilter` 的一部分）会将数据包与容器组（pod）最初建立的连接进行匹配，并且由于最初应用了 DNAT，所以可通过将源 IP 从 EKS 控制面板 ENI 的 IP 重写到 `kubernetes` 服务 IP 来反转这一过程：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 172.16.0.1 | Src: 443            |                 |
| Dst: 10.80.0.2  | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

 **1。CNI 处理** 

CNI 确定此数据包属于它之前应用过 SNAT 的连接。它会反转 SNAT，将目标 IP 改回容器组（pod）的 IP：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 172.16.0.1 | Src: 443            |                 |
| Dst: 10.85.1.56 | Dst: 67493          |                 |
+-----------------+---------------------+-----------------+
```

CNI 检测到目标 IP 属于其网络中的某个容器组（pod），并将数据包分发到正确的容器组（pod）网络命名空间。

此流程展示了 CNI NAT 操作如何允许将数据包路由回节点，而无需为容器组（pod）CIDR 进行额外路由，从而简化配置。

## EKS 控制面板到混合节点上运行的容器组（pod）（Webhook）
<a name="hybrid-nodes-concepts-traffic-flows-cp-to-pod"></a>

![\[EKS 控制面板到混合节点上运行的容器组（pod）\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-cp-to-pod.png)


这种流量模式最常见于 Webhook，其中 EKS 控制面板需要直接启动与在混合节点上的容器组（pod）中运行的 Webhook 服务器的连接。示例包括验证和变更准入 Webhook，它们由 API 服务器在资源验证或变更过程中调用。

### 请求
<a name="_request_5"></a>

 **1。EKS Kubernetes API 服务器启动请求** 

如果集群中配置了 Webhook 并且相关的 API 操作触发了它，EKS Kubernetes API 服务器需要直接连接到 Webhook 服务器容器组（pod）。API 服务器首先从与 Webhook 关联的服务或端点资源中查找容器组（pod）的 IP 地址。

假设 Webhook 容器组在 IP 为 `10.85.1.23` 的混合节点上运行，则 EKS Kubernetes API 服务器会创建一个针对 Webhook 端点的 HTTPS 请求。初始数据包通过 VPC 中的 EKS 控制面板 ENI 发送，因为目标 IP `10.85.1.23` 属于配置的远程容器组 CIDR (`10.85.0.0/16`)。数据包类似于以下示例：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.132 | Src: 41892 (random) |                 |
| Dst: 10.85.1.23 | Dst: 8443           |                 |
+-----------------+---------------------+-----------------+
```

 **2. VPC 网络处理** 

数据包离开 EKS 控制面板 ENI，进入 VPC 网络层，子网的路由器作为下一个跃点。

 **3. VPC 路由表查找** 

包含 EKS 控制面板 ENI 的子网的 VPC 路由表包含远程容器组 CIDR (`10.85.0.0/16`) 的专用路由。此路由规则将数据包引导至“VPC 到本地”网关（例如，用于 Direct Connect 或 VPN 连接的虚拟专用网关）：

```
Destination     Target
10.0.0.0/16     local
10.85.0.0/16    vgw-id (VPC-to-onprem gateway)
```

 **4. 跨边界传输** 

网关通过您建立的连接（例如 Direct Connect 或 VPN）将数据包跨云边界传输到本地网络。数据包在穿过此连接时会保留其原始源和目标 IP 地址。

 **5. 本地网络接收** 

数据包到达您的本地路由器。路由器会查询其路由表以确定如何访问 10.85.1.23 地址。为此，您的本地网络必须拥有容器组（pod）CIDR 的路由，这些路由可以将流量引导到相应的混合节点。

在这种情况下，路由器的路由表中将包含一个条目，指示可通过 IP 为 `10.80.0.2` 的混合节点访问 `10.85.1.0/24` 子网：

```
Destination     Next Hop
10.85.1.0/24    10.80.0.2
```

 **6. 分发到节点** 

根据路由表条目，路由器将数据包转发到混合节点 (`10.80.0.2`)。数据包到达节点时，它看起来与 EKS Kubernetes API 服务器发送它时相同，目标 IP 仍然是容器组（pod）的 IP。

 **7. CNI 处理** 

节点的网络堆栈接收数据包，由于目标 IP 不是节点自己的 IP，因此将其传递给 CNI 进行处理。CNI 确定目标 IP 属于在此节点上本地运行的容器组（pod），并通过相应的虚拟接口将数据包转发到正确的容器组（pod）：

```
Original packet -> node routing -> CNI -> Pod's network namespace
```

容器组（pod）中的 Webhook 服务器接收并处理请求。

### 响应
<a name="_response_5"></a>

在 Webhook 容器组（pod）处理请求后，它会按照相同的路径反向发送响应：

 **7. 容器组（pod）发送响应** 

Webhook 容器组（pod）创建响应数据包，并以自己的 IP 作为源，原始请求者（EKS 控制面板 ENI）作为目标：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.23 | Src: 8443           |                 |
| Dst: 10.0.0.132 | Dst: 41892          |                 |
+-----------------+---------------------+-----------------+
```

CNI 识别此数据包发送到外部网络（不是本地容器组），并将数据包传递到节点的网络堆栈，同时保留原始源 IP。

 **6. 节点网络处理** 

节点确定目标 IP (`10.0.0.132`) 不在本地网络中，并将数据包转发到其默认网关（本地路由器）。

 **5. 本地路由器路由** 

本地路由器会查询其路由表并确定目标 IP (`10.0.0.132`) 属于 VPC CIDR (`10.0.0.0/16`)。它会将数据包转发到连接到 AWS 的网关。

 **4. 跨边界传输** 

数据包通过同一个本地到 VPC 的连接返回，朝相反的方向穿过云边界。

 **3. VPC 路由** 

数据包到达 VPC 时，路由表确定目标 IP 属于该 VPC 内的子网。数据包将在 VPC 内相应路由。

 **2. 和 1. EKS 控制面板 ENI 接收** 

数据包到达附加到 Kubernetes API 服务器的 ENI，从而完成往返行程。API 服务器接收 Webhook 响应，并根据此响应继续处理原始 API 请求。

此流量说明了为什么必须正确配置和路由远程容器组（pod）CIDR：
+ VPC 必须具有指向本地网关的远程容器组（pod）CIDR 的路由
+ 您的本地网络必须具有容器组（pod）CIDR 的路由，这些路由可以将流量引导到托管这些容器组（pod）的特定节点
+ 如果没有此路由配置，则无法从 EKS 控制面板访问混合节点上的容器组（pod）中运行的 Webhook 和其他类似服务。

## 在混合节点上运行的容器组（pod）到容器组（pod）
<a name="hybrid-nodes-concepts-traffic-flows-pod-to-pod"></a>

![\[在混合节点上运行的容器组（pod）到容器组（pod）\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-pod-to-pod.png)


本节介绍在不同混合节点上运行的容器组（pod）如何相互通信。此示例假设您的 CNI 使用 VXLAN 进行封装，这在 Cilium 或 Calico 等 CNI 中很常见。其他封装协议（例如 Geneve 或 IP-in-IP）的整体过程与示例相似。

### 请求
<a name="_request_6"></a>

 **1。容器组（pod）A 启动通信** 

节点 1 上的容器组 A (`10.85.1.56`) 想要向节点 2 上的容器组 B (`10.85.2.67`) 发送流量。初始数据包类似于以下示例：

```
+------------------+-----------------+-------------+-----------------+
| Ethernet Header  | IP Header       | TCP/UDP     | Payload         |
| Src: Pod A MAC   | Src: 10.85.1.56 | Src: 43721  |                 |
| Dst: Gateway MAC | Dst: 10.85.2.67 | Dst: 8080   |                 |
+------------------+-----------------+-------------+-----------------+
```

 **2. CNI 拦截并处理数据包** 

容器组（pod）A 的数据包离开其网络命名空间时，CNI 会拦截它。CNI 会查询其路由表并确定：– 目标 IP (`10.85.2.67`) 属于容器组 CIDR – 此 IP 不在本地节点上，但属于节点 2 (`10.80.0.3`) – 数据包需要用 VXLAN 进行封装。

封装的决定至关重要，因为底层物理网络不知道如何直接路由容器组（pod）CIDR，它只知道如何在节点 IP 之间路由流量。

CNI 将整个原始数据包封装在 VXLAN 帧中。这实际上创建了一个带有新标头的“数据包中的数据包”：

```
+-----------------+----------------+--------------+------------+---------------------------+
| Outer Ethernet  | Outer IP       | Outer UDP    | VXLAN      | Original Pod-to-Pod       |
| Src: Node1 MAC  | Src: 10.80.0.2 | Src: Random  | VNI: 42    | Packet (unchanged         |
| Dst: Router MAC | Dst: 10.80.0.3 | Dst: 8472    |            | from above)               |
+-----------------+----------------+--------------+------------+---------------------------+
```

关于此封装的要点：– 外部数据包从节点 1 (`10.80.0.2`) 寻址到节点 2 (`10.80.0.3`) – UDP 端口 `8472` 是 Cilium 默认使用的 VXLAN 端口 – VXLAN 网络标识符（VNI）确定此数据包属于哪个叠加网络 – 整个原始数据包（以容器组 A 的 IP 作为源，容器组 B 的 IP 作为目标）完好无损地保留在内部

封装后的数据包现在进入节点 1 的常规网络堆栈，并按照与任何其他数据包相同的方式处理：

1.  **节点网络处理**：节点 1 的网络堆栈根据其目标路由数据包 (`10.80.0.3`)

1.  **本地网络分发**：
   + 如果两个节点都在同一个第 2 层网络上，则数据包将直接发送到节点 2
   + 如果它们位于不同的子网上，则首先将数据包转发到本地路由器

1.  **路由器处理**：路由器根据其路由表转发数据包，然后将其分发到节点 2

 **3. 接收节点处理** 

当封装后的数据包到达节点 2 (`10.80.0.3`) 时：

1. 该节点的网络堆栈接收它并将其标识为 VXLAN 数据包（UDP 端口 `4789`）

1. 数据包传递到 CNI 的 VXLAN 接口进行处理

 **4. VXLAN 解封装** 

节点 2 上的 CNI 处理 VXLAN 数据包：

1. 去掉外部标头（以太网、IP、UDP 和 VXLAN）

1. 提取原始的内部数据包

1. 数据包现在恢复为原始形式：

```
+------------------+-----------------+-------------+-----------------+
| Ethernet Header  | IP Header       | TCP/UDP     | Payload         |
| Src: Pod A MAC   | Src: 10.85.1.56 | Src: 43721  |                 |
| Dst: Gateway MAC | Dst: 10.85.2.67 | Dst: 8080   |                 |
+------------------+-----------------+-------------+-----------------+
```

节点 2 上的 CNI 会检查目标 IP (`10.85.2.67`)，并且：

1. 确定此 IP 属于本地容器组（pod）

1. 通过相应的虚拟接口路由数据包

1. 将数据包分发到容器组（pod）B 的网络命名空间

### 响应
<a name="_response_6"></a>

容器组（pod）B 响应容器组（pod）A 时，整个过程是相反的：

1. 容器组 B 向容器组 A 发送数据包 (`10.85.1.56`)

1. 节点 2 的 CNI 使用 VXLAN 将其封装，并将目标设置为节点 1 (`10.80.0.2`)

1. 封装后的数据包分发到节点 1

1. 节点 1 的 CNI 将其解封并将原始响应分发给容器组（pod）A

## 云节点上的容器组（pod）到混合节点上的容器组（pod）（东西向流量）
<a name="hybrid-nodes-concepts-traffic-flows-east-west"></a>

![\[云节点上的容器组（pod）到混合节点上的容器组（pod）\]](http://docs.aws.amazon.com/zh_cn/eks/latest/userguide/images/hybrid-nodes-east-west.png)


### 请求
<a name="_request_7"></a>

 **1。容器组（pod）A 启动通信** 

EC2 节点上的容器组 A (`10.0.0.56`) 想要向混合节点上的容器组 B (`10.85.1.56`) 发送流量。初始数据包类似于以下示例：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.0.0.56  | Src: 52390 (random) |                 |
| Dst: 10.85.1.56 | Dst: 8080           |                 |
+-----------------+---------------------+-----------------+
```

使用 VPC CNI 时，容器组（pod）A 拥有来自 VPC CIDR 的 IP，并直接附加到 EC2 实例上的 ENI。容器组（pod）的网络命名空间连接到 VPC 网络，因此数据包直接进入 VPC 路由基础设施。

 **2. VPC 路由** 

VPC 路由表包含远程容器组 CIDR (`10.85.0.0/16`) 的专用路由，该路由将此流量引导至“VPC 到本地”网关：

```
Destination     Target
10.0.0.0/16     local
10.85.0.0/16    vgw-id (VPC-to-onprem gateway)
```

根据此路由规则，数据包将被引导至连接到您的本地网络的网关。

 **3. 跨边界传输** 

网关通过您建立的连接（例如 Direct Connect 或 VPN）将数据包跨云边界传输到本地网络。在此整个传输过程中，数据包会保留其原始源和目标 IP 地址。

 **4. 本地网络接收** 

数据包到达您的本地路由器。路由器会查询其路由表，确定到达 10.85.1.56 地址的下一个跃点。您的本地路由器必须拥有容器组（pod）CIDR 的路由，这些路由可以将流量引导到相应的混合节点。

路由器的路由表中将包含一个条目，指示可通过 IP 为 `10.80.0.2` 的混合节点访问 `10.85.1.0/24` 子网：

```
Destination     Next Hop
10.85.1.0/24    10.80.0.2
```

 **5. 节点网络处理** 

路由器将数据包转发到混合节点 (`10.80.0.2`)。当数据包到达节点时，它仍将容器组（pod）A 的 IP 作为源，将容器组（pod）B 的 IP 作为目标。

 **6. CNI 处理** 

节点的网络堆栈接收数据包，由于目标 IP 不是自己的 IP，因此将其传递给 CNI 进行处理。CNI 确定目标 IP 属于在此节点上本地运行的容器组（pod），并通过相应的虚拟接口将数据包转发到正确的容器组（pod）：

```
Original packet -> node routing -> CNI -> Pod B's network namespace
```

容器组（pod）B 接收数据包并根据需要进行处理。

### 响应
<a name="_response_7"></a>

 **6. 容器组（pod）B 发送响应** 

容器组（pod）B 创建一个以自己的 IP 作为源、容器组（pod）A 的 IP 作为目标的响应数据包：

```
+-----------------+---------------------+-----------------+
| IP Header       | TCP Header          | Payload         |
| Src: 10.85.1.56 | Src: 8080           |                 |
| Dst: 10.0.0.56  | Dst: 52390          |                 |
+-----------------+---------------------+-----------------+
```

CNI 确定此数据包发往外部网络，并将其传递到节点的网络堆栈。

 **5. 节点网络处理** 

节点确定目标 IP (`10.0.0.56`) 不属于本地网络，并将数据包转发到其默认网关（本地路由器）。

 **4. 本地路由器路由** 

本地路由器会查询其路由表并确定目标 IP (`10.0.0.56`) 属于 VPC CIDR (`10.0.0.0/16`)。它会将数据包转发到连接到 AWS 的网关。

 **3. 跨边界传输** 

数据包通过同一个本地到 VPC 的连接返回，朝相反的方向穿过云边界。

 **2. VPC 路由** 

数据包到达 VPC 时，路由系统确定目标 IP 属于该 VPC 内的子网。数据包通过 VPC 网络路由到托管容器组（pod）A 的 EC2 实例。

 **1。容器组（pod）A 收到响应** 

数据包到达 EC2 实例，并通过其附加的 ENI 直接分发到容器组（pod）A。由于 VPC CNI 不对 VPC 中的容器组（pod）使用叠加网络，因此无需进行额外的解封 – 数据包到达时其原始标头保持不变。

此东西向流量说明了为什么必须正确配置远程容器组（pod）CIDR 并可从两个方向路由：
+ VPC 必须具有指向本地网关的远程容器组（pod）CIDR 的路由
+ 您的本地网络必须具有容器组（pod）CIDR 的路由，这些路由可以将流量引导到托管这些容器组（pod）的特定节点。

# 混合节点 `nodeadm` 参考
<a name="hybrid-nodes-nodeadm"></a>

Amazon EKS 混合节点功能 CLI (`nodeadm`) 简化了混合节点组件的安装、配置、注册和卸载。您可以将 `nodeadm` 包含在操作系统映像中以自动执行混合节点引导过程，有关更多信息，请参阅[为混合节点准备操作系统](hybrid-nodes-os.md)。

用于混合节点的 `nodeadm` 版本，与用于引导 Amazon EC2 实例以作为 Amazon EKS 集群中节点的 `nodeadm` 版本不同。请按照相应 `nodeadm` 版本的文档和参考进行操作。此文档页面适用于混合节点 `nodeadm` 版本。

https://github.com/aws/eks-hybrid GitHub 存储库发布了混合节点 `nodeadm` 的源代码。

**重要**  
您必须使用具有 root/sudo 权限的用户运行 `nodeadm`。

## 下载 `nodeadm`
<a name="_download_nodeadm"></a>

`nodeadm` 的混合节点版本在 Amazon S3 中托管，由 Amazon CloudFront 分发。要在每台本地主机上安装 `nodeadm`，您可以在本地主机上运行以下命令。

 **x86\$164 主机：**

```
curl -OL 'https://hybrid-assets.eks.amazonaws.com/releases/latest/bin/linux/amd64/nodeadm'
```

 **ARM 主机** 

```
curl -OL 'https://hybrid-assets.eks.amazonaws.com/releases/latest/bin/linux/arm64/nodeadm'
```

将可执行文件权限添加到每台主机上下载的二进制文件。

```
chmod +x nodeadm
```

## `nodeadm install`
<a name="_nodeadm_install"></a>

`nodeadm install` 命令用于安装运行和将混合节点加入 Amazon EKS 集群所需的构件和依赖项。`nodeadm install` 命令可以在每个混合节点上单独运行，也可以在映像生成管道期间运行，以便在操作系统映像中预装混合节点依赖项。

 **用法** 

```
nodeadm install [KUBERNETES_VERSION] [flags]
```

 **定位参数** 

（必需）`KUBERNETES_VERSION` 要安装的 EKS Kubernetes 的主要.次要版本，例如 `1.32` 

 **Flags** 


| 名称 | 必需 | 说明 | 
| --- | --- | --- | 
|   `-p`,  `--credential-provider`   |  TRUE  |  要安装的凭证提供者。支持的值为 `iam-ra` 和 `ssm`。请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)了解更多信息。  | 
|   `-s`,  `--containerd-source`   |  FALSE  |  `containerd` 的来源。`nodeadm` 支持从操作系统发行版、Docker 软件包安装 `containerd` 以及跳过 `containerd` 安装。  **值**   `distro`：此为默认值。`nodeadm` 会安装由节点操作系统分发的、与 EKS Kubernetes 版本兼容的最新 `containerd` 软件包。`distro` 并非 Red Hat Enterprise Linux（RHEL）操作系统的有效值。  `docker`：`nodeadm` 会安装由 Docker 编译并分发的、与 EKS Kubernetes 版本兼容的最新 `containerd` 软件包。`docker` 并非 Amazon Linux 2023 的有效值。  `none`：`nodeadm` 不会安装 `containerd` 软件包。您必须首先手动安装 `containerd`，然后再运行 `nodeadm init`。  | 
|   `-r`,  `--region`   |  FALSE  |  指定用于下载 SSM Agent 等构件的 AWS 区域。默认值为 `us-west-2`。  | 
|   `-t`,  `--timeout`   |  FALSE  |  安装命令的最大持续时间。输入遵循持续时间格式。例如 `1h23m`。安装命令的默认下载超时设置为 20 分钟。  | 
|   `-h`, `--help`   |  FALSE  |  显示带有可用标志、子命令和位置值参数的帮助消息。  | 

 **示例** 

安装 Kubernetes 版本 `1.32`，并将 AWS Systems Manager（SSM）作为凭证提供者

```
nodeadm install 1.32 --credential-provider ssm
```

安装 Kubernetes 版本 `1.32`，并将 AWS Systems Manager（SSM）作为凭证提供者，将 Docker 作为 containerd 源，下载超时设置为 20 分钟。

```
nodeadm install 1.32 --credential-provider ssm --containerd-source docker --timeout 20m
```

安装 Kubernetes 版本 `1.32`，并将 AWS IAM Roles Anywhere 作为凭证提供者

```
nodeadm install 1.32 --credential-provider iam-ra
```

## `nodeadm config check`
<a name="_nodeadm_config_check"></a>

`nodeadm config check` 命令会检查提供的节点配置是否存在错误。此命令可用于确认和验证混合节点配置文件的正确性。

 **用法** 

```
nodeadm config check [flags]
```

 **Flags** 


| 名称 | 必需 | 说明 | 
| --- | --- | --- | 
|   `-c`,  `--config-source`   |  TRUE  |  nodeadm 配置的来源。对于混合节点，输入应遵循带文件架构的 URI。  | 
|   `-h`, `--help`   |  FALSE  |  显示带有可用标志、子命令和位置值参数的帮助消息。  | 

 **示例** 

```
nodeadm config check -c file://nodeConfig.yaml
```

## `nodeadm init`
<a name="_nodeadm_init"></a>

`nodeadm init` 命令会启动混合节点并将其连接到配置的 Amazon EKS 集群。有关如何配置 `nodeConfig.yaml` 文件的详细信息，请参阅[SSM 混合激活的节点配置](#hybrid-nodes-node-config-ssm)或[IAM Roles Anywhere 的节点配置](#hybrid-nodes-node-config-iamra)。

 **用法** 

```
nodeadm init [flags]
```

 **Flags** 


| 名称 | 必需 | 说明 | 
| --- | --- | --- | 
|   `-c`,  `--config-source`   |  TRUE  |  `nodeadm` 配置的来源。对于混合节点，输入应遵循带文件架构的 URI。  | 
|   `-s`,  `--skip`   |  FALSE  |  要跳过的 `init` 阶段。除非有助于解决问题，否则不建议跳过任何阶段。  **值**   `install-validation` 会跳过检查之前的安装命令是否成功运行。  如果节点上启用了防火墙，则 `cni-validation` 会跳过检查 Cilium 或 Calico CNI 的 VXLAN 端口是否已打开  如果节点 IP 在远程节点网络的 CIDR 范围内，`node-ip-validation` 将会跳过检查。  | 
|   `-h`, `--help`   |  FALSE  |  显示带有可用标志、子命令和位置值参数的帮助消息。  | 

 **示例** 

```
nodeadm init -c file://nodeConfig.yaml
```

## `nodeadm upgrade`
<a name="_nodeadm_upgrade"></a>

`nodeadm upgrade` 命令会将所有已安装的构件升级到最新版本，启动节点以配置升级后的构件并加入 AWS 上的 EKS 集群。对于在节点上运行的工作负载，升级是一个中断性命令。在运行升级之前，请将您的工作负载转移至其他节点。

 **用法** 

```
nodeadm upgrade [KUBERNETES_VERSION] [flags]
```

 **定位参数** 

（必需）`KUBERNETES_VERSION` 要安装的 EKS Kubernetes 的主要.次要版本，例如 `1.32` 

 **Flags** 


| 名称 | 必需 | 说明 | 
| --- | --- | --- | 
|   `-c`,  `--config-source`   |  TRUE  |  `nodeadm` 配置的来源。对于混合节点，输入应遵循带文件架构的 URI。  | 
|   `-t`,  `--timeout`   |  FALSE  |  下载构件超时。输入遵循持续时间格式。例如，1h23m。升级命令的默认下载超时设置为 10 分钟。  | 
|   `-s`,  `--skip`   |  FALSE  |  要跳过的升级阶段。除非有助于解决问题，否则不建议跳过任何阶段。  **值**   `pod-validation` 会跳过检查除进程守护程序集和静态容器组外，是否节点上的所有容器组都在运行。  `node-validation` 会跳过检查节点是否已被封锁。  `init-validation` 会跳过检查节点在运行升级之前是否已成功初始化。  `containerd-major-version-upgrade` 可避免在节点升级期间对 containerd 执行大版本升级操作。  | 
|   `-h`, `--help`   |  FALSE  |  显示带有可用标志、子命令和位置值参数的帮助消息。  | 

 **示例** 

```
nodeadm upgrade 1.32 -c file://nodeConfig.yaml
```

```
nodeadm upgrade 1.32 -c file://nodeConfig.yaml --timeout 20m
```

## `nodeadm uninstall`
<a name="_nodeadm_uninstall"></a>

`nodeadm uninstall` 命令会停止并移除在 `nodeadm install` 期间安装的构件 `nodeadm`，包括 kubelet 和 containerd。请注意，卸载命令不会从集群中清空或删除混合节点。您必须分别运行清空和删除操作，有关更多信息，请参阅[移除混合节点](hybrid-nodes-remove.md)。默认情况下，如果节点上还有容器组，则 `nodeadm uninstall` 不会执行。同样，`nodeadm uninstall` 也不会移除 CNI 依赖项或您在集群上运行的其他 Kubernetes 附加组件的依赖项。要从主机上完全移除 CNI 安装，请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md) 中的说明。如果将 AWS SSM 混合激活作为本地凭证提供者，则 `nodeadm uninstall` 命令将从 AWS SSM 托管式实例中注销您的主机。

 **用法** 

```
nodeadm uninstall [flags]
```

 **Flags** 


| 名称 | 必需 | 说明 | 
| --- | --- | --- | 
|   `-s`,  `--skip`   |  FALSE  |  要跳过的卸载阶段。除非有助于解决问题，否则不建议跳过任何阶段。  **值**   `pod-validation` 会跳过检查除进程守护程序集和静态容器组外，是否节点上的所有容器组都在运行。  `node-validation` 会跳过检查节点是否已被封锁。  `init-validation` 会跳过检查节点在运行卸载之前是否已成功初始化。  | 
|   `-h`,  `--help`   |  FALSE  |  显示带有可用标志、子命令和位置值参数的帮助消息。  | 
|   `-f`,  `--force`   |  FALSE  |  强制删除可能包含 Kubernetes 和 CNI 组件中剩余文件的其他目录。  **WARNING**  此操作将删除默认 Kubernetes 和 CNI 目录（`/var/lib/cni`、`/etc/cni/net.d` 等）中的所有内容。如果您将自己的数据存储在这些位置，请不要使用此标志。 从 nodeadm `v1.0.9` 开始，`./nodeadm uninstall --skip node-validation,pod-validation --force` 命令不再删除 `/var/lib/kubelet` 目录。这是因为该目录可能包含容器组（pod）卷和 volume-subpath 目录，这些目录有时会包含已挂载的节点文件系统。  **安全处理提示**  - 删除已挂载的路径可能会导致意外删除实际挂载的节点文件系统。在手动删除 `/var/lib/kubelet` 目录之前，请仔细检查所有活动的挂载并安全地卸载卷，以免丢失数据。  | 

 **示例** 

```
nodeadm uninstall
```

```
nodeadm uninstall --skip node-validation,pod-validation
```

## `nodeadm debug`
<a name="_nodeadm_debug"></a>

`nodeadm debug` 命令可用于对运行不正常或配置有错误的混合节点进行故障排除。此命令可以验证以下要求是否已经满足。
+ 该节点具有必需 AWS API 的网络访问权限以获取凭证，
+ 该节点能够获取所配置混合节点 IAM 角色的 AWS 凭证，
+ 该节点具有对 EKS Kubernetes API 端点的网络访问权限，并且 EKS Kubernetes API 端点证书的有效，
+ 该节点能够通过 EKS 集群身份验证，其在集群中的身份有效，并且该节点可以通过为 EKS 集群配置的 VPC 访问 EKS 集群。

如果发现错误，该命令的输出会提供故障排除步骤建议。某些验证步骤会显示子进程。如果这些子进程失败，则输出将显示在验证错误下的 stderr 部分中。

 **用法** 

```
nodeadm debug [flags]
```

 **Flags** 


| 名称 | 必需 | 说明 | 
| --- | --- | --- | 
|   `-c`, `--config-source`   |  TRUE  |  `nodeadm` 配置的来源。对于混合节点，输入应遵循带文件架构的 URI。  | 
|   `--no-color`   |  FALSE  |  禁用彩色输出。对自动化很有用。  | 
|   `-h`, `--help`   |  FALSE  |  显示带有可用标志、子命令和位置值参数的帮助消息。  | 

 **示例** 

```
nodeadm debug -c file://nodeConfig.yaml
```

## nodeadm 文件位置
<a name="_nodeadm_file_locations"></a>

### nodeadm 安装
<a name="_nodeadm_install_2"></a>

运行 `nodeadm install` 时，将配置以下文件和文件位置。


| Artifact | 路径 | 
| --- | --- | 
|  IAM Roles Anywhere CLI  |  /usr/local/bin/aws\$1signing\$1helper  | 
|  Kubelet 二进制包  |  /usr/bin/kubelet  | 
|  Kubectl 二进制包  |  usr/local/bin/kubectl  | 
|  ECR 凭证提供者  |  /etc/eks/image-credential-provider/ecr-credential-provider  | 
|   AWS IAM 身份验证器  |  /usr/local/bin/aws-iam-authenticator  | 
|  SSM 安装 CLI  |  /opt/ssm/ssm-setup-cli  | 
|  SSM Agent  |  在 Ubuntu 上：/snap/amazon-ssm-agent/current/amazon-ssm-agent 在 RHEL 和 AL2023 上：/usr/bin/amazon-ssm-agent  | 
|  Containerd  |  在 Ubuntu 和 AL2023 上：/usr/bin/containerd 在 RHEL 上：/bin/containerd  | 
|  Iptables  |  在 Ubuntu 和 AL2023 上：/usr/sbin/iptables 在 RHEL 上：/sbin/iptables  | 
|  CNI 插件  |  /opt/cni/bin  | 
|  安装的构件跟踪器  |  /opt/nodeadm/tracker  | 

### nodeadm init
<a name="_nodeadm_init_2"></a>

运行 `nodeadm init` 时，将配置以下文件和文件位置。


| 名称 | 路径 | 
| --- | --- | 
|  Kubelet kubeconfig  |  /var/lib/kubelet/kubelet/kubecconfig  | 
|  Kubelet config  |  /etc/kubernetes/kubelet/config.json  | 
|  Kubelet systemd 单元  |  /etc/systemd/system/kubelet.service  | 
|  映像凭证提供者配置  |  /etc/eks/image-credential-provider/config.json  | 
|  Kubelet 环境文件  |  /etc/eks/kubelet/environment  | 
|  Kubelet 证书  |  /etc/kubernetes/pki/ca.crt  | 
|  Containerd 配置  |  /etc/containerd/config.toml  | 
|  Containerd 内核模块配置  |  /etc/modules-load.d/contianerd.conf  | 
|   AWS 配置文件  |  /etc/aws/hybrid/config  | 
|   AWS 凭证文件（如果启用了凭证文件）  |  /eks-hybrid/.aws/credentials  | 
|   AWS 签名助手系统单元  |  /etc/systemd/system/aws\$1signing\$1helper\$1update.service  | 
|  Sysctl conf 文件  |  /etc/sysctl.d/99-nodeadm.conf  | 
|  Ca-certificates  |  /etc/ssl/certs/ca-certificates.crt  | 
|  Gpg 密钥文件  |  /etc/apt/keyrings/docker.asc  | 
|  Docker 存储库源文件  |  /etc/apt/sources.list.d/docker.list  | 

## SSM 混合激活的节点配置
<a name="hybrid-nodes-node-config-ssm"></a>

以下是将 AWS SSM 混合激活作为混合节点凭证的示例 `nodeConfig.yaml`。

```
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name:             # Name of the EKS cluster
    region:           # AWS Region where the EKS cluster resides
  hybrid:
    ssm:
      activationCode: # SSM hybrid activation code
      activationId:   # SSM hybrid activation id
```

## IAM Roles Anywhere 的节点配置
<a name="hybrid-nodes-node-config-iamra"></a>

以下是将 AWS IAM Roles Anywhere 作为混合节点凭证的示例 `nodeConfig.yaml`。

如果将 AWS IAM Roles Anywhere 作为本地凭证提供者，您在 `nodeadm` 配置中使用的 `nodeName` 必须与您为混合节点 IAM 角色设定的权限范围一致。例如，假设混合节点 IAM 角色的权限仅允许 AWS IAM Roles Anywhere 在角色会话名称等于主机证书的 CN 时代入该角色，则 `nodeadm` 配置中的 `nodeName` 必须与证书的 CN 相同。您使用的 `nodeName` 长度不能超过 64 个字符。有关更多信息，请参阅 [准备用于混合节点的凭证](hybrid-nodes-creds.md)。

```
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name:              # Name of the EKS cluster
    region:            # AWS Region where the EKS cluster resides
  hybrid:
    iamRolesAnywhere:
      nodeName:        # Name of the node
      trustAnchorArn:  # ARN of the IAM Roles Anywhere trust anchor
      profileArn:      # ARN of the IAM Roles Anywhere profile
      roleArn:         # ARN of the Hybrid Nodes IAM role
      certificatePath: # Path to the certificate file to authenticate with the IAM Roles Anywhere trust anchor
      privateKeyPath:  # Path to the private key file for the certificate
```

## 自定义 kubelet 的节点配置（可选）
<a name="hybrid-nodes-nodeadm-kubelet"></a>

您可以在 `nodeadm` 配置中传递 kubelet 配置和标志。有关如何添加额外节点标签 `abc.amazonaws.com/test-label` 和配置，以将 `shutdownGracePeriod` 设置为 30 秒的信息，请参阅以下示例。

```
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name:             # Name of the EKS cluster
    region:           # AWS Region where the EKS cluster resides
  kubelet:
    config:           # Map of kubelet config and values
       shutdownGracePeriod: 30s
    flags:            # List of kubelet flags
       - --node-labels=abc.company.com/test-label=true
  hybrid:
    ssm:
      activationCode: # SSM hybrid activation code
      activationId:   # SSM hybrid activation id
```

## 自定义 containerd 的节点配置（可选）
<a name="_node_config_for_customizing_containerd_optional"></a>

您可以在 `nodeadm` 配置中传递自定义 containerd 配置。`nodeadm` containerd 配置接受内联 TOML。要了解如何配置 containerd 以禁用删除 containerd 内容存储中未打包的映像层，请参阅以下示例。

```
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name:             # Name of the EKS cluster
    region:           # AWS Region where the EKS cluster resides
  containerd:
    config: |         # Inline TOML containerd additional configuration
       [plugins."io.containerd.grpc.v1.cri".containerd]
       discard_unpacked_layers = false
  hybrid:
    ssm:
      activationCode: # SSM hybrid activation code
      activationId:   # SSM hybrid activation id
```

**注意**  
containerd 1.x 与 2.x 采用不同的配置文件格式。containerd 1.x 使用配置版本 2，而 containerd 2.x 使用配置版本 3。虽然 containerd 2.x 对配置版本 2 仍保持向下兼容，但为实现最优性能，建议使用配置版本 3。您可通过 `containerd --version` 命令查看 containerd 版本，也可查阅 `nodeadm` 安装日志。有关配置版本控制的更多详细信息，请参阅 https://containerd.io/releases/

您还可以使用 containerd 配置来实现 SELinux 支持。在 containerd 上启用 SELinux 后，确保在节点上调度的容器组启用了正确的 securityContext 和 seLinuxOptions。有关配置安全上下文的更多信息，请参阅 [Kubernetes 文档](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)。

**注意**  
Red Hat Enterprise Linux（RHEL）8 和 RHEL 9 在主机上默认启用了 SELinux 并设置为严格模式。Amazon Linux 2023 默认启用 SELinux 并设置为宽松模式。当主机上的 SELinux 设置为宽容模式时，在 containerd 上启用此功能不会阻止请求，但会根据主机上的 SELinux 配置记录请求。

```
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
  cluster:
    name:             # Name of the EKS cluster
    region:           # AWS Region where the EKS cluster resides
  containerd:
    config: |         # Inline TOML containerd additional configuration
       [plugins."io.containerd.grpc.v1.cri"]
       enable_selinux = true
  hybrid:
    ssm:
      activationCode: # SSM hybrid activation code
      activationId:   # SSM hybrid activation id
```

# 混合节点故障排除
<a name="hybrid-nodes-troubleshooting"></a>

本主题介绍在使用 Amazon EKS 混合节点功能时可能遇到的一些常见错误以及修复方法。有关其他故障排除信息，请参阅[排查 Amazon EKS 集群和节点问题](troubleshooting.md)以及 AWS re:Post** 上[有关 Amazon EKS 的知识中心标签](https://repost.aws/tags/knowledge-center/TA4IvCeWI1TE66q4jEj4Z9zg/amazon-elastic-kubernetes-service)。如果您无法解决问题，请联系 AWS Support。

 **使用 `nodeadm debug` 对节点进行故障排除** 您可以从混合节点运行 `nodeadm debug` 命令来验证是否满足联网和凭证要求。有关 `nodeadm debug` 命令的更多信息，请参阅 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

 **使用集群见解检测混合节点的问题** Amazon EKS 集群见解包括*见解检查*，可检测集群中 EKS 混合节点配置的常见问题。您可以从 AWS 管理控制台、AWS CLI 和 AWS SDK 中查看所有见解检查的结果。有关集群见解的更多信息，请参阅 [利用集群见解为 Kubernetes 版本升级做好准备并对错误配置进行问题排查](cluster-insights.md)。

## 混合节点安装故障排除
<a name="hybrid-nodes-troubleshooting-install"></a>

以下故障排除主题与使用 `nodeadm install` 命令在主机上安装混合节点依赖项有关。

 ** `nodeadm`命令失败，`must run as root`**

运行 `nodeadm install` 命令的用户必须具有主机上的根权限或 `sudo` 权限。如果以没有根权限或 `sudo` 权限的用户身份运行 `nodeadm install`，则会在 `nodeadm` 输出中看到以下错误。

```
"msg":"Command failed","error":"must run as root"
```

 **无法连接到依赖项** 

`nodeadm install` 命令会安装混合节点必需的依赖项。混合节点依赖项包括 `containerd`、`kubelet`、`kubectl` 和 AWS SSM 或 AWS IAM Roles Anywhere 组件。您必须具有从运行 `nodeadm install` 的位置访问的权限才能下载这些依赖项。要详细了解您必须具有访问权限的位置列表，请参阅[准备混合节点的联网](hybrid-nodes-networking.md)。如果您没有访问权限，则会在 `nodeadm install` 输出中看到与以下类似的错误。

```
"msg":"Command failed","error":"failed reading file from url: ...: max retries achieved for http request"
```

 **更新软件包管理器失败** 

`nodeadm install` 命令会在安装混合节点依赖项之前运行 `apt update` 或 `yum update` 或 `dnf update`。如果此步骤未成功，您可能会看到与以下类似的错误。要修复错误，您可以首先运行 `apt update` 或 `yum update` 或 `dnf update`，然后再运行 `nodeadm install`，也可以尝试重新运行 `nodeadm install`。

```
failed to run update using package manager
```

 **超时或超过上下文截止时间** 

运行 `nodeadm install` 时，如果您在安装过程的若干阶段看到问题，并错误消息指示超时或超过上下文截止时间，则可能说明连接速度较慢，导致无法在超时之前安装混合节点依赖项。要解决这些问题，您可以尝试在 `nodeadm` 中使用 `--timeout` 标志来延长下载依赖项的超时期限。

```
nodeadm install K8S_VERSION --credential-provider CREDS_PROVIDER --timeout 20m0s
```

## 混合节点连接故障排除
<a name="hybrid-nodes-troubleshooting-connect"></a>

本节中的故障排除主题与使用 `nodeadm init` 命令将混合节点连接到 EKS 集群的过程有关。

 **操作错误或架构不受支持** 

运行 `nodeadm init` 时，如果您看到与 `operation error` 或 `unsupported scheme` 相关的错误，请检查 `nodeConfig.yaml` 以确保其格式正确并且已传递给 `nodeadm`。有关 `nodeConfig.yaml` 格式和选项的更多信息，请参阅[混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

```
"msg":"Command failed","error":"operation error ec2imds: GetRegion, request canceled, context deadline exceeded"
```

 **混合节点 IAM 角色缺少 `eks:DescribeCluster` 操作的权限** 

运行 `nodeadm init` 时，`nodeadm` 会尝试通过调用 EKS `DescribeCluster` 操作来收集有关 EKS 集群的信息。若混合节点 IAM 角色不具备 `eks:DescribeCluster` 操作的权限，则在执行 `nodeadm init` 时，您必须在传入 `nodeadm` 的节点配置中，手动指定 Kubernetes API 端点、集群 CA 证书包以及服务 IPv4 CIDR。请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)，以了解有关混合节点 IAM 角色所需权限的更多信息。

```
"msg":"Command failed","error":"operation error EKS: DescribeCluster, https response error StatusCode: 403 ... AccessDeniedException"
```

 **混合节点 IAM 角色缺少 `eks:ListAccessEntries` 操作的权限** 

执行 `nodeadm init` 时，`nodeadm` 会尝试调用 EKS `ListAccessEntries` 操作，验证 EKS 集群是否存在一个与该混合节点 IAM 角色绑定的、类型为 `HYBRID_LINUX` 的访问条目。若混合节点 IAM 角色不具备 `eks:ListAccessEntries` 操作的权限，那么在执行 `nodeadm init` 命令时，您必须传入 `--skip cluster-access-validation` 标记。请参阅[准备用于混合节点的凭证](hybrid-nodes-creds.md)，以了解有关混合节点 IAM 角色所需权限的更多信息。

```
"msg":"Command failed","error":"operation error EKS: ListAccessEntries, https response error StatusCode: 403 ... AccessDeniedException"
```

 **节点 IP 不在远程节点网络 CIDR 范围内** 

运行 `nodeadm init` 时，如果节点 IP 地址不在指定远程节点网络 CIDR 范围内，则可能会出现错误。此错误将与以下示例类似：

```
node IP 10.18.0.1 is not in any of the remote network CIDR blocks [10.0.0.0/16 192.168.0.0/16]
```

此示例显示一个 IP 为 10.18.0.1 的节点正在尝试加入一个远程网络 CIDR 为 10.0.0.0/16 和 192.168.0.0/16 的集群。之所以出现此错误，是因为这两个 CIDR 均不包含 10.18.0.1。

确认您已正确配置 `RemoteNodeNetworks`，使其包含所有节点 IP 地址。有关网络配置的更多信息，请参阅[准备混合节点的联网](hybrid-nodes-networking.md)。
+ 在集群所在区域运行以下命令，检查您的 `RemoteNodeNetwork` 配置。验证输出中列出的 CIDR 块是否包含您的节点 IP 范围，并且与错误消息中列出的 CIDR 块相同。如果不一致，请确认 `nodeConfig.yaml` 中的集群名称和区域与预期的集群一致。

```
aws eks describe-cluster --name CLUSTER_NAME --region REGION_NAME --query cluster.remoteNetworkConfig.remoteNodeNetworks
```
+ 确认您使用的是预期的节点：
  + 检查节点的主机名和 IP 地址是否与您计划注册到集群的主机名和 IP 地址一致，从而确认节点是否正确。
  + 确认此节点所在的本地网络是否正确（其 CIDR 范围在集群设置期间注册为 `RemoteNodeNetwork`）。

如果节点 IP 仍不符合预期，请检查以下内容：
+ 如果您使用的是 IAM Roles Anywhere，`kubelet` 将对 IAM Roles Anywhere `nodeName` 执行 DNS 查找，并使用与节点名称关联的 IP（如果可用）。如果您负责维护节点的 DNS 条目，请确认这些条目指向远程节点网络 CIDR 内的 IP。
+ 如果节点有多个网络接口，`kubelet` 选择的默认接口的 IP 地址可能在远程节点网络 CIDR 范围外。要使用其他接口，请使用 `nodeConfig.yaml` 中的 `--node-ip` `kubelet` 标志指定其 IP 地址。有关更多信息，请参阅 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。您可以通过在节点上运行以下命令，来查看节点的网络接口及其 IP 地址：

```
ip addr show
```

 **混合节点未在 EKS 集群中出现** 

如果运行 `nodeadm init`，但在运行完成后，您的混合节点未在集群中出现，则说明混合节点与 EKS 控制面板之间的网络连接可能存在问题，您可能没有配置所需的安全组权限，或者可能没有将混合节点 IAM 角色映射到 Kubernetes 基于角色的访问控制（RBAC）。您可以使用以下命令检查 `kubelet` 和 `kubelet` 日志的状态，从而启动调试进程。从加入集群失败的混合节点上运行以下命令。

```
systemctl status kubelet
```

```
journalctl -u kubelet -f
```

 **无法与集群通信** 

如果混合节点无法与集群控制面板通信，则可能会看到与以下类似的日志。

```
"Failed to ensure lease exists, will retry" err="Get ..."
```

```
"Unable to register node with API server" err="Post ..."
```

```
Failed to contact API server when waiting for CSINode publishing ... dial tcp <ip address>: i/o timeout
```

如果您看到此类消息，请检查以下内容以确保其符合[准备混合节点的联网](hybrid-nodes-networking.md)中详述的混合节点要求。
+ 确认传递给 EKS 集群的 VPC 具有指向本地节点以及（可选）容器组 CIDR 的中转网关（TGW）或虚拟专用网关（VGW）的路由。
+ 确认您的 EKS 集群还有一个额外的安全组，其中包含针对本地节点 CIDR 和（可选）容器组 CIDR 的入站规则。
+ 确认您的本地路由器已配置为允许进出 EKS 控制面板的流量。

 **未授权** 

如果混合节点能够与 EKS 控制面板通信但无法注册，则可能会看到与以下类似的日志。请注意，以下日志消息的主要区别在于 `Unauthorized` 错误。这表明该节点无法执行其任务，因为没有所需的权限。

```
"Failed to ensure lease exists, will retry" err="Unauthorized"
```

```
"Unable to register node with API server" err="Unauthorized"
```

```
Failed to contact API server when waiting for CSINode publishing: Unauthorized
```

如果您看到此类消息，请检查以下内容以确保其符合[准备用于混合节点的凭证](hybrid-nodes-creds.md)和[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)中详述的混合节点要求。
+ 确认混合节点的身份与您预期的混合节点 IAM 角色相符。这可以通过在混合节点上运行 `sudo aws sts get-caller-identity` 来完成。
+ 确认混合节点 IAM 角色具有必需的权限。
+ 确认集群中是否有混合节点 IAM 角色的 EKS 访问条目，或者确认 `aws-auth` ConfigMap 中是否有混合节点 IAM 角色的条目。如果使用 EKS 访问条目，请确认混合节点 IAM 角色的访问条目具有 `HYBRID_LINUX` 访问类型。如果使用 `aws-auth` ConfigMap，请确认您输入的混合节点 IAM 角色符合[准备混合节点的集群访问权限](hybrid-nodes-cluster-prep.md)中详述的要求和格式。

### 混合节点已在 EKS 集群中注册但显示的状态为 `Not Ready`
<a name="hybrid-nodes-troubleshooting-not-ready"></a>

如果混合节点已成功注册到您的 EKS 集群，但混合节点显示状态为 `Not Ready`，则首先要检查的是容器网络接口（CNI）状态。如果您尚未安装 CNI，则混合节点状态预期将为 `Not Ready`。一旦 CNI 安装并成功运行，节点的状态就会更新为 `Ready`。如果您尝试安装 CNI 但未成功运行，请参阅本页上的[混合节点 CNI 故障排除](#hybrid-nodes-troubleshooting-cni)。

 **证书签名请求（CSR）停滞在待处理状态** 

将混合节点连接到 EKS 集群后，如果您发现混合节点有待处理的 CSR，则表示您的混合节点不满足自动批准的要求。如果混合节点的 CSR 是由带有 `eks.amazonaws.com/compute-type: hybrid` 标签的节点创建的，并且 CSR 具有以下主体备用名称（SAN），则会自动批准和颁发混合节点的 CSR：至少有一个 DNS SAN 等于节点名称且 IP SAN 属于远程节点网络 CIDR。

 **混合配置文件已经存在** 

如果您更改了 `nodeadm` 配置并尝试使用新配置重新注册节点，则可能会看到一条错误消息，指示混合配置文件已经存在，但其内容已更改。请勿在配置更改之间运行 `nodeadm init`，而应运行 `nodeadm uninstall`，然后再运行 `nodeadm install` 和 `nodeadm init`。这样可以确保根据配置更改进行正确的清理。

```
"msg":"Command failed","error":"hybrid profile already exists at /etc/aws/hybrid/config but its contents do not align with the expected configuration"
```

 **混合节点解析私有 API 失败** 

运行 `nodeadm init` 后，如果您在 `kubelet` 日志中看到某个错误，显示由于存在 `no such host` 而无法连接到 EKS Kubernetes API 服务器，则可能需要在本地网络或主机级别更改 EKS Kubernetes API 端点的 DNS 条目。请参阅《AWS Route53 文档》**中的 [Forwarding inbound DNS queries to your VPC](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver-forwarding-inbound-queries.html)。

```
Failed to contact API server when waiting for CSINode publishing: Get ... no such host
```

 **无法在 EKS 控制台中查看混合节点** 

如果您已注册了混合节点，但无法在 EKS 控制台中查看，请检查您用于查看控制台的 IAM 主体的权限。您使用的 IAM 主体必须具有特定的最低 IAM 和 Kubernetes 权限，才能在控制台中查看资源。有关更多信息，请参阅 [在 AWS 管理控制台中查看 Kubernetes 资源](view-kubernetes-resources.md)。

## 混合节点运行故障排查
<a name="_running_hybrid_nodes_troubleshooting"></a>

如果混合节点已注册到 EKS 集群并且状态为 `Ready`，但状态很快变为 `Not Ready`，则可能存在多种导致运行不正常的问题，例如节点缺少足够的 CPU、内存或可用磁盘空间资源，或者节点与 EKS 控制面板之间的连接已断开等。您可以使用以下步骤对节点进行故障排除，如果无法解决问题，请联系 AWS Support。

从您的混合节点运行 `nodeadm debug` 以验证是否满足网络和凭证要求。有关 `nodeadm debug` 命令的更多信息，请参阅 [混合节点 `nodeadm` 参考](hybrid-nodes-nodeadm.md)。

 **获取节点状态** 

```
kubectl get nodes -o wide
```

 **检查节点条件和事件** 

```
kubectl describe node NODE_NAME
```

 **获取容器组状态** 

```
kubectl get pods -A -o wide
```

 **检查容器组状况和事件** 

```
kubectl describe pod POD_NAME
```

 **检查容器组日志** 

```
kubectl logs POD_NAME
```

 **检查 `kubectl` 日志** 

```
systemctl status kubelet
```

```
journalctl -u kubelet -f
```

 **容器组存活探针失败或 Webhook 不起作用** 

如果在混合节点上运行的应用程序、附加组件或 Webhook 未正常启动，则可能存在网络问题，阻碍了与容器组的通信。要让 EKS 控制面板连接到在混合节点上运行的 Webhook，您必须将 EKS 集群配置为远程容器组网络，并在 VPC 路由表中包含本地容器组 CIDR 的路由，以中转网关（TGW）、虚拟专用网关（VPW）或您用于将 VPC 与本地网络连接的其他网关为目标。有关混合节点联网要求的更多信息，请参阅[准备混合节点的联网](hybrid-nodes-networking.md)。此外，您还必须在本地防火墙中允许此流量，并确保您的路由器可以正确路由到您的容器组。要详细了解在混合节点上运行 Webhook 的要求，请参阅[为混合节点配置 Webhook](hybrid-nodes-webhooks.md)。

下方显示了此场景的一条常见容器组日志消息，其中 ip-address 是 Kubernetes 服务的集群 IP。

```
dial tcp <ip-address>:443: connect: no route to host
```

 **`kubectl logs` 或者 `kubectl exec` 命令不起作用（`kubelet` API 命令）** 

如果 `kubectl attach`、`kubectl cp`、`kubectl exec`、`kubectl logs` 和 `kubectl port-forward` 命令超时，而其他 `kubectl` 命令能够成功运行，则问题可能与远程网络配置有关。这些命令通过集群连接到节点上的 `kubelet` 端点。有关更多信息，请参阅 [`kubelet` 端点](hybrid-nodes-concepts-kubernetes.md#hybrid-nodes-concepts-k8s-kubelet-api)。

确认节点 IP 和容器组 IP 位于为集群配置的远程节点网络和远程容器组网络 CIDR 范围内。使用以下命令检查 IP 分配。

```
kubectl get nodes -o wide
```

```
kubectl get pods -A -o wide
```

将这些 IP 与您配置的远程网络 CIDR 进行比较，确保路由正确。有关网络配置要求，请参阅[准备混合节点的联网](hybrid-nodes-networking.md)。

## 混合节点 CNI 故障排除
<a name="hybrid-nodes-troubleshooting-cni"></a>

如果您在首次使用混合节点启动 Cilium 或 Calico 时遇到问题，则通常是由于混合节点或在混合节点上运行的 CNI 容器组与 EKS 控制面板之间的网络问题所致。确保您的环境符合“准备混合节点的联网”中的要求。将问题分解成若干部分会非常实用。

EKS 集群配置  
RemoteNodeNetwork 和 RemotePodNetwork 的配置是否正确？

VPC 配置  
VPC 路由表中是否有 RemoteNodeNetwork 和 RemotePodNetwork 的路由，并以中转网关或虚拟专用网关为目标？

安全组配置  
是否有 RemoteNodeNetwork 和 RemoteNetwork 的入站和出站规则？

本地网络  
是否存在往返于 EKS 控制面板、混合节点以及在混合节点上运行的容器组的路由和访问权限？

CNI 配置  
如果使用叠加网络，CNI 的 IP 池配置是否与使用 Webhook 时为 EKS 集群配置的 RemotePodNetwork 相匹配？

 **混合节点的状态为 `Ready`，但未安装 CNI** 

如果混合节点显示状态为 `Ready`，但您尚未在集群上安装 CNI，则说明混合节点上可能存在旧的 CNI 构件。默认情况下，当您使用 Helm 等工具卸载 Cilium 和 Calico 时，磁盘上的资源不会从物理计算机或虚拟机中移除。此外，在旧安装中，这些 CNI 的自定义资源定义（CRD）可能仍存在于集群上。有关更多信息，请参阅[为混合节点配置 CNI](hybrid-nodes-cni.md)中的 Cilium 和 Delete Calico 部分。

 **Cilium 故障排除** 

如果您在混合节点上运行 Cilium 时遇到问题，请参阅 Cilium 文档中的[故障排除步骤](https://docs.cilium.io/en/stable/operations/troubleshooting/)。以下章节介绍了在混合节点上部署 Cilium 时可能遇到的特有问题。

 **Cilium 未启动** 

如果在每个混合节点上运行的 Cilium 代理都未启动，请检查 Cilium 代理容器组的日志中是否存在错误。Cilium 代理需要连接到 EKS Kubernetes API 端点才能启动。如果此连接配置不正确，Cilium 代理将无法启动。在这种情况下，您将在 Cilium 代理容器组日志中看到与以下类似的日志消息。

```
msg="Unable to contact k8s api-server"
level=fatal msg="failed to start: Get \"https://<k8s-cluster-ip>:443/api/v1/namespaces/kube-system\": dial tcp <k8s-cluster-ip>:443: i/o timeout"
```

Cilium 代理在主机网络上运行。您的 EKS 集群必须将 Cilium 连接配置为 `RemoteNodeNetwork`。确认您的 EKS 集群还有一个额外的安全组，其中包含 `RemoteNodeNetwork` 的入站规则，您的 VPC 中有 `RemoteNodeNetwork` 的路由，并且您的本地网络配置正确，从而能够连接到 EKS 控制面板。

如果 Cilium 操作符正在运行，并且某些但不是全部 Cilium 代理正在运行，请确认您有可用的容器组 IP 可以分配给集群中的所有节点。在 Cilium 配置中使用带 `clusterPoolIPv4PodCIDRList` 的集群池 IPAM 时，您需要配置可分配的容器组 CIDR 的大小。每节点 CIDR 大小是使用 Cilium 配置中的 `clusterPoolIPv4MaskSize` 设置来配置的。有关更多信息，请参阅 Cilium 文档中的 [Expanding the cluster pool](https://docs.cilium.io/en/stable/network/concepts/ipam/cluster-pool/#expanding-the-cluster-pool)。

 **Cilium BGP 不起作用** 

如果您使用 Cilium BGP 控制面板向本地网络公开您的容器组或服务地址，则可以使用以下 Cilium CLI 命令来检查 BGP 是否在公开指向您的资源的路由。有关安装 Cilium CLI 的步骤，请参阅 Cilium 文档中的 [Install the Cilium CLI](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/#install-the-cilium-cli)。

如果 BGP 工作正常，则应在输出中看到会话状态为 `established` 的混合节点。您可能需要联系网络团队，确定环境的本地 AS、对等连接 AS 和对等连接地址的正确值。

```
cilium bgp peers
```

```
cilium bgp routes
```

如果您使用 Cilium BGP 来公开 `LoadBalancer` 类型的服务 IP，则您的 `CiliumLoadBalancerIPPool` 和服务上必须使用相同的标签，该标签应在 `CiliumBGPAdvertisement` 的选择器中使用。下面显示了一个示例。注意，如果您使用 Cilium BGP 来公开 LoadBalancer 类型服务的 IP，则在 Cilium 代理重启期间，BGP 路由可能会中断。有关更多信息，请参阅 Cilium 文档中的 [Failure Scenarios](https://docs.cilium.io/en/latest/network/bgp-control-plane/bgp-control-plane-operation/#failure-scenarios)。

 **服务**：

```
kind: Service
apiVersion: v1
metadata:
  name: guestbook
  labels:
    app: guestbook
spec:
  ports:
  - port: 3000
    targetPort: http-server
  selector:
    app: guestbook
  type: LoadBalancer
```

 **CiliumLoadBalancerIPPool** 

```
apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
  name: guestbook-pool
  labels:
    app: guestbook
spec:
  blocks:
  - cidr: <CIDR to advertise>
  serviceSelector:
    matchExpressions:
      - { key: app, operator: In, values: [ guestbook ] }
```

 **CiliumBGPAdvertisement** 

```
apiVersion: cilium.io/v2alpha1
kind: CiliumBGPAdvertisement
metadata:
  name: bgp-advertisements-guestbook
  labels:
    advertise: bgp
spec:
  advertisements:
    - advertisementType: "Service"
      service:
        addresses:
          - ExternalIP
          - LoadBalancerIP
      selector:
        matchExpressions:
          - { key: app, operator: In, values: [ guestbook ] }
```

 **Calico 故障排除** 

如果您在混合节点上运行 Calico 时遇到问题，请参阅 Calico 文档中的[故障排除步骤](https://docs.tigera.io/calico/latest/operations/troubleshoot/)。以下章节介绍了在混合节点上部署 Calico 时可能遇到的特有问题。

下表总结了 Calico 的组件以及这些组件默认情况下是在节点网络还是在容器组网络上运行。如果将 Calico 配置为使用 NAT 来处理传出的容器组流量，则必须将本地网络配置为将流量路由到本地节点 CIDR，并且 VPC 路由表必须配置本地节点 CIDR 的路由，并将中转网关（TGW）或虚拟专用网关（VGW）作为目标。如果未将 Calico 配置为使用 NAT 来处理传出的容器组流量，则必须将本地网络配置为将流量路由到本地容器组 CIDR，并且 VPC 路由表必须配置本地容器组 CIDR 的路由，并将中转网关（TGW）或虚拟专用网关（VGW）作为目标。


| 组件 | Network | 
| --- | --- | 
|  Calico API 服务器  |  节点  | 
|  适用于 Kubernetes 的 Calico 控制器  |  Pod  | 
|  Calico 节点代理  |  节点  | 
|  Calico `typha`   |  节点  | 
|  Calico CSI 节点驱动程序  |  Pod  | 
|  Calico 操作符  |  节点  | 

 **Calico 资源在封锁的节点上调度或运行** 

默认情况下，不作为 DaemonSet 运行的 Calico 资源具有灵活的容忍度，可以将其调度到尚未准备好调度或运行容器组的封锁节点上。您可以通过更改操作符安装来包括以下内容，从而收紧对非 DaemonSet Calico 资源的容忍度。

```
installation:
  ...
  controlPlaneTolerations:
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  calicoKubeControllersDeployment:
    spec:
      template:
        spec:
          tolerations:
          - effect: NoExecute
            key: node.kubernetes.io/unreachable
            operator: Exists
            tolerationSeconds: 300
          - effect: NoExecute
            key: node.kubernetes.io/not-ready
            operator: Exists
            tolerationSeconds: 300
  typhaDeployment:
    spec:
      template:
        spec:
          tolerations:
          - effect: NoExecute
            key: node.kubernetes.io/unreachable
            operator: Exists
            tolerationSeconds: 300
          - effect: NoExecute
            key: node.kubernetes.io/not-ready
            operator: Exists
            tolerationSeconds: 300
```

## 凭证故障排除
<a name="hybrid-nodes-troubleshooting-creds"></a>

对于 AWS SSM 混合激活和 AWS IAM Roles Anywhere，您都可以通过在混合节点上运行以下命令来验证混合节点上的混合节点 IAM 角色凭证配置是否正确。确认节点名称和混合节点 IAM 角色名称是否符合预期。

```
sudo aws sts get-caller-identity
```

```
{
    "UserId": "ABCDEFGHIJKLM12345678910:<node-name>",
    "Account": "<aws-account-id>",
    "Arn": "arn:aws:sts::<aws-account-id>:assumed-role/<hybrid-nodes-iam-role/<node-name>"
}
```

 ** AWSSystems Manager（SSM）故障排除** 

如果将 AWS SSM 混合激活用作混合节点凭证，请注意以下将由 `nodeadm` 在混合节点上安装的 SSM 目录和构件。有关更多信息，请参阅《AWS Systems Manager 用户指南》**中的[使用 SSM Agent](https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html)。


| 说明 | 位置 | 
| --- | --- | 
|  SSM 代理  |  Ubuntu – `/snap/amazon-ssm-agent/current/amazon-ssm-agent` RHEL 和 AL2023 – `/usr/bin/amazon-ssm-agent`   | 
|  SSM 代理日志  |   `/var/log/amazon/ssm`   | 
|   AWS 凭证  |   `/root/.aws/credentials`   | 
|  SSM 安装 CLI  |   `/opt/ssm/ssm-setup-cli`   | 

 **重新启动 SSM Agent** 

有些问题可以通过重新启动 SSM Agent 来解决。您可以使用以下命令重新启动此代理。

 **AL2023 和其他操作系统** 

```
systemctl restart amazon-ssm-agent
```

 **Ubuntu** - 

```
systemctl restart snap.amazon-ssm-agent.amazon-ssm-agent
```

 **检查与 SSM 端点的连接** 

确认您可以从混合节点连接到 SSM 端点。有关 SSM 端点列表，请参阅 [AWS Systems Manager endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/ssm.html)。对于 AWS SSM 混合激活，请将以下命令中的 `us-west-2` 替换为 AWS 区域。

```
ping ssm.us-west-2.amazonaws.com
```

 **查看已注册 SSM 实例的连接状态** 

您可以使用以下 AWS CLI 命令检查通过 SSM 混合激活注册的实例的连接状态。请将 machine ID 替换为实例的机器 ID。

```
aws ssm get-connection-status --target mi-012345678abcdefgh
```

 **SSM 安装 CLI 校验和不匹配** 

运行 `nodeadm install` 时，如果您发现 `ssm-setup-cli` 校验和不匹配问题，应确认主机上没有早期版本的现有 SSM 安装。如果您的主机上有早期版本的 SSM 安装，请将其移除并重新运行 `nodeadm install` 以解决问题。

```
Failed to perform agent-installation/on-prem registration: error while verifying installed ssm-setup-cli checksum: checksum mismatch with latest ssm-setup-cli.
```

 **SSM `InvalidActivation`** 

如果您在将实例注册到 AWS SSM 时看到错误，请确认 `nodeConfig.yaml` 中的 `region`、`activationCode` 和 `activationId` 正确无误。EKS 集群的 AWS 区域必须与 SSM 混合激活区域一致。如果这些值的配置错误，则可能会看到与以下类似的错误。

```
ERROR Registration failed due to error registering the instance with AWS SSM. InvalidActivation
```

 **SSM `ExpiredTokenException`：请求中包含的安全令牌已过期** 

如果 SSM Agent 无法刷新凭证，您可能会看到 `ExpiredTokenException`。在这种情况下，如果能够从混合节点连接到 SSM 端点，则可能需要重新启动 SSM Agent 以强制刷新凭证。

```
"msg":"Command failed","error":"operation error SSM: DescribeInstanceInformation, https response error StatusCode: 400, RequestID: eee03a9e-f7cc-470a-9647-73d47e4cf0be, api error ExpiredTokenException: The security token included in the request is expired"
```

 **运行注册计算机命令时出现 SSM 错误** 

如果在将计算机注册到 SSM 时看到错误，则可能需要重新运行 `nodeadm install` 以确保正确安装所有 SSM 依赖项。

```
"error":"running register machine command: , error: fork/exec /opt/aws/ssm-setup-cli: no such file or directory"
```

 **SSM `ActivationExpired`** 

运行 `nodeadm init` 时，如果在将实例注册到 SSM 时因激活已过期而出现错误，则需要创建新的 SSM 混合激活，使用新 SSM 混合激活的 `activationCode` 和 `activationId` 更新 `nodeConfig.yaml`，然后重新运行 `nodeadm init`。

```
"msg":"Command failed","error":"SSM activation expired. Please use a valid activation"
```

```
ERROR Registration failed due to error registering the instance with AWS SSM. ActivationExpired
```

 **SSM 刷新缓存的凭证失败** 

如果发现无法刷新缓存的凭证，则说明 `/root/.aws/credentials` 文件可能已从主机中删除。首先检查您的 SSM 混合激活并确保其处于活动状态，并且混合节点已正确配置为使用该激活。检查 `/var/log/amazon/ssm` 中的 SSM Agent 日志，并在解决 SSM 端的问题后重新运行 `nodeadm init` 命令。

```
"Command failed","error":"operation error SSM: DescribeInstanceInformation, get identity: get credentials: failed to refresh cached credentials"
```

 **清理 SSM** 

要从主机上移除 SSM Agent，可以运行以下命令。

```
dnf remove -y amazon-ssm-agent
sudo apt remove --purge amazon-ssm-agent
snap remove amazon-ssm-agent
rm -rf /var/lib/amazon/ssm/Vault/Store/RegistrationKey
```

 ** AWSIAM Roles Anywhere 故障排除** 

如果将 AWS IAM Roles Anywhere 用作混合节点凭证，请注意将由 `nodeadm` 在混合节点上安装的以下目录和构件。有关 IAM Roles Anywhere 故障排除的更多信息，请参阅《AWS IAM Roles Anywhere 用户指南》**中的 [Troubleshooting AWS IAM Roles Anywhere identity and access](https://docs.aws.amazon.com/rolesanywhere/latest/userguide/security_iam_troubleshoot.html)。


| 说明 | 位置 | 
| --- | --- | 
|  IAM Roles Anywhere CLI  |   `/usr/local/bin/aws_signing_helper`   | 
|  默认证书位置和名称  |   `/etc/iam/pki/server.pem`   | 
|  默认密钥位置和名称  |   `/etc/iam/pki/server.key`   | 

 **IAM Roles Anywhere 刷新缓存的证书失败** 

如果您发现刷新缓存的证书失败，请检查 `/etc/aws/hybrid/config` 的内容并确认 `nodeadm` 配置中正确配置了 IAM Roles Anywhere。确认 `/etc/iam/pki` 存在。每个节点都必须具有唯一的证书和密钥。默认情况下，凭证提供者为 IAM Roles Anywhere 作时，`nodeadm` 将 `/etc/iam/pki/server.pem` 作为证书位置和名称，并将 `/etc/iam/pki/server.key` 作为私有密钥。在将证书和密钥放入目录之前，您可能需要首先使用 `sudo mkdir -p /etc/iam/pki` 创建目录。您可以使用以下命令验证证书的内容。

```
openssl x509 -text -noout -in server.pem
```

```
open /etc/iam/pki/server.pem: no such file or directory
could not parse PEM data
Command failed {"error": "... get identity: get credentials: failed to refresh cached credentials, process provider error: error in credential_process: exit status 1"}
```

 **IAM Roles Anywhere 无权执行 `sts:AssumeRole`** 

在 `kubelet` 日志中，如果您在使用 IAM Roles Anywhere 时看到 `sts:AssumeRole` 操作出现访问被拒绝的问题，请检查混合节点 IAM 角色的信任策略，以确认允许 IAM Roles Anywhere 服务主体代入该混合节点 IAM 角色。此外，请确认在混合节点 IAM 角色信任策略中正确配置了信任锚 ARN，并且已将混合节点 IAM 角色添加到 IAM Roles Anywhere 配置文件中。

```
could not get token: AccessDenied: User: ... is not authorized to perform: sts:AssumeRole on resource: ...
```

 **IAM Roles Anywhere 无权设置 `roleSessionName`** 

在 `kubelet` 日志中，如果您发现设置 `roleSessionName` 时出现访问被拒绝的问题，请确认您已将 IAM Roles Anywhere 配置文件的 `acceptRoleSessionName` 设置为 true。

```
AccessDeniedException: Not authorized to set roleSessionName
```

## 操作系统故障排除
<a name="hybrid-nodes-troubleshooting-os"></a>

### RHEL
<a name="_rhel"></a>

 **授权或订阅管理器注册失败** 

如果您运行的是 `nodeadm install`，但由于授权注册问题而无法安装混合节点依赖项，请确保在主机上正确设置了 Red Hat 用户名和密码。

```
This system is not registered with an entitlement server
```

### Ubuntu
<a name="_ubuntu"></a>

 **找不到 GLIBC** 

如果您的操作系统为 Ubuntu 操作系统，混合节点的凭证提供者为 IAM Roles Anywhere，但出现找不到 GLIBC 的问题，则可以通过手动安装该依赖项来解决问题。

```
GLIBC_2.32 not found (required by /usr/local/bin/aws_signing_helper)
```

运行以下命令安装依赖项：

```
ldd --version
sudo apt update && apt install libc6
sudo apt install glibc-source
```

### Bottlerocket
<a name="_bottlerocket"></a>

如果启用了 Bottlerocket 管理容器，则可以使用 SSH 访问该容器，从而使用更高的权限进行高级调试和故障排除。以下章节包含需要在 Bottlerocket 主机的上下文中运行的命令。进入管理容器后，您可以运行 `sheltie` 来获取 Bottlerocket 主机中的完整根 Shell。

```
sheltie
```

此外还可以通过在各个命令前加上前缀 `sudo chroot /.bottlerocket/rootfs`，从而在管理容器 Shell 中运行以下章节中的命令。

```
sudo chroot /.bottlerocket/rootfs <command>
```

 **使用 logdog 收集日志** 

Bottlerocket 提供了 `logdog` 实用程序，可用来高效地收集日志和系统信息，以满足故障排除的需要。

```
logdog
```

`logdog` 实用程序可从 Bottlerocket 主机的不同位置收集日志，然后组合成压缩包。默认情况下，该压缩包将在 `/var/log/support/bottlerocket-logs.tar.gz` 位置创建，并且可以从主机容器的 `/.bottlerocket/support/bottlerocket-logs.tar.gz` 位置访问。

 **使用 journalctl 访问系统日志** 

您可以使用以下命令检查各种系统服务（例如 `kubelet`、`containerd` 等）的状态以及查看其日志。`-f` 标志会实时跟踪日志。

要检查 `kubelet` 服务状态和检索 `kubelet` 日志，您可以运行以下命令：

```
systemctl status kubelet
journalctl -u kubelet -f
```

要检查 `containerd` 服务状态和检索已编排的 `containerd` 实例的日志，您可以运行以下命令：

```
systemctl status containerd
journalctl -u containerd -f
```

要检查 `host-containerd` 服务状态和检索主机 `containerd` 实例的日志，您可以运行以下命令：

```
systemctl status host-containerd
journalctl -u host-containerd -f
```

要检索引导容器和主机容器的日志，您可以运行以下命令：

```
journalctl _COMM=host-ctr -f
```