在 Azure Kubernetes 服务 (AKS) 中使用双堆栈 Kubenet 网络

在使用 kubenet 网络和双堆栈 Azure 虚拟网络时,可以在双堆栈模式中部署 AKS 群集。 在此配置中,节点从 Azure 虚拟网络子网接收 IPv4 和 IPv6 地址。 Pod 接收从逻辑上不同的地址空间到节点的 Azure 虚拟网络子网的 IPv4 和 IPv6 地址。 然后配置网络地址转换 (NAT),以便 Pod 可以访问 Azure 虚拟网络上的资源。 流量的源 IP 地址是 NAT 到同一系列的节点主 IP 地址(从 IPv4 到 IPv4 和从 IPv6 到 IPv6)。

本文演示了如何将双堆栈网络与 AKS 群集一起使用。 有关网络选项和注意事项的详细信息,请参阅 Kubernetes 和 AKS 的网络概念

限制

  • Azure 路由表的硬性限制是每个表 400 个路由。
    • 双堆栈群集中的每个节点都需要两个路由(每个 IP 地址系列一个路由),因此双堆栈群集限制为 200 个节点。
  • 在 Azure Linux 节点池中,服务对象仅支持用于 externalTrafficPolicy: Local
  • Azure 虚拟网络和 Pod CIDR 需要双堆栈网络。
    • 节点或 Pod IP 地址不支持单堆栈仅 IPv6。 可在 IPv4 或 IPv6 上预配服务。
  • 双堆栈 kubenet 不支持以下功能:

先决条件

  • 配置 kubenet 网络的所有先决条件适用。
  • AKS 双堆栈群集需要 Kubernetes v1.21.2 或更高版本。 推荐 v1.22.2 或更高版本。
  • 如果使用 Azure 资源管理器模板,需要架构版本 2021-10-01。

Kubernetes 中的双堆栈网络概述

Kubernetes v1.23 为 IPv4/IPv6 双堆栈群集(包括 Pod 和服务网络)提供稳定的上游支持。 节点和 Pod 始终获得 IPv4 和 IPv6 两种地址,而服务在每种地址系列上可以是双堆栈也可以是单堆栈。

AKS 为双堆栈网络配置所需的支持服务。 该配置包括:

  • 双堆栈虚拟网络配置(如果使用托管虚拟网络)。
  • IPv4 和 IPv6 节点和 Pod 地址。
  • IPv4 和 IPv6 流量的出站规则。
  • IPv4 和 IPv6 服务的负载均衡器设置。

备注

将 Dualstack 与用户定义的路由出站类型配合使用时,可以选择为 IPv6 设置默认路由,具体取决于是否需要 IPv6 流量访问 Internet。 如果没有为 IPv6 设置默认路由,创建群集时会显示警告,但不会阻止群集的创建。

部署双堆栈群集

提供了下列属性来支持双堆栈群集:

  • --ip-families:采用要在群集上启用的 IP 系列列表,以逗号分隔。
    • 仅支持 ipv4ipv4,ipv6
  • --pod-cidrs:采用 CIDR 表示法 IP 范围的逗号分隔列表,从中分配 Pod IP。
    • 此列表中范围的计数和顺序必须与提供给 --ip-families 的值匹配。
    • 如果未提供值,则使用默认值 10.244.0.0/16,fd12:3456:789a::/64
  • --service-cidrs:采用 CIDR 表示法 IP 范围的逗号分隔列表,从中分配服务 IP。
    • 此列表中范围的计数和顺序必须与提供给 --ip-families 的值匹配。
    • 如果未提供值,则使用默认值 10.0.0.0/16,fd12:3456:789a:1::/108
    • 分配给 --service-cidrs 的 IPv6 子网不能大于 /108。

部署双堆栈 AKS 群集

  1. 使用 az group create 命令为群集创建 Azure 资源组。

    az group create -l <region> -n <resourceGroupName>
    
  2. 使用 --ip-families 参数设置为 ipv4,ipv6az aks create 命令创建双堆栈 AKS 群集。

    az aks create -l <region> -g <resourceGroupName> -n <clusterName> --ip-families ipv4,ipv6
    
  3. 创建群集后,使用 az aks get-credentials 命令获取群集管理员凭据。

    az aks get-credentials -g <resourceGroupName> -n <clusterName>
    

检查节点来查看两个 IP 系列

  • 预配群集后,使用 kubectl get nodes 命令确认节点已预配双堆栈网络。

    kubectl get nodes -o=custom-columns="NAME:.metadata.name,ADDRESSES:.status.addresses[?(@.type=='InternalIP')].address,PODCIDRS:.spec.podCIDRs[*]"
    

    kubectl get nodes 命令的输出显示节点具有来自 IPv4 和 IPv6 的地址和 Pod IP 分配空间。

    NAME                                ADDRESSES                           PODCIDRS
    aks-nodepool1-14508455-vmss000000   10.240.0.4,2001:1234:5678:9abc::4   10.244.0.0/24,fd12:3456:789a::/80
    aks-nodepool1-14508455-vmss000001   10.240.0.5,2001:1234:5678:9abc::5   10.244.1.0/24,fd12:3456:789a:0:1::/80
    aks-nodepool1-14508455-vmss000002   10.240.0.6,2001:1234:5678:9abc::6   10.244.2.0/24,fd12:3456:789a:0:2::/80
    

创建示例工作负载

创建群集后,便可部署工作负载。 本文将指导你完成 NGINX Web 服务器的示例工作负载部署。

部署 NGINX Web 服务器

  1. 使用 kubectl create deployment nginx 命令创建 NGINX Web 服务器。

    kubectl create deployment nginx --image=nginx:latest --replicas=3
    
  2. 使用 kubectl get pods 命令查看 Pod 资源。

    kubectl get pods -o custom-columns="NAME:.metadata.name,IPs:.status.podIPs[*].ip,NODE:.spec.nodeName,READY:.status.conditions[?(@.type=='Ready')].status"
    

    输出显示 Pod 同时具有 IPv4 地址和 IPv6 地址。 Pod 在获得 IP 地址前,不会显示 IP 地址。

    NAME                     IPs                                NODE                                READY
    nginx-55649fd747-9cr7h   10.244.2.2,fd12:3456:789a:0:2::2   aks-nodepool1-14508455-vmss000002   True
    nginx-55649fd747-p5lr9   10.244.0.7,fd12:3456:789a::7       aks-nodepool1-14508455-vmss000000   True
    nginx-55649fd747-r2rqh   10.244.1.2,fd12:3456:789a:0:1::2   aks-nodepool1-14508455-vmss000001   True
    

通过 LoadBalancer 类型服务公开工作负载

重要

从 AKS v1.27 开始,你可以创建双堆栈 LoadBalancer 服务,该服务将预配 1 个 IPv4 公共 IP 和 1 个 IPv6 公共 IP。 但在旧版本中,只有服务的第一个 IP 地址将预配到负载均衡器,因此双堆栈服务只会获得第一个列出的 IP 系列的公共 IP。 要为单个部署提供双堆栈服务,请创建两个面向同一选择器的服务:一个针对 IPv4,一个针对 IPv6。

v1.27 及更高版本的 AKS

  1. 使用 kubectl expose deployment nginx 命令公开 NGINX 部署。

    kubectl expose deployment nginx --name=nginx --port=80 --type=LoadBalancer --overrides='{"spec":{"ipFamilyPolicy": "PreferDualStack", "ipFamilies": ["IPv4", "IPv6"]}}'
    

    你会收到一个输出,显示服务已公开。

    service/nginx exposed
    
  2. 公开部署并完全预配 LoadBalancer 服务后,使用 kubectl get services 命令获取服务的 IP 地址。

    kubectl get services
    
    NAME         TYPE           CLUSTER-IP               EXTERNAL-IP         PORT(S)        AGE
    nginx        LoadBalancer   10.0.223.73   2603:1030:20c:9::22d,4.156.88.133   80:30664/TCP   2m11s
    
    kubectl get services nginx -ojsonpath='{.spec.clusterIPs}'
    
    ["10.0.223.73","fd17:d93e:db1f:f771::54e"]
    
  3. 在支持 IPv6 的主机中通过命令行 Web 请求来验证功能。 Azure Cloud Shell 不支持 IPv6。

    SERVICE_IP=$(kubectl get services nginx -o jsonpath='{.status.loadBalancer.ingress[1].ip}')
    curl -s "http://[${SERVICE_IP}]" | head -n5
    
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    

早于 v1.27 版本的 AKS

  1. 使用 kubectl expose deployment nginx 命令公开 NGINX 部署。

    kubectl expose deployment nginx --name=nginx-ipv4 --port=80 --type=LoadBalancer'
    kubectl expose deployment nginx --name=nginx-ipv6 --port=80 --type=LoadBalancer --overrides='{"spec":{"ipFamilies": ["IPv6"]}}'
    

    你会收到一个输出,显示服务已公开。

    service/nginx-ipv4 exposed
    service/nginx-ipv6 exposed
    
  2. 公开部署并完全预配 LoadBalancer 服务后,使用 kubectl get services 命令获取服务的 IP 地址。

    kubectl get services
    
    NAME         TYPE           CLUSTER-IP               EXTERNAL-IP         PORT(S)        AGE
    nginx-ipv4   LoadBalancer   10.0.88.78               20.46.24.24         80:30652/TCP   97s
    nginx-ipv6   LoadBalancer   fd12:3456:789a:1::981a   2603:1030:8:5::2d   80:32002/TCP   63s
    
  3. 在支持 IPv6 的主机中通过命令行 Web 请求来验证功能。 Azure Cloud Shell 不支持 IPv6。

    SERVICE_IP=$(kubectl get services nginx-ipv6 -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    curl -s "http://[${SERVICE_IP}]" | head -n5
    
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>