在 Azure Kubernetes 服务 (AKS) 中结合自己的 IP 地址范围使用 kubenet 网络

默认情况下,AKS 群集使用 kubenet,系统会为你创建 Azure 虚拟网络和子网。 节点使用 kubenet 从 Azure 虚拟网络子网获取 IP 地址。 Pod 接收从逻辑上不同的地址空间到节点的 Azure 虚拟网络子网的 IP 地址。 然后配置网络地址转换 (NAT),以便 Pod 可以访问 Azure 虚拟网络上的资源。 流量的源 IP 地址通过 NAT 转换为节点的主 IP 地址。 这种方法大大减少了需要在网络空间中保留供 Pod 使用的 IP 地址数量。

借助 Azure 容器网络接口 (CNI),每个 Pod 都可以从子网获得 IP 地址,并且可供直接访问。 这些 IP 地址在网络空间中必须唯一,并且必须事先计划。 每个节点都有一个配置参数来表示它支持的最大 Pod 数。 这样,就会为每个节点预留相应的 IP 地址数。 使用此方法需要经过更详细的规划,并且经常会耗尽 IP 地址,或者在应用程序需求增长时需要在更大的子网中重建群集。 可以在创建群集时或新建节点池时,配置可部署到节点的最大 Pod 数。 如果在创建新节点池时未指定 maxPod,则会收到 kubenet 的默认值 110。

本文介绍如何使用 kubenet 网络来创建和使用 AKS 群集的虚拟网络子网。 有关网络选项和注意事项的详细信息,请参阅 Kubernetes 和 AKS 的网络概念

先决条件

  • AKS 群集的虚拟网络必须允许出站 Internet 连接。
  • 不要在同一子网中创建多个 AKS 群集。
  • AKS 群集不得将 169.254.0.0/16172.30.0.0/16172.31.0.0/16192.0.2.0/24 用于 Kubernetes 服务地址范围、Pod 地址范围或群集虚拟网络地址范围。
  • AKS 群集使用的群集标识在虚拟网络中的子网上必须至少具有网络参与者角色。 CLI 可帮助自动执行角色分配。 如果使用 ARM 模板或其他客户端,则需要手动完成角色分配。 你还必须具有相应的权限(如订阅所有者),才能创建群集标识并向其分配权限。 如果希望定义自定义角色而不是使用内置的网络参与者角色,则需要以下权限:
    • Microsoft.Network/virtualNetworks/subnets/join/action
    • Microsoft.Network/virtualNetworks/subnets/read

警告

若要使用 Windows Server 节点池,必须使用 Azure CNI。 对于 Windows Server 容器,无法将 kubenet 用作网络模型。

准备阶段

需要安装并配置 Azure CLI 2.0.65 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI

使用自有子网的 kubenet 网络概述

在许多环境中,你已定义了具有分配的 IP 地址范围的虚拟网络和子网。 这些虚拟网络资源用于支持多个服务和应用程序。 若要提供网络连接,AKS 群集可以使用 kubenet(基本网络)或 Azure CNI(高级网络)。

使用 kubenet 时,只有节点接收虚拟网络子网中的 IP 地址。 Pod 无法直接相互通信。 用户定义的路由 (UDR) 和 IP 转发用于不同节点中 Pod 之间的连接。 默认情况下,UDR 和 IP 转发配置由 AKS 服务进行创建和维护,但你可以选择自带路由表以进行自定义路由管理。 此外,可以在接收分配的 IP 地址的服务后面部署 Pod,并对应用程序的流量进行负载均衡。 下图显示了 AKS 节点(不是 Pod)如何接收虚拟网络子网中的 IP 地址:

使用 AKS 群集的 Kubenet 网络模型

Azure 在一个 UDR 中最多支持 400 个路由,因此,AKS 群集中的节点数不能超过 400 个。 Kubenet 不支持 AKS 虚拟节点和 Azure 网络策略。 可以使用 Calico 网络策略,因为 kubenet 支持这些策略。

使用 Azure CNI 时,每个 Pod 将接收 IP 子网中的 IP 地址,并且可以直接与其他 Pod 和服务通信。 群集的最大大小可为指定的 IP 地址范围上限。 但是,必须提前规划 IP 地址范围,AKS 节点根据它们支持的最大 Pod 数消耗所有 IP 地址。 Azure CNI 支持虚拟节点或网络策略(Azure 或 Calico)等高级网络功能和方案。

kubenet 的限制 & 注意事项

  • 在 Kubenet 的设计中需要额外的跃点,这会导致 Pod 通信出现轻微延迟。
  • 需要路由表和用户定义的路由才能使用 Kubenet,这会增加操作的复杂性。
  • 由于 Kubenet 设计,Kubenet 不支持直接 Pod 寻址。
  • 与 Azure CNI 群集不同,多个 Kubenet 群集无法共享一个子网。
  • AKS 不将网络安全组 (NSG) 应用于其子网,也不会修改与该子网相关的任何 NSG。 如果提供自己的子网并添加与该子网相关的 NSG,则必须确保 NSG 中的安全规则允许节点和 Pod CIDR 之间的流量。 有关详细信息,请参阅网络安全组
  • Kubenet 不支持的功能包括:

IP 地址可用性和耗尽

使用 Azure CNI 时,一个常见问题是分配的 IP 地址范围太小,以致在扩展或升级群集时需要添加更多的节点。 网络团队可能无法提供足够大的 IP 地址范围来支持预期的应用程序需求。

作为一种折衷方案,可以创建使用 kubenet 的 AKS 群集并连接到现有虚拟网络子网。 这种方法可让节点接收定义的 IP 地址,而无需提前为群集中可能运行的所有潜在 Pod 节点预留大量的 IP 地址。

使用 kubenet 时,可以大幅减小要使用的 IP 地址范围,并且可以支持大型群集和应用程序的需求。 例如,即使在子网上使用 /27 IP 地址范围,也可运行包括 20-25 个节点的群集,空间足以进行缩放或升级。 此群集大小最多支持 2,200-2,750 个 Pod(每个节点的最大 Pod 数默认为 110 个)。 可以在 AKS 中使用 kubenet 配置的每个节点的最大 Pod 数为 110。

以下基本计算方法对网络模型的差异做了比较:

  • kubenet -一个简单的 /24 IP 地址范围最多可以支持群集中的 251 个节点(每个 Azure 虚拟网络子网预留前三个 IP 地址用于管理操作)
    • 此节点计数最多可以支持 27,610 个 Pod(使用 kubenet 的每个节点的最大 Pod 数默认为 110 个)
  • Azure CNI - 相同的基本 /24 子网范围最多只能支持群集中的 8 个节点
    • 此节点计数最多只能支持 240 个 Pod(使用 Azure CNI 的每个节点的最大 Pod 数默认为 30 个)

注意

这些最大值未考虑到帐户升级或扩展操作。 在实践中,不可能会运行子网 IP 地址范围支持的节点数上限。 必须留出一些 IP 地址,供扩展或升级操作期间使用。

虚拟网络对等互连和 ExpressRoute 连接

若要提供本地连接,kubenetAzure CNI 网络方法都可以使用 Azure 虚拟网络对等互连ExpressRoute 连接。 精心规划 IP 地址范围,以防止地址重叠和流量路由错误。 例如,许多本地网络使用通过 ExpressRoute 连接播发的 10.0.0.0/8 地址范围。 建议在此地址范围(例如 172.16.0.0/16)外部的 Azure 虚拟网络子网中创建 AKS 群集。

选择要使用的网络模型

选择用于 AKS 群集的网络插件通常需要在灵活性与高级配置需求之间进行平衡。 如果每种网络模型似乎都很合适,以下考虑因素可帮助你做出决策:

对于以下情况,可使用 kubenet

  • IP 地址空间有限。
  • 大部分 Pod 通信在群集中进行。
  • 不需要虚拟节点或 Azure 网络策略等高级 AKS 功能。 使用 Calico 网络策略

对于以下情况,可使用 Azure CNI

  • 有可用的 IP 地址空间。
  • 大部分 Pod 通信是与群集外部的资源进行的。
  • 不想管理用户定义的 Pod 连接路由。
  • 需要虚拟节点或 Azure 网络策略等 AKS 高级功能。 使用 Calico 网络策略

有关帮助你决定使用哪个网络模型的详细信息,请参阅比较网络模型及其支持范围

创建虚拟网络和子网

若要开始使用 kubenet 和自己的虚拟网络子网,请先使用 az group create 命令创建一个资源组。 以下示例在“chinaeast2”位置创建名为“myResourceGroup”的资源组:

az group create --name myResourceGroup --location chinaeast2

如果没有可用的现有虚拟网络和子网,请使用 az network vnet create 命令创建这些网络资源。 在以下示例中,虚拟网络名为 myAKSVnet,其地址前缀为 192.168.0.0/16。 创建了名为 myAKSSubnet、地址前缀为 192.168.1.0/24 的子网。

az network vnet create \
    --resource-group myResourceGroup \
    --name myAKSVnet \
    --address-prefixes 192.168.0.0/16 \
    --subnet-name myAKSSubnet \
    --subnet-prefix 192.168.1.0/24

获取子网资源 ID,并将其存储为变量:

SUBNET_ID=$(az network vnet subnet show --resource-group myResourceGroup --vnet-name myAKSVnet --name myAKSSubnet --query id -o tsv)

在虚拟网络中创建 AKS 群集

现在,请使用 az aks create 命令在虚拟网络和子网中创建 AKS 群集。

创建具有系统分配的托管标识的 AKS 群集

可以通过运行以下 CLI 命令使用系统分配的托管标识来创建 AKS 群集。

注意

使用系统分配的标识时,azure-cli 将在群集创建完成后向系统分配的标识授予网络参与者角色。 如果要使用 ARM 模板或其他客户端,则需要使用用户分配的托管标识

az aks create \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --node-count 3 \
    --network-plugin kubenet \
    --vnet-subnet-id $SUBNET_ID 

注意

如果希望启用 AKS 群集以包括 Calico 网络策略,可以使用以下命令。

az aks create \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --node-count 3 \
    --network-plugin kubenet --network-policy calico \
    --vnet-subnet-id $SUBNET_ID 

创建具有用户分配的托管标识的 AKS 群集

创建或获取托管标识

如果你没有托管标识,应运行 az identity 命令创建一个托管标识。

az identity create --name myIdentity --resource-group myResourceGroup

输出应如下所示:

{                                  
  "clientId": "<client-id>",
  "clientSecretUrl": "<clientSecretUrl>",
  "id": "/subscriptions/<subscriptionid>/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity", 
  "location": "chinaeast2",
  "name": "myIdentity",
  "principalId": "<principal-id>",
  "resourceGroup": "myResourceGroup",                       
  "tags": {},
  "tenantId": "<tenant-id>",
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}

如果有一个现成的托管标识,可以通过运行以下命令来查找主体 ID:

az identity show --ids <identity-resource-id>

输出应如下所示:

{
  "clientId": "<client-id>",
  "id": "/subscriptions/<subscriptionid>/resourcegroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity",
  "location": "chinaeast2",
  "name": "myIdentity",
  "principalId": "<principal-id>",
  "resourceGroup": "myResourceGroup",
  "tags": {},
  "tenantId": "<tenant-id>",
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}

为托管标识添加角色分配

如果使用 Azure CLI,将自动添加角色,你可以跳过此步骤。 如果使用 ARM 模板或其他客户端,则需要使用群集托管标识的主体 ID 来执行角色分配。

若要在剩余步骤中分配正确的委托,请使用 az network vnet showaz network vnet subnet show 命令获取所需的资源 ID。 这些资源 ID 存储为变量,并在剩余的步骤中引用:

VNET_ID=$(az network vnet show --resource-group myResourceGroup --name myAKSVnet --query id -o tsv)

现在,使用 az role assignment create 命令为 AKS 群集的托管标识分配虚拟网络中的“网络参与者”权限。 根据上一命令的输出中所示,提供 <principalId> 来创建标识:

az role assignment create --assignee <control-plane-identity-principal-id> --scope $VNET_ID --role "Network Contributor"

示例:

az role assignment create --assignee 22222222-2222-2222-2222-222222222222 --scope "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myAKSVnet" --role "Network Contributor"

注意

向 Azure 使用的群集托管标识授予的权限最长可能需要 60 分钟才能填充完成。

创建 AKS 群集

现在,可以通过运行以下 CLI 命令使用用户分配的托管标识来创建 AKS 群集。 通过 assign-identity 提供控制平面标识资源 ID

az aks create \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --node-count 3 \
    --network-plugin kubenet \
    --vnet-subnet-id $SUBNET_ID \
    --enable-managed-identity \
    --assign-identity <identity-resource-id>

创建 AKS 群集时,将自动创建网络安全组和路由表。 这些网络资源可以通过 AKS 控制平面进行管理。 网络安全组自动与节点上的虚拟 NIC 相关联。 路由表自动与虚拟网络子网相关联。 在你创建和公开服务时,系统会自动更新网络安全组规则和路由表。

在 kubenet 中自带子网和路由表

使用 kubenet 时,群集子网上必须存在路由表。 AKS 支持自带现有的子网和路由表。

如果自定义子网不包含路由表,AKS 会为你创建一个路由表,并在整个群集生命周期中向其添加规则。 如果在创建群集时自定义子网包含路由表,AKS 将在群集操作期间确认现有路由表,并相应地为云提供程序操作添加/更新规则。

警告

可以将自定义规则添加到自定义路由表中并进行更新。 但是,规则由 Kubernetes 云提供商添加,不能更新或删除。 诸如 0.0.0.0/0 的规则必须始终存在于给定的路由表中,并映射到 internet 网关的目标,例如 NVA 或其他出口网关。 在更新规则时,请注意只修改自定义规则。

了解有关设置自定义路由表的详细信息。

Kubenet 网络需要使用经过规划和组织的路由表规则才能成功路由请求。 由于此原因,需要为依赖路由表的每个群集精心维护路由表。 多个群集无法共享一个路由表,因为不同群集的 Pod CIDR 可能会相互重叠,从而导致意外路由和路由中断。 在同一虚拟网络上配置多个群集或为每个群集设置专用虚拟网络时,请确保考虑以下限制。

的限制:

  • 在创建 AKS 群集之前,需要将自定义路由表与子网关联。
  • 创建群集后,无法更新关联的路由表资源。 虽然无法更新路由表资源,但可以在路由表上修改自定义规则。
  • 每个 AKS 群集必须为与群集关联的所有子网使用同一个唯一的路由表。 由于可能存在重叠的 Pod CIDR 和发生路由规则冲突,无法对多个群集重复使用同一个路由表。
  • 对于系统分配的托管标识,仅支持通过 Azure CLI 提供你自己的子网和路由表。 这是因为 CLI 会自动添加角色分配。 如果要使用 ARM 模板或其他客户端,你必须使用用户分配的托管标识,在创建群集之前分配权限,并确保用户分配的标识对你的自定义子网和自定义路由表具有写入权限。
  • 不支持对多个 AKS 群集使用同一路由表。

注意

若要通过 kubenet 网络插件创建和使用自己的 VNet 和路由表,需要使用用户分配的控制平面标识。 对于系统分配的控制平面标识,无法在创建群集之前检索标识 ID,这会导致在角色分配过程中出现延迟。

通过 azure 网络插件创建和使用自己的 VNet 和路由表,支持系统分配的和用户分配的托管标识。 但对于 BYO 方案而言,更建议使用用户分配的托管标识。

创建自定义路由表并将其与虚拟网络中的子网相关联后,可以创建新的 AKS 群集,使用用户分配的托管标识指定路由表。 需要使用计划将 AKS 群集部署到的子网 ID。 此子网还必须与自定义路由表关联。

# Find your subnet ID
az network vnet subnet list --resource-group
                            --vnet-name
                            [--subscription]
# Create a kubernetes cluster with with a custom subnet preconfigured with a route table
az aks create -g myResourceGroup -n myManagedCluster --vnet-subnet-id mySubnetIDResourceID --enable-managed-identity --assign-identity controlPlaneIdentityResourceID

后续步骤

在现有虚拟网络子网中部署 AKS 群集后,现在可以像平时一样使用该群集。 开始使用 Helm 创建新应用使用 Helm 部署现有应用