我该如何通过 Amazon EKS 使用多个 CIDR 范围?

上次更新日期:2022 年 12 月 27 日

我想通过 Amazon Elastic Kubernetes Service(Amazon EKS)使用多个 CIDR 范围以解决我的容器组(pod)遇到的问题。例如,如何通过添加到我的 Amazon Virtual Private Cloud (Amazon VPC) 的不同 CIDR 范围运行 Pod? 此外,当子网的 IP 地址耗尽时,如何为它增加更多 IP 地址? 最后,我要如何确保在工作线程节点上运行的 Pod 有不同的 IP 范围?

简短描述

在您完成解决方法部分的步骤前,确保您有以下各项:

  • 处于运行状态的 Amazon EKS 集群
  • 可访问版本号不低于 1.16.284 的 AWS 命令行界面 (AWS CLI) 的权限
  • 可管理 Amazon VPC 的 AWS Identity and Access Management (IAM) 权限
  • kubectl 和创建自定义资源及编辑 DaemonsSet 的权限
  • 系统上已安装的 jq 版本(来自 jq 网站)
  • 带有 Bash shell 的基于 Unix 的系统

请记住:

重要提示:在某些情况下,创建集群后,Amazon EKS 无法与通过添加到 VPC 的其他 CIDR 数据块在子网中启动的节点进行通信。向现有集群添加 CIDR 数据块所导致的更新范围可能需要长达 5 小时才能显示。

解决方法

注意:如果在运行 AWS CLI 命令时收到错误,请确保您使用的是最新版本的 AWS CLI

在以下解决方案中,您首先需要设置 VPC。然后,配置 CNI 插件以使用新的 CIDR 范围。

添加额外的 CIDR 范围以扩展您的 VPC 网络

1.    查找您的 VPC。

如果您的 VPC 有标签,运行以下命令来查找您的 VPC:

VPC_ID=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=yourVPCName | jq -r '.Vpcs[].VpcId')

如果您的 VPC 没有标签,则运行以下命令以列出 AWS 区域中的全部 VPC:

aws ec2 describe-vpcs --filters  | jq -r '.Vpcs[].VpcId'

2.    要将您的 VPC 附加到 VPC_ID 变量,运行以下命令:

export VPC_ID=vpc-xxxxxxxxxxxx

3.    要将范围为 100.64.0.0/16 的额外 CIDR 块关联到 VPC,运行以下命令:

aws ec2 associate-vpc-cidr-block --vpc-id $VPC_ID --cidr-block 100.64.0.0/16

使用新的 CIDR 范围创建子网

1.    要列出您的 AWS 区域中的全部可用区,运行以下命令:

aws ec2 describe-availability-zones --region us-east-1 --query 'AvailabilityZones[*].ZoneName'

注:us-east-1 替换为您的 AWS 区域。

2.    选择您想要添加子网的可用区,然后将这些可用区分配给变量。例如:

export AZ1=us-east-1a
export AZ2=us-east-1b
export AZ3=us-east-1c

注意:您可以通过创建更多变量来添加更多可用区。

3.    要在 VPC 下使用新的 CIDR 范围创建新子网,运行以下命令:

CUST_SNET1=$(aws ec2 create-subnet --cidr-block 100.64.0.0/19 --vpc-id $VPC_ID --availability-zone $AZ1 | jq -r .Subnet.SubnetId)
CUST_SNET2=$(aws ec2 create-subnet --cidr-block 100.64.32.0/19 --vpc-id $VPC_ID --availability-zone $AZ2 | jq -r .Subnet.SubnetId)
CUST_SNET3=$(aws ec2 create-subnet --cidr-block 100.64.64.0/19 --vpc-id $VPC_ID --availability-zone $AZ3 | jq -r .Subnet.SubnetId)

为新子网贴标签

对于在 Kubernetes 1.18 及更早版本上运行的集群,您必须为全部子网贴标签,以便 Amazon EKS 可以发现这些子网。

注意:从 Kubernetes 版本 1.19 开始,Amazon EKS 支持自动发现子网,而不需要任何 kubernetes.io 标签。有关更多信息,请参阅 Kubernetes GitHub 站点上的变更日志

1.    (可选)通过设置键值对为您的子网添加名称标签。例如:

aws ec2 create-tags --resources $CUST_SNET1 --tags Key=Name,Value=SubnetA
aws ec2 create-tags --resources $CUST_SNET2 --tags Key=Name,Value=SubnetB
aws ec2 create-tags --resources $CUST_SNET3 --tags Key=Name,Value=SubnetC

2.    对于 Kubernetes 1.18 及更低版本上运行的集群,请贴标签以方便 Amazon EKS 发现子网。例如:

aws ec2 create-tags --resources $CUST_SNET1 --tags Key=kubernetes.io/cluster/yourClusterName,Value=shared
aws ec2 create-tags --resources $CUST_SNET2 --tags Key=kubernetes.io/cluster/yourClusterName,Value=shared
aws ec2 create-tags --resources $CUST_SNET3 --tags Key=kubernetes.io/cluster/yourClusterName,Value=shared

注意:yourClusterName 替换为您的 Amazon EKS 集群的名称。

如果您计划使用弹性负载均衡,则考虑添加其他标签

将您的新子网关联到路由表

1.    要列出 VPC 下方的完整路由表,运行以下命令:

aws ec2 describe-route-tables --filters Name=vpc-id,Values=$VPC_ID |jq -r '.RouteTables[].RouteTableId'

2.    对于要与子网关联的路由表,请运行以下命令以导出到变量。然后,用步骤 1 中的值替换 rtb-xxxxxxxxx

export RTASSOC_ID=rtb-xxxxxxxxx

3.    将路由表关联到所有新子网。例如:

aws ec2 associate-route-table --route-table-id $RTASSOC_ID --subnet-id $CUST_SNET1
aws ec2 associate-route-table --route-table-id $RTASSOC_ID --subnet-id $CUST_SNET2
aws ec2 associate-route-table --route-table-id $RTASSOC_ID --subnet-id $CUST_SNET3

有关更多信息,请参阅路由

配置 CNI 插件以使用新的 CIDR 范围

1.    确保集群中正在运行 vpc-cni 插件的最新推荐版本。
要验证集群中正在运行的版本,请运行以下命令:

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

要查看 vpc-cni 的最新推荐版本,并在需要时更新插件,请参阅 Updating the Amazon VPC CNI plugin for Kubernetes add-on(更新适用于 Kubernetes 附加组件的 Amazon VPC CNI 插件)。

2.    要打开 CNI 插件的自定义网络配置,运行以下命令:

kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true

3.    要添加 ENIConfig 标签以便于识别您的工作线程节点,运行以下命令:

kubectl set env daemonset aws-node -n kube-system ENI_CONFIG_LABEL_DEF=failure-domain.beta.kubernetes.io/zone

4.    要为所有子网和可用区创建 ENIConfig 自定义资源,运行以下命令:

cat <<EOF  | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ1
spec:
  subnet: $CUST_SNET1
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ2
spec:
  subnet: $CUST_SNET2
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ3
spec:
  subnet: $CUST_SNET3
EOF

注意:ENIConfig 必须与您的 Worker 节点的可用区匹配。

5.    启动新的 Worker 节点。

注意:此步骤允许 CNI 插件(ipamd)从新的 CIDR 范围中为新的 Worker 节点分配 IP 地址。

当您使用自定义联网时,主网络接口不会用于容器组(pod)置放。在这种情况下,您必须首先使用以下公式更新 max-pods

maxPods = (number of interfaces - 1) * (max IPv4 addresses per interface - 1) + 2
  • 对于自我管理的节点组,请按照启动自我管理的 Amazon Linux 节点中的说明部署节点组。不要指定您在已部署的 ENIConfig 资源中使用的子网。相反,请为 BootstrapArguments 参数指定以下文本:
--use-max-pods false --kubelet-extra-args '--max-pods=<20>'
  • 对于托管节点组,如果不使用启动模板,或者使用未指定 AMI ID 的启动模板,则托管节点组会自动计算 Amazon EKS 建议的最大容器组(pod)值。按照创建托管节点组中的步骤进行操作。或者,使用 Amazon EKS CLI 创建托管节点组:
aws eks create-nodegroup --cluster-name <sample-cluster-name> --nodegroup-name <sample-nodegroup-name> --subnets <subnet-123 subnet-456> --node-role <arn:aws:iam::123456789012:role/SampleNodeRole>

注意:对于子网字段,请勿指定您在 ENIConfig 资源中指定的子网。可以根据需要指定更多选项

  • 对于托管节点组,如果使用指定 AMI ID 的启动模板,请在启动模板中提供“--max-pods= 附加参数作为用户数据。在启动模板中,指定 Amazon EKS 优化的 AMI ID,或基于 Amazon EKS 优化的 AMI 构建的自定义 AMI。然后,使用启动模板部署节点组,并在启动模板中提供以下用户数据:
#!/bin/bash
/etc/eks/bootstrap.sh <my-cluster-name> --kubelet-extra-args <'--max-pods=20'>

6.    创建节点组后,记下子网的安全组,并将该安全组应用于关联的 ENIConfig

将以下示例中的 sg-xxxxxxxxxxxx 替换为您的安全组:

cat <<EOF  | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ1
spec:
  securityGroups: 
    - sg-xxxxxxxxxxxx
  subnet: $CUST_SNET1
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ2
spec:
  securityGroups: 
    - sg-xxxxxxxxxxxx
  subnet: $CUST_SNET2
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ3
spec:
  securityGroups: 
    - sg-xxxxxxxxxxxx
  subnet: $CUST_SNET3
EOF

7.    终止旧的 Worker 节点。然后,通过启动新部署来测试配置。添加了 10 个新的容器组(pod),并且为新的 Worker 节点安排了新的 CIDR 范围:

kubectl create deployment nginx-test --image=nginx --replicas=10
    
kubectl get pods -o wide --selector=app=nginx-test

这篇文章对您有帮助吗?


您是否需要账单或技术支持?