如何选择特定 IP 子网用于我的 Amazon EKS 集群中的容器组(pod)?

如何选择特定 IP 子网用于我的 Amazon EKS 集群中的容器组(pod)?

我想在 Amazon Elastic Kubernetes Service(Amazon EKS)中为我的容器组(pod)使用自定义子网或 IP 范围。
如何选择特定 IP 子网用于我的 Amazon EKS 集群中的容器组(pod)? 2023-08-22 07:19:47
如何选择特定 IP 子网用于我的 Amazon EKS 集群中的容器组(pod)? 0
如何选择特定 IP 子网用于我的 Amazon EKS 集群中的容器组(pod)?
## 简短描述 有时容器组(pod)不会使用您的 Amazon EKS 集群中的所有可用子网。当某些节点子网没有可用的 IP 地址,但是 Amazon Virtual Private Cloud(Amazon VPC)中的其他子网仍未得到充分利用时,会发生这种情况。 Amazon EKS 中的节点和容器组(pod)使用来自相同地址空间的 IP 地址:与集群 VPC 关联的 IP CIDR 范围。具体而言,Amazon EKS 从调度容器组(pod)的 Worker 节点的同一子网为容器组(pod)分配 IP。 例如,假设 node-1 在 subnet-1 中启动。也就是说,该节点的主要弹性网络接口位于 subnet-1 中。稍后,pod-A 可能会被部署并调度到 node-1。默认情况下,Amazon VPC CNI 插件在 subnet-1 中分配辅助弹性网络接口和 IP,为 pod-A 分配 IP 地址。 因此,用户无法直接控制容器组(pod)到 IP 子网的自定义分配,因为容器组(pod)和节点使用相同的子网。如果节点有足够的计算容量来运行多个容器组(pod),那么容器组(pod)可能会使用节点子网中所有可用的 IP 地址。由于节点子网中的 IP 地址耗尽,新容器组(pod)无法运行。即使 Amazon VPC 中的其他子网可能有可用的 IP 地址,也会发生这种情况。 ## 解决方法 您可以使用 Amazon VPC CNI 的自定义联网组件修复此问题。此功能允许您在 Amazon VPC 集群中定义特定的子网以供您的容器组(pod)使用。它将您的子网与 Worker 节点使用的子网区分开来。另外一个优势是,您可以为您的容器组(pod)定义安全组。有关自定义联网应用场景的更多信息,请参阅[教程:自定义联网](https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html?trk=cndc-detail)。 ### 先决条件 开始之前,请执行以下操作: 作为最佳实践,请确保您的集群中正在运行最新版本的 Amazon VPC CNI 插件。运行以下命令验证您的 Amazon VPC 集群中的版本: ``` kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2 ``` **注意**:有关最佳使用版本的更多信息,请参阅[更新自行管理附加组件的 Amazon VPC CNI 插件](https://docs.aws.amazon.com/eks/latest/userguide/managing-vpc-cni.html?trk=cndc-detail)。 ### 配置您的自定义子网和 IP 范围 按照以下步骤使用 Amazon VPC CNI 自定义联网功能: 1.    开启 Amazon VPC CNI 自定义联网功能: ``` kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true ``` 2.    创建 ENIConfig 对象来定义子网和安全组以供容器组(pod)使用。 一个 ENIConfig 对象定义一个子网和一个安全组列表。当一个节点仅使用一个 ENIConfig 对象进行注释或标记时,调度到该节点的所有容器组(pod)都使用该 ENIConfig 对象中定义的子网和安全组。 您可以自动或手动将 ENIConfig 对象与节点关联。 **自动将 ENIConfig 对象与节点关联** 此选项仅允许每个可用区(AZ)一个 ENIConfig 对象(一个子网)。ENIConfig 名称必须是可用区的名称。 1.    使用可用区名称创建 ENIConfig 对象: ``` cat <<EOF | kubectl apply -f - apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: us-east-2a spec: securityGroups: - sg-xxxxxxxxxxxx subnet: subnet-XXXXXXXX EOF cat <<EOF | kubectl apply -f - apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: us-east-2b spec: securityGroups: - sg-xxxxxxxxxxxx subnet: subnet-YYYYYYYYY EOF ``` 2.    启用 Amazon VPC-CNI,使用与节点可用区匹配的 ENIConfig 对象自动标记节点。 ``` kubectl set env daemonset aws-node -n kube-system ENI_CONFIG_LABEL_DEF=topology.kubernetes.io/zone ``` **手动将 ENIConfig 对象与节点关联** 此选项允许每个可用区有多个 ENIConfig 对象。请注意,您可以为每个 ENIConfig 对象使用自定义名称。确保节点和关联的 ENIConfig 对象位于同一个可用区内。 \*\*注意:\*\*您只能使用一个 ENIConfig 对象注释一个节点,但您可以使用同一 ENIConfig 对象注释多个节点。 1.    使用自定义名称创建 ENIConfig 对象,如下所示: ``` cat <<EOF | kubectl apply -f - apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: my-conf-1-us-east-2a spec: securityGroups: - sg-xxxxxxxxxxxx subnet: subnet-XXXXXXXX EOF cat <<EOF | kubectl apply -f - apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: my-conf-2-us-east-2a spec: securityGroups: - sg-xxxxxxxxxxxx subnet: subnet-ZZZZZZZZZZ EOF ``` 2.    使用 **ENIConfig** 对象手动注释节点。确保关联的 **ENIConfig** 对象中的节点和子网位于同一个可用区内。 ``` kubectl annotate node ip-192-168-0-126.us-east-2.compute.internal k8s.amazonaws.com/eniConfig=my-conf-1-us-east-2a ``` 此手动注释优先于 Amazon VPC CNI 自动添加的标记。 ### 启动新节点以替换当前的 Worker 节点 您在 Amazon VPC CNI 中开启自定义联网功能之前,现有 Worker 节点可能具有来自节点子网的辅助弹性网络接口和 IP。因此,您必须启动新节点,这样它们才能从与该节点关联的 ENIConfig 对象中定义的子网中分配辅助弹性网络接口和 IP 1.    验证您是否正在使用以下任一节点组选项: * 自行管理的节点组 * 具有自定义 AMI ID 的托管节点组 **注意**:如果您以这些节点组类型创建节点,请继续执行步骤 2,手动定义节点的容器组(pod)最大数量。如果您在未指定自定义 AMI 的情况下启动托管节点组中的节点,则 Amazon EKS 会自动更新节点的容器组(pod)最大数量。有关更多信息,请参阅[托管节点组](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html?trk=cndc-detail)。 2.    确定每个节点的容器组(pod)最大数量。当您使用自定义联网时,节点的主要网络接口不会用于容器组(pod)IP。要使用最大容器组(pod)计算器脚本确定最大容器组(pod)值,请参阅 [Amazon EKS 建议每种 EC2 实例类型的最大容器组(pod)数量](https://docs.aws.amazon.com/eks/latest/userguide/choosing-instance-type.html#determine-max-pods?trk=cndc-detail)。 **注意**:在上述脚本中使用 cni-custom-networking-enabled 标志,在您自己的实例以外的子网中启动容器组(pod)。 3.    更新新节点上的用户数据脚本以包含所需的标志。例如: ``` #!/bin/bash /etc/eks/bootstrap.sh my_cluster_name --use-max-pods false --kubelet-extra-args '--max-pods=20' ``` **注意**:将 my_cluster_name 替换为您的 EKS 集群名称。有关引导启动功能的更多信息,请参阅 GitHub 网站上的 [awslabs/amazon-eks-ami](https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh?trk=cndc-detail)。 4.    重新创建容器组(pod)以使用新的容器组(pod)自定义联网配置。 ### 其他注意事项 * 默认情况下,从容器组(pod)到集群 VPC CIDR 外部的 IP 地址的流量使用节点的主接口和 IP 地址。因此,此流量不使用 ENIConfig 中定义的子网和安全组。相反,流量使用节点主要网络接口的安全组和子网。有关更多信息,请参阅[适用于容器组(pod)的 SNAT](https://docs.aws.amazon.com/eks/latest/userguide/external-snat.html?trk=cndc-detail)。 * 如果您还为容器组(pod)使用安全组,则使用 SecurityGroupPolicy 中指定的安全组,而不是 ENIConfig 对象中指定的安全组。 * 有关 GitHub 网站上的最新更新,请参阅[简化 CNI 自定义联网](https://github.com/aws/containers-roadmap/issues/867?trk=cndc-detail)。 * 要向您的 VPC 添加更多 IP CIDR 范围,请按照[如何在 Amazon EKS 中使用多个 CIDR 范围?](https://repost.aws/zh-Hans/knowledge-center/eks-multiple-cidr-ranges?trk=cndc-detail)中的步骤进行操作。