View a markdown version of this page

Amazon VPC CNI - Amazon EKS

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Amazon VPC CNI

亚马逊 EKS 通过亚马逊 VPC 容器网络接口插件(也称为 VPC CNI)实现集群联网。CNI 插件允许 Kubernetes Pod 具有与 VPC 网络上相同的 IP 地址。更具体地说,Pod 内的所有容器共享一个网络命名空间,它们可以使用本地端口相互通信。

亚马逊 VPC CNI 有两个组件:

  • CNI 二进制,它将设置 Pod 网络以启用 Pod-to-Pod 通信。CNI 二进制文件在节点根文件系统上运行,当向该节点添加新 Pod 或将现有 Pod 从该节点中移除时,由 kubelet 调用。

  • ipamd,一个长时间运行的节点本地 IP 地址管理 (IPAM) 守护程序,负责:

    • 管理节点上的 ENI,以及

    • 维护可用的 IP 地址或前缀的温水池

创建实例时,EC2 会创建并连接与主子网关联的主 ENI。主子网可以是公有的,也可以是私有的。在主机网络模式下运行的 Pod 使用分配给节点主 ENI 的主 IP 地址,并与主机共享相同的网络命名空间。

CNI 插件管理节点上的弹性网络接口 (ENI)。配置节点时,CNI 插件会自动将节点子网中的插槽池(IP 或前缀)分配给主 ENI。该池称为温池,其大小由节点的实例类型决定。根据 CNI 设置,插槽可以是 IP 地址或前缀。在 ENI 上分配了插槽后,CNI 可能会将带有热插槽池的其他 ENI 连接到节点。这些额外的 ENI 称为次要 ENI。根据实例类型,每个 ENI 只能支持一定数量的插槽。CNI 根据所需的插槽数量(通常对应于 Pod 的数量)将更多 ENI 连接到实例。此过程一直持续到节点无法再支持其他 ENI 为止。CNI 还预先分配 “热” 的 ENI 和插槽,以更快地启动 Pod。请注意,每种实例类型都有最大可连接的 ENI 数量。除了计算资源外,这是 Pod 密度(每个节点的 Pod 数量)的一个限制。

流程图说明了何时需要新的 ENI 委托前缀的程序

您可以使用的最大网络接口数量和最大插槽数因 EC2 实例的类型而异。由于每个 Pod 在插槽上消耗一个 IP 地址,因此您可以在特定 EC2 实例上运行的 Pod 数量取决于可以连接多少 ENI 以及每个 ENI 支持多少插槽。我们建议设置每个 EKS 用户指南的最大 Pod 数,以避免耗尽实例的 CPU 和内存资源。使用hostNetwork的 Pod 不包括在此计算中。有关更多信息,请参阅《亚马逊 EKS 用户指南》中的 MaxPods 是如何确定的。

概述

辅助 IP 模式是 VPC CNI 的默认模式。本指南概述了启用辅助 IP 模式时的 VPC CNI 行为。ipamd(IP 地址分配)的功能可能会有所不同,具体取决于 VPC CNI 的配置设置,例如Linux 的前缀模式每个 Pod 的安全组数、和。自定义网络

亚马逊 VPC CNI 作为名为 aws-node 的 Kubernetes 守护程序集部署在工作节点上。配置工作节点时,它会附加一个默认 ENI,称为主 ENI。CNI 从连接到节点主网卡的子网中分配一个 ENI 和辅助 IP 地址的温水池。默认情况下,ipamd 会尝试为该节点分配额外的 ENI。当调度单个 Pod 并从主 ENI 中分配辅助 IP 地址时,IPAMD 会分配额外的 ENI。这种 “温暖” 的 ENI 支持更快的 Pod 联网。随着辅助 IP 地址池的用完,CNI 会添加另一个 ENI 来分配更多。

池中 ENI 和 IP 地址的数量是通过名为 WARM_ENI_TARGET、WARM_IP_TARGET、MINIMUM_IP_TARGET、MINIMUM_IP_TARGET 的环境变量配置的。aws-node守护程序集将定期检查是否连接了足够数量的 ENI。当所有或WARM_IP_TARGETMINIMUM_IP_TARGET条件都满足时WARM_ENI_TARGET,将附加足够数量的 ENI。如果连接的 ENI 不足,CNI 将向 EC2 发出 API 调用以连接更多,直到MAX_ENI达到上限。

  • WARM_ENI_TARGET-整数,大于 0 的值表示要求已启用

    • 要维护的 Warm ENI 的数量。当 ENI 作为辅助 ENI 连接到节点时,它处于 “温暖” 状态,但不被任何 Pod 使用。更具体地说,没有任何 ENI 的 IP 地址与 Pod 相关联。

    • 示例:假设一个具有 2 个 ENI 的实例,每个 ENI 支持 5 个 IP 地址。WARM_ENI_TARGET 设置为 1。如果恰好有 5 个 IP 地址与该实例关联,CNI 将保持 2 个 ENI 连接到该实例。第一个 ENI 正在使用中,并且使用了此 ENI 的所有 5 个可能的 IP 地址。第二个 ENI 是 “温热的”,所有 5 个 IP 地址都在池中。如果在实例上启动另一个 Pod,则需要第 6 个 IP 地址。CNI 将为第 6 个 Pod 分配来自第二个 ENI 和池中的 5 个 IP 地址的 IP 地址。第二个 ENI 现在正在使用中,不再处于 “热” 状态。CNI 将分配第 3 个 ENI 以维持至少 1 个预热的 ENI。

注意

热网卡仍会消耗来自您的 VPC 的 CIDR 的 IP 地址。IP 地址在与工作负载(例如 Pod)关联之前,它们是 “未使用的” 或 “热的”。

  • WARM_IP_TARGET、整数、大于 0 的值表示要求已启用

    • 要维护的温暖 IP 地址的数量。Warm IP 可在主动连接的 ENI 上使用,但尚未分配给 Pod。换句话说,可用的 Warm IP 数量是指无需额外的 ENI 即可分配给 Pod 的 IP 数量。

    • 示例:假设一个具有 1 个 ENI 的实例,每个 ENI 支持 20 个 IP 地址。WARM_IP_TARGET 设置为 5。WARM_ENI_TARGET 设置为 0。在需要第 16 个 IP 地址之前,只会连接 1 个 ENI。然后,CNI 将连接第二个 ENI,消耗子网 CIDR 中的 20 个可能的地址。

  • MINIMUM_IP_TARGET、整数、大于 0 的值表示要求已启用

    • 任何时候要分配的最小 IP 地址数。这通常用于在实例启动时预先加载多个 ENI 的分配。

    • 示例:假设一个新启动的实例。它有 1 个 ENI,每个 ENI 支持 10 个 IP 地址。MINIMUM_IP_TARGET 设置为 100。ENI 立即再连接 9 个 ENI,总共 100 个地址。无论任何 WARM_IP_TARGET 或 WARM_ENI_TARGET 值为何,都会发生这种情况。

该项目包括子网计算器 Excel 文档。本计算器文档模拟了不同 ENI 配置选项(例如WARM_IP_TARGETWARM_ENI_TARGET)下指定工作负载的 IP 地址消耗。

为 Pod 分配 IP 地址所涉及的组件示意图

当 Kubelet 收到添加 Pod 请求时,CNI 二进制文件会向 ipamd 查询可用的 IP 地址,然后 ipamd 会将其提供给 Pod。CNI 二进制文件连接了主机和 Pod 网络。

默认情况下,部署在节点上的 Pod 会被分配到与主 ENI 相同的安全组。或者,可以将 Pod 配置为不同的安全组。

为 pod 分配 IP 地址所涉及的组件的第二个示例

在 IP 地址池耗尽时,该插件会自动附加另一个弹性网络接口到实例,并将另外一组辅助 IP 地址分配到接口。此过程将继续,直到节点不再支持额外的弹性网络接口。

为容器分配 IP 地址所涉及的组件的第三张插图

删除 Pod 后,VPC CNI 会将该 Pod 的 IP 地址放入 30 秒的冷却缓存中。冷却缓存中的 IP 不会分配给新的 Pod。冷却期结束后,VPC CNI 会将 Pod IP 移回温池。冷却期可防止 Pod IP 地址过早回收,并允许所有集群节点上的 kube-proxy 完成 iptables 规则的更新。当 IP 或 ENI 的数量超过温池设置的数量时,ipamd 插件会将 IP 和 ENI 返回到 VPC。

如上所述,在辅助 IP 模式下,每个 Pod 从连接到实例的其中一个 ENI 中接收一个辅助私有 IP 地址。由于每个 Pod 都使用一个 IP 地址,因此你可以在特定 EC2 实例上运行的 Pod 的数量取决于它可以连接多少个 ENI 以及它支持多少个 IP 地址。VPC CNI 检查限制文件,以了解每种类型的实例允许使用多少个 ENI 和 IP 地址。

你可以使用以下公式来确定你可以在一个节点上部署的最大 Pod 数量。

(Number of network interfaces for the instance type * (the number of IP addresses per network interface - 1)) + 2

+2 表示需要主机网络的 Pod,例如 kube-proxy 和 VPC CNI。亚马逊 EKS 要求 kube-proxy 和 VPC CNI 在每个节点上运行,这些要求已计入最大容量值。如果你想运行更多的主机网络 pod,可以考虑更新 max-pods 的值。可以在启动模板中指定--kubelet-extra-args "—max-pods=110"为用户数据。

例如,在拥有 3 个 c5.large 节点(3 个 ENI 和每个 ENI 最多 10 个 IP)的集群上,当集群启动并拥有 2 个 CoreDNS 容器时,CNI 将消耗 50 个 IP 地址并保留 43 个 IP 在温池中。部署应用程序时,温水池可以更快地启动 Pod。

节点 1(带有 CoreDNS 容器):2 个 ENI,分配 20 个 IP

节点 2(带有 CoreDNS 容器):2 个 ENI,分配 20 个 IP

节点 3(无 Pod):1 个 ENI。分配了 10 个 IP。

对于节点 1 和节点 2(相同配置):

  • 2 个 ENI × 每个 ENI 10 个 IP = 总计 20 个 IP

  • 减去 2 个主 IP(每个 ENI 1 个)= 18 个 IP

  • 减去 CoreDNS pod 的 1 个 IP = 17 个可用 IP

  • 因此,每个节点在温水池中都有 17 个 IP

对于节点 3:

  • 1 个 ENI × 10 个 IP = 总计 10 个 IP

  • 减去 1 个主 IP = 温水池中有 9 个 IP 可用

总热池计算:-17(节点 1)+ 17(节点 2)+ 9(节点 3)= 43 个 IP

请记住,基础架构 pod 通常作为守护程序集运行,每个容器都占最大容量 pod 数量。这些可能包括:

  • CoreDNS

  • 亚马逊弹性 LoadBalancer

  • 指标服务器的操作舱

我们建议您通过组合这些 Pod 的容量来规划基础架构。有关每种实例类型支持的最大 Pod 数量的列表,请参阅的 eni-max-pods.txt GitHub。

连接到一个节点的多个 ENI 的图示

建议

使用自动模式部署 EKS 集群

当您使用 EKS 自动模式创建集群时,AWS 会管理您的集群的 VPC 容器网络接口 (CNI) 配置。使用 Amazon EKS 自动模式时,您无需安装或升级联网附加组件。但是,请确保您的工作负载与托管的 VPC CNI 配置兼容。

部署 VPC CNI 托管 Add-On

当您预置集群时,亚马逊 EKS 会自动安装 VPC CNI。但是,Amazon EKS 支持托管插件,使集群能够与计算、存储和联网等底层 AWS 资源进行交互。我们强烈建议您使用包括 VPC CNI 在内的托管插件部署集群。

亚马逊 EKS 托管插件为亚马逊 EKS 集群提供 VPC CNI 安装和管理。亚马逊 EKS 插件包括最新的安全补丁和错误修复,并经 AWS 验证可与亚马逊 EKS 配合使用。VPC CNI 插件使您能够持续确保 Amazon EKS 集群的安全性和稳定性,并减少安装、配置和更新插件所需的工作量。此外,可以通过亚马逊 EKS API、AWS 管理控制台、AWS CLI 和 eksctl 添加、更新或删除托管插件。

您可以使用带有kubectl get命令的--show-managed-fields标志来查找 VPC CNI 的托管字段。

kubectl get daemonset aws-node --show-managed-fields -n kube-system -o yaml

托管插件每 15 分钟自动覆盖配置,从而防止配置偏差。这意味着,在插件创建后通过 Kubernetes API 对托管插件所做的任何更改都将被自动防漂移过程覆盖,并在插件更新过程中设置为默认值。

由 EKS 管理的字段列在 managedFields 下,管理员名为 EKS。EKS 管理的字段包括服务帐号、图片、图片 URL、存活率探测、就绪探测、标签、卷和音量挂载。

注意

诸如 WARM_ENI_TARGET、WARM_IP_TARGET 和 MINIMUM_IP_TARGET 等最常用的字段不受管理,也无法进行协调。更新插件后,对这些字段的更改将保留。

我们建议在更新生产集群之前,针对特定配置测试非生产集群中的插件行为。此外,请按照 EKS 用户指南中的步骤进行插件配置。

迁移到托管 Add-On

您将管理自建的 VPC CNI 的版本兼容性并更新安全补丁。要更新自我管理的插件,必须使用 EKS 用户指南中概述的 Kubernetes API 和说明。https://docs.aws.amazon.com/eks/latest/userguide/managing-vpc-cni.html#updating-vpc-cni-add-on我们建议将现有 EKS 集群迁移到托管插件,并强烈建议在迁移之前创建当前 CNI 设置的备份。要配置托管插件,您可以使用 Amazon EKS API、AWS 管理控制台或 AWS 命令行接口。

kubectl apply view-last-applied daemonset aws-node -n kube-system  aws-k8s-cni-old.yaml

如果该字段列为使用默认设置进行管理,Amazon EKS 将替换 CNI 配置设置。我们提醒不要修改托管字段。该插件不协调温暖环境变量和 CNI 模式等配置字段。当你迁移到托管 CNI 时,Pod 和应用程序将继续运行。

更新前备份 CNI 设置

VPC CNI 在客户数据平面(节点)上运行,因此,在新版本发布时或将集群更新到新的 Kubernetes 次要版本之后,Amazon EKS 不会自动更新插件(托管和自管理)。要更新现有集群的插件,必须通过 update-addon API 触发更新,或者在 EKS 控制台中单击插件的 “立即更新” 链接来触发更新。如果您已部署自行管理的插件,请按照更新自管 VPC CNI 插件中提及的步骤进行操作。

我们强烈建议您一次更新一个次要版本。例如,如果您的当前的次要版本为 1.9,并且您想要更新到 1.11,则应首先更新到最新的补丁版本 1.10,再更新到最新的补丁版本 1.11

在更新亚马逊 VPC CNI 之前,对 aws-node 守护程序集进行检查。备份现有设置。如果使用托管插件,请确认您没有更新 Amazon EKS 可能覆盖的任何设置。我们建议在自动化工作流程中使用更新后挂钩,或者在插件更新后手动应用步骤。

kubectl apply view-last-applied daemonset aws-node -n kube-system aws-k8s-cni-old.yaml

对于自行管理的插件,请将备份与 releases on 进行比较 GitHub 以查看可用版本并熟悉要更新到的版本中的更改。我们建议使用 Helm 来管理自我管理的插件,并利用值文件来应用设置。任何涉及 Daemonset 删除的更新操作都将导致应用程序停机,必须避免。

了解安全背景

我们强烈建议您了解为高效管理 VPC CNI 而配置的安全环境。亚马逊 VPC CNI 有两个组件:CNI 二进制文件和 ipamd(aws-node)守护程序集。CNI 在节点上以二进制形式运行,可以访问节点根文件系统,在节点级别处理 iptables 时也有特权访问权限。当 Pod 被添加或移除时,kubelet 会调用 CNI 二进制文件。

aws-node 守护程序集是一个长期运行的进程,负责节点级别的 IP 地址管理。aws-node 以hostNetwork模式运行,允许访问环回设备以及同一节点上其他 Pod 的网络活动。aws-node 初始化容器在特权模式下运行并挂载 CRI 套接字,允许 Daemonset 监控节点上运行的 Pod 的 IP 使用情况。亚马逊 EKS 正在努力取消对 aws-node 初始化容器的特权要求。此外,aws-node 需要更新 NAT 条目并加载 iptables 模块,因此以 NET_ADMIN 权限运行。

亚马逊 EKS 建议部署由 aws-node 清单定义的安全策略,用于 Pod 和网络设置的 IP 管理。请考虑更新到最新版本的 VPC CNI。此外,如果您有特定的安全要求,请考虑提出GitHub 问题。

为 CNI 使用单独的 IAM 角色

AWS VPC CNI 需要 AWS 身份和访问管理 (IAM) 权限。需要先设置 CNI 政策,然后才能使用 IAM 角色。您可以使用 AmazonEKS_CNI_Policy,这是适用于 IPv4 集群的 AWS 托管策略。亚马逊的 CNI 托管策略仅具有 IPv4 集群的权限。您必须使用此处列出的权限为 IPv6 集群创建单独的 IAM 策略

默认情况下,VPC CNI 继承亚马逊 EKS 节点 IAM 角色(包括托管节点组和自管理节点组)。

强烈建议使用亚马逊 VPC CNI 的相关策略配置单独的 IAM 角色。否则,Amazon VPC CNI 的容器将获得分配给节点 IAM 角色的权限,并有权访问分配给该节点的实例配置文件。

VPC CNI 插件创建和配置了一个名为 aws-node 的服务账户。默认情况下,服务账户绑定到附有亚马逊 EKS CNI 政策的亚马逊 EKS 节点 IAM 角色。要使用单独的 IAM 角色,我们建议您创建一个附有 Amazon EKS CNI 政策的新服务账户。要使用新的服务帐号,必须重新部署 CNI pod。创建新集群时,可以考虑--service-account-role-arn为 VPC CNI 托管插件指定。确保从亚马逊 EKS 节点角色中删除针对 IPv4 和 IPv6 的亚马逊 EKS CNI 政策。

建议您屏蔽访问实例元数据,以最大限度地减少安全漏洞的爆炸半径。

处理 Liveness/Readiness 探测故障

我们建议增加 EKS 1.20 及更高版本集群的存活率和就绪探测超时值(默认timeoutSeconds: 10),以防止探测失败导致应用程序的 Pod 停留在容器创建状态。在数据密集型和批处理集群中已经出现了这个问题。CPU 使用率过高会导致 aws-node 探测器运行状况失败,从而导致 Pod CPU 请求未完成。除了修改探测超时时间外,还要确保 aws-node 的 CPU 资源请求(默认CPU: 25m)配置正确。除非您的节点出现问题,否则我们不建议更新设置。

我们强烈建议您在获得亚马逊 EKS 支持服务的同时在节点bash /opt/cni/bin/aws-cni-support.sh上运行 sudo。该脚本将帮助评估节点上的 kubelet 日志和内存利用率。请考虑在亚马逊 EKS 工作节点上安装 SSM 代理来运行脚本。

在非 EKS 优化的 AMI 实例上配置 IPtables 转发策略

如果你使用自定义 AMI,请务必在 kub elet.service 下将 iptables 转发策略设置为 ACCEPT。许多系统将 iptables 转发策略设置为 DROP。您可以使用 HashiCorp Packer 和包含来自 AWS GitHub 亚马逊 EKS AMI 存储库的资源和配置脚本的构建规范来构建自定义 AMI。您可以更新 kubelet.service 并按照此处指定的说明创建自定义 AMI。

定期升级 CNI 版本

VPC CNI 向后兼容。最新版本适用于 Amazon EKS 支持的所有 Kubernetes 版本。此外,VPC CNI 作为 EKS 插件提供(请参阅上面的 “部署托管 VPC CNI Add-On”)。虽然 EKS 插件负责协调插件的升级,但它不会自动升级 CNI 等插件,因为它们在数据平面上运行。在托管和自我管理的工作节点升级之后,您有责任升级 VPC CNI 插件。