アプリの耐障害性を高めるための開発とテスト
IBM Cloud Kubernetes Service がコントロールプレーンのメンテナンスをどのように処理するか、メンテナンス更新が実行中のワークロードにどのような影響を与えるか、そして高い耐障害性を実現するためにアプリケーションをテストし、アーキテクチャを設計する方法について学びましょう。
クラスタのアーキテクチャと役割の概要
IBM Cloud Kubernetes Service は、管理対象の Kubernetes サービスです。 各クラスターにおいて、アーキテクチャは、それぞれ [異なる責任範囲](/docs/containers?topic=containers-responsibilities_Kubernetes Service) を持つ2つのプレーンに分割されています
- コントロール・プレーン
- 運営: IBM。 Kubernetes APIサーバー、 etcd、コントローラーマネージャー、およびスケジューラーが含まれています。
- データ・プレーン
- あなた自身が管理します。 ワーカーノード、アプリケーションポッド、ストレージ構成、およびネットワークアドオンが含まれます。
| 飛行機 | 管理サービス | コンポーネント |
|---|---|---|
| コントロール・プレーン | IBM | APIサーバー、 etcd、コントローラーマネージャー、スケジューラー |
| データ・プレーン | You | ワーカーノード、アプリケーションポッド、ストレージ、ネットワークアドオン |
IBM コントロールプレーンに対して、定期的にパッチバージョンの更新を適用します。 これらのパッチは、セキュリティの脆弱性を修正し、重要なバグ修正を適用するとともに、クラスタが IBM のセキュリティ要件に準拠し続けることを保証します。 これらのパッチがどのように適用されるかを理解することで、アプリケーションのアーキテクチャについて、十分な情報に基づいた判断を下すことができます。
クラウド環境で実行されるアプリケーションは、一時的なネットワーク障害、ホスティングインフラのメンテナンス、サードパーティサービスの遅延など、動的な状況の影響を受けます。 あらゆる状況下での耐障害性を考慮した設計とテストを行うことで、信頼性の高い本番ワークロードが確保されます。
IBM によるコントロールプレーンのパッチ適用方法
すべての IBM Cloud Kubernetes Service クラスタのコントロールプレーンコンポーネントは、高可用性(HA)構成で実行されます。 各コンポーネントの複数のレプリカが独立したアベイラビリティゾーン全体に分散配置されており、これによりコントロールプレーン内に単一障害点が存在しないようになっています。
パッチのアップグレードが適用される際、 IBM はローリング再作成戦略を採用します。 レプリカは順次更新されます:
- アップグレード中も、 Kubernetes APIサーバーには引き続きアクセス可能です。
- スケジューリング、オートスケーリング、ヘルスチェックなどのクラスタ操作は、中断されることなく継続されます。
- IBM ポッドが削除される前に、進行中の接続が完了できるよう、正常なシャットダウンまでの遅延時間を確保します。
コントロールプレーンのパッチによるアップグレードは、データプレーンで実行中のユーザーアプリケーションに影響を与えないように設計されています。 このプロセス全体を通じて、ポッド、サービス、およびワークロードはワーカーノード上で通常通り実行され続けます。
コントロールプレーンの更新時のワークロードへの影響
データプレーンはユーザーによって管理されるため、 IBM のコントロールプレーンによるパッチ適用では、ワーカーノードや実行中のアプリケーションポッドの再起動、再スケジューリング、変更は行われません。
ただし、 Kubernetes API に対して頻繁に直接呼び出しを行うアプリケーションやツール(カスタムコントローラー、オペレーター、CI/CD パイプライン、クラスターの状態を監視するモニタリングエージェントなど)は、一時的な API エラーに対して適切に対処する必要があります。 Kubernetes の一般的なベストプラクティスに従ってください:
- すべてのAPI呼び出しに対して、指数関数的なバックオフを用いたリトライロジックを実装する。
- 再接続ロジックがない状態で、APIサーバーへの永続的なオープン接続に依存することは避けてください。
シナリオをシミュレートしてアプリケーションの回復力を検証する
アプリケーションの耐障害性に対する信頼性を高めるため、定期メンテナンスや予期せぬ障害が発生する前に、本番環境以外の環境で本番環境の障害状況をシミュレートしてください。
シミュレーション中は、アプリケーションを監視し、予期せぬポッドの再起動、エラーログの急増、応答時間の悪化、クライアントリクエストの切断など、障害の兆候がないか確認してください。 これらの観察結果を活用して、再試行ロジックの改良、ヘルスプローブの調整、あるいはレプリカトポロジーの調整を行ってください。
クラスタ管理コマンド(マスターのリフレッシュやワーカープールのサイズ変更など)を実行するには、プラットフォームへの「管理者」または「オペレーター」権限と、クラスタ管理サービスの権限が必要です。 クラスタインフラストラクチャへのアクセス権限を持たないアプリケーション開発者の方は、クラスタ管理者と連携して、これらのシミュレーションを実行してください。
コントロールプレーンのリフレッシュを用いたコントロールプレーンパッチのシミュレーション
コントロールプレーンの更新をトリガーすると、 IBM がパッチアップグレードの際に使用するローリングアップデートプロセスが開始されます。 このテストでは、アプリケーションとツールがコントロールプレーンのレプリカ移行を円滑に処理できるかどうかを確認します。
-
クラスターでコントロールプレーンの更新を実行します。
ibmcloud ks cluster master refresh --cluster CLUSTER_NAME_OR_ID -
アプリケーションが中断することなくトラフィックの処理を継続していること、およびクライアント向けエンドポイントが引き続き正常に動作していることを確認してください。
ワーカーノードの追加および削除によるネットワークルーティング更新のシミュレーション
ワーカーノードの追加や削除が行われると、 Kubernetes はクラスタ全体の内部ネットワークルーティングロジックを更新し、インフラストラクチャのメンテナンス中にノードがサイクルされる際に発生する状況をシミュレートします。
-
ワーカープールのサイズを変更して、一時的なワーカーノードを追加してください。
ibmcloud ks worker-pool resize --cluster CLUSTER_NAME_OR_ID --worker-pool WORKER_POOL_NAME --size-per-zone NEW_SIZE -
新しいワーカーノードが初期化され、クラスタネットワークに参加する間、アプリケーションのログと応答遅延を監視してください。
-
テストが完了したら、テスト用ワーカーノードを削除してください。
手順 1 で作成した特定のワーカーノードを、対象を絞って削除するには:
- ワーカーノードを削除する前に、そのノードをコルドーンし、ドレインを行って、ワークロードが正常に再スケジューリングされるようにしてください。
kubectl cordon NODE_NAME kubectl drain NODE_NAME --ignore-daemonsets --delete-emptydir-data- クラスターからワーカーノードを削除します。
ibmcloud ks worker rm --cluster CLUSTER_NAME_OR_ID --worker WORKER_IDibmcloud ks worker-pool resizeコマンドを使用し、元の--size-per-zoneの値を指定して、ワーカープールの容量を元の状態に戻してください。
より限定的なアプローチではない代替手段として、ステップ1の
ibmcloud ks worker-pool resizeコマンドを使用し、特定のノードを明示的に削除することなく、ワーカープールを元のサイズに戻すこともできます。
ワークロードの耐障害性に関するベストプラクティス
クラスタでイベントが発生した際のアプリケーションの回復力は、ワークロードの設計および構成方法によって異なります。 Kubernetes のワークロード仕様には、以下の推奨事項を適用してください:
すべてのワークロードに対して複数のレプリカを実行する
シングルレプリカ構成では、障害に耐えることができません。 spec.replicas を少なくとも 2 に設定してください(本番環境のワークロードでは、 3 以上が推奨されます)。これにより、単一のポッドの損失や再スケジューリングによってダウンタイムが発生するのを防ぐことができます。
レプリカを各ゾーンおよびワーカーノードに分散させる
デプロイメントの設定で、 topologySpreadConstraints またはポッドのアンチアフィニティルールを設定します。 ポッドを複数のアベイラビリティゾーンやワーカーノードに分散させることで、単一のゾーンでの障害やノードのメンテナンス作業によって、すべてのレプリカが同時に停止することを防ぐことができます。
Pod ディスラプション・バジェット(PDB)の設定
PodDisruptionBudget リソースは、ノードのドレインやクラスターの更新など、意図的な中断が発生した際に、利用可能な状態を維持しなければならないポッドの最小数または割合を指定します。 重要なワークロードごとにPDBを定義し、管理操作によってアプリケーションが許容できる数以上のポッドがエヴィクションされるのを防ぎます。
レディネス・プローブとライブネス・プローブを定義する
コンテナの仕様で、レディネス・プローブとライブネス・プローブを設定します:
- 準備状態のプローブ: Kubernetes が、初期化が完了し、リクエストを処理できる状態にあるポッドにのみトラフィックをルーティングするようにします。
- ライブネスプローブ: Kubernetes が、デッドロック状態または不健全な状態になったコンテナを自動的に再起動するように設定します。
適切なリソースの要求と制限を設定する
各コンテナについて、現実的なCPUおよびメモリの要求値と上限値を指定してください。 リクエストにより、 Kubernetes スケジューラが、十分な容量を持つノードにポッドを配置するよう保証されます。 制限を設けることで、単一のコンテナが過度のリソースを消費し、同じワーカーノード上に配置された他のワークロードのパフォーマンスを低下させることを防ぎます。
正常なシャットダウン処理を実装する
ポッドが終了する際、 Kubernetes は、 SIGKILL を送信する前に、 SIGTERM シグナルを送信します。 アプリケーションを設計する際は、 SIGTERM をキャッチし、新規接続の受け入れを停止し、進行中のトランザクションを完了させ、正常に終了するようにしてください。 アプリケーションがトラフィックを適切に処理し終えるのに十分な時間を確保できるよう、Podの仕様で適切な terminationGracePeriodSeconds を設定してください。
APIサーバーへの長期接続に依存しないようにしてください
Kubernetes ウォッチリクエストやストリーミング接続( kubectl exec、ポートフォワード、カスタムAPIクライアントによるウォッチなど)は、特定のコントロールプレーンレプリカに直接接続されます。 パッチのアップグレード中にそのレプリカがサイクルすると、接続が切断されます。 ワークロードおよびツールは、指数関数的なバックオフを伴う自動再接続ロジックを実装しなければならない。
リトライロジックとサーキットブレーカーを使用する
アプリケーションが Kubernetes API、外部データベース、または下流のマイクロサービスとやり取りを行う場合は、指数関数的なバックオフとジッターを用いたリトライロジックを実装してください。 上流または下流の依存関係が一時的に利用できない場合に、連鎖的な障害を防ぐために、サーキットブレーカーパターンを使用します。
次のステップ
- 「 アプリの展開計画 」を確認し、ワークロードの種類や Kubernetes オブジェクトについて詳しく学びましょう。
- 完全な設定例を交えながら、 クラスターへのアプリ展開 について学びましょう。
- クラスタレベルの可用性戦略については、「 高可用性と災害復旧 」をご覧ください。