多叢集疑難排解

本頁說明如何疑難排解在多個叢集和/或網路中部署 Istio 的問題。在閱讀本文之前,您應該執行多叢集安裝中的步驟,並閱讀部署模型指南。

跨叢集負載平衡

多網路安裝中最常見但也最廣泛的問題是跨叢集負載平衡無法運作。通常,這會表現為僅看到來自服務叢集本機執行個體的回應

$ for i in $(seq 10); do kubectl --context=$CTX_CLUSTER1 -n sample exec curl-dd98b5f48-djwdw -c curl -- curl -s helloworld:5000/hello; done
Hello version: v1, instance: helloworld-v1-578dd69f69-j69pf
Hello version: v1, instance: helloworld-v1-578dd69f69-j69pf
Hello version: v1, instance: helloworld-v1-578dd69f69-j69pf
...

當遵循驗證多叢集安裝的指南時,我們預期會收到 v1v2 的回應,這表示流量正在傳送到兩個叢集。

此問題可能有多種原因。

連線和防火牆問題

在某些環境中,防火牆可能正在封鎖叢集之間的流量,這可能不明顯。ICMP(ping)流量可能成功,但 HTTP 和其他類型的流量可能不成功。這可能會顯示為逾時,或者在某些情況下會出現更令人困惑的錯誤,例如:

upstream connect error or disconnect/reset before headers. reset reason: local reset, transport failure reason: TLS error: 268435612:SSL routines:OPENSSL_internal:HTTP_REQUEST

雖然 Istio 提供服務探索功能使其更容易,但如果每個叢集中的 Pod 都在沒有 Istio 的單一網路上,跨叢集流量仍然應該成功。為了排除 TLS/mTLS 的問題,您可以使用沒有 Istio sidecar 的 Pod 進行手動流量測試。

在每個叢集中,為此測試建立一個新的命名空間。不要啟用 sidecar 注入。

$ kubectl create --context="${CTX_CLUSTER1}" namespace uninjected-sample
$ kubectl create --context="${CTX_CLUSTER2}" namespace uninjected-sample

然後部署在驗證多叢集安裝中使用的相同應用程式。

$ kubectl apply --context="${CTX_CLUSTER1}" \
    -f samples/helloworld/helloworld.yaml \
    -l service=helloworld -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER2}" \
    -f samples/helloworld/helloworld.yaml \
    -l service=helloworld -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER1}" \
    -f samples/helloworld/helloworld.yaml \
    -l version=v1 -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER2}" \
    -f samples/helloworld/helloworld.yaml \
    -l version=v2 -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER1}" \
    -f samples/curl/curl.yaml -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER2}" \
    -f samples/curl/curl.yaml -n uninjected-sample

使用 -o wide 旗標驗證 cluster2 中是否有 helloworld Pod 正在執行,這樣我們可以取得 Pod IP。

$ kubectl --context="${CTX_CLUSTER2}" -n uninjected-sample get pod -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
curl-557747455f-jdsd8            1/1     Running   0          41s   10.100.0.2   node-2   <none>           <none>
helloworld-v2-54df5f84b-z28p5    1/1     Running   0          43s   10.100.0.1   node-1   <none>           <none>

記下 helloworldIP 欄位。在這個例子中,它是 10.100.0.1

$ REMOTE_POD_IP=10.100.0.1

接下來,嘗試將流量從 cluster1 中的 curl Pod 直接傳送到此 Pod IP。

$ kubectl exec --context="${CTX_CLUSTER1}" -n uninjected-sample -c curl \
    "$(kubectl get pod --context="${CTX_CLUSTER1}" -n uninjected-sample -l \
    app=curl -o jsonpath='{.items[0].metadata.name}')" \
    -- curl -sS $REMOTE_POD_IP:5000/hello
Hello version: v2, instance: helloworld-v2-54df5f84b-z28p5

如果成功,應該只會有來自 helloworld-v2 的回應。重複這些步驟,但這次將流量從 cluster2 傳送到 cluster1

如果這成功,您可以排除連線問題。如果沒有成功,問題的原因可能在您的 Istio 設定之外。

本地負載平衡

本地性負載平衡可以用來讓客戶端偏好將流量傳送到最近的目的地。如果叢集位於不同的區域(region/zone),本地性負載平衡會偏好本地叢集,並且會按照預期運作。如果本地性負載平衡已停用,或叢集位於同一區域,則可能存在其他問題。

信任設定

跨叢集流量,如同叢集內流量一樣,依賴於 Proxy 之間的共同信任根。預設的 Istio 安裝將使用它們各自產生的根憑證授權單位。對於多叢集,我們必須手動設定共用的信任根。請遵循以下的「外掛憑證」或閱讀身分識別與信任模型以了解更多資訊。

外掛憑證

要驗證憑證是否已正確設定,您可以比較每個叢集中的根憑證。

$ diff \
   <(kubectl --context="${CTX_CLUSTER1}" -n istio-system get secret cacerts -ojsonpath='{.data.root-cert\.pem}') \
   <(kubectl --context="${CTX_CLUSTER2}" -n istio-system get secret cacerts -ojsonpath='{.data.root-cert\.pem}')

如果根憑證不符或 Secret 根本不存在,您可以遵循外掛 CA 憑證指南,並確保對每個叢集執行這些步驟。

逐步診斷

如果您已完成以上各節並且仍然遇到問題,那麼是時候深入挖掘了。

以下步驟假設您正在遵循HelloWorld 驗證。在繼續之前,請確保 helloworldcurl 都已部署在每個叢集中。

從每個叢集中,找到 curl 服務針對 helloworld 的端點。

$ istioctl --context $CTX_CLUSTER1 proxy-config endpoint curl-dd98b5f48-djwdw.sample | grep helloworld

疑難排解資訊會根據流量的來源叢集而有所不同。

$ istioctl --context $CTX_CLUSTER1 proxy-config endpoint curl-dd98b5f48-djwdw.sample | grep helloworld
10.0.0.11:5000                   HEALTHY     OK                outbound|5000||helloworld.sample.svc.cluster.local

只顯示一個端點,表示控制平面無法讀取遠端叢集的端點。驗證遠端 Secret 是否已正確設定。

$ kubectl get secrets --context=$CTX_CLUSTER1 -n istio-system -l "istio/multiCluster=true"
  • 如果 Secret 遺失,請建立它。
  • 如果 Secret 存在
    • 查看 Secret 中的設定。請確保叢集名稱用作遠端 kubeconfig 的資料金鑰。
    • 如果 Secret 看起來正確,請檢查 istiod 的日誌,以了解連線或存取遠端 Kubernetes API 伺服器的權限問題。日誌訊息可能包含 Failed to add remote cluster from secret 以及錯誤原因。
這個資訊對您有幫助嗎?
您有任何改進建議嗎?

感謝您的回饋!