排解 GKE 網路觀測問題

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

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

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

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

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

核心網路概念

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

  • eBPF (Extended Berkeley Packet Filter):一種作業系統技術,可直接在 Linux 核心中執行安全監控和轉送程式。GKE Dataplane V2 使用 eBPF 轉送封包及強制執行 NetworkPolicies,效能負擔極低。
  • 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 資料表。如果節點處理過多並行連線,其中一個追蹤表格可能會填滿 (conntrack 耗盡),導致節點自動捨棄新封包。
  • Hubble:GKE Dataplane V2 的觀測能力引擎。它在 eBPF 上執行,可即時掌握流量、封包捨棄和 NetworkPolicy 評估。

第 1 級:Pod 和 Service (應用程式) 觀測能力

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

診斷 DNS 解析失敗

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

  • 重點領域:Pod 與 CoreDNS 或 NodeLocal DNSCache 之間的通訊、DNS 延遲時間、上游 DNS 解析逾時,以及 FQDN NetworkPolicy 驗證。
  • 必要條件:啟用 GKE Dataplane V2 指標;具備 kubectl 存取權。
  • CNI 相容性:GKE Dataplane V2 (Advanced Datapath) 和標準 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 為基礎的 NetworkPolicies (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 中,以 kubernetes.io/networking/dns/ 前置字元公開內建 DNS 指標。

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

  1. 在 Google Cloud 控制台,依序前往「Cloud Monitoring」>「Dashboards」(資訊主頁)。
  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 與 Service 物件之間的流量捨棄、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 記錄

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 Service 路由無法平衡已建立 HTTP/2 連線內的要求。
    • ClientIP 工作階段相依性:確認 Service 是否已設定 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

Step 4: Remediation and actionable fixes

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

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

第 2 級:節點和 CNI (核心) 觀測能力

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

系統完整性檢查:偵測 anetd 是否有未經授權的修補

GKE Dataplane V2 會在 kube-system 命名空間中,以代管 DaemonSet (anetd) 的形式執行。在 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 代理程式飽和、conntrack 耗盡。
  • 必要條件:已啟用 Compute Engine VM 指標;具備 kubectl 存取權。
  • CNI 相容性:GKE Dataplane V2 和標準 GKE CNI。
  • 症狀:跨節點流量的延遲時間大幅增加或隨機下降,而節點內流量則維持正常。
  • 目標:區分主機 VM 網路節流、Linux 核心捨棄和 CNI 層級瓶頸。

步驟 1:區分 GKE 內外的問題

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

  • 如果獨立 VM 發生相同的封包遺失或延遲問題:問題位於 GKE 外部 (虛擬私有雲防火牆、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 核心 conntrack 計數:查看主機上的有效 conntrack 計數:

    # 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 egress 頻寬限制)。
  • 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 級:虛擬私有雲和路由 (雲端網路) 觀測能力

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

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

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

  • 重點領域:Kubernetes 內部轉送和虛擬私有雲雲端轉送之間的邊界隔離。
  • 必要條件:gcloud CLI;建立 Connectivity Tests 的權限。
  • CNI 相容性:所有叢集。
  • 症狀:Pod 無法連線至外部資源 (例如 Cloud SQL、地端部署 API 或第三方端點)。
  • 目標:快速判斷封包遺失是發生在 GKE 節點內,還是 Google Cloud 虛擬私有雲或外部網路內。

步驟 1:Compute Engine VM 基準測試

如要部署基準 VM,並評估問題是否在 GKE 以外持續發生,請按照下列步驟操作:

  1. 在與 GKE 節點集區相同的虛擬私有雲子網路和可用區中,部署臨時 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 無法連線:問題出在虛擬私有雲或外部網路 (防火牆規則、轉送表、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 \
    --round-trip

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


使用 Connectivity Tests 診斷連線

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

  • 重點領域:GKE Pod、Service、NetworkPolicy 和虛擬私有雲路徑的自動化靜態路徑模擬。
  • 必要條件:已啟用 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 \
    --round-trip

在 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 \
    --round-trip

模擬追蹤記錄會顯示:

  1. 虛擬私有雲路由比對。
  2. 虛擬私有雲防火牆輸出和輸入允許。
  3. 抵達 GKE 節點。
  4. Service DNAT 至後端 Pod IP 位址。
  5. 評估後端 Pod 的輸入 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 \
        --round-trip
    
  2. 檢查 drop point:

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

第 4 級:外部閘道和費用 (網際網路和網路位址轉譯) 觀測能力

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

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

分析傳出網際網路和 NAT 流量前,請先詳閱診斷範圍和必要條件:

  • 重點領域:傳出網際網路流量、Cloud NAT 通訊埠使用率、外部資料移轉費用。
  • 必要條件:已啟用 GKE Dataplane V2 流量觀測功能。
  • CNI 相容性:GKE Dataplane V2。
  • 症狀:Cloud NAT 通訊埠耗盡錯誤,或傳出至網際網路的輸出費用異常高昂。
  • 目標:找出哪些 GKE Pod 和 Service 物件正在將流量傳輸至外部網際網路端點。

步驟 1:瞭解 GKE Dataplane V2 的「to-stack」和「world」概念

在 GKE Dataplane V2 中:

  • world:代表 GKE 叢集和虛擬私有雲 (公開網際網路) 以外的任何目的地。
  • 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

如要找出傳出流量最多的通訊者,您也可以將 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 工作負載,並最佳化位置,不必查詢原始記錄。

必要條件

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

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

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

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

  1. 前往 Google Cloud 控制台的「Flow Analyzer」頁面。
  2. 按一下「Source bucket」(來源 bucket),然後選取存放流程記錄檔的記錄檔 bucket。除非您將記錄檔轉送至其他位置,否則系統會將記錄檔儲存至 _Default bucket。
  3. 在「流量匯總」中,選取「來源 - 目的地」。
  4. 設定分析日期範圍。
  5. 在「Organize flows by」(流程整理依據) 下方,選取 GKE Pod 或工作負載欄位。
  6. 點按「執行新查詢」。「Highest data flows」(最高資料流量) 圖表會顯示哪些工作負載移動的資料量最多。

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

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

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

修復:

  • 實作 Kubernetes topologySpreadConstraints 或 podAffinity,將通訊服務集中在同一個可用區。
  • 在 Service 啟用拓撲感知轉送 (service.kubernetes.io/topology-mode: Auto),將流量保留在來源可用區。

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

在 Flow Analyzer 中,按一下「View in Log Analytics」(在記錄檔分析中查看),即可對流量資料執行 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 輸出內容。

後續步驟