提高 Amazon EC2 节点的可用 IP 地址数量 - Amazon EKS

提高 Amazon EC2 节点的可用 IP 地址数量

每个 Amazon EC2 实例支持最大数量的弹性网络接口以及可分配给每个网络接口的最大数量的 IP 地址。每个节点的每个网络接口都需要一个 IP 地址。可以将所有其他可用 IP 地址分配给 Pods。每个都 Pod 需要自己的 IP 地址。因此,您的节点可能有可用的计算和内存资源,但无法容纳其他 Pods,因为该节点已用完分配给 Pods 的 IP 地址。

在本主题中,您将学习如何通过分配 IP 前缀而不是为节点分配单个辅助 IP 地址来显著增加节点可以分配给 Pods 的 IP 地址数量。每个前缀都包含多个 IP 地址。如果您没有为集群配置 IP 前缀分配,则您的集群必须进行更多 Amazon EC2 应用程序编程接口(API)调用才能配置 Pod 连接所需的网络接口和 IP 地址。随着集群规模的扩大,这些 API 调用的频率可能会导致 Pod 和实例启动时间延长。这会导致扩展延迟以满足大型和尖峰工作负载的需求,并增加成本和管理开销,因为您需要配置额外的集群和 VPC 来满足扩展需求。有关更多信息,请参阅 GitHub 上的 Kubernetes 可扩展性阈值

注意事项
  • 每种 Amazon EC2 实例类型支持最大数量的 Pods。如果您的托管节点组由多种实例类型组成,则集群中某个实例的最大 Pods 数量的最小值将应用于集群中的所有节点。

  • 默认情况下,可以在节点上运行的最大 Pods 数量为 110,但您可以更改该数字。如果您更改该数量并且有现有的托管节点组,则节点组的下一次 AMI 或启动模板更新会导致新节点出现时使用更改后的值。

  • 从分配 IP 地址过渡到分配 IP 前缀时,建议您创建新的节点组以增加可用 IP 地址的数量,而不是滚动替换现有节点。在同时分配 IP 地址和前缀的节点上运行 Pods 可能会导致通告的 IP 地址容量不一致,从而影响节点上未来的工作负载。有关执行过渡的推荐方式,请参阅 Amazon EKS 最佳实践指南中的在从辅助 IP 模式迁移到前缀委派模式期间替换所有节点(反之亦然)

  • 仅适用于具有 Linux 节点的集群。

    • 将附加组件配置为向网络接口分配前缀后,您将无法在不删除集群所有节点组中的所有节点的情况下将 Amazon VPC CNI plugin for Kubernetes 附加组件版本降级到 1.9.0(或 1.10.1)以下。

    • 如果您的 Pods 在与 VPC 外部的端点通信的同时使用了 Pods 的安全组(POD_SECURITY_GROUP_ENFORCING_MODE=standard 和 AWS_VPC_K8S_CNI_EXTERNALSNAT=false),则使用节点的安全组,而不是您分配给 Pods 的任何安全组。

      如果您的 Pods 在与 VPC 外部的端点通信的同时使用了 Pods 的安全组 (POD_SECURITY_GROUP_ENFORCING_MODE=strict),则使用 Pod's 安全组。

先决条件
  • 现有集群。要部署一个角色,请参阅 创建 Amazon EKS 集群

  • 您的 Amazon EKS 节点所在的子网必须有足够的连续 /28(适用于 IPv4 集群)或 /80(适用于 IPv6 集群)无类别域间路由 (CIDR) 块。IPv6 集群中只能有 Linux 节点。如果 IP 地址分散在整个子网 CIDR 中,则使用 IP 前缀可能会失败。建议执行下列操作:

    • 使用子网 CIDR 预留,这样即使保留范围内的任何 IP 地址仍在使用,在其释放后,这些 IP 地址也不会重新分配。这样可以确保前缀在不分段的情况下进行分配。

    • 使用专门用于运行分配 IP 前缀的工作负载的新子网。分配 IP 前缀时,Windows 和 Linux 工作负载可以在同一个子网中运行。

  • 要为节点分配 IP 前缀,您的节点必须基于 AWS Nitro。不基于 Nitro 的实例会继续分配单个辅助 IP 地址,但分配给 Pods 的 IP 地址数量比 Nitro-based 实例少得多。

  • 仅适用于具有 Linux 节点的集群 - 如果您的集群是针对 IPv4 系列配置的,则必须安装 Amazon VPC CNI plugin for Kubernetes 附加组件的 1.9.0 版或更高版本。您可以使用以下命令检查当前版本。

    kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2

    如果您的集群是针对 IPv6 系列配置的,则必须安装附加组件的 1.10.1 版。如果您的插件版本低于所需版本,则必须进行更新。想要了解更多信息,请参阅 使用 Amazon VPC CNI plugin for Kubernetes Amazon EKS 附加组件 的更新部分。

  • 仅适用于具有 Windows 节点的集群

    • 您的集群及其平台版本必须等于或高于下表中的版本。要升级集群版本,请参阅 更新 Amazon EKS 集群 Kubernetes 版本。如果您的集群未达到最低平台版本,则在 Amazon EKS 更新您的平台版本之前,您无法为节点分配 IP 前缀。

      Kubernetes 版本 平台版本
      1.27 eks.3
      1.26 eks.4
      1.25 eks.5

      您可以通过将以下命令中的 my-cluster 替换为集群名称,然后运行修改后的命令来检查当前 Kubernetes 和平台版本:aws eks describe-cluster --name my-cluster --query 'cluster.{"Kubernetes Version": version, "Platform Version": platformVersion}'

    • 为集群启用 Windows 支持。有关更多信息,请参阅为 Amazon EKS 集群启用 Windows 支持

提高 Amazon EC2 节点的可用 IP 地址数量的步骤
  1. 配置集群以将 IP 地址前缀分配给节点。在与节点的操作系统相匹配的选项卡上完成步骤。

    Linux
    1. 启用参数,以便为 Amazon VPC CNI DaemonSet 的网络接口分配前缀。当您部署 1.21 或更高版本的集群时,1.10.1 或更高版本的 Amazon VPC CNI plugin for Kubernetes 附加组件随它一起部署。如果您使用 IPv6 系列创建集群,这个设置将被默认设置为 true。如果您使用 IPv4 系列创建集群,这个设置将被默认设置为 false

      kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true
      重要

      即使您的子网有可用的 IP 地址,如果子网没有任何连续 /28 数据块可用,您也将在 Amazon VPC CNI plugin for Kubernetes 日志中看到以下错误。

      InsufficientCidrBlocks: The specified subnet does not have enough free cidr blocks to satisfy the request

      发生这种情况的原因可能是分散在子网中的现有辅助 IP 地址的碎片。要解决此错误,请创建一个新子网并在那里启动 Pods,或者使用 Amazon EC2 子网 CIDR 预留在子网中预留空间以便与前缀分配一起使用。有关更多信息,请参阅《Amazon VPC 用户指南》中的子网 CIDR 预留

    2. 如果您计划在没有启动模板的情况下部署托管节点组,或者采用尚未在其中指定 AMI ID 的启动模板,并且您使用的是在先决条件中列出的 Amazon VPC CNI plugin for Kubernetes 版本或更高版本,则跳至下一步。托管节点组会自动为您计算最大 Pods 数量。

      如果您正在部署自我管理的节点组或带有启动模板的托管节点组,且其启动模板已指定了 AMI ID,则必须确定 Amazon EKS 为节点推荐的最大 Pods 数量。按照 Amazon EKS 建议每种 Amazon EC2 实例类型的最大 Pods 数量 中的说明进行操作,将 --cni-prefix-delegation-enabled 添加到步骤 3。请记下输出的内容,以便在下一个步骤中使用。

      重要

      托管节点组强制执行 maxPods 的值的最大数量。对于 vCPUs 少于 30 个的实例,最大数量为 110,对于所有其他实例,最大数量为 250。无论是否启用前缀委派,均应用此最大数量。

    3. 如果您使用配置为使用 IPv61.21 或更高版本的集群,请跳至下一步。

      在以下选项中指定参数。要确定哪个选项适合您以及为其提供哪些值,请参阅 GitHub 上的 WARM_PREFIX_TARGETWARM_IP_TARGETMINIMUM_IP_TARGET

      您可以将 example values 替换为大于零的值。

      • WARM_PREFIX_TARGET

        kubectl set env ds aws-node -n kube-system WARM_PREFIX_TARGET=1
      • WARM_IP_TARGETMINIMUM_IP_TARGET:如果设置了两种值之一,则其会覆盖所设置的 WARM_PREFIX_TARGET 的值。

        kubectl set env ds aws-node -n kube-system WARM_IP_TARGET=5
        kubectl set env ds aws-node -n kube-system MINIMUM_IP_TARGET=2
    4. 使用至少一种 Amazon EC2 Nitro Amazon Linux 2 实例类型创建以下类型之一的节点组。有关 Nitro 实例类型的列表,请参阅适用于 Linux 实例的 Amazon EC2 用户指南中的基于 Nitro 系统构建的实例。Windows 中不支持此功能。对于包含 110 的选项,将其替换为第 3 步中的值(建议)或您自己的值。

      • 自行管理的节点组 – 按照 启动自行管理的 Amazon Linux 节点 中的说明部署节点组。为 BootstrapArguments 参数指定以下文本。

        --use-max-pods false --kubelet-extra-args '--max-pods=110'

        如果使用 eksctl 创建节点组,可以使用下面的命令。

        eksctl create nodegroup --cluster my-cluster --managed=false --max-pods-per-node 110
      • 托管:使用以下选项之一部署您的节点组:

        • 没有启动模板或者没有指定 AMI ID 的启动模板:完成 创建托管节点组 中的过程。托管节点组会自动为您计算 Amazon EKS 建议的 max-pods 值。

        • 使用具有指定 AMI ID 的启动模板:在启动模板中,指定 Amazon EKS 优化的 AMI ID,或者指定基于 Amazon EKS 优化 AMI 构建的自定义 AMI,然后使用启动模板部署节点组并在启动模板中提供以下用户数据。此用户数据会将实际参数传递到 bootstrap.sh 文件中。有关引导文件的更多信息,请参阅 GitHub 上的 bootstrap.sh

          /etc/eks/bootstrap.sh my-cluster \ --use-max-pods false \ --kubelet-extra-args '--max-pods=110'

          如果使用 eksctl 创建节点组,可以使用下面的命令。

          eksctl create nodegroup --cluster my-cluster --max-pods-per-node 110

          如果您创建的自定义 AMI 不是基于 Amazon EKS 优化 AMI 构建的,则需要自行自定义创建配置。

        注意

        如果您还想将 IP 地址分配给不同于实例子网的 Pods,则需要在此步骤中启用该功能。有关更多信息,请参阅容器组(pod)的自定义网络

    Windows
    1. 启用 IP 前缀的分配。

      1. 打开 amazon-vpc-cni ConfigMap 进行编辑。

        kubectl edit configmap -n kube-system amazon-vpc-cni -o yaml
      2. 将以下行添加到 data 部分。

        enable-windows-prefix-delegation: "true"
      3. 保存文件,然后关闭编辑器。

      4. 确认该行已添加到 ConfigMap

        kubectl get configmap -n kube-system amazon-vpc-cni -o "jsonpath={.data.enable-windows-prefix-delegation}"

        如果返回的输出并非 true,则可能存在错误。尝试再次完成该步骤。

        重要

        即使您的子网有可用的 IP 地址,如果子网没有任何连续 /28 数据块可用,您也将在节点事件中看到以下错误。

        "failed to allocate a private IP/Prefix address: InsufficientCidrBlocks: The specified subnet does not have enough free cidr blocks to satisfy the request"

        发生这种情况的原因可能是分散在子网中的现有辅助 IP 地址的碎片。要解决此错误,请创建一个新子网并在那里启动 Pods,或者使用 Amazon EC2 子网 CIDR 预留在子网中预留空间以便与前缀分配一起使用。有关更多信息,请参阅《Amazon VPC 用户指南》中的子网 CIDR 预留

    2. (可选)指定其他配置以控制集群的预扩展和动态扩展行为。有关更多信息,请参阅 GitHub 上的在 Windows 上使用前缀委派模式的配置选项

      1. 打开 amazon-vpc-cni ConfigMap 进行编辑。

        kubectl edit configmap -n kube-system amazon-vpc-cni -o yaml
      2. 用大于零的值替换 example values,然后将所需的条目添加到 ConfigMap 的 data 部分。如果您为 warm-ip-target 或 minimum-ip-target 设置了值,则该值将覆盖为 warm-prefix-target 设置的任何值。

        warm-prefix-target: "1" warm-ip-target: "5" minimum-ip-target: "2"
      3. 保存文件,然后关闭编辑器。

    3. 创建至少有一种 Amazon EC2 Nitro 实例类型的 Windows 节点组。有关 Nitro 实例类型的列表,请参阅《适用于 Windows 实例的 Amazon EC2 用户指南》中的基于 Nitro 系统构建的实例。默认情况下,您可以部署到节点的最大 Pods 数量为 110。如果要增加或减少该数量,则请在引导配置的用户数据中指定以下内容。将 max-pods-quantity 替换为最大容器组值。

      -KubeletExtraArgs '--max-pods=max-pods-quantity'

      如果您要部署托管节点组,则需要在启动模板中添加此配置。有关更多信息,请参阅使用启动模板自定义托管节点。有关 Windows 引导脚本配置参数的更多信息,请参阅 引导脚本配置参数

  2. 节点部署完成后,请查看集群中的节点。

    kubectl get nodes

    示例输出如下。

    NAME STATUS ROLES AGE VERSION ip-192-168-22-103.region-code.compute.internal Ready <none> 19m v1.XX.X-eks-6b7464 ip-192-168-97-94.region-code.compute.internal Ready <none> 19m v1.XX.X-eks-6b7464
  3. 描述其中一个节点以确定该节点的 max-pods 值和可用 IP 地址数量。将 192.168.30.193 替换为之前输出中返回的其中一个节点名称中的 IPv4 地址。

    kubectl describe node ip-192-168-30-193.region-code.compute.internal | grep 'pods\|PrivateIPv4Address'

    示例输出如下。

    pods:                                  110
    vpc.amazonaws.com/PrivateIPv4Address:  144

    在先前的输出中,110 是 Kubernetes 将部署到节点的最大 Pods 数量,尽管有 144 个 IP 地址可用。