在 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 提供支持的 Azure CNI 的 AKS 群集。
- Azure 网络策略管理器。
- Calico,一种由 Tigera 构建的开源网络和网络安全解决方案。
Cilium 是我们推荐的网络策略引擎。 Cilium 使用 Linux Berkeley 数据包筛选器 (BPF) 对流量强制执行网络策略,这通常比“IPTables”更有效。 有关详细信息,请参阅由 Cilium 提供支持的 Azure CNI 文档。
为了强制实施指定的策略,适用于 Linux 的 Azure 网络策略管理器会使用 Linux IPTables。 适用于 Windows 的 Azure 网络策略管理器使用主机网络服务 (HNS) ACLPolicies。 策略将转换为一系列允许和禁止的 IP 对。 然后,这些对作为 IPTable
或 HNS 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-plugin
和 network-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-username
和 windows-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
现在,在群集中创建名为 client
和 server
的两个 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 网络策略。