自定义网络安全组阻止流量
访问托管在 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 describe 命令:
$ 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 run、 apt-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 群集的自定义虚拟网络和自定义子网,则这种安排很常见。 子网级别的规则集可能类似于下表。
优先级 名称 端口 协议 Source 目标 操作 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 管理。 相应的规则集可能类似于下表。
优先级 名称 端口 协议 Source 目标 操作 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 反馈社区提交产品反馈。