Cassandra 復元のトラブルシューティング

現在、ApigeeApigee ハイブリッドのドキュメントが表示されています。
このトピックに対応する Apigee Edge のドキュメントはありません。

症状

Apigee ハイブリッドでの Cassandra の復元時に、復元ログでエラーが見つかることがあります。

エラー メッセージ

ログに、次のいずれかが表示されます。

java.net.ConnectException: Connection timed out (Connection timed out)
/tmp/tmp/schema.cql:662:OperationTimedOut: errors={'10.0.0.1': 'Client request timeout. See Session.execute[_async](timeout)'}, last_host=10.0.0.1
/tmp/tmp/schema.cql:6409:AlreadyExists: Table 'kvm_myorg.kvm_map_keys_descriptor' already exists

考えられる原因

原因 説明 トラブルシューティングの実施対象
接続がタイムアウトした このエラーは、apigee-cassandra-restore Pod と apigee-cassandra-default-* Pod の間の接続エラーです。 Apigee ハイブリッド
オペレーションがタイムアウトした このエラーは、復元が 15 分以上経過した後にタイムアウトした場合に発生します。 Apigee ハイブリッド
すでに存在する このエラー メッセージは、問題の原因に関したものではなく、復元ジョブの再試行オペレーションの結果です。 Apigee ハイブリッド

原因: 接続がタイムアウトした

次のエラーは、apigee-cassandra-restore Pod と apigee-cassandra-default-* Pod 間の接続エラーです。

java.net.ConnectException: Connection timed out (Connection timed out)

診断

  1. ホスト ネットワークに Pod ネットワークから到達できない場合は、バックアップからのリージョンの復元に示すように、overrides.yamlcassandra で、hostNetworkfalse に設定されていることを確認します。
  2. 接続をテストするには、apigee-cassandra-restore ジョブと同じネットワークにある apigee-mart Pod または apigee-runtime Pod にログインします。Pod ネットワーク内の他の Pod を使用することもできます。
    1. apigee-mart Pod の名前を取得します。
      kubectl -n apigee get po --selector=app=apigee-mart --no-headers -o custom-columns=":metadata.name"
    2. MART Pod 内で bash セッションを実行します。
      kubectl exec -it MART_POD_NAME -n apigee -- bash

      MART_POD_NAME を MART Pod の名前に置き換えます。例: apigee-mart-myorg--9a8228a-191-t0xh1-qz5fl

    3. Cassandra ポートに接続テストを実行します。
      curl -v -m 5 telnet://apigee-cassandra-default-0.apigee-cassandra-default.apigee.svc.cluster.local:9042
      curl -v -m 5 telnet://apigee-cassandra-default-0.apigee-cassandra-default.apigee.svc.cluster.local:7001

    出力に Connection timed out エラーが表示されている場合は、接続に問題があることを意味します。ただし、接続が成功したことを示す Connected to メッセージが表示された場合は、Ctrl+C キーを押して接続を終了し、続行する必要があります。

解決策

復元に使用する overrides.yaml ファイルで HostNetwork 設定が false に設定されていることを確認し、復元プロセスを繰り返します。設定がすでに false に設定されているにもかかわらず接続エラーが表示される場合は、次のコマンドを使用して、Cassandra Pod が稼働していることを確認します。

kubectl get pods -n apigee -l app=apigee-cassandra

出力は次のようになります。

NAME                         READY   STATUS    RESTARTS   AGE
apigee-cassandra-default-0   1/1     Running   0          14m
apigee-cassandra-default-1   1/1     Running   0          13m
apigee-cassandra-default-2   1/1     Running   0          11m
exampleuser@example hybrid-files %

原因: オペレーションがタイムアウトした

次のエラーは、復元が 15 分以上経過した後にタイムアウトした場合に発生します。このエラーは、ストレージやネットワークがバックアップの非圧縮コンテンツを時間どおりに送信できないなど、I/O に問題があることを示しています。

/tmp/tmp/schema.cql:662:OperationTimedOut: errors={'10.0.0.1': 'Client
request timeout. See Session.execute[_async](timeout)'}, last_host=10.0.0.1

診断

  1. apigee-cassandra-default-0 ログを調べて、復元開始のタイムスタンプをメモします。

    kubectl logs apigee-cassandra-default-0 -n apigee | grep 'MigrationManager.java' | head -n 1
  2. タイムスタンプとテーブル作成の最新のログを比較します。

    kubectl logs apigee-cassandra-default-0 -n apigee | grep 'Create new table' | tail -n 1

    この比較の結果は、タイムアウトを超えた後に Cassandra Pod がまだテーブルを作成中であったことを示しています。

  3. 次のコマンドを使用して、ストレージの帯域幅をテストします。

    kubectl -n apigee exec -it apigee-cassandra-default-0 -- bash -c 'dd if=/dev/zero of=/opt/apigee/data/test.img bs=200M count=1 ; rm /opt/apigee/data/test.img'
    kubectl -n apigee exec -it apigee-cassandra-default-1 -- bash -c 'dd if=/dev/zero of=/opt/apigee/data/test.img bs=200M count=1 ; rm /opt/apigee/data/test.img'
    kubectl -n apigee exec -it apigee-cassandra-default-2 -- bash -c 'dd if=/dev/zero of=/opt/apigee/data/test.img bs=200M count=1 ; rm /opt/apigee/data/test.img'

    書き込み速度が 100 M/s 未満の場合、適切な StorageClass(SSD)が使用されていない可能性があります。

  4. ネットワークの帯域幅をテストします。

    1. Cassandra Pod で netcat を実行して、ポートをリッスンします。

      kubectl -n apigee exec -it apigee-cassandra-default-0 -- bash -c 'nc -l -p 3456 > /dev/null'
    2. 別のシェル セッションで apigee-mart Pod の名前を取得します。

      kubectl -n apigee get po --selector=app=apigee-mart --no-headers -o custom-columns=":metadata.name"
    3. apigee-mart Pod 内で bash セッションを実行します。Pod ネットワーク内の他の Pod を使用することもできます。

      kubectl exec -it MART_POD_NAME -n apigee -- bash

      MART_POD_NAME を MART Pod の名前に置き換えます。例: apigee-mart-myorg--9a8228a-191-t0xh1-qz5fl

    4. まだ netcat を実行している Cassandra Pod に対して、ネットワーク帯域幅テストを実行します。

      dd if=/dev/zero bs=50M count=1 | nc apigee-cassandra-default-0.apigee-cassandra-default.apigee.svc.cluster.local 3456

    他の Cassandra Pod についても、このプロセスを繰り返します。動作速度が 10 M / 秒未満の場合、ネットワーク帯域幅が原因である可能性が高いと考えられます。

解決策

上記の手順で I/O 速度が遅いことを確認した場合、クラスタが最小限のネットワーク要件とストレージ要件を満たしていることを確認します。後で帯域幅のテストを再度行います。

原因: すでに存在する

診断

次のようなエラーが表示されます。

/tmp/tmp/schema.cql:6409:AlreadyExists: Table 'kvm_myorg.kvm_map_keys_descriptor' already exists

解決策

このエラー メッセージは、問題の原因に関したものではなく、復元ジョブの再試行オペレーションの結果です。実際のエラー メッセージは、最初に失敗した Pod のログに表示されます。

問題を診断するために、最初のエラーのログを取得します。

問題が解決しない場合は、診断情報の収集が必要な場合をご覧ください。

既知の問題 391861216 の回避策

診断

番号が最も大きい Cassandra Pod が復元後に CrashLoopBackoff 状態になります。これは、既知の問題 391861216 が原因で発生することがあります。Cassandra Pod のログに次のようなエラーが記録されています。

Cannot change the number of tokens from 512 to 256

解決策

次の手順に沿って、根本的な問題を解消します。これにより、データを保持しながら Cassandra を正常に起動できます。

  1. CrashLoopBackoff 状態のままになっている Cassandra Pod の PVC の削除を開始します。POD_NAME は、CrashLoopBackoff 状態の Pod の名前に設定します。APIGEE_NAMESPACE は、Apigee がインストールされているクラスタの Namespace に設定します。

    kubectl delete pvc cassandra-data-POD_NAME -n APIGEE_NAMESPACE --wait=false
  2. CrashLoopBackoff 状態にある Pod を削除します。

    kubectl delete pod POD_NAME -n APIGEE_NAMESPACE
  3. Cassandra のシードホストを、番号が最も大きい Pod に手動で変更します。たとえば、3 つのレプリカがある場合は、SEED_POD_NAMEapigee-cassandra-default-2 にします。これは一度だけ必要であり、後続の Pod ではスキップできます。

    kubectl patch apigeeds/default -n APIGEE_NAMESPACE --type='merge' -p '{"spec": {"components": {"cassandra": {"properties": {"externalSeedHost":"SEED_POD_NAME.apigee-cassandra-default.APIGEE_NAMESPACE.svc.cluster.local"}}}}}'
  4. 512 トークンを持つノードを Cassandra リングから削除します。

    kubectl exec -n APIGEE_NAMESPACE -t sts/apigee-cassandra-default -c apigee-cassandra -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD status' | awk '/^DN .*\?.* 512 / {print $6; exit}; /^DN .* [KMG]iB.* 512 / {print $7; exit}' | xargs -I {} kubectl exec -n APIGEE_NAMESPACE -t sts/apigee-cassandra-default -c apigee-cassandra -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD removenode {}'
  5. Cassandra Pod が復元するまで待ちます。おそらく複数回再起動した後、Ready 状態が 2/2 になります。番号が次に大きい Pod が CrashLoopBackoff 状態になります。

    kubectl get pods -n APIGEE_NAMESPACE -l app=apigee-cassandra -w
  6. 別の Pod が CrashLoopBackoff 状態に移行するたびに、残りの Pod に対して 1 つずつ POD_NAME を更新しながら上記の手順を繰り返します。すべての Pod の Ready 状態が 2/2 になり、そのステータスが Running になるまでこれを続けます。

  7. すべての Pod が Cassandra リングに正常に参加したことを確認します。

    kubectl exec -n APIGEE_NAMESPACE -t sts/apigee-cassandra-default -c apigee-cassandra -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD status'

    すべての Cassandra ノードのステータスが UN で、256 個のトークンを持っている必要があります。

  8. Cassandra のシードホストに対する変更を元に戻します。

    kubectl patch apigeeds/default -n APIGEE_NAMESPACE --type='merge' -p '{"spec": {"components": {"cassandra": {"properties": {"externalSeedHost":""}}}}}'

    シードホストの変更を元に戻すため、Apigee Datastore コントローラによって Cassandra Pod が再起動されます。

診断情報の収集が必要な場合

上記の手順でも問題が解決しない場合は、次の診断情報を収集して Google Cloud カスタマーケアに連絡してください。

  1. 提出を求められる可能性のある通常のデータに加えて、次のコマンドを使用して、すべての Cassandra Pod から診断データを収集します。

    for p in $(kubectl -n apigee get pods -l app=apigee-cassandra --no-headers -o custom-columns=":metadata.name") ; do \
            for com in info describecluster failuredetector version status ring info gossipinfo compactionstats tpstats netstats cfstats proxyhistograms gcstats ; do kubectl \
            -n apigee exec ${p} -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD '"$com"' 2>&1 '\
            | tee /tmp/k_cassandra_nodetool_${com}_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt | head -n 40 ; echo '...' ; done; done
          
  2. 圧縮してサポートケースに提出します。

    tar -cvzf /tmp/cassandra_data_$(date +%Y.%m.%d_%H.%M.%S).tar.gz /tmp/k_cassandra_nodetool*
  3. 復元 Pod からログを収集して提出します。ログは有効期間が短いため、エラーの直後に収集する必要があります。
  4. 上記の診断手順に沿って操作を行ったら、すべてのコンソール出力を収集してファイルにコピーし、サポートケースにファイルを添付します。