從今天開始,您可以在 Amazon Elastic Kubernetes Service (EKS) 上部署使用 IPv6 位址的應用程式。
我們的許多客戶正在將 Kubernetes 標準化為他們用於雲端和本地應用程式的計算基礎架構平台。 Amazon EKS 使部署容器化工作負載變得容易。 它提供高可用的集群並自動執行修補、節點分配和更新等任務。Kubernetes 使用平面網路模型,要求每個 pod 接收一個 IP 位址。 這種簡化的方法可以實現應用程式從虛擬機到容器的低摩擦移植,但需要大量的 IP 位址,而許多私有 VPC IPv4 網路無法處理這些網址。 一些集群管理員通過安裝容器網路插件 (CNI) 來解決 IPv4 空間限制,該插件將 IP 位址虛擬化為 VPC 之上的一層,但這種架構限制了管理員有效觀察和排除應用程式故障的能力,並對大規模網路性能產生負面影響 . 此外,為了與 VPC 外部的網路服務進行通訊,來自 IPv4 pod 的流量在到達目的地之前會通過多個網路躍點進行路由,這會增加延遲並給需要維護複雜路由設置的網絡工程團隊帶來壓力。
為了避免 IP 網址耗盡、大規模減少延遲並簡化路由分配,解決方案是使用 IPv6 位址空間。IPv6 並不是新的,1996 年我買了第一本關於“IPng,下一代網路協議”的書,這是它在 25 年前的稱號。 它提供 128 位網址空間,允許我們的設備、服務器或容器使用 3.4 x 10^38 個可能的 IP 網址。 我們可以為地球表面的每個原子分配一個 IPv6 網址,並且仍然有足夠的網址來做另外 100 多個地球。
將 Amazon EKS 集群與 IPv6 網路結合使用有一些優勢。 首先,您可以在單個主機或子網上運行更多 pod,而不會冒用 VPC 中所有可用 IPv4 位址的風險。 其次,它通過避免額外的 NAT 躍點,允許與在本地、AWS 或網路上運行的其他 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並分配stack cdk bootstrap && cdk deploy。
創建具有 IPv6 的 VPC 時,我使用控制台分配,將 IPv6 位址自動分配給部署在公有子網中的資源(我為每個公有子網執行此操作)。
我記下了由上面CDK 腳本所創建的子網 ID(它們在腳本的輸出中列出)並定義了幾個我將整個範例中使用的變量。 我還創建了一個IAM 角色的集群和一個 IAM 角色的節點,如 Amazon EKS 檔案中所述。 當您已經部署了集群時,這兩個角色已經存在。
我打開Terminal並打指令:
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 集群。在terminal,我打的指令如下:
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 命令列介面(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
我使用kubectl 指令從 Kubernetes 的角度去驗證集群。
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 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 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 is available at 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
my-deployment-5dd5dfd6b9-h6mrt 1/1 Running 0 17m 2600:0000:0000:0000:46f9:: ip-10-0-0-108.us-west-2.compute.internal
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
我記下了我的 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 中啟動了一個 dual stack(IPv4 和 IPv6)EC2 實例。 我通過 SSH 連接到實例並再次嘗試 curl指令。 我看到我收到了 nginx 提供的默認 HTML 頁面, 與 Pod 的 IPv6 連接有效!
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>
如果它不適合您,請驗證這三個參數去啟用子網的 Internet 訪問:您的 VPC 是否有 Internet Gateway? 附加到子網的路由表是否有到 Internet 網關的默認路由? 集群 EC2 節點的安全組是否具有允許從 ::/0埠到 TCP 80上的傳入連接的規則? Internet Gateway和路由表由我在此範例中提供 CDK 腳本自動配置。
在結束之前,我想回答一些已經嘗試過這項新功能的客戶經常提出的問題:
- IPv6 由與您目前用於 IPv4 的相同 VPC CNI Kubernetes plugin 啟用。 該插件會自動分配為 IPv4 或 IPv6,具體取決於您在創建集群時所做的 pod 網路選擇。
- 您還可以在自我管理的集群中安裝為 IPv6 分配的 VPC CNI plugin。 然而,在您管理集群時,您有責任分配控制平面以支持 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 區域推出,無需額外費用。
立即嘗試並構建您的第一個 IPv6 集群。