自定义网络安全组阻止流量
访问托管在 Azure Kubernetes 服务 (AKS) 群集上的应用程序时,会收到“超时”错误消息。 即使应用程序正在运行,其余配置似乎是正确的,也可能发生此错误。
先决条件
用于连接到群集的 Kubernetes kubectl 工具或类似工具。 若要使用 Azure CLI 安装 kubectl,请运行 az aks install-cli 命令。
客户端 URL (cURL) 工具或类似的命令行工具。
用于处理包的 apt-get 命令行工具。
现象
如果运行以下 kubectl get 和 cURL 命令,则会出现类似于以下控制台输出的“超时”错误:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-deployment-66648877fc-v78jm 1/1 Running 0 5m53s
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-loadbalancer-service LoadBalancer 10.0.107.79 10.81.x.x 80:31048/TCP 4m14s
$ curl -Iv http://10.81.124.39 # Use an IP address that fits the "EXTERNAL-IP" pattern.
* Trying 10.81.x.x:80...
* connect to 10.81.x.x port 80 failed: Timed out
* Failed to connect to 10.81.x.x port 80 after 21033 ms: Timed out
* Closing connection 0
curl: (28) Failed to connect to 10.81.x.x port 80 after 21033 ms: Timed out
原因
如果每次遇到相同的“超时”错误,这通常表明网络组件正在阻止流量。
若要解决此问题,可以先检查 Pod 的访问权限,然后在内部方法中转到客户端。
若要检查 Pod,请运行以下命令 kubectl get
并 kubectl 描述 命令:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-deployment-66648877fc-v78jm 1/1 Running 0 53s 172.25.0.93 aks-agentpool-42617579-vmss000000
$ kubectl describe pod my-deployment-66648877fc-v78jm # Specify the pod name from the previous command.
...
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 117s default-scheduler Successfully assigned default/my-deployment-66648877fc-v78jm to aks-agentpool-42617579-vmss000000
Normal Pulling 116s kubelet Pulling image "httpd"
Normal Pulled 116s kubelet Successfully pulled image "httpd" in 183.532816ms
Normal Created 116s kubelet Created container webserver
Normal Started 116s kubelet Started container webserver
根据此输出,Pod 似乎运行正确,无需重启。
打开测试 Pod 以检查对应用程序 Pod 的访问权限。 运行以下 kubectl get
kubectl runapt-get
和 cURL 命令:
$ kubectl get pods -o wide # Get the pod IP address.
NAME READY STATUS RESTARTS AGE IP NODE
my-deployment-66648877fc-v78jm 1/1 Running 0 7m45s 172.25.0.93 aks-agentpool-42617579-vmss000000
$ kubectl run -it --rm aks-ssh --image=debian:stable # Launch the test pod.
If you don't see a command prompt, try pressing enter.
$ root@aks-ssh:
$ # Install packages inside the test pod.
$ root@aks-ssh: apt-get update -y && apt-get install dnsutils -y && apt-get install curl -y
Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB]
Get:2 http://deb.debian.org/debian bullseye-updates InRelease [39.4 kB]
...
...
Running hooks in /etc/ca-certificates/update.d...
done.
$ # Try to check access to the pod using the pod IP address from the "kubectl get" output.
$ curl -Iv http://172.25.0.93
* Trying 172.25.0.93:80...
* Connected to 172.25.0.93 (172.25.0.93) port 80 (#0)
...
...
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
...
...
* Connection #0 to host 172.25.0.93 left intact
可以直接访问 Pod。 因此,应用程序正在运行。
定义的服务是一种 LoadBalancer
类型。 这意味着请求从结束客户端流向 Pod 将如下所示:
客户端 >> 负载均衡器 >> AKS 节点 >> 应用程序 Pod
在此请求流中,我们可以通过以下组件阻止流量:
- 群集中的网络策略
- AKS 子网和 AKS 节点的网络安全组 (NSG)
若要检查网络策略,请 kubectl get
运行以下命令:
$ kubectl get networkpolicy --all-namespaces
NAMESPACE NAME POD-SELECTOR AGE
kube-system konnectivity-agent app=konnectivity-agent 3h8m
只有 AKS 默认策略存在。 因此,网络策略似乎并没有阻止流量。
若要使用 AKS 检查 NSG 及其关联规则,请执行以下步骤:
在Azure 门户中,搜索并选择虚拟机规模集。
在规模集实例列表中,选择正在使用的实例。
在规模集实例的菜单窗格中,选择
Networking
。
此时将显示规模集实例的“网络”页。 在 “入站端口规则 ”选项卡中,将显示两组规则,这些规则基于对规模集实例执行操作的两个 NSG:
第一组由子网级别的 NSG 规则组成。 这些规则显示在以下注释标题下:
网络安全组 my-aks-nsg> (附加到子网:<my-aks-subnet>)<
如果使用 AKS 群集的自定义虚拟网络和自定义子网,则这种安排很常见。 子网级别的规则集可能与下表类似。
优先级 名称 端口 协议 源 目标 操作 65000 AllowVnetInBound 任意 任意 VirtualNetwork VirtualNetwork 允许 65001 AllowAzureLoadBalancerInBound 任意 任意 AzureLoadBalancer 任意 允许 65500 DenyAllInBound 任意 任意 任意 任意 拒绝 第二组由网络适配器级别的 NSG 规则组成。 这些规则显示在以下注释标题下:
网络安全组 aks-agentpool-agentpool-number-nsg<> (附加到网络接口:aks-agentpool-vm-scale-set-number-vmss)<>
此 NSG 由 AKS 群集应用,并由 AKS 管理。 相应的规则集可能与下表类似。
优先级 名称 端口 协议 源 目标 操作 500 <guid-TCP-80-Internet> 80 TCP Internet 10.81.x.x 允许 65000 AllowVnetInBound 任意 任意 VirtualNetwork VirtualNetwork 允许 65001 AllowAzureLoadBalancerInBound 任意 任意 AzureLoadBalancer 任意 允许 65500 DenyAllInBound 任意 任意 任意 任意 拒绝
在网络适配器级别,IP 地址为 10.81 的 TCP 有 NSG 入站规则。x.端口 80 上的 x (在表中突出显示)。 但是,子网级别的 NSG 规则中缺少等效的规则。
为什么 AKS 不会将规则应用于自定义 NSG? 由于 AKS 不会将 NSG 应用到其子网,因此不会修改与该子网关联的任何 NSG。 AKS 将仅在网络适配器级别修改 NSG。 有关详细信息,请参阅 是否可以使用 AKS 配置 NSG?。
解决方案
如果为应用程序启用了特定端口的访问权限,则必须确保自定义 NSG 允许该端口作为 Inbound
规则。 在子网级别的自定义 NSG 中添加相应的规则后,可以访问该应用程序。
$ curl -Iv http://10.81.x.x
* Trying 10.81.x.x:80...
* Connected to 10.81.x.x (10.81.x.x) port 80 (#0)
...
...
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
...
...
* Connection #0 to host 10.81.x.x left intact
联系我们寻求帮助
如果你有任何疑问或需要帮助,请创建支持请求或联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区。