亚马逊AWS官方博客
Amazon Elastic Kubernetes Service 增加 IPv6 网络
即日起,您可以在 Amazon Elastic Kubernetes Service (EKS) 上部署使用 IPv6 地址空间的应用程序。
我们许多客户正在将 Kubernetes 标准化为其云和本地应用程序的计算基础设施平台。Amazon EKS 使您能够轻松部署容器化工作负载。它提供有高度可用的集群,并且可自动执行诸如修补、节点预置和更新之类的任务。
Kubernetes 使用扁平化网络模型,该模型需要每个 pod 接收 IP 地址。这种简单的方法支持从虚拟机到容器的应用程序进行低摩擦移植,但需要大量 IP 地址,而许多私有 VPC IPv4 网络无法处理这些地址。有些集群管理员通过安装将 IP 地址虚拟化为 VPC 上的层的容器网络插件 (CNI) 来规避此 IPv4 空间限制,但此架构对管理员有效观察和排查应用程序问题会有限制,并且对大规模网络性能存在负面影响。此外,为了与 VPC 外的 Internet 服务进行通信,来自 IPv4 pod 的流量在到达其目的地之前将通过多个网络跃点路由,这就增加了延迟,并给需要维持复杂路由步骤的网络工程师团队带来压力。
为了避免 IP 地址耗尽,大规模缩小延迟和简化路由配置,解决方案是使用 IPv6 地址空间。
IPv6 并不是新事物。1996 年,我购买了我的第一本关于“IPng,下一代 Internet 协议”的书籍,这本书在 25 年前采用的是这个名字。它提供 64 位地址空间,允许在我们的设备、服务器或容器中使用 3.4 x 10^38 个可能的 IP 地址。我们可以向地球表面上的每个原子分配一个 IPv6 地址,并且仍留有足够的地址来为另外 100 多个地球来执行此操作。
在 IPv6 网络中使用 Amazon EKS 集群具有许多好处。首先,您可以在单个主机或子网中运行多个 pod,而不会产生耗尽 VPC 中所有可用 IPv4 地址的风险。其次,它可以避免使用额外的 NAT 跃点,从而实现与其他在本地、AWS 或 Internet 上运行的 IPv6 服务的低延迟通信。第三,它减轻了网络工程师维护复杂路由配置的负担。
Kubernetes 集群管理员可以专注于迁移和扩展应用程序,而无需花精力来解决 IPv4 限制。最后,pod 网络经过配置,pod 可以与集群外部基于 IPv4 的应用程序进行通信,这使您能够在 Amazon EKS 上享受到 IPv6 的优势,而无需先将组织中部署的所有依赖服务迁移到 IPv6。
与以往一样,我制作了一个简短的演示来向您介绍其工作原理。
工作原理
在开始之前,我先创建一个 IPv6 VPC。我会在几分钟后使用此 CDK 脚本来创建一个支持 IPv6 的 VPC(感谢 Angus Lees 提供的代码)。只需安装 CDK v2 (npm install -g aws-cdk@next
) 并部署堆栈 (cdk bootstrap && cdk deploy
)。
创建带有 IPv6 的 VPC 时,我使用控制台进行配置,以便将 IPv6 地址自动分配给在公共子网中部署的资源(我会为每个公共子网执行此操作)。
我需要记下上面的 CDK 脚本(它们已在脚本输出中列出)创建的子网 ID,并定义将在整个演示中使用的几个变量。此外,我还会创建一个集群 IAM 角色和一个 节点 IAM 角色,如 Amazon EKS 文档中所述。集群部署完毕之后,这两个角色就已存在。
我打开一个终端并键入:
CLUSTER_ROLE_ARN="arn:aws:iam::0123456789:role/EKSClusterRole"
NODE_ROLE_ARN="arn:aws:iam::0123456789:role/EKSNodeRole"
SUBNET1="subnet-06000a8"
SUBNET2="subnet-03000cc"
CLUSTER_NAME="AWSNewsBlog"
KEYPAIR_NAME="my-key-pair-name"
接下来,我将创建一个 Amazon EKS IPv6 集群。在终端中,键入:
aws eks create-cluster --cli-input-json "{
\"name\": \"${CLUSTER_NAME}\",
\"version\": \"1.21\",
\"roleArn\": \"${CLUSTER_ROLE_ARN}\",
\"resourcesVpcConfig\": {
\"subnetIds\": [
\"${SUBNET1}\", \"${SUBNET2}\"
],
\"endpointPublicAccess\": true,
\"endpointPrivateAccess\": true
},
\"kubernetesNetworkConfig\": {
\"ipFamily\": \"ipv6\"
}
}"
{
"cluster": {
"name": "AWSNewsBlog",
"arn": "arn:aws:eks:us-west-2:486652066693:cluster/AWSNewsBlog",
"createdAt": "2021-11-02T17:29:32.989000+01:00",
"version": "1.21",
...redacted for brevity...
"status": "CREATING",
"certificateAuthority": {},
"platformVersion": "eks.4",
"tags": {}
}
}
在等待集群创建时,我将会使用 describe-cluster
。集群就绪后,它将具有 "status" : "ACTIVE"
aws eks describe-cluster --name "${CLUSTER_NAME}"
然后,我将会创建一个节点组:
aws eks create-nodegroup \
--cluster-name ${CLUSTER_NAME} \
--nodegroup-name AWSNewsBlog-nodegroup \
--node-role ${NODE_ROLE_ARN} \
--subnets "${SUBNET1}" "${SUBNET2}" \
--remote-access ec2SshKey=${KEYPAIR_NAME}
{
"nodegroup": {
"nodegroupName": "AWSNewsBlog-nodegroup",
"nodegroupArn": "arn:aws:eks:us-west-2:0123456789:nodegroup/AWSNewsBlog/AWSNewsBlog-nodegroup/3ebe70c7-6c45-d498-6d42-4001f70e7833",
"clusterName": "AWSNewsBlog",
"version": "1.21",
"releaseVersion": "1.21.4-20211101",
"status": "CREATING",
"capacityType": "ON_DEMAND",
... redacted for brevity ...
}
节点组创建完毕之后,我将会在控制台中看到两个 EC2 实例。我将使用 AWS Command Line Interface (CLI) 验证这两个实例是否已接收到 IPv6 地址:
aws ec2 describe-instances --query "Reservations[].Instances[? State.Name == 'running' ][].NetworkInterfaces[].Ipv6Addresses" --output text
2600:1f13:812:0000:0000:0000:0000:71eb
2600:1f13:812:0000:0000:0000:0000:3c07
从 Kubernetes 的角度来看,我将使用 kubectl
命令来验证该集群。
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-0-0-108.us-west-2.compute.internal Ready <none> 2d13h v1.21.4-eks-033ce7e 2600:1f13:812:0000:0000:0000:0000:2263 18.0.0.205 Amazon Linux 2 5.4.149-73.259.amzn2.x86_64 docker://20.10.7
ip-10-0-1-217.us-west-2.compute.internal Ready <none> 2d13h v1.21.4-eks-033ce7e 2600:1f13:812:0000:0000:0000:0000:7f3e 52.0.0.122 Amazon Linux 2 5.4.149-73.259.amzn2.x86_64 docker://20.10.7
然后我将会部署一个 Pod。我按照 EKS 文档中的步骤进行操作。它部署了一个示例 nginx Web 服务器。
kubectl create namespace aws-news-blog
namespace/aws-news-blog created
# sample-service.yml 可从 https://docs.aws.amazon.com/eks/latest/userguide/sample-deployment.html 处获得
kubectl apply -f sample-service.yml
service/my-service created
deployment.apps/my-deployment created
kubectl get pods -n aws-news-blog -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-deployment-5dd5dfd6b9-7rllg 1/1 Running 0 17m 2600:0000:0000:0000:405b::2 ip-10-0-1-217.us-west-2.compute.internal <none> <none>
my-deployment-5dd5dfd6b9-h6mrt 1/1 Running 0 17m 2600:0000:0000:0000:46f9:: ip-10-0-0-108.us-west-2.compute.internal <none> <none>
my-deployment-5dd5dfd6b9-mrkfv 1/1 Running 0 17m 2600:0000:0000:0000:46f9::1 ip-10-0-0-108.us-west-2.compute.internal <none> <none>
我记下 pod 的 IPv6 地址,并尝试从我的笔记本电脑连接它。由于我的服务提供商还没有为我家提供 IPv6,连接失败。这是意料之中的事情,因为 pod 根本没有 IPv4 地址。请注意,-g
选项告知 curl
不要将 IP 地址中的 :
视为端口号的分隔符,-6
选项告知 curl
仅通过 IPv6 连接(当您为 curl
提供 DNS 主机名时需要)。
curl -g -6 http://\[2600:0000:0000:35000000:46f9::1\]
curl: (7) Couldn't connect to server
为了测试 IPv6 连接,我在与集群相同的 VPC 中启动了一个双堆栈(IPv4 和 IPv6)EC2 实例。我通过 SSH 的方式连接到该实例,并再次尝试使用 curl
命令。我看到我收到了 nginx 提供的默认 HTML 页面。IPv6 至该 pod 的连接正常!
curl -g -6 http://\[2600:0000:0000:35000000:46f9::1\]
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
... redacted for brevity ...
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
如果它不起作用,请验证集群 EC2 节点的安全组,并确保它具有允许 ::/0
的端口 TCP 80
上的传入连接。
需要记住的几点
在总结之前,我想回答一些从已体验过此新功能的客户处收到的常见问题:
- IPv6 由与您现在用于 IPv4 的相同 VPC CNI Kubernetes 插件启用。该插件将会自动针对 IPv4 或 IPv6 配置,具体取决于您在创建集群时选择的 pod 网络。
- 此外,您还可以在自行管理的集群中安装针对 IPv6 配置的 VPC CNI 插件。但是,在您管理集群时,您有责任将控制面板配置为支持 IPv6。
- IPv6 支持只会在创建集群时启用。至目前为止,您无法将集群从 IPv4 迁移到 IPv6。如果您想要迁移现有集群,则您可能需要将工作负载重新部署到一个基于 IPv6 的新集群,然后逐渐将流量从 IPv4 迁移到 IPv6 集群,如此技术说明中所述。
- 您可以自带 IPv6 范围。按照这些说明在 EC2 上自带 IP 地址范围。
- 您可以在 IPv6 集群中部署 Linux。目前不支持 Windows。
- 请务必在集群中安装最新版本的 AWS Load Balancer Controller,以便使用 Application Load Balancers 和/或 Network Load Balancers 将外部流量路由到 IPv6 pod。
定价和可用性
适用于 Amazon Elastic Kubernetes Service (EKS) 集群的 IPv6 支持现已在提供 Amazon EKS 的所有 AWS 区域提供,且无需额外费用。