マルチクラスタのトラブルシューティング

このページでは、複数のクラスタやネットワークに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はサービス検出機能を提供して容易にしていますが、各クラスタのポッドがIstioなしで単一のネットワーク上にある場合でも、クラスタ間のトラフィックは成功するはずです。TLS/mTLSに関する問題を除外するために、Istioサイドカーなしのポッドを使用して手動でトラフィックテストを行うことができます。

各クラスタで、このテスト用に新しい名前空間を作成します。サイドカーインジェクションは**有効にしないでください**。

$ 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ポッドが実行されていることを確認します。これにより、ポッドの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

次に、cluster1curlポッドからこのポッド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の設定外にある可能性があります。

ローカルロードバランシング

ローカルロードバランシングを使用すると、クライアントがトラフィックを最も近い宛先に送信することを優先できます。クラスタが異なるロケーション(リージョン/ゾーン)にある場合、ローカルロードバランシングはローカルクラスタを優先し、意図したとおりに機能します。ローカルロードバランシングが無効になっている場合、またはクラスタが同じロケーションにある場合、別の問題がある可能性があります。

信頼設定

クラスタ内トラフィックと同様に、クラスタ間トラフィックは、プロキシ間の共通の信頼の根拠に依存します。デフォルトのIstioインストールでは、それぞれ個別に生成されたルート認証機関が使用されます。マルチクラスタの場合、共有された信頼の根拠を手動で設定する必要があります。以下のプラグイン証明書の手順に従うか、IDと信頼モデルを参照して詳細を確認してください。

プラグイン証明書

証明書が正しく設定されていることを確認するには、各クラスタのルート証明書を比較できます。

$ 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}')

ルート証明書が一致しない場合、またはシークレットがまったく存在しない場合は、プラグイン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

エンドポイントは1つしか表示されず、コントロールプレーンがリモートクラスタからエンドポイントを読み取ることができないことを示しています。リモートシークレットが正しく設定されていることを確認してください。

$ kubectl get secrets --context=$CTX_CLUSTER1 -n istio-system -l "istio/multiCluster=true"
  • シークレットが見つからない場合は、作成してください。
  • シークレットが存在する場合
    • シークレットの設定を確認します。リモートkubeconfigのデータキーとして、クラスタ名が使用されていることを確認してください。
    • シークレットが正しく見える場合は、リモートKubernetes APIサーバーにアクセスするための接続または権限の問題について、istiodのログを確認します。ログメッセージには、エラー理由とともにFailed to add remote cluster from secretが含まれる場合があります。
この情報は役に立ちましたか?
改善のための提案はありますか?

ご意見ありがとうございます!