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

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

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

开始之前

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

卸载 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

网络策略概述

默认情况下,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
支持的网络选项 Azure 容器网络接口 (CNI)。 Azure CNI(Linux、Windows Server 2019 和 2022)和 kubenet (Linux)。 Azure CNI。
符合 Kubernetes 规范 支持的所有策略类型 支持所有策略类型。 支持所有策略类型。
其他功能 无。 扩展的策略模型,包括全局网络策略、全局网络集和主机终结点。 有关使用 calicoctl CLI 管理这些扩展功能的详细信息,请参阅 calicoctl 用户参考 无。
支持 受 Azure 支持和工程团队支持。 受 Azure 支持和工程团队支持。 受 Azure 支持和工程团队支持。

限制

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

在 Windows 中,Azure 网络策略管理器不支持:

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

注意

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

缩放

对于适用于 Linux 的 Azure 网络策略管理器,我们不允许缩放超过 250 个节点和 20,000 个 Pod。 如果尝试缩放超出这些限制,可能会遇到“内存不足”(OOM) 错误。 若要提高内存限制,请创建支持票证。

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

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

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

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

[!Note} 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

创建启用了 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

创建群集需要几分钟时间。 默认情况下,仅使用 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 节点还默认启用 直接服务器返回 (DSR)

对于使用早期版本 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

创建群集需要几分钟时间。 默认情况下,仅使用 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

清理资源

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

kubectl delete namespace demo

后续步骤

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

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