排解 GKE 網路觀測問題

本文提供操作說明和診斷程序,協助您使用 GKE Dataplane V2 觀測功能、Hubble 和 Cloud Monitoring,診斷 Google Kubernetes Engine (GKE) 叢集中的網路問題。

如需架構總覽和概念最佳做法,請參閱「網路可觀測性最佳做法」。

疑難排解決策樹和核心概念

在查看程序之前,請先使用下列決策矩陣,找出可能導致問題的 GKE 網路堆疊層級,然後前往對應的章節。

症狀或診斷型問題 疑似層級 建議程序
Pod 無法解析外部網域或內部 Kubernetes 服務 (DNS 超時、NXDOMAIN、SERVFAIL)。 第 1 層:Pod 和服務 (DNS) 診斷 DNS 解析失敗問題
服務無法通訊;Pod 之間的連線逾時或封包遭到捨棄。 第 1 層:Pod 和服務 (政策或封包捨棄) 診斷封包丟棄和 NetworkPolicy 封鎖問題
工作負載副本的流量負載不均,或 Pod 記錄的 TCP 重設率 (RST) 偏高。 第 1 層:Pod 和服務 (負載平衡或傳輸) 診斷流量失衡和 TCP 重設問題
一般延遲、間歇性逾時或節點間的 CNI 重新啟動。 第 2 層:節點和 CNI (核心) 節點層級延遲和 CNI 瓶頸的分類
Pod 無法連線至 GKE 外部的資源 (Cloud SQL、外部 API 或其他 VPC)。 第 3 層:虛擬私有雲和路由 區分 GKE 與虛擬私有雲或外部連線問題
需要自動路徑模擬,確認防火牆規則、路徑或 NetworkPolicy 是否會封鎖流量。 第 3 層:虛擬私有雲和路由 (模擬) 使用 Connectivity Tests 診斷連線問題
您需要找出哪些工作負載會將流量傳送至網際網路,並進行 NAT。 第 4 級:外部閘道和費用 識別 NAT 流量 (輸出至網際網路)
區域間資料移轉費用高昂,或需要顯示通話量最高的通話者,但不想編寫 SQL 查詢。 第 4 級:外部閘道和費用 使用 Flow Analyzer 分析叢集流量成本和效能

核心網路概念

如果您剛開始使用 Kubernetes 或 Google Cloud 網路,請記住下列核心概念:

  • eBPF (擴充 Berkeley 封包篩選器):作業系統技術,可直接在 Linux 核心中執行安全監控和路由程式。GKE Dataplane V2 使用 eBPF 路由傳送封包,並強制執行 NetworkPolicy,效能負擔極低。
  • IP 偽裝 (SNAT):重新編寫封包來源 IP 位址的程序。當 GKE Pod (具有私人 IP 位址) 與網際網路或外部 VPC 資源通訊時,GKE 會將 Pod IP 位址偽裝 (重新編寫) 為節點 IP 位址,讓外部系統知道如何轉送回覆。
  • 連線追蹤 (Conntrack):這項核心功能會追蹤所有有效網路連線。在 GKE Dataplane V2 叢集中,這項追蹤作業會分成兩個表格:標準 Linux 核心 conntrack (由 ip-masq-agent 使用),以及儲存在 eBPF 對應中的 Cilium 和 GKE Dataplane V2 管理的 conntrack 表格。如果節點處理的並行連線過多,這兩個追蹤表就會填滿 (連線追蹤耗盡),導致節點自動捨棄新封包。
  • Hubble:GKE Dataplane V2 的觀測引擎。這項功能以 eBPF 為基礎,可即時掌握流量、封包丟棄情形和 NetworkPolicy 評估結果。

第 1 層:Pod 和服務 (應用程式) 可觀測性

Pod 和 Service 層級涵蓋 Pod、Service 和叢集 DNS 之間的網路通訊。這個層級的問題通常會導致應用程式連線逾時、名稱解析失敗或負載分配不均。

診斷 DNS 解析失敗問題

排解 DNS 問題前,請先查看診斷範圍和必要條件:

  • 重點領域:Pod 與 CoreDNS 或 NodeLocal DNSCache 之間的通訊、DNS 延遲、上游 DNS 解析逾時,以及 FQDN NetworkPolicy 驗證。
  • 必要條件:已啟用 GKE Dataplane V2 指標;kubectl存取權。
  • CNI 相容性:GKE Dataplane V2 (進階資料路徑) 和標準 GKE CNI。
  • 症狀:Pod 會記錄 dial tcp: lookup <domain>: i/o timeout、NXDOMAIN,或外送 API 呼叫發生間歇性延遲。
  • 目標:判斷 DNS 故障是否源自叢集內部 (kube-dns 或 NodeLocal DNSCache 飽和)、NetworkPolicy 封鎖 UDP 或 TCP 通訊埠 53,或是上游網路效能降低。

步驟 1:基本可連線性檢查

排解 DNS 層問題前,請先確認是否可直接從受影響的 Pod 使用目的地 IP 位址連線:

# 1. Test raw IP reachability (bypasses DNS entirely)
kubectl exec -it my-pod -n default -- curl -v --connect-timeout 5 http://10.240.0.10:8080

# 2. Test domain resolution
kubectl exec -it my-pod -n default -- curl -v --connect-timeout 5 http://my-service.default.svc.cluster.local:8080
  • 如果 IP 連線成功,但網域連線失敗:問題出在 DNS 解析層。繼續執行步驟 2。
  • 如果兩者都失敗:問題出在網路層級的路由或政策強制執行。 請參閱「診斷封包遺失和 NetworkPolicy 封鎖問題」。
檢查 FQDN NetworkPolicy DNS 預先填入作業

如果叢集使用以 FQDN 為基礎的 NetworkPolicy (FQDNNetworkPolicy),請確認網域名稱已明確獲得許可。如果 Pod 查詢的外部網域未預先填入 GKE Dataplane V2 DNS Proxy 快取,或政策不允許,GKE Dataplane V2 會封鎖傳出流量至已解析的 IP 位址:

# Verify whether UDP or TCP port 53 egress is permitted in the Pod's namespace
kubectl get networkpolicy -n default -o yaml | grep -A 5 -B 2 "port: 53"

步驟 2:在 Cloud Monitoring 中查看 DNS 指標

GKE 會在 Cloud Monitoring 中公開內建 DNS 指標,並加上 kubernetes.io/networking/dns/ 前置字元。

如要在 Cloud Monitoring 中查看 DNS 指標,請按照下列步驟操作:

  1. 在 Google Cloud 控制台中,依序前往「Cloud Monitoring」>「資訊主頁」。
  2. 選取預先定義的 GKE DNS Observability - Cluster View 資訊主頁 (或前往 Metrics Explorer 並篩選 kubernetes.io/networking/dns/)。
  3. 評估下列主要信號 (如果是 NodeLocal DNSCache,請將指標路徑中的 kubedns 替換為 node_local_dns):
指標名稱 警告性問題門檻 根本原因
kubernetes.io/networking/dns/kubedns/max_concurrent_rejected_request_count > 0 已達並行查詢上限,kube-dns 或 NodeLocal DNSCache 正在捨棄查詢。
kubernetes.io/networking/dns/kubedns/dns_request_latencies p99 > 100 毫秒 kube-dns 或 NodeLocal DNSCache 的端對端 DNS 解析延遲時間較長。
kubernetes.io/networking/dns/kubedns/forwarding_request_latencies p99 > 100 毫秒 上游 DNS 伺服器延遲或飽和。
DNS 效能和逾時的分類順序

請按照下列分類順序診斷 DNS 延遲、快取未命中和上游逾時問題:

  1. 檢查快取命中率:依 cache_status 標籤分組的查詢 kubernetes.io/networking/dns/kubedns/dns_cache_request_count (或 node_local_dns/dns_cache_request_count)。如果 cache_status="hit" 偏低且 cache_status="miss" 偏高,應用程式可能發出非 FQDN 查詢 (例如 my-service 而非 my-service.default.svc.cluster.local),導致搜尋路徑遍歷 /etc/resolv.conf 中的所有項目。
  2. 評估上游延遲時間:如果延遲時間較長forwarding_request_latencies,表示上游 DNS 伺服器有問題 (例如透過 Cloud Interconnect 或 Cloud VPN 連線的地端部署公司 DNS,或是 Cloud DNS 限制)。
  3. 稽核自訂 DNS 覆寫:檢查自訂 kube-dns ConfigMap 是否有設定錯誤的存根或上游轉送:

    kubectl get configmap kube-dns -n kube-system -o yaml
    

步驟 3:使用 Hubble CLI 串流即時 DNS 流量

使用 Hubble CLI 輔助別名,檢查從節點核心串流的即時 DNS 要求和回應:

# 1. Ensure the helper alias is set in your terminal session
alias gke-hubble="kubectl exec -it -n gke-managed-dpv2-observability deployment/hubble-relay -c hubble-cli -- hubble"

# 2. Observe live DNS (Port 53) traffic for a specific Pod
gke-hubble observe --pod default/my-pod --port 53

步驟 4:驗證修正內容

如果發生並行查詢遭拒的情況,請套用 NodeLocal DNSCache,直接在節點上吸收高頻率的 DNS 查詢,避免達到叢集範圍的 kube-dns 限制:

# Verify NodeLocal DNSCache DaemonSet is running
kubectl get daemonset node-local-dns -n kube-system

診斷封包遺失和 NetworkPolicy 封鎖問題

調查封包遺失和政策拒絕問題前,請先查看診斷範圍和必要條件:

  • 重點領域:Pod 物件之間或 Pod 與服務物件之間的流量下降、NetworkPolicy 強制執行、核心 eBPF 捨棄原因。
  • 必要條件:啟用 GKE Dataplane V2 流量觀測功能;設定 NetworkPolicy 記錄。
  • CNI 相容性:僅限 GKE Dataplane V2。
  • 症狀:應用程式連線嘗試失敗,並顯示 Connection timed out 或 Connection reset by peer。
  • 目標:找出導致封包遭到捨棄的確切 NetworkPolicy 或 eBPF 原因,不必透過試誤方式變更安全性政策。

步驟 1:監控 Hubble 捨棄指標

當 GKE Dataplane V2 捨棄封包時,會發出標記有捨棄原因和來源/目的地中繼資料的指標 hubble_drop_total。如要監控 Hubble 捨棄指標,請按照下列步驟操作:

  1. 如果尚未設定,請部署 Google Cloud Managed Service for Prometheus PodMonitoring 資源,以擷取 Hubble 指標:

    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: hubble-metrics
      namespace: gke-managed-dpv2-observability
    spec:
      selector:
        matchLabels:
          k8s-app: cilium
      endpoints:
      - port: hubble-metrics
        interval: 30s
    
  2. 在 Cloud Monitoring > Metrics Explorer 中執行下列查詢,即可依據原因查看捨棄的封包:

    sum by (reason) (rate(hubble_drop_total[5m])) > 0
    
  3. 解讀常見的 reason 代碼:

    • Policy denied:Kubernetes NetworkPolicy 明確或隱含地封鎖連線。
    • CT: Map insertion failed:連線追蹤 (conntrack) 表格已用盡。
    • Unsupported L3 protocol:非 IPv4 或 IPv6 封包,或標頭已損毀。

步驟 2:在 Cloud Logging 中檢查 NetworkPolicy 記錄

網路政策記錄會匯出所有政策決策的結構化 JSON 記錄。如要在 Cloud Logging 中查詢 NetworkPolicy 記錄,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的「Cloud Logging」>「Logs Explorer」頁面。
  2. 執行以下查詢:

    resource.type="k8s_node"
    log_name:"projects/PROJECT_ID/logs/events"
    jsonPayload.connection.verdict="DENY"
    jsonPayload.src.pod_name="my-source-pod"
    
  3. 檢查 JSON 酬載:

    • jsonPayload.drop_reason:顯示封包遭捨棄的原因。
    • jsonPayload.policies:列出經過評估的 NetworkPolicy。如果傳回的清單為空白,且判決結果為 DENY,表示命名空間是以預設拒絕模式運作,且沒有任何政策允許流量。

如果沒有顯示 NetworkPolicy 記錄,請確認叢集的 NetworkLogging 自訂資源是否已啟用記錄功能。舉例來說,請確認 spec.cluster.deny.log 欄位是否設為 true:

kubectl get networklogging default -o yaml

步驟 3:使用 Hubble CLI 追蹤即時捨棄的封包

使用 Hubble CLI 檢查即時封包,直接串流即時捨棄的封包:

gke-hubble observe --verdict DROPPED --namespace default --follow

輸出內容範例:

TIMESTAMP             SOURCE               DESTINATION          TYPE     VERDICT
10:14:22.102          default/frontend     default/backend:80   to-stack DROPPED (Policy denied by NetworkPolicy: backend-deny-all)

輸出內容會指出確切的 NetworkPolicy 封鎖流量 (backend-deny-all)。

步驟 4:檢查 conntrack 耗盡情形

如果捨棄原因顯示 CT: Map insertion failed:

  1. 檢查 GKE Dataplane V2 代理記錄,瞭解 conntrack 資料表飽和度:

    kubectl logs -n kube-system daemonset/anetd -c cilium-agent --tail=100 | grep "Conntrack table full"
    
  2. 檢查受影響節點上 conntrack 資料表的最大大小:

    kubectl exec -it -n kube-system daemonset/anetd -c cilium-agent -- cilium status --all-controllers | grep -i conntrack
    

    如果 conntrack 資料表已滿,請在更多節點上水平擴展工作負載,或降低用戶端 Pod 的連線速率。


診斷流量失衡和 TCP 重設問題

排解流量不平衡和連線重設問題前,請先查看診斷範圍和必要條件:

  • 重點領域:負載平衡不均、TCP 交握失敗、連線突然終止。
  • 必要條件:啟用 GKE Dataplane V2 指標。
  • CNI 相容性:GKE Dataplane V2。
  • 症狀:某些 Pod 副本收到過多流量,其他副本則閒置;用戶端應用程式會記錄 connection reset by peer 或 broken pipe。
  • 目標:判斷流量失衡是因傳輸層 (OSI 第 4 層,TCP) 的連線黏性所致,還是應用程式層 (OSI 第 7 層,HTTP/2 或 gRPC) 所致,並找出 TCP RST 封包的來源。

步驟 1:比較 Pod 層級的流量

如要判斷流量是否平均分配給所有副本,請執行下列操作:

  1. 在 Cloud Monitoring 中,查詢 Deployment 中所有 Pod 的連入流量計數:

    sum by (pod) (rate(pod_flow_ingress_flows_count{destination_workload="my-service"}[5m]))
    
  2. 評估 Pod 之間的流量分配情形。如果單一 Pod 接收到大部分流量,請調查連線重複使用或固定工作階段:

    • gRPC 或 HTTP/2:長期存在的 TCP 連線會導致所有要求都透過單一 TCP 串流,傳送至一個後端 Pod。傳輸層 (OSI 第 4 層,TCP) Kubernetes 服務路由無法平衡已建立的 HTTP/2 連線內的要求。
    • ClientIP 工作階段相依性:確認服務是否已設定 sessionAffinity: ClientIP。
    • 無頭服務:用戶端可能會解析 DNS 一次,並永久快取單一 IP 位址。

步驟 2:分析 TCP 重設指標

TCP 重設 (RST) 會立即終止連線。當端點收到不明連接埠的封包,或應用程式關閉連線時,作業系統核心會發出這些事件,但緩衝區中仍有未讀取的資料。

在 Cloud Monitoring 中執行下列 MQL 查詢:

fetch prometheus_target
| metric 'prometheus.googleapis.com/hubble_tcp_flags_total/counter'
| filter (metric.flag == 'RST')
| align rate(1m)
| every 1m
| group_by [metric.source, metric.destination, metric.traffic_direction], sum(val())

查看查詢結果,判斷重設來源:

  • 傳出 RST (traffic_direction=egress):本機 Pod 正在產生重設。檢查 Pod 應用程式是否當機、達到連線限制或主動拒絕連線。
  • 傳入 RST (traffic_direction=ingress):遠端對等互連 (外部資料庫、API 或遠端 Pod) 傳送了重設。檢查目的地伺服器健康狀態和防火牆狀態。

步驟 3:即時串流 TCP 重設

使用 Hubble CLI 擷取即時重設信號交換:

gke-hubble observe --type trace --verdict FORWARDED --tcp-flags RST --namespace default

步驟 4:修復和可執行的修正措施

請根據流量失衡或 TCP 重設的原因,採取下列補救措施:

  • 應用程式層 (OSI 第 7 層) 或 gRPC 連線黏性:
    • 部署 Cloud Service Mesh,啟用應用程式層 (OSI 第 7 層) 要求層級的負載平衡。
    • 設定用戶端連線限制或 keep-alive 逾時 (例如 gRPC MAX_CONNECTION_AGE 和 MAX_CONNECTION_AGE_GRACE),強制定期重新建立連線。
  • 服務 IP 親和性:除非應用程式狀態嚴格要求,否則請移除 service.spec.sessionAffinity。
  • 無標題服務 DNS 快取:確保應用程式執行階段 (例如 JVM networkaddress.cache.ttl) 不會無限期快取 DNS 結果。
  • 應用程式待處理佇列溢位:應用程式接聽佇列已滿時,Linux 核心會捨棄傳入的 SYN 封包,或傳送 TCP RST。水平擴展 Pod 副本,或增加應用程式接聽積壓工作 (somaxconn)。

第 2 層:節點和 CNI (核心) 可觀測性

節點和 CNI 層包含主機 Linux 核心、eBPF 程式和節點網路介面。這個層級的瓶頸會影響在受影響節點上執行的所有工作負載。

系統完整性檢查:偵測未經授權的 anetd 修補程式

GKE Dataplane V2 會以代管式 DaemonSet (anetd) 的形式在 kube-system 命名空間中執行。在 Cloud Logging 中,您可以查詢 Kubernetes 稽核記錄,偵測未經授權的使用者或自動化指令碼是否已修補或重新啟動 anetd:

protoPayload.methodName="io.k8s.core.v1.daemonsets.patch" OR
protoPayload.methodName="io.k8s.core.v1.daemonsets.update"
protoPayload.resourceName="namespaces/kube-system/daemonsets/anetd"

如果偵測到未經授權的修補作業,請將 DaemonSet 還原為預設設定,或觸發節點集區重建作業,以還原受管理狀態。


節點層級延遲和 CNI 瓶頸的分類

診斷節點層級延遲和核心瓶頸前,請先查看診斷範圍和必要條件:

  • 重點領域:主機核心延遲、VM 介面封包丟棄、GKE Dataplane V2 eBPF 代理程式飽和度、連線追蹤耗盡。
  • 必要條件:已啟用 Compute Engine VM 指標;kubectl 存取權。
  • CNI 相容性:GKE Dataplane V2 和標準 GKE CNI。
  • 症狀:跨節點流量發生延遲尖峰或隨機下降情形,但節點內流量仍維持正常。
  • 目標:區分主機 VM 網路節流、Linux 核心捨棄和 CNI 層級瓶頸。

步驟 1:區分 GKE 外部和內部問題

執行 Compute Engine VM 基準測試:在與 GKE 叢集節點相同的 VPC 子網路中,部署獨立的 Compute Engine VM。測試從 VM 到目標目的地的連線。

  • 如果獨立 VM 發生相同的封包遺失或延遲情形:問題位於 GKE 外部 (VPC 防火牆、Cloud NAT、Cloud Interconnect 或外部伺服器)。請繼續進行「區分 GKE 與虛擬私有雲或外部連線問題」。
  • 如果獨立 VM 通訊正常,但 GKE Pod 失敗:問題出在 GKE 內部 (節點層級 eBPF、conntrack 或 CNI)。繼續執行步驟 2。

步驟 2:區分應用程式問題與節點和 CNI 層級問題

如要判斷延遲時間是源自應用程式,還是節點和 CNI 層級,請按照下列步驟操作:

  1. 檢查應用程式資源飽和度:確認節點未發生 CPU 節流或記憶體壓力,這會延遲使用者空間中的封包處理作業:

    kubectl top nodes
    kubectl top pods -n default
    
  2. 檢查 Linux 核心連線追蹤計數:檢查主機上的有效連線追蹤計數:

    # On a node where you have debugging access
    cat /proc/sys/net/netfilter/nf_conntrack_count
    cat /proc/sys/net/netfilter/nf_conntrack_max
    

    如果 nf_conntrack_count 接近 nf_conntrack_max,主機核心會捨棄新的 TCP SYN 封包。

步驟 3:使用 Compute Engine 遙測功能,驗證 VM 層級的封包丟棄情形

Google Cloud Compute Engine 會將 VM 層級的網路介面指標匯出至 Cloud Monitoring。

在 Cloud Monitoring > Metrics Explorer 中,查詢:

sum by (drop_reason) (rate(compute_googleapis_com:instance_network_dropped_packets_count[5m]))
  • FQ_CODEL_DROP:封包因公平佇列或 CoDel 佇列飽和而遭捨棄 (超過 VM 輸出頻寬限制)。
  • FIREWALL_RULE_DROP:遭虛擬私有雲防火牆規則捨棄的封包。
  • RATE_LIMIT_DROP:封包遭到捨棄,因為 VM 超出網路介面每秒封包數 (PPS) 配額上限。

步驟 4:使用 eBPF 偵查核心層級的捨棄

如果 VM 層級指標顯示封包丟棄次數為零,但 GKE Pod 仍會丟棄封包,請檢查 GKE Dataplane V2 代理程式 (anetd) 的 eBPF 對應丟棄次數:

kubectl logs -n kube-system daemonset/anetd -c cilium-agent --tail=200 | grep -i "drop"

尋找 ct-map-insertion-failed 或 fib-lookup-failed。


第 3 層:虛擬私有雲和路由 (雲端網路) 可觀測性

VPC 和雲端路由層級會將 GKE 節點連線至其他 Google Cloud 服務、地端部署網路和網際網路。此處的失敗通常源自虛擬私有雲防火牆規則、自訂路徑或閘道設定。

區分 GKE 與虛擬私有雲或外部連線問題

請先查看診斷範圍和必要條件,再將叢集外部網路問題與叢集內部故障隔離:

  • 重點領域:Kubernetes 內部路由與 VPC 雲端路由之間的邊界隔離。
  • 必要條件:gcloud CLI;建立連線測試的權限。
  • CNI 相容性:所有叢集。
  • 症狀:Pod 無法連線至外部資源 (例如 Cloud SQL、地端部署 API 或第三方端點)。
  • 目標:快速判斷封包是否在 GKE 節點內、 Google Cloud 虛擬私有雲或外部網路中遭到捨棄。

步驟 1:Compute Engine VM 基準測試

如要部署基準 VM 並評估問題是否仍存在於 GKE 以外的環境,請按照下列步驟操作:

  1. 在與 GKE 節點集區相同的 VPC 子網路和可用區中,部署臨時 Compute Engine VM 執行個體:

    gcloud compute instances create gke-baseline-tester \
        --zone=us-central1-a \
        --subnet=gke-subnet \
        --machine-type=e2-micro
    
  2. 使用 SSH 連線至執行個體,並測試與目的地的連線:

    curl -v --connect-timeout 5 https://api.example.com
    
  3. 評估結果:

    • 如果 Compute Engine VM 無法連線:問題出在 VPC 或外部網路 (防火牆規則、路由表、Cloud NAT IP 耗盡或外部 IP 位址加入允許清單)。
    • 如果 Compute Engine VM 連線成功:問題出在 GKE 內部 (NetworkPolicy 封鎖輸出、非偽裝的 Pod CIDR 或容器層級 DNS)。

步驟 2:執行隨選 Connectivity Tests 測試

從節點 VM 執行 Google Cloud Connectivity Tests,前往目的地:

gcloud network-management connectivity-tests create test-node-to-dest \
    --source-instance=projects/PROJECT_ID/zones/us-central1-a/instances/gke-baseline-tester \
    --destination-ip-address=203.0.113.10 \
    --destination-port=443 \
    --protocol=TCP

在控制台中檢查結果 Google Cloud ,判斷是否有虛擬私有雲防火牆規則或路徑捨棄流量。


使用 Connectivity Tests 診斷連線問題

Connectivity Tests 會模擬 GKE 和 VPC 資源之間的封包路徑,不會傳送即時流量。這項模擬作業會評估 Service ClusterIP 到 Pod 的 DNAT 解析度、GKE Dataplane V2 NetworkPolicy 輸入和輸出規則,以及節點 IP 偽裝 (SNAT)。執行自動路徑模擬前,請先查看診斷範圍和先決條件:

  • 重點領域:自動模擬 GKE Pod、服務、NetworkPolicy 和 VPC 路由的靜態路徑。
  • 必要條件:啟用 Network Intelligence Center 和 Network Management API。
  • CNI 相容性:GKE Dataplane V2 (強化分析)。
  • 症狀:連線不明原因中斷,手動檢查後所有設定都有效。
  • 目標:靜態模擬及追蹤從 Pod 來源到目的地的整個封包路徑,找出導致捨棄的確切政策行。

情境 A:確認 GKE NetworkPolicy 是否封鎖指標收集作業

從安全命名空間中的 Pod 擷取指標時,Google Cloud Managed Service for Prometheus 收集器可能會遭到預設拒絕的 NetworkPolicy 封鎖:

gcloud network-management connectivity-tests create test-gmp-to-pod \
    --source-ip-address=10.0.0.15 \
    --destination-gke-pod=projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME/k8s/namespaces/prod/pods/backend-pod \
    --destination-port=8080 \
    --protocol=TCP

在 Google Cloud 控制台中檢查測試追蹤記錄。如果測試在步驟 GKE Network Policy evaluation 終止,並顯示 DROP,則必須新增輸入規則,允許來自收集器 Pod 的流量。

情境 B:驗證 GKE 服務的可連線性

模擬從用戶端 VM 到內部 Kubernetes 服務的可連線性:

gcloud network-management connectivity-tests create test-vm-to-service \
    --source-instance=projects/PROJECT_ID/zones/us-central1-a/instances/client-vm \
    --destination-ip-address=10.96.0.100 \
    --destination-port=80 \
    --protocol=TCP

模擬追蹤記錄會顯示:

  1. 虛擬私有雲路由相符。
  2. 允許虛擬私有雲防火牆輸出和輸入。
  3. 抵達 GKE 節點。
  4. Service DNAT 至後端 Pod IP 位址。
  5. 評估後端 Pod 的 Ingress NetworkPolicy。

情境 C:診斷 Pod 到網際網路的輸出問題

如果 Pod 無法連上網際網路上的外部 API:

  1. 從 Pod 建立測試,連至外部公開 IP 位址 (例如 8.8.8.8):

    gcloud network-management connectivity-tests create test-pod-to-internet \
        --source-gke-pod=projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME/k8s/namespaces/prod/pods/app-pod \
        --destination-ip-address=8.8.8.8 \
        --destination-port=53 \
        --protocol=UDP
    
  2. 檢查投遞地點:

    • 在 NetworkPolicy 中遭到捨棄:Pod 缺少允許流量傳輸至 0.0.0.0/0 的輸出 NetworkPolicy。
    • 在 VPC 防火牆中捨棄:VPC 防火牆規則拒絕來自節點子網路的外送流量。
    • 在 Cloud NAT 或路由中遭到捨棄:子網路缺少網際網路閘道的預設路由,或子網路未設定 Cloud NAT。

第 4 層:外部閘道和成本 (網際網路和 NAT) 可觀測性

外部閘道層會透過 Cloud NAT 或外部閘道,管理前往公用網際網路目的地的輸出流量。這個層級的可觀測性有助於找出高輸出工作負載,並控管資料傳輸費用。

識別 NAT 流量 (輸出至網際網路)

分析對外網際網路和 NAT 流量前,請先查看診斷範圍和必要條件:

  • 重點領域:網際網路傳出流量、Cloud NAT 連接埠用量、外部資料移轉費用。
  • 必要條件:啟用 GKE Dataplane V2 流量觀測功能。
  • CNI 相容性:GKE Dataplane V2。
  • 症狀:Cloud NAT 連接埠耗盡錯誤,或非預期的高額網際網路輸出費用。
  • 目標:找出將流量傳輸至外部網際網路端點的特定 GKE Pod 和 Service 物件。

步驟 1:瞭解 GKE Dataplane V2 中的「堆疊」和「世界」概念

在 GKE Dataplane V2 中:

  • world:代表 GKE 叢集和 VPC 以外的任何目的地 (公開網際網路)。
  • to-stack:代表封包從 eBPF 容器 veth 介面轉換至主機 Linux 網路堆疊,在抵達 Cloud NAT 前進行 IP 偽裝 (SNAT)。

步驟 2:使用 Hubble CLI 串流及篩選 NAT 流量

從叢集發起的網際網路外送流量進行直播:

# Stream egress flows heading to external internet ("world")
gke-hubble observe \
    --traffic-direction egress \
    --verdict FORWARDED \
    --to-identity world \
    --follow

輸出內容範例:

TIMESTAMP             SOURCE               DESTINATION          TYPE     VERDICT
10:25:01.120          default/worker-pod   142.250.190.46:443   to-stack FORWARDED

如要找出最常對外通訊的 Pod,您也可以將 Hubble JSON 輸出內容透過管道傳送至 jq,藉此計算各 Pod 的外部輸出流量:

timeout 60s gke-hubble observe \
    --traffic-direction egress \
    --verdict FORWARDED \
    --to-identity world \
    -o json | jq -r '.flow.source.namespace + "/" + .flow.source.pod_name' | sort | uniq -c | sort -nr | head -n 10

步驟 3:使用指標監控外部流量

在 Cloud Monitoring 中,追蹤外部流程的數量:

fetch prometheus_target
| metric 'prometheus.googleapis.com/pod_flow_egress_flows_count/counter'
| filter (metric.destination_identity == 'world')
| align rate(1m)
| every 1m
| group_by [metric.source_workload, metric.source_namespace], sum(val())

使用 Flow Analyzer 分析叢集流量成本和效能

在顯示流量和跨區域費用前,請先查看診斷範圍和必要條件:

  • 重點領域:跨區域資料移轉費用、熱門通訊對象、節點間流量可視性 (無須 SQL 查詢)。
  • 必要條件:啟用虛擬私有雲流量記錄 INCLUDE_ALL_METADATA;啟用節點內瀏覽權限;在記錄檔 bucket 中啟用 Observability Analytics。
  • CNI 相容性:所有叢集。
  • 症狀:月結單上的區域間資料移轉費用偏高。Google Cloud
  • 目標:以視覺化方式找出產生跨區域流量的 GKE 工作負載,並最佳化放置位置,不必查詢原始記錄。

必要條件

如要使用 GKE 適用的 Flow Analyzer,請按照下列步驟操作:

  1. 虛擬私有雲流量記錄:必須在叢集子網路上啟用,且 metadata="INCLUDE_ALL_METADATA"。
  2. 節點內瀏覽功能:必須在叢集上啟用,才能將 Pod 對 Pod 流量公開至 VPC 流量記錄管道。
  3. 記錄檔分析:Cloud Logging 中的 _Default bucket 必須升級,才能使用 Observability Analytics。

步驟 1:在 Flow Analyzer 中找出 GKE 流量最多的項目

如要在 Flow Analyzer 中查看高用量工作負載,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的「Flow Analyzer」頁面。
  2. 按一下「來源記錄檔 bucket」,然後選取包含流程記錄的記錄檔 bucket。除非您已將這些項目轉送至其他位置,否則這些項目會存放在「_Default」值區。
  3. 在「流量匯總」中,選取「來源 - 目的地」。
  4. 設定分析視窗的時間範圍。
  5. 在「依下列項目整理流程」下方,選取 GKE Pod 或工作負載欄位。
  6. 點按「執行新查詢」。「資料流量最高」圖表會顯示哪些工作負載移動的資料最多。

步驟 2:分析可用區間流量費用

跨可用區的流量會產生資料移轉費用。如要找出跨可用區傳輸的工作負載,請按照下列步驟操作:

  1. 在「Organize flows by」(依流量分類) 下方,選取來源可用區和目的地可用區欄位。
  2. 點按「執行新查詢」,然後閱讀「所有資料流量」表格。來源和目的地區域不同的資料列,就是跨區域流量。Flow Analyzer 篩選器會比對值,因此您無法篩選「不等於」的值;請改為比較結果中的區域配對。
  3. 展開高用量區域配對,即可查看基礎來源和目的地 GKE 工作負載。

補救措施:

  • 實作 Kubernetes topologySpreadConstraints 或 podAffinity,在同一個可用區內共置通訊服務。
  • 在服務上啟用「拓撲感知路由」 (service.kubernetes.io/topology-mode: Auto),將流量保留在來源區域內。

步驟 3:深入瞭解 Observability Analytics (適用於進階 SQL 查詢)

在 Flow Analyzer 中,按一下「在記錄檔分析中查看」,即可針對流程資料執行 SQL 查詢。

下列 SQL 查詢會計算跨區域的熱門 Pod 傳送者:

SELECT
  JSON_VALUE(json_payload.src_gke_details.pod.workload.workload_name) AS src_workload,
  JSON_VALUE(json_payload.dest_gke_details.pod.workload.workload_name) AS dest_workload,
  JSON_VALUE(json_payload.src_instance.zone) AS src_zone,
  JSON_VALUE(json_payload.dest_instance.zone) AS dest_zone,
  SUM(CAST(JSON_VALUE(json_payload.bytes_sent) AS INT64)) / 1024 / 1024 / 1024 AS total_gb_sent
FROM
  `PROJECT_ID.global._Default._AllLogs`
WHERE
  log_name LIKE '%vpc_flows%'
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
  AND JSON_VALUE(json_payload.src_instance.zone) != JSON_VALUE(json_payload.dest_instance.zone)
GROUP BY
  1, 2, 3, 4
ORDER BY
  total_gb_sent DESC
LIMIT 20;

Hubble CLI 參考資料和查詢一覽表

Hubble CLI 會直接從 GKE Dataplane V2 核心環形緩衝區串流及篩選即時網路流量資料。

設定:建立輔助別名

由於 Hubble 會在叢集控制層內執行,請設定殼層別名,以便執行 Hubble 指令,而不需部署本機二進位檔:

alias gke-hubble="kubectl exec -it -n gke-managed-dpv2-observability deployment/hubble-relay -c hubble-cli -- hubble"

常見的篩選配方

疑難排解目標 Hubble CLI 指令
即時觀察叢集中的所有捨棄封包 gke-hubble observe --verdict DROPPED --follow
串流任何命名空間中特定 Pod 的所有流量 gke-hubble observe --pod default/my-pod --follow
篩選兩個特定命名空間之間的流量 gke-hubble observe --from-namespace frontend --to-namespace backend
隔離特定通訊埠 (例如通訊埠 80) 的流量 gke-hubble observe --port 80
檢查即時 DNS 查詢和回應 gke-hubble observe --port 53
查看即時 TCP 重設 (RST 封包) gke-hubble observe --type trace --verdict FORWARDED --tcp-flags RST
將所有傳出流量導向公開網際網路 gke-hubble observe --traffic-direction egress --to-identity world
檢查 HTTP 應用程式層 (OSI 第 7 層) 流量 gke-hubble observe --protocol http

使用否定條件進行進階篩選 (--not)

您可以排除已知的高流量或正常流量,專注於異常狀況:

# Observe drops, but exclude internal kube-system health probes and DNS
gke-hubble observe \
    --verdict DROPPED \
    --not --namespace kube-system \
    --not --port 53

輸出格式設定和 jq 整合

如要以程式輔助方式處理流程記錄,請以 JSON 格式輸出:

# Extract only source, destination, and drop reason from the last 100 flows
gke-hubble observe --verdict DROPPED -o json --last 100 | \
    jq -r '[.time, .flow.source.pod_name, .flow.destination.pod_name, .flow.drop_reason_desc] | @tsv'

限制

使用 Hubble CLI 進行即時疑難排解時,請注意下列技術限制:

  • 暫時性節點本機環形緩衝區:Hubble 流量會儲存在每個節點的記憶體內環形緩衝區中。在高流量事件期間,較舊的流程記錄會在幾秒內遭到覆寫。如要進行歷來分析,請使用 Cloud Logging 中的 NetworkPolicy 記錄和虛擬私有雲流量記錄。
  • 沒有內建的邏輯 OR:Hubble CLI 標記會使用邏輯 AND 評估多個引數。如要搜尋多個條件 (例如通訊埠 80 或通訊埠 443),請執行個別指令,或使用 jq 篩選 JSON 輸出內容。

後續步驟