Azure Kubernetes Service (AKS)のステートフル ワークロードのアップグレード パターン

Note

この記事には、スレーブ (レプリカ) という用語への参照が含まれています。これは、Microsoft使用されなくなった用語です。 Redis ソフトウェアから用語が削除されたら、この記事から削除します。

これらのパターンを使用して、データベースの可用性をAzure Kubernetes Service (AKS)ノード プールのローリング アップグレードと調整します。

この記事の手順は、可用性やデータ持続性の保証ではなく、フレームワークを計画することです。 結果は、データベース トポロジ、レプリケーション モード、ストレージ、オペレーター、中断設定、クライアントの再試行動作、ワークロードによって異なります。 代表的な環境で完全な手順をリハーサルし、目標復旧時間 (RTO) と目標復旧時点 (RPO) を満たしているかどうかを測定します。

この記事で説明するデータベース のアップグレード パターン

この記事では、ステートフル ワークロードを含む AKS クラスターのデータベース固有のアップグレード パターンについて説明します。

  • PostgreSQL によって制御される切り替え。
  • Redis クラスターのレプリカ優先ローリングアップグレード。
  • MongoDB レプリカセットのセカンダリから順に行うローリングアップグレード。
  • セキュリティ対応のための緊急アップグレードチェックリスト。
  • 検証とロールバックの計画。

標準的な AKS ノード プールのアップグレードとは異なり、これらのパターンは、Kubernetes ノードの置換を使用してデータベース レプリケーションのチェックとロールの変更を調整します。 データベース管理者と AKS 管理者は、これらのパターンを使用できます。 デプロイを管理するデータベース オペレーターに対して、文書化されている切り替えまたはアップグレード操作を使用します。 これらのパターンを演算子固有の命令に置き換えないでください。

詳細については、次の関連記事を参照してください。


クイック スタートでは、デプロイされた製品とトポロジのパターンを選択します。

データベースのアップグレード パターンを選択する

データベースの種類 アップグレードパターン 可用性に関する考慮事項 適しているケース:
PostgreSQL 制御されたスイッチオーバー 接続ドレインおよび切り替え中は、書き込みが一時停止します。 環境内の間隔を測定します。 サポートされているフェールオーバー メカニズムを使用したプライマリおよびストリーミング スタンバイのデプロイ
Redis クラスター レプリカ優先ローリングアップグレード クライアントは、フェールオーバー中に一時的なエラーまたはリダイレクトを受け取る可能性があります。 Redis クラスターでは非同期レプリケーションが使用されます。 各プライマリに1つのレプリカを持つ Redis Cluster のデプロイ構成
MongoDB セカンダリ先行のローリング アップグレード 書き込みは、ステップ ダウンから新しいプライマリが選択されるまで失敗します。 選択可能なセカンダリを持つ 3 メンバー以上のレプリカ セット

緊急アップグレードのチェックリスト

セキュリティの問題に対処するために迅速なアップグレードが必要な場合は、データベースの正常性と復旧のチェックをスキップしないでください。

  1. ワークロードと AKS アップグレードの前提条件を確認します。

    # Verify the database pods and their node placement.
    kubectl get pods -l tier=database -o wide
    
    # Confirm that the latest backup job completed.
    kubectl get job backup-job -o jsonpath='{.status.completionTime}'
    

    また、データベースまたはオペレーターがサポートするコマンドを使用して、レプリケーションの正常性を確認します。 分離された環境で最新のバックアップを復元し、クライアントが一時的な接続と選択エラーを再試行することを確認します。

  2. 製品とトポロジに一致するパターンのみを選択します。

    他のデータベース製品の場合は、その製品またはその Kubernetes オペレーターのアップグレード ガイダンスに従ってください。

  3. セーフティ ネットを使用して実行する:

    • ロールバック プロシージャは必ず事前にテストしてください。
    • アップグレード中にアプリケーション メトリックを監視します。
    • データベース チームをスタンバイ状態のままにします。
    • レプリケーション、クォーラム、スロット カバレッジ、またはアプリケーションの正常性が低下した場合は、アップグレードを停止します。

PostgreSQL で制御される切り替え

ストリーミング スタンバイを使用する PostgreSQL プライマリには、この制御されたスイッチオーバー パターンを使用します。 例は正常性チェックを示していますが、メンバーの昇格、フェンス、再参加を行うコマンドは、PostgreSQL オペレーターまたは高可用性の実装によって異なります。

Important

アプリケーションの書き込みが一時停止され、候補が追い付き、高可用性メカニズムが古いプライマリをフェンスまたは再構成できるようになるまで、スタンバイを昇格させないでください。 古いプライマリが書き込みを受け入れる間にスタンバイを昇格すると、異なるデータベース タイムラインが作成される可能性があります。

Prerequisites

  • サポートされている PostgreSQL バージョンと、サポートされているオペレーターまたは高可用性の実装を使用します。
  • 障害ドメイン間でメンバーを配置します。 デプロイメントの Pod の中断バジェットとトポロジー分散制約を設定します。
  • 分離された環境で復元して、最近のバックアップを確認します。
  • プライマリ変更後にアプリケーションが再接続されることを確認します。
  • AKS アップグレードを開始する前に、スイッチオーバー、ロールバック、および再参加のオペレーター固有のコマンドを記録します。

手順 1: レプリケーション トポロジを検証する

現在のプライマリで次のクエリを実行します。

kubectl exec <current-primary-pod> -- psql -X -c "
SELECT application_name, state, sync_state, write_lsn, flush_lsn, replay_lsn
FROM pg_stat_replication;"

目的の切り替え候補は、 streaming 状態である必要があります。 RPOで同期レプリケーションが必要な場合は、候補にご使用の構成で想定される sync_state があることも確認してください。

目的のスタンバイで次のクエリを実行します。

kubectl exec <candidate-standby-pod> -- psql -X -c "
SELECT pg_is_in_recovery(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();"

pg_is_in_recovery()trueを返し、受信と再生の場所がテストされたスイッチオーバーのしきい値を満たしていることを確認します。 PostgreSQL のストリーミングレプリケーションは既定で非同期であるため、Pod が Ready 状態であるだけでは、スタンバイが最新状態に追いついているとは言えません。

手順 2: 書き込みを一時停止し、プライマリを切り替える

すべてのアプリケーション トラフィックが PgBouncer を通過する場合は、PgBouncer 管理データベースに接続し、アプリケーション データベースを一時停止します。

kubectl exec <pgbouncer-pod> -- psql -p 6432 -U <admin-user> pgbouncer -c "PAUSE app_db;"

PAUSE は、構成されたプーリング モードに従ってサーバー接続が解放されるのを待機します。 このコントロールに依存する前に、アプリケーションの書き込みが PgBouncer をバイパスできないことを確認します。

書き込みを一時停止したら、オペレーターまたは高可用性の実装を使用して、次のアクションを完了します。

  1. 候補の WAL 受信位置と再生位置を再確認します。
  2. サポートされているスイッチオーバー操作を実行します。
  3. 書き込み可能なプライマリが 1 つだけ存在することを確認します。
  4. 以前のプライマリがフェンシングされているか、スタンバイとして再構成されていることを確認します。
  5. ライター サービスまたはエンドポイントが新しいプライマリを参照していることを確認してください。

次のチェックに合格した後にのみ PgBouncer を再開します。

kubectl exec <pgbouncer-pod> -- psql -p 6432 -U <admin-user> pgbouncer -c "RESUME app_db;"

手順 3: スイッチオーバーを検証する

# Verify the new primary is writable and no longer in recovery.
kubectl exec <new-primary-pod> -- psql -X -c "SELECT pg_is_in_recovery();"

# Verify all expected standbys stream from the new primary.
kubectl exec <new-primary-pod> -- psql -X -c "
SELECT application_name, state, sync_state, replay_lsn
FROM pg_stat_replication;"

アプリケーションの読み取り、書き込み、トランザクション、再接続の動作をテストします。 続行する前に、書き込みを実行できなかった期間とレプリケーション結果を RTO および RPO と比較してください。

オプションの同期レプリケーション構成

同期レプリケーションでは、受信確認済みトランザクションの RPO を減らすことができますが、コミットの待機時間が長く、必要なスタンバイが使用できない場合は書き込みの可用性を低下させることができます。 次の例では、2 つの名前付き直接接続スタンバイがコミットされた各トランザクションを再生するのを待機します。

# Use synchronous replication with multiple standbys
# postgresql.conf
synchronous_standby_names = 'ANY 2 (standby1, standby2, standby3)'
synchronous_commit = 'remote_apply'

測定された待機時間、障害ドメインの配置、持続性の要件に基づいて、 synchronous_standby_namessynchronous_commit を選択します。 この構成では、特定の切り替え期間は保証されません。

成功の検証

進行状況を検証するには、次のチェックリストを使用します。

  • 新しいプライマリは、読み取りと書き込みを受け入れます。
  • すべてのレプリカに正常なレプリケーションが表示されます。
  • アプリケーションは自動的に再接続します。
  • データ整合性とアプリケーションの整合性チェックが成功します。
  • バックアップと復元のテストは、新しいプライマリ上で成功します。

AKS ノード プールをアップグレードする

az aks nodepool upgrade操作では、ノード プール全体がアップグレードされます。 AKS は、サージ容量を追加し、古いノードを切断してドレインし、再イメージ化し、ノード プールのアップグレード設定に従ってプロセスを繰り返します。 各ノードに対してコマンドを 1 回実行したり、管理操作の前にノードを手動でドレインしたりしないでください。

  1. クラスターでサポートされているアップグレード ターゲットを一覧表示します。

    az aks get-upgrades \
       --resource-group <resource-group-name> \
       --name <cluster-name> \
       --output table
    
  2. コントロール プレーンが既に選択されているターゲット バージョンにあることを確認します。 テストされたワークロードの動作、クォータ、使用可能なサブネット アドレスに基づいて、ノード プールのローリング アップグレード設定を構成します。 次の例では、推奨される運用 maxSurge 値を使用します。

    az aks nodepool update \
       --resource-group <resource-group-name> \
       --cluster-name <cluster-name> \
       --name <node-pool-name> \
       --max-surge 33% \
       --drain-timeout <minutes> \
       --node-soak-duration <minutes>
    
  3. az aks get-upgradesによって返されたターゲットを使用して、ノード プールに対して 1 つのマネージド アップグレードを開始します。

    az aks nodepool upgrade \
       --resource-group <resource-group-name> \
       --cluster-name <cluster-name> \
       --name <node-pool-name> \
       --kubernetes-version <target-version>
    
  4. 操作全体で AKS アップグレード イベントとデータベースの正常性を監視します。

    kubectl events --all-namespaces
    kubectl get pods -l app=postgres -o wide --watch
    

    監視システムでレプリケーション、データベースの可用性、アプリケーション エラー、待機時間、ストレージの正常性を監視します。 ポッド中断予算がドレインをブロックしている場合は、予算をバイパスするのではなく、ワークロードの可用性の問題を修正します。

検証と回復

マネージド アップグレードが完了したら、ノードのバージョン、PostgreSQL トポロジ、およびアプリケーションの動作を確認します。

kubectl get nodes
kubectl get pods -l app=postgres -o wide
kubectl exec <current-primary-pod> -- psql -X -c "
SELECT application_name, state, sync_state, replay_lsn
FROM pg_stat_replication;"

AKS では、クラスターまたはノード プールを以前の Kubernetes バージョンにダウングレードすることはできません。 データベースが異常な場合は、アプリケーションの書き込みを停止し、データベース オペレーターでサポートされている復旧または切り替え手順を使用します。 現在のタイムラインに安全に再参加し、高可用性メカニズムによって昇格された場合を除き、以前の PostgreSQL プライマリに書き込みをリダイレクトしないでください。 Kubernetes のアップグレードによって回復不能な互換性の問題が発生する場合は、ワークロードをテスト済みのクラスターまたはノード プールに移動し、復旧計画に従ってデータを復元またはレプリケートすることで、サービスを復元します。


Redis Cluster のレプリカ優先ローリングアップグレード

このパターンは、少なくとも 3 つのプライマリ ノードを持ち、プライマリごとに少なくとも 1 つのレプリカを持つ Redis クラスターに使用します。 Redis クラスターノードのアップグレード順序は、最初にレプリカをアップグレードし、各プライマリをアップグレードされたレプリカに手動でフェールオーバーしてから、降格された以前のプライマリをアップグレードすることです。 Redis クラスターは、トポロジの変更中に一時的なエラーまたはリダイレクトを返す可能性があります。 Redis クラスターでは非同期レプリケーションが使用されるため、受信確認書き込みが失われる可能性があります。 アップグレードの前に、クライアントの再試行動作と許容される RPO を検証します。

Note

Redis オペレーターがクラスターを管理する場合は、文書化されたローリング アップグレード ワークフローを使用します。 手動のクラスター コマンドをアクティブなオペレーターと組み合わせないでください。ただし、そのドキュメントで指示されている場合を除きます。

手順 1: トポロジを記録して検証する

kubectl exec <redis-pod> -- redis-cli CLUSTER NODES
kubectl exec <redis-pod> -- redis-cli --cluster check 127.0.0.1:6379

各ノード ID、ロール、プライマリからレプリカへの割り当て、ハッシュ スロットの範囲を記録します。 すべての 16,384 スロットがカバーされ、すべてのプライマリが別の障害ドメインに正常なレプリカを持ち、クラスターが cluster_state:ok報告しない限り、続行しないでください。

手順 2: レプリカをアップグレードする

レプリカごとに、一度に 1 つずつ:

  1. オペレーターまたはワークロードのデプロイ メカニズムを使用して、アップグレードされた AKS 容量でレプリカを交換または再起動します。
  2. ポッドが Ready 状態になり、レプリケーションが完了するまで待ちます。
  3. CLUSTER NODES で、想定されるプライマリに割り当てられたままであることを確認します。

Redis ノード ID を保持するポッドの再起動に対して CLUSTER FORGET を実行しないでください。 置換に新しいノード ID がある場合は、--cluster-slaveredis-cli --cluster add-nodeを使用し、--cluster-master-idを使用して目的のプライマリのレプリカとして追加します。 新しいレプリカがクラスター トポロジに表示されるまで待ちます。

kubectl exec <existing-redis-pod> -- redis-cli --cluster add-node \
   <new-replica-ip>:6379 127.0.0.1:6379 \
   --cluster-slave \
   --cluster-master-id <primary-node-id>

手順 3: プライマリのフェールオーバーとアップグレード

プライマリごとに、一度に 1 つずつ:

  1. そのプライマリのアップグレードされ、キャッチアップ済みのレプリカを選択します。

  2. 現在のプライマリではなく、昇格させるレプリカCLUSTER FAILOVER:

    kubectl exec <candidate-replica-pod> -- redis-cli CLUSTER FAILOVER
    
  3. 候補がプライマリで、前のプライマリがそのレプリカになるまで、 ROLEINFO REPLICATION、または CLUSTER NODES をポーリングします。 OK応答は、Redis がフェールオーバー要求を受け入れたことを意味するだけです。

  4. アップグレード後の AKS 容量で、降格された元プライマリ ノードを置き換えるか再起動します。

  5. 次のプライマリに移動する前に、それが同期済みレプリカとして復帰するのを待ちます。

計画的なアップグレード中は、 CLUSTER FAILOVER FORCETAKEOVER は使用しないでください。 これらのオプションは、通常の調整をバイパスし、個別の障害復旧手順を必要とします。

手順 4: Redis クラスターを検証する

kubectl exec <redis-pod> -- redis-cli CLUSTER INFO
kubectl exec <redis-pod> -- redis-cli CLUSTER NODES
kubectl exec <redis-pod> -- redis-cli --cluster check 127.0.0.1:6379

スロット カバレッジ、プライマリからレプリカへの割り当て、レプリケーションの正常性、アプリケーションの読み取りと書き込み、リダイレクト処理、観察された RPO を確認します。


MongoDB レプリカセットのセカンダリ先行ローリングアップグレード

選択可能なセカンダリを持つ 3 メンバー以上の MongoDB レプリカ セットには、このパターンを使用します。 プライマリ のステップ ダウンと選択中、書き込みは新しいプライマリが選択されるまで失敗します。 アプリケーションは、MongoDB ドライバーのガイダンスに従って、適格な書き込みと一時的なトランザクションを再試行する必要があります。

Note

MongoDB オペレーターがレプリカ セットを管理する場合は、文書化されているローリング アップグレード ワークフローと準備チェックを使用します。

手順 1: レプリカ セットを検証する

kubectl exec <mongodb-pod> -- mongosh --quiet --eval "rs.status()"

予想されるすべてのメンバーが正常であることを確認し、現在のプライマリを特定し、少なくとも 1 つの選択可能なセカンダリがキャッチされていることを確認します。 また、テスト復元を使用して最新のバックアップを確認します。

手順 2: セカンダリをアップグレードする

各セカンダリについて、1つずつ:

  1. オペレーターまたはワークロードのデプロイ メカニズムを使用して、アップグレードされた AKS 容量のメンバーを置き換えるか再起動します。

  2. ポッドの準備が整うのを待ちます。

  3. メンバーが SECONDARY 状態に戻り、別のメンバーを更新する前に同期が完了することを確認します。

    kubectl exec <mongodb-pod> -- mongosh --quiet --eval \
       "rs.status().members.map(member => ({name: member.name, state: member.stateStr, optime: member.optimeDate}))"
    

手順 3: プライマリをステップ ダウンする

現在のプライマリに対してのみ rs.stepDown() を実行します。 最初の引数は、前者のプライマリを再選択できない期間を指定します。 2 番目の引数は、選択可能なセカンダリが追いつく必要がある期間を指定します。 テストした選択動作に基づいて値を選択します。

kubectl exec <current-primary-pod> -- mongosh --quiet --eval "rs.stepDown(60, 30)"

コマンドは、プライマリがステップダウンするときに切断されるか、エラーが返されることがあります。 1 つの新しいプライマリが選択されるまで、レプリカ セットの状態を別のメンバーからポーリングします。

kubectl exec <mongodb-pod> -- mongosh --quiet --eval \
   "rs.status().members.map(member => ({name: member.name, state: member.stateStr}))"

設定された期間内に選出可能なセカンダリがプライマリに追いつかない場合、プライマリは降格しません。 再試行する前に、レプリケーションの正常性に関する問題を解決してください。 計画的なアップグレード中にステップダウンを強制しないでください。

手順 4: 以前のプライマリをアップグレードして検証する

アップグレードされた AKS 容量で、以前のプライマリを置き換えるか再起動します。 正常なセカンダリとして返されるのを待ってから、次の検証を行います。

  • メンバーのうち、ちょうど 1 つが PRIMARY です。
  • 他のすべてのデータを保持しているメンバーは SECONDARY で、最新の状態に追いついています。
  • アプリケーションの読み取り、書き込み、再試行可能な書き込み、トランザクションは想定どおりに動作します。
  • 測定された選択間隔は、アプリケーション RTO を満たしています。
  • バックアップと復元のチェックに合格します。