在 AKS 中使用网络策略保护 Pod 之间的流量

在 Kubernetes 中运行最新的基于微服务的应用程序时,通常想要控制哪些组件可以相互通信。 应将最小特权原则应用于在 Azure Kubernetes 服务 (AKS) 群集中的 Pod 之间流动的流量。 假设你想要阻止直接流向后端应用程序的流量。 在 Kubernetes 中,使用网络策略功能可在群集中定义用于 Pod 之间的入口和出口流量的规则。

本文介绍如何安装网络策略引擎并创建 Kubernetes 网络策略,来控制 AKS 中各 Pod 之间的流量流。 网络策略可用于 AKS 中基于 Linux 或基于 Windows 的节点和 Pod。

网络策略概述

默认情况下,AKS 群集中的所有 Pod 可以无限制地发送和接收流量。 为了提高安全性,可定义用来控制流量流的规则。 例如,后端应用程序通常只向所需的前端服务公开。 或者,数据库组件只能由连接到它们的应用层访问。

网络策略是一种 Kubernetes 规范,用于为 Pod 之间的通信定义访问策略。 使用网络策略时,可以定义一组有序的规则来发送和接收流量。 将规则应用于与一个或多个标签选择器匹配的 Pod 集合。

这些网络策略规则定义为 YAML 清单。 可以包含网络策略作为也会创建部署或服务的更丰富清单的一部分。

AKS 中的网络策略选项

Azure 提供了三个用于强制执行网络策略的网络策略引擎:

Cilium 是我们推荐的网络策略引擎。 Cilium 使用 Linux Berkeley 数据包筛选器 (BPF) 对流量强制执行网络策略,这通常比“IPTables”更有效。 有关详细信息,请参阅由 Cilium 提供支持的 Azure CNI 文档。
为了强制实施指定的策略,适用于 Linux 的 Azure 网络策略管理器会使用 Linux IPTables。 适用于 Windows 的 Azure 网络策略管理器使用主机网络服务 (HNS) ACLPolicies。 策略将转换为一系列允许和禁止的 IP 对。 然后,这些对作为 IPTableHNS ACLPolicy 筛选规则进行编程。

网络策略引擎之间的差异:Cilium、Azure NPM 和 Calico

功能 Azure 网络策略管理器 Calico Cilium
支持的平台 Linux、Windows Server 2022(预览版)。 Linux、Windows Server 2019 和 2022。 Linux。
支持的网络选项 Azure 容器网络接口 (CNI)。 Azure CNI(Linux、Windows Server 2019 和 2022)和 kubenet (Linux)。 Azure CNI。
符合 Kubernetes 规范 支持的所有策略类型 支持所有策略类型。 支持所有策略类型。
其他功能 无。 扩展的策略模型,包括全局网络策略、全局网络集和主机终结点。 有关使用 calicoctl CLI 管理这些扩展功能的详细信息,请参阅 calicoctl 用户参考 无。
支持 受 Azure 支持和工程团队支持。 受 Azure 支持和工程团队支持。 受 Azure 支持和工程团队支持。

Azure 网络策略管理器的限制

注意

对于适用于 Linux 的 Azure NPM,我们不允许缩放超过 250 个节点20,000 个 pod。 如果尝试超出这些限制进行缩放,可能会遇到内存不足 (OOM) 错误。 为了获得更好的可伸缩性和 IPv6 支持,如果存在以下限制,我们建议使用或升级到由 Cilium 提供支持的 Azure CNI 以将 Cilium 用作网络策略引擎。

Azure NPM 不支持 IPv6。 否则,它完全支持 Linux 中的网络策略规范。

在 Windows 中,Azure NPM 不支持网络策略规范的以下功能:

  • 命名端口。
  • 流式传输控制传输协议 (SCTP)。
  • 负匹配标签或命名空间选择器。 例如,除 debug=true 之外的所有标签。
  • except 无类别域际路由选择 (CIDR) 块(具有异常的 CIDR)。

注意

如果创建了不受支持的网络策略,Azure 网络策略管理器 pod 日志会记录错误。

编辑/删除网络策略

在某些罕见情况下,在编辑或删除“足够大”的网络策略时,可能会出现争用条件,这可能会导致受影响节点上与 pod 之间的新连接出现临时的意外连接。 达到此争用条件永远不会影响活动连接。

如果某个节点发生此争用条件,该节点上的 Azure NPM pod 将进入无法更新安全规则的状态,这可能会导致受影响节点上 pod 的新连接出现意外连接。 为了缓解该问题,Azure NPM pod 会在进入此状态后自动重启约 15 秒。 在受影响的节点上重新启动 Azure NPM 时,它会删除所有安全规则,然后重新应用所有网络策略的安全规则。 尽管重新应用了所有安全规则,但对于受影响节点上 pod 的新连接,可能会发生临时的意外连接。

若要限制达到此争用条件的可能性,可以减小网络策略的大小。 此问题很可能发生在具有多个 ipBlock 部分的网络策略中。 包含四个或更少 ipBlock 部分的网络策略不太可能遇到该问题。

开始之前

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

创建 AKS 群集并启用网络策略

若要查看实际的网络策略,请创建支持网络策略的 AKS 群集,然后处理添加策略。

若要使用 Azure 网络策略管理器,必须使用 Azure CNI 插件。 Calico 既可与 Azure CNI 插件一起使用,也可与 Kubenet CNI 插件一起使用。

以下示例脚本使用系统分配的标识创建 AKS 群集,并使用 Azure 网络策略管理器启用网络策略。

注意

Calico 可与 --network-plugin azure--network-plugin kubenet 参数配合使用。

也可以使用用户分配的标识,而不是系统分配的标识。 有关详细信息,请参阅使用托管标识

创建启用了 Azure 网络策略管理器的 AKS 群集 - 仅限 Linux

在本部分中,你将创建启用了 Linux 节点池和 Azure 网络策略管理器的群集。

开始时,请替换变量 $RESOURCE_GROUP_NAME$CLUSTER_NAME 变量的值。

$RESOURCE_GROUP_NAME=myResourceGroup-NP
$CLUSTER_NAME=myAKSCluster
$LOCATION=canadaeast

创建 AKS 群集并为 network-pluginnetwork-policy 指定 azure

若要创建群集,请使用以下命令:

az aks create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --node-count 1 \
    --network-plugin azure \
    --network-policy azure \
    --generate-ssh-keys

创建启用了 Azure 网络策略管理器的 AKS 群集 - Windows Server 2022(预览版)

在本部分中,你将创建启用了 Windows 节点池和 Azure 网络策略管理器的群集。

注意

带 Windows 节点的 Azure 网络策略管理器仅在 Windows Server 2022 上可用。

安装 aks-preview Azure CLI 扩展

重要

AKS 预览功能是可选择启用的自助功能。 预览功能是“按现状”和“按可用”提供的,不包括在服务级别协议和有限保证中。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:

要安装aks-preview 扩展,请运行以下命令:

az extension add --name aks-preview

运行以下命令,以更新到已发布的最新扩展版本:

az extension update --name aks-preview

注册 WindowsNetworkPolicyPreview 功能标志

使用 WindowsNetworkPolicyPreview 命令注册 WindowsNetworkPolicyPreview 功能标志,如以下示例所示:

az feature register --namespace "Microsoft.ContainerService" --name "WindowsNetworkPolicyPreview"

状态显示为“已注册”需要几分钟时间。 使用 az feature show 命令验证注册状态:

az feature show --namespace "Microsoft.ContainerService" --name "WindowsNetworkPolicyPreview"

当状态反映“已注册”时,使用 az provider register 命令来刷新 Microsoft.ContainerService 资源提供程序的注册

az provider register --namespace Microsoft.ContainerService

创建 AKS 群集

现在,替换变量 $RESOURCE_GROUP_NAME$CLUSTER_NAME$WINDOWS_USERNAME 变量的值。

$RESOURCE_GROUP_NAME=myResourceGroup-NP
$CLUSTER_NAME=myAKSCluster
$WINDOWS_USERNAME=myWindowsUserName
$LOCATION=canadaeast

创建一个用户名,用作群集上 Windows Server 容器的管理员凭据。 以下命令提示输入用户名。 将其设置为 $WINDOWS_USERNAME。 请记住,本文中的命令是输入到 Bash shell 中的。

echo "Please enter the username to use as administrator credentials for Windows Server containers on your cluster: " && read WINDOWS_USERNAME

若要创建群集,请使用以下命令:

az aks create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --node-count 1 \
    --windows-admin-username $WINDOWS_USERNAME \
    --network-plugin azure \
    --network-policy azure \
    --generate-ssh-keys

创建群集需要几分钟时间。 默认情况下,仅使用 Linux 节点池创建群集。 如果想要使用 Windows 节点池,可以进行添加。 下面是一个示例:

az aks nodepool add \
    --resource-group $RESOURCE_GROUP_NAME \
    --cluster-name $CLUSTER_NAME \
    --os-type Windows \
    --name npwin \
    --node-count 1

创建已启用 Calico 的 AKS 群集

创建 AKS 群集并指定 --network-plugin azure--network-policy calico。 指定 --network-policy calico 可在 Linux 和 Windows 节点池上启用 Calico。

如果计划将 Windows 节点池添加到群集,请包括满足 Windows Server 密码要求的参数 windows-admin-usernamewindows-admin-password

重要

目前,在使用 Calico 3.17.2 的 Kubernetes 1.20 或更高版本的新集群上可以使用具备 Windows 节点的 Calico 网络策略,并且需要使用 Azure CNI 网络。 已启用 Calico 的 AKS 群集上的 Windows 节点还默认启用了浮动 IP。

对于使用早期版本 Calico 的只用 Linux 节点池运行 Kubernetes 1.20 的群集,Calico 版本将自动升级到 3.17.2。

创建一个用户名,用作群集上 Windows Server 容器的管理员凭据。 以下命令提示输入用户名。 将其设置为 $WINDOWS_USERNAME。 请记住,本文中的命令是输入到 Bash shell 中的。

echo "Please enter the username to use as administrator credentials for Windows Server containers on your cluster: " && read WINDOWS_USERNAME
az aks create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --node-count 1 \
    --windows-admin-username $WINDOWS_USERNAME \
    --network-plugin azure \
    --network-policy calico \
    --generate-ssh-keys

创建群集需要几分钟时间。 默认情况下,仅使用 Linux 节点池创建群集。 如果想要使用 Windows 节点池,可以进行添加。 例如:

az aks nodepool add \
    --resource-group $RESOURCE_GROUP_NAME \
    --cluster-name $CLUSTER_NAME \
    --os-type Windows \
    --name npwin \
    --node-count 1

在现有群集中安装 Azure 网络策略管理器或 Calico

此外,还支持在现有 AKS 群集上安装 Azure 网络策略管理器或 Calico。

警告

升级过程将触发每个节点池同时重新映像。 不支持单独升级每个节点池。 群集网络的任何中断会类似于节点映像升级或 Kubernetes 版本升级,其中节点池中的每个节点会重新映像。

安装 Azure 网络策略管理器的示例命令:

az aks update
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --network-policy azure

安装 Calico 的示例命令:

警告

此警告适用于将已启用 Calico 的 Kubenet 群集升级到已启用 Calico 的 Azure CNI 覆盖的情况。

  • 在已启用 Calico 的 Kubenet 群集中,Calico 用作 CNI 和网络策略引擎。
  • 在 Azure CNI 群集中,Calico 仅用于网络策略强制执行,而不用作 CNI。 这可能会导致 Pod 启动和 Calico 允许来自 Pod 的出站流量之间出现短暂的延迟。

建议使用 Cilium 而不是 Calico 来避免此问题。 在由 Cilium 提供支持的 Azure CNI 中了解详细信息

az aks update
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --network-policy calico

将已安装 Azure NPM 或 Calico 的现有群集升级到由 Cilium 提供支持的 Azure CNI

若要将已安装网络策略引擎的现有群集升级到由 Cilium 提供支持的 Azure CNI,请参阅将现有群集升级到由 Cilium 提供支持的 Azure CNI

验证网络策略设置

群集准备就绪后,使用 az aks get-credentials 命令将 kubectl 配置为连接到 Kubernetes 群集。 此命令将下载凭据,并将 Kubernetes CLI 配置为使用这些凭据:

az aks get-credentials --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME

若要开始验证网络策略,请创建示例应用程序并设置流量规则。

首先,创建名为 demo 的命名空间以运行示例 Pod:

kubectl create namespace demo

现在,在群集中创建名为 clientserver 的两个 Pod。

注意

如果想在特定节点上计划客户端或服务器,请在 Pod 创建 kubectl run 命令中的 --command 参数之前添加以下位:

--overrides='{"spec": { "nodeSelector": {"kubernetes.io/os": "linux|windows"}}}'

创建 server Pod。 此 Pod 在 TCP 端口 80 上提供服务:

kubectl run server -n demo --image=k8sgcr.azk8s.cn/e2e-test-images/agnhost:2.33 --labels="app=server" --port=80 --command -- /agnhost serve-hostname --tcp --http=false --port "80"

创建 client Pod。 以下命令在 client Pod 上运行 Bash:

kubectl run -it client -n demo --image=k8sgcr.azk8s.cn/e2e-test-images/agnhost:2.33 --command -- bash

现在,在一个单独的窗口中,运行以下命令来获取服务器 IP:

kubectl get pod --output=wide -n demo

输出应如下所示:

NAME     READY   STATUS    RESTARTS   AGE   IP            NODE             NOMINATED NODE   READINESS GATES
server   1/1     Running   0          30s   10.224.0.72   akswin22000001   <none>           <none>

在没有网络策略的情况下测试连接

在客户端的 shell 中,运行以下命令来验证与服务器的连接。 使用在运行上一个命令的输出中找到的 IP 来替换 server-ip。 如果连接成功,则无任何输出。

/agnhost connect <server-ip>:80 --timeout=3s --protocol=tcp

使用网络策略测试连接

若要添加网络策略,请创建名为 demo-policy.yaml 的文件并粘贴以下 YAML 清单:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: demo-policy
  namespace: demo
spec:
  podSelector:
    matchLabels:
      app: server
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: client
    ports:
    - port: 80
      protocol: TCP

指定 YAML 清单的名称并使用 kubectl apply 应用该名称:

kubectl apply �f demo-policy.yaml

现在,在客户端的 shell 中,通过运行以下 /agnhost 命令来验证与服务器的连接:

/agnhost connect <server-ip>:80 --timeout=3s --protocol=tcp

由于服务器标记为 app=server,但客户端未标记,因此与流量的连接将被阻止。 上面的连接命令将生成以下输出:

TIMEOUT

运行以下命令来标记 client 并验证与服务器的连接。 输出应不返回任何内容。

kubectl label pod client -n demo app=client

卸载 Azure 网络策略管理器或 Calico(预览版)

要求:

  • aks-preview Azure CLI 扩展版本 0.5.166 或更高版本。 请参阅安装 aks-preview Azure CLI 扩展
  • Azure CLI 2.54 或更高版本
  • AKS REST API 版本 2023-08-02-preview 或更高版本

注意

  • 卸载过程不会删除 Calico 使用的自定义资源定义 (CRD) 和自定义资源 (CR)。 这些 CRD 和 CR 的名称以“projectcalico.org”或“tigera.io”结尾。 成功卸载 Calico 后,可以手动删除这些 CRD 和关联的 CR(在删除 Calico 之前删除 CRD 会中断群集)
  • 升级将不会删除群集中的任何 NetworkPolicy 资源,但在卸载后,这些策略不再强制执行。

警告

升级过程将触发每个节点池同时重新映像。 不支持单独升级每个节点池。 群集网络的任何中断会类似于节点映像升级或 Kubernetes 版本升级,其中节点池中的每个节点会重新映像。

若要从群集中删除 Azure 网络策略管理器或 Calico,请运行以下命令:

az aks update
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CLUSTER_NAME \
    --network-policy none

清理资源

在本文中,你创建了一个命名空间和两个 Pod,并应用了网络策略。 若要清理这些资源,请使用 kubectl delete 命令并指定资源名称:

kubectl delete namespace demo

后续步骤

有关网络资源的详细信息,请参阅 Azure Kubernetes 服务 (AKS) 中应用程序的网络概念

若要详细了解策略,请参阅 Kubernetes 网络策略