針對 AKS 叢集中的網路問題進行疑難解答

新的 Kubernetes 安裝或當您增加 Kubernetes 負載時,可能會發生網路問題。 其他與網路問題相關的問題也可能發生。 請一律檢查 AKS 疑難解答 指南,以查看您的問題是否描述於該處。 本文說明網路疑難解答觀點和可能發生的特定問題的其他詳細數據和考慮。

用戶端無法連線到 API 伺服器

這些錯誤牽涉到您無法透過 Kubernetes 叢集命令行工具 (kubectl) 或任何其他工具連線到 Azure Kubernetes Service (AKS) 叢集 API 伺服器時所發生的連線問題,例如透過程式設計語言的 REST API。

錯誤

您可能會看到如下所示的錯誤:

Unable to connect to the server: dial tcp <API-server-IP>:443: i/o timeout 
Unable to connect to the server: dial tcp <API-server-IP>:443: connectex: A connection attempt
failed because the connected party did not properly respond after a period, or established 
connection failed because connected host has failed to respond. 

原因 1

API 伺服器授權的IP範圍有可能在叢集的 API 伺服器上啟用,但用戶端的IP位址不包含在這些IP範圍中。 若要判斷是否啟用IP範圍,請在 Azure CLI 中使用下列 az aks show 命令。 如果啟用IP範圍,命令將會產生IP範圍清單。

az aks show --resource-group <cluster-resource-group> \ 
    --name <cluster-name> \ 
    --query apiServerAccessProfile.authorizedIpRanges 

解決方案 1

請確定用戶端的 IP 位址位於叢集 API 伺服器授權的範圍內:

  1. 尋找您的本機IP位址。 如需如何在 Windows 和 Linux 上尋找它的資訊,請參閱 如何尋找我的 IP

  2. 使用 az aks update Azure CLI 中的 命令,更新 API 伺服器授權的範圍。 授權用戶端的IP位址。 如需指示,請參閱 更新叢集的 API 伺服器授權 IP 範圍

原因 2

如果您的 AKS 叢集是私人叢集,API 伺服器端點就不會有公用 IP 位址。 您必須使用具有 AKS 叢集虛擬網路之網路存取權的 VM。

解決方案 2

如需如何解決此問題的資訊,請參閱 連線到私人叢集的選項。

Pod 無法設定 IP 位址

錯誤

Pod 停滯於 ContainerCreating 狀態中,而其事件會回報 Failed to allocate address 錯誤:

Normal   SandboxChanged          5m (x74 over 8m)    kubelet, k8s-agentpool-00011101-0 Pod sandbox
changed, it will be killed and re-created. 

  Warning  FailedCreatePodSandBox  21s (x204 over 8m)  kubelet, k8s-agentpool-00011101-0 Failed 
create pod sandbox: rpc error: code = Unknown desc = NetworkPlugin cni failed to set up pod 
"deployment-azuredisk6-874857994-487td_default" network: Failed to allocate address: Failed to 
delegate: Failed to allocate address: No available addresses 

或錯誤 not enough IPs available

Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox 
'ac1b1354613465324654c1588ac64f1a756aa32f14732246ac4132133ba21364': plugin type='azure-vnet' 
failed (add): IPAM Invoker Add failed with error: Failed to get IP address from CNS with error: 
%w: AllocateIPConfig failed: not enough IPs available for 9c6a7f37-dd43-4f7c-a01f-1ff41653609c, 
waiting on Azure CNS to allocate more with NC Status: , IP config request is [IPConfigRequest: 
DesiredIPAddress , PodInterfaceID a1876957-eth0, InfraContainerID 
a1231464635654a123646565456cc146841c1313546a515432161a45a5316541, OrchestratorContext 
{'PodName':'a_podname','PodNamespace':'my_namespace'}]

檢查外掛程式IPAM存放區中配置的IP位址。 您可能會發現已設定所有 IP 位址,但數目遠小於執行中的 Pod 數目:

如果使用 kubenet

# Kubenet, for example. The actual path of the IPAM store file depends on network plugin implementation. 
chroot /host/
ls -la "/var/lib/cni/networks/$(ls /var/lib/cni/networks/ | grep -e "k8s-pod-network" -e "kubenet")" | grep -v -e "lock\|last\|total" -e '\.$' | wc -l
244

注意

對於沒有 Calico 的 kubenet,路徑為 /var/lib/cni/networks/kubenet。 對於具有 Calico 的 kubenet,路徑為 /var/lib/cni/networks/k8s-pod-network。 上述文稿會在執行命令時自動選取路徑。

# Check running Pod IPs
kubectl get pods --field-selector spec.nodeName=<your_node_name>,status.phase=Running -A -o json | jq -r '.items[] | select(.spec.hostNetwork != 'true').status.podIP' | wc -l
7 

如果使用 Azure CNI 進行動態 IP 配置

kubectl get nnc -n kube-system -o wide
NAME                               REQUESTED IPS  ALLOCATED IPS  SUBNET  SUBNET CIDR   NC ID                                 NC MODE  NC TYPE  NC VERSION
aks-agentpool-12345678-vmss000000  32             32             subnet  10.18.0.0/15  559e239d-f744-4f84-bbe0-c7c6fd12ec17  dynamic  vnet     1
# Check running Pod IPs
kubectl get pods --field-selector spec.nodeName=aks-agentpool-12345678-vmss000000,status.phase=Running -A -o json | jq -r '.items[] | select(.spec.hostNetwork != 'true').status.podIP' | wc -l
21

原因 1

此錯誤可能是網路外掛程式中的錯誤所造成。 當 Pod 終止時,外掛程式無法解除分配 IP 位址。

解決方案 1

請連絡 Microsoft 以取得因應措施或修正。

原因 2

Pod 建立速度比垃圾收集終止的 Pod 快得多。

解決方案 2

設定 kubelet 的快速垃圾收集。 如需指示,請參閱 Kubernetes 垃圾收集檔

Pod 記憶體取的服務

解決此問題的第一個步驟是檢查是否已為服務自動建立端點:

kubectl get endpoints <service-name> 

如果您收到空的結果,則服務的標籤選取器可能錯誤。 確認標籤正確:

# Query Service LabelSelector. 
kubectl get svc <service-name> -o jsonpath='{.spec.selector}' 

# Get Pods matching the LabelSelector and check whether they're running. 
kubectl get pods -l key1=value1,key2=value2 

如果上述步驟傳回預期的值:

  • 檢查 Pod containerPort 是否與服務 containerPort相同。

  • 檢查是否 podIP:containerPort 正常運作:

    # Testing via cURL. 
    curl -v telnet ://<Pod-IP>:<containerPort>
    
    # Testing via Telnet. 
    telnet <Pod-IP>:<containerPort> 
    

以下是服務問題的其他一些可能原因:

  • 容器不會接聽指定的 containerPort。 (檢查 Pod 描述。)
  • 發生 CNI 外掛程式錯誤或網路路由錯誤。
  • kube-proxy 未執行,或 iptables 規則未正確設定。
  • 網路原則正在卸除流量。 如需套用和測試網路原則的資訊,請參閱 Azure Kubernetes 網路原則概觀
    • 如果您使用 Calico 作為網路外掛程式,您也可以擷取網路原則流量。 如需設定該設定的資訊,請參閱 Calico 網站

節點無法連線到 API 伺服器

許多附加元件和容器都需要存取 Kubernetes API(例如 kube-dns 和操作員容器)。 如果此程式期間發生錯誤,下列步驟可協助您判斷問題的來源。

首先,確認 Kubernetes API 是否可在 Pod 中存取:

kubectl run curl --image=mcr.microsoft.com/azure-cli -i -t --restart=Never --overrides='[{"op":"add","path":"/spec/containers/0/resources","value":{"limits":{"cpu":"200m","memory":"128Mi"}}}]' --override-type json --command -- sh

然後,從您現在殼層進入的容器內執行下列命令。

# If you don't see a command prompt, try selecting Enter. 
KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) 
curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/default/pods

狀況良好的輸出看起來會如下所示。

{ 
  "kind": "PodList", 
  "apiVersion": "v1", 
  "metadata": { 
    "selfLink": "/api/v1/namespaces/default/pods", 
    "resourceVersion": "2285" 
  }, 
  "items": [ 
   ... 
  ] 
} 

如果發生錯誤,請檢查服務及其端點是否 kubernetes-internal 狀況良好:

kubectl get service kubernetes-internal
NAME                TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE 
kubernetes-internal ClusterIP   10.96.0.1    <none>        443/TCP   25m 
kubectl get endpoints kubernetes-internal
NAME                ENDPOINTS          AGE 
kubernetes-internal 172.17.0.62:6443   25m 

如果這兩個測試都傳回如上述的回應,且傳回的IP和埠符合容器的回應,則 kube-apiserver 可能未執行或遭到網路封鎖。

存取可能會遭到封鎖的主要原因有四個:

您也可以使用容器深入解析來檢查 kube-apiserver 記錄。 如需查詢 kube-apiserver 記錄和其他許多查詢的資訊,請參閱 如何從容器深入解析查詢記錄。

最後,您可以檢查 kube-apiserver 狀態及其叢集本身的記錄:

# Check kube-apiserver status. 
kubectl -n kube-system get pod -l component=kube-apiserver 

# Get kube-apiserver logs. 
PODNAME=$(kubectl -n kube-system get pod -l component=kube-apiserver -o jsonpath='{.items[0].metadata.name}')
kubectl -n kube-system logs $PODNAME --tail 100

如果傳 403 - Forbidden 回錯誤,kube-apiserver 可能已使用角色型訪問控制 (RBAC) 設定,且您的容器 ServiceAccount 可能未獲授權存取資源。 在此情況下,您應該建立適當的 RoleBindingClusterRoleBinding 物件。 如需角色和角色系結的相關信息,請參閱 存取和身分識別。 如需如何在叢集上設定 RBAC 的範例,請參閱 使用 RBAC 授權

參與者

本文由 Microsoft 維護。 原始投稿人如下。

主體作者:

其他投稿人:

下一步