亚马逊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 多个地球来执行此操作。

“IPng,下一代 Internet 协议”书籍在 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 地址自动分配给在公共子网中部署的资源(我会为每个公共子网执行此操作)。

在子网中自动分配 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 上的传入连接。

需要记住的几点
在总结之前,我想回答一些从已体验过此新功能的客户处收到的常见问题:

定价和可用性
适用于 Amazon Elastic Kubernetes Service (EKS) 集群的 IPv6 支持现已在提供 Amazon EKS 的所有 AWS 区域提供,且无需额外费用。

快来试试构建您的第一个 IPv6 集群吧

– seb