k8s 學習札記

武平宁發表於2024-07-04

深入 Kubernetes 網路:實戰K8s網路故障排查與診斷策略

k8s常見網路故障

通用排查思路

Kubernetes 叢集內不同服務之間的網路通訊出現異常,表現為請求超時、連線失敗或響應緩慢,導致服務間依賴關係中斷,依賴服務的功能不可用或效能下降,甚至可能波及整個微服務架構,引發連鎖反應,造成系統整體不穩定。

排查方法:

第一步:檢查Pod網路配置與狀態

檢視Pod網路配置:

程式碼語言:js
複製
kubectl describe pod -n
這裡要重點關注Events部分是否有網路配置相關的錯誤提示,以及IP地址是否已正確分配,如果沒有異常則再檢查Pod執行狀態。

程式碼語言:js
複製
kubectl get pods -n
檢視Pod是否處於Running狀態,如果不是,檢查其狀態(如CrashLoopBackOff)並進一步分析日誌。

第二步:網路連通性測試

這裡主要還是透過常用的ping命令來測試。

進行Pod間連通性測試,在有問題的兩個Pod中分別執行以下命令測試連通性,例如使用ping或nc(netcat)。

程式碼語言:js
複製

在源Pod中執行

kubectl exec -it -n -- ping

或者使用nc測試埠連通性

kubectl exec -it -n -- nc -zv

第三步:檢視網路策略規則

如果以上都沒有問題,則有可能是網路策略問題,執行如下命令確認是否有網路策略限制了Pod間的訪問。

程式碼語言:js
複製
kubectl get networkpolicies -n
如果有相關策略,檢查其spec-ingress和spec-egress規則,確保沒有意外地拒絕了必要的通訊。

第四步:檢查Service配置

程式碼語言:js
複製
kubectl describe service -n

kubectl get endpoints -n
再次執行上述命令來確認Service的型別、選擇器、埠配置是否正確,並確保Service有對應的Endpoints,即後端Pod列表。

第五步:檢視叢集日誌

根據異常Pod所在節點,檢查節點上的kubelet、網路外掛的日誌,尋找有關網路配置、連線嘗試或錯誤的資訊。

程式碼語言:js
複製
kubectl logs -n

1 . Pod訪問外部服務超時

現象: Pod嘗試訪問外部服務(如資料庫或API)時超時。

原因分析:通常情況下是egress規則未正確設定,導致流量無法流出叢集。

排查方法:

第一步:確認網路策略

首先,還是檢查是否有網路策略限制了Pod訪問外部網路,確保沒有規則阻止Egress(外出)流量。

程式碼語言:js
複製
kubectl get networkpolicies -n

第二步:檢視Pod網路配置

確認Pod的網路配置,尤其是iptables規則和路由表。進入Pod內部檢查:

程式碼語言:js
複製
kubectl exec -it -n -- bash
在Pod內執行以下命令檢視路由表:

程式碼語言:js
複製
ip route
並檢查iptables規則:

程式碼語言:js
複製
iptables -L -nv

第三步:測試外部連線

直接在Pod中嘗試訪問外部服務,比如ping一個公共DNS伺服器或測試埠連線:

程式碼語言:js
複製
ping 8.8.8.8
nc -vz example.com 443

第四步:DNS解析測試

如果服務訪問依賴域名,檢查DNS解析是否正常:

程式碼語言:js
複製
nslookup www.baidu.com

第五步:Egress配置檢查

如果發現是因為網路策略限制了Egress流量,那麼可以建立或修改一個網路策略來允許外部訪問。例如,允許所有Egress流量的網路策略:

程式碼語言:js
複製
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress
spec:
podSelector: {}
policyTypes:

  • Egress
    egress:
  • {}
    然後應用此策略:

程式碼語言:js
複製
kubectl apply -f allow-egress.yaml -n
生產環境中請確保根據實際情況調整策略,僅開放必要的埠和目標,保證系統的安全性。

2 . 服務ClusterIP不可達

現象: 服務的ClusterIP地址無法從叢集內部訪問。

原因分析: 服務的Kubernetes Service配置錯誤,或kube-proxy服務異常。

排查方法:

第一步:確認服務狀態

老生常談了,第一步還是確認服務的狀態,檢查服務是否已經建立並且狀態正常:

程式碼語言:js
複製
kubectl get svc -n
需要確保服務存在且其型別為ClusterIP。

第二步:服務詳情檢查

檢視服務的詳細資訊,重點關注ClusterIP、埠對映和Selector是否配置正確:

程式碼語言:js
複製
kubectl describe svc -n
確認Endpoints列表中至少有一個Pod IP,這表明服務能夠找到匹配的Pod。

第三步:驗證DNS解析

在有問題的Pod中,嘗試解析服務名以確認DNS是否工作正常:

程式碼語言:js
複製
kubectl exec -it -n -- nslookup
此時正常來說應能看到服務對應的ClusterIP地址。

第四步:網路連通性測試

從問題Pod向服務的ClusterIP和埠發起ping或TCP連線測試:

程式碼語言:js
複製
kubectl exec -it -n -- bash -c "nc -zv "

第五步:kube-proxy狀態檢查

kube-proxy負責服務的網路代理,確保它在所有節點上執行正常:

程式碼語言:js
複製
kubectl get pods -n kube-system | grep kube-proxy
如果kube-proxy有問題,檢視其日誌:

程式碼語言:js
複製
kubectl logs -n kube-system

第六步:重啟kube-proxy

如果以上都沒有異常,作為最後的嘗試,可以在所有節點上重啟kube-proxy服務,可能會解決可能的臨時問題,不過一定需要謹慎!:

程式碼語言:js
複製
sudo systemctl restart kube-proxy

3 . Ingress 502 Bad Gateway

當使用Ingress資源時遇到502 Bad Gateway錯誤,這意味著Ingress控制器無法從後端服務正確接收響應。

第一步:檢查Ingress資源配置

首先,確保Ingress資源配置正確,包括路徑、服務名稱、埠等:

程式碼語言:js
複製
kubectl describe ingress -n

第二步:檢查Ingress資源配置

檢查關聯的服務和Pod是否執行正常:

程式碼語言:js
複製
kubectl get svc -n
kubectl get pods -n
確認Pod無CrashLoopBackOff或Error狀態,服務有正確的埠對映和Selector。

第三步:檢查Endpoints

驗證服務是否繫結了正確的Pod:

程式碼語言:js
複製
kubectl describe svc -n
在輸出中查詢Endpoints部分,確保有Pod IP列表。

第四步:檢視Ingress控制器日誌

根據使用的Ingress控制器(如Nginx Ingress Controller、Istio Ingress Gateway等),獲取其日誌以獲取更多資訊:

程式碼語言:js
複製

對於Nginx Ingress Controller

kubectl logs -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx
分析日誌中是否有與502錯誤相關的錯誤資訊或警告。

第五步:確認後端服務可達性

從Ingress所在節點或Pod內嘗試直接訪問後端服務,以排除網路問題:

程式碼語言:js

kubectl run -it --rm --restart=Never debug --image=busybox -- /bin/sh -n <namespace>

# 在新Pod中執行
nc -vz <backend-service-ip> <service-port>

第六步:重啟Ingress控制器

如果上述步驟未解決問題,嘗試重啟Ingress控制器Pod:

程式碼語言:js
複製
kubectl delete pod -n

附:常用k8s排查命令

容器網路故障
確認容器是否已正確啟動並執行,並且是否已被正確配置為使用正確的網路。
執行命令,確認 Pod 是否已正確啟動並執行。

程式碼語言:js
複製
kubectl get pods
執行命令,確認容器的網路配置是否正確。

程式碼語言:js
複製
kubectl describe pod
檢查 Pod 和容器的網路配置,例如 IP 地址、子網掩碼、閘道器、DNS 等是否正確配置。
執行命令檢視容器的網路配置資訊。

程式碼語言:js
複製
kubectl describe pod
執行命令 ,檢視容器的網路介面資訊。

程式碼語言:js
複製
kubectl exec -- ifconfig
檢查網路外掛是否正常工作,並嘗試重啟網路外掛。
如果使用 Flannel 網路外掛,執行命令 檢視 Flannel 的日誌資訊。

程式碼語言:js
複製
kubectl logs -n kube-system -l k8s-app=flannel
如果使用 Calico 網路外掛,執行命令,檢視 Calico 的日誌資訊。

程式碼語言:js
複製
kubectl logs -n kube-system -l k8s-app=calico-node
重啟網路外掛:如果使用 Flannel 網路外掛,執行命令

程式碼語言:js
複製
kubectl delete pod -n kube-system -l k8s-app=flannel
如果使用 Calico 網路外掛,執行命令。

程式碼語言:js
複製
kubectl delete pod -n kube-system -l k8s-app=calico-node
檢查網路裝置是否正常工作,例如交換機、路由器、防火牆等是否出現故障。
檢查網路裝置的日誌或配置資訊,確認網路裝置是否正常工作。

嘗試使用 Kubernetes 工具進行診斷,例如 kubectl,以檢視 Pod 和容器的狀態和日誌。
執行命令,檢視容器的日誌資訊。

程式碼語言:js
複製
kubectl logs
執行命令 ,檢視容器的狀態資訊。

程式碼語言:js
複製
kubectl describe pod
如果以上方法無法解決問題,可以考慮重新部署容器網路或更換網路外掛。
如果使用 Flannel 網路外掛,執行命令 重新部署 Flannel 網路外掛。

程式碼語言:js
複製
kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml && kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml,
如果使用 Calico 網路外掛,執行命令重新部署 Calico 網路外掛。

程式碼語言:js
複製
kubectl delete -f https://docs.projectcalico.org/manifests/calico.yaml && kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
網路策略故障
檢視所有網路策略:
程式碼語言:js
複製
kubectl get networkpolicies --all-namespaces
檢視網路策略的詳細資訊:
程式碼語言:js
複製
kubectl describe networkpolicy -n
檢查網路策略的規則是否正確:
程式碼語言:js
複製
kubectl get networkpolicy -n -o yaml
檢查容器是否正確標記:
程式碼語言:js
複製
kubectl get pods --selector= -n -o wide
檢查容器的埠是否正確配置:
程式碼語言:js
複製
kubectl get pods -n -o yaml
檢查節點是否正確配置:
程式碼語言:js
複製
kubectl get nodes -o wide
檢查網路裝置是否正常工作:
程式碼語言:js
複製
kubectl logs -n
如果你的Kubernetes叢集使用的是Calico網路策略,你可以使用以下命令:
檢視所有Calico網路策略:

程式碼語言:js
複製
kubectl get networkpolicies.projectcalico.org --all-namespaces
檢視Calico網路策略的詳細資訊:

程式碼語言:js
複製
kubectl describe networkpolicy -n
檢查Calico網路策略的規則是否正確:

程式碼語言:js
複製
kubectl get networkpolicy -n -o yaml
檢查Calico網路裝置是否正常工作:

程式碼語言:js
複製
kubectl logs -n kube-system -l k8s-app=calico-node
DNS 故障
檢查網路裝置是否連通:
程式碼語言:js
複製
ping
檢查網路裝置的日誌資訊:
程式碼語言:js
複製
kubectl logs -n
檢查網路裝置的配置資訊:
程式碼語言:js
複製
kubectl exec -it -n --
檢查網路裝置的版本資訊:
程式碼語言:js
複製
kubectl exec -it -n --
檢查網路裝置的連線狀態:
程式碼語言:js
複製
kubectl exec -it -n --

相關文章