自定義網路安全組會封鎖流量

當您存取裝載於 Azure Kubernetes Service (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 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 叢集的自定義虛擬網路和自定義子網,這種安排很常見。 子網層級的規則集可能類似下表。

    優先順序 名稱 連接埠 Protocol (通訊協定) 來源 Destination 動作
    65000 AllowVnetInBound 任何 任何 VirtualNetwork VirtualNetwork 允許
    65001 AllowAzureLoadBalancerInBound 任何 任何 AzureLoadBalancer 任何 允許
    65500 DenyAllInBound 任何 任何 任何 任何 Deny
  • 第二個集合是由網路適配器層級的NSG規則所組成。 這些規則會顯示在下列附註標題下:

    已連結至網路介面的網路安全組 aks-agentpool-agentpool-number-nsg<> (:aks-agentpool-vm-scale-set-number-vmss<>)

    此 NSG 由 AKS 叢集套用,並由 AKS 管理。 對應的規則集可能類似下表。

    優先順序 名稱 連接埠 Protocol (通訊協定) 來源 Destination 動作
    500 <guid-TCP-80-Internet> 80 TCP 網際網路 10.81.x。X Allow
    65000 AllowVnetInBound 任何 任何 VirtualNetwork VirtualNetwork 允許
    65001 AllowAzureLoadBalancerInBound 任何 任何 AzureLoadBalancer 任何 允許
    65500 DenyAllInBound 任何 任何 任何 任何 Deny

在網路適配器層級,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 community 支援。 您也可以將產品意見反應提交給 Azure 意應見反社群