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

上次更新时间:2021 年 12 月 10 日

我想通过 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 网站)
  • 基于 Unix 的系统和 Bash Shell

请记住以下内容:

  • 如果在不同的 CIDR 范围上运行 Pod,那么您将获得由 Amazon EKS 管理的适用于 Pod 的更多可用 IP 地址。您还可以更灵活地使用联网架构。在两种条件下,您的 Pod 都不会使用 VPC 中的任何 RFC 1918 IP 地址。第一个条件,您从 100.64.0.0/10198.19.0.0/16 范围内向 VPC 添加辅助 CIDR 数据块。第二个条件是您使用 CNI 自定义联网
  • 在运营商级网络地址转换 (NAT) 的情况下,100.64.0.0/10 是专用网络范围。此专用网络范围用于共享地址空间,以实现服务提供商与其订阅者之间的通信。您的 NAT 网关必须在路由表中被配置为用于 Pod 和互联网之间的通信。AWS Fargate 集群不支持 Daemonsets。要将辅助 CIDR 范围添加到 Fargate 配置文件,使用 VPC 的辅助 CIDR 块中的子网。然后,标记新子网后再将子网添加到您的 Fargate 配置文件。

重要提示:在某些情况下,创建集群后,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 集群的名称。

提示:如果您计划使用 Elastic Load Balancing,考虑添加更多标签

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

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.    要验证您有最新版本的 CNI 插件,运行以下命令。

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

如果您的 CNI 插件版本低于 1.5.3,则运行以下命令以更新至最新版本:

kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/v1.5/aws-k8s-cni.yaml

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 自定义资源定义(从 Kubernetes 网站),运行以下命令:

cat << EOF | kubectl apply -f -
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: eniconfigs.crd.k8s.amazonaws.com
spec:
  scope: Cluster
  group: crd.k8s.amazonaws.com
  version: v1alpha1
  names:
    plural: eniconfigs
    singular: eniconfig
    kind: ENIConfig
EOF

5.    要为所有子网和可用区创建 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 必须与您的工件节点的可用区匹配。

6.    启动新的 Worker 节点。注意:此步骤让 CNI 插件(ipamd)可以从新的 CIDR 范围中为新的 Worker 节点分配 IP 地址。

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

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 值。按照创建托管节点组中的步骤操作,或使用 AWS 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。然后, 使用启动模板部署节点组,并在启动模板中提供以下用户数据。

  • 如果要在创建托管节点组时使用指定 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'>

7.    创建节点组后,记下子网的安全组,并将该安全组应用于关联的 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

8.    终止旧的 Worker 节点,然后通过启动新部署来测试配置:

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

添加了 10 个新的 Pod,并且为新的 Worker 节点安排了新的 CIDR 范围。


这篇文章对您有帮助吗?


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