自定义网络安全组阻止流量

访问托管在 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 getkubectl 描述 命令:

$ 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 getkubectl 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 及其关联规则,请执行以下步骤:

  1. Azure 门户中,搜索并选择虚拟机规模集

  2. 在规模集实例列表中,选择正在使用的实例。

  3. 在规模集实例的菜单窗格中,选择 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 反馈社区