Amazon Web Services ブログ
Istio と ARC ゾーンシフトによる Amazon EKS におけるモニタリングとAZ障害からのリカバリ自動化
イントロダクション
マイクロサービスアーキテクチャをクラウドで実行することは、すぐに複雑な運用になる可能性があります。個々のワークロードにおける複数のインスタンスのような増え続ける変動要素を、インフラストラクチャの依存関係と合わせて考慮する必要があります。その上、これらの要素は、複数の Amazon Elastic Compute Cloud (Amazon EC2) インスタンスや、アベイラビリティーゾーン (AZ)、AWS リージョンなど、さまざまなトポロジードメインに分散されている場合があります。Kubernetes は、前述のトポロジーに基づいてコンテナのワークロードとインフラストラクチャを自動的にデプロイすることで、これらの環境の構築と管理に伴う運用上の負担をいくらか軽減します。ただし、これらの環境は規模、複雑さ、ネットワークへの依存性があるため、ある時点でアーキテクチャ全体の一部分が機能低下した状態または障害状態になることは避けられません。そのため、チームは実行時の Kubernetes アプリケーションとインフラストラクチャーの状態を把握することで Design for Failure を実践し、ワークロードの可用性を危険にさらす予期しないイベントに迅速に適応して回復できるように構築する必要があります。
アプリケーションとインフラストラクチャの両方におけるベストプラクティスであり共通的なアプローチは、冗長性を確保し、単一障害点を防ぐことです。単一障害点をなくすために、複数のアベイラビリティーゾーンにまたがる Amazon Elastic Kubernetes Service (Amazon EKS) に高可用性アプリケーションをデプロイするお客様が増えています。ただし、アプリケーションとインフラストラクチャの冗長性は、最良の結果を得るために適用すべき複数ある戦略の ひとつにすぎません。特定の耐障害性あるいは障害の設計メカニズムを適用するかどうか、またそれらをどのように適用するかは、アプリケーションの目標復旧時間目標 (RTO) と目標復旧時点 (RPO) によって異なります。アプリケーションによっては、ダウンタイム要件が最小限またはゼロのクリティカルな性質のものもあれば、この型にはまらないものもあります。
障害または劣化の範囲は、さまざまなレベルで発生する可能性があります。Amazon EKS 環境では、1 つのワーカーノード、一部のワーカーノード、または AZ 全体に問題が発生することがあります。AZ の障害が発生した場合は、回復力と復旧戦略の一環として Amazon Application Recovery Controller (ARC) のゾーンシフトを使用できます。ARC ゾーンシフトを使用すると、クラスター内のネットワークトラフィックを、影響を受けた AZ から一時的にリダイレクトできます。ただし、ゾーンシフトのプロセスを適切に管理するには、AZ 障害を検出するための十分なモニタリングを実施する必要があります。
あるいは、ゾーンオートシフトを使用してこれを管理することを AWS に許可することもできます。ゾーンオートシフトでは、AWS がお客様の AZ の全体的な状態を監視し、潜在的な障害が発生した場合は、お客様に代わってクラスター環境内の障害が発生した AZ からトラフィックを自動的に移動させることで対応します。また、その AZ が正常な状態に戻ったときに、その AZ へのクラスター内トラフィックの復元も AWS が管理します。
現在、多くのお客様が Istio などのサービスメッシュ実装を使用して、アプリケーション環境におけるネットワークインフラストラクチャを管理しています。Istio はシステムのネットワークオブザーバビリティの向上に役立ちます。そのデータプレーンプロキシは、特定の AZ の問題など、さまざまな問題を示すネットワークリクエストやマイクロサービスインタラクションに関連する主要なメトリクスを公開するためです。この投稿では、ゾーンシフトを管理するためのシグナルとして Istio のメトリクスを利用し、AZ における異常または劣化が発生した際に、アプリケーションの迅速な復旧を監視および自動化する方法に焦点を当てています。この記事で紹介するソリューションは、すでに Istio を Amazon EKS 環境に導入しているチームにとって最適です。別の方法として、チームはカスタムメトリクスをログデータに埋め込むことができる Amazon CloudWatch とその埋め込みメトリクス形式 (EMF) の使用を検討することもできます。
ソリューション概要
このチュートリアルでは、EKS で複数の AZ にサンプルアプリケーションをデプロイします。このアプリケーションはサイドカーモードで動作する Istio サービスメッシュの一部です。つまり、各 Pod にはコンテナアプリケーションと Istio サイドカープロキシ (Envoy) の両方が含まれます。サイドカープロキシは、アプリケーションへのインバウンド通信とアウトバウンド通信を仲介します。すべての AZ の状態を判断するには、これらのアプリケーションサイドカープロキシによってキャプチャされたリクエストに対するネットワーク応答 (2xx や 5xx など) を AZ レベルで継続的に評価します。そのために、Prometheus を使用してこれらのサイドカープロキシの Envoy クラスターを監視します。ここで使用するメトリクスは envoy_cluster_zone_availability_zone__upstream_rq です。わかりやすく言うと、Envoy クラスター (EKS クラスターと混同しないでください) とは、特定のアプリケーションのトラフィックを受け入れる類似したアップストリームホストのグループを指します。さらに、Grafana は各 AZ のデータを可視化し、問題が発生した場合には Slack チャンネルにアラートを送信するためにも使用されます。最後に、Amazon EKS で ARC ゾーンシフトを作動させて、アプリケーションの復旧をテストします。この例では 、AZ ヘルスモニタリング用の 1 つのシグナルに焦点を当てていますが、本番環境でマルチ AZ 環境を監視する場合、環境全体と AZ の健全性と状態をよりよく把握するために、レイテンシー、(トラフィックを受信していない) サイレント障害、グレー障害、定期的な障害など、さまざまなタイプの問題や障害も考慮する必要があります。Envoy が公開しているクラスター統計のリストを参照できます。
以下の図は、この記事で説明するアプリケーション環境を示しています。
前述したように、このソリューションでは、AZ 内の Pod からの全体的なネットワーク応答を一定の間隔で使用して、AZ が正常かどうかを示します。次の図は、AZ が正常と見なされるクラスターを示しています。
次の図は、一定期間において、AZ ごとの Pod ネットワークにおけるリクエストで発生したサーバー側のエラーの数に基づいて、異常と見なされる AZ (af-south-1c) を示しています。
次の図は、ARC ゾーンシフトを開始して迅速に回復し、Amazon EKS 環境の変化に適応することで、影響を受けた AZ を一時的に隔離し、east-to-west または north-to-southトラフィックを受信しないようにする方法を示しています。Amazon EKS で ARC ゾーンシフトを開始すると、EndpointSlice コントローラーは正常でない AZ の Pod エンドポイントを EndpointSlice から削除します。しかし、これを Istio のサービスディスカバリーにどう結び付けるのでしょうか。
Istioのサイドカープロキシは、xDS APIと呼ばれるサービスディスカバリーAPIのセットを使用します。xDS API の 1 つがエンドポイント検出サービス (EDS) API です。これにより、上流の Envoy クラスターのメンバー (エンドポイント) を自動的に検出できます。ゾーンシフト中、検出可能なエンドポイント (上流の Envoy クラスターのメンバー) のリストは、クラスターの正常な AZ で実行されているものだけです。ゾーンシフト中も、宛先ルールを使用して Istio ネットワークポリシーを適用できます。
準備
このサンプルを実行するには、以下の前提条件を満たす必要があります。
- AWS アカウント
- 複数の AZ にプロビジョニングされた EKS クラスター (v 1.28 以上)
- EKS クラスターでの ARC ゾーンシフト有効化
- Istio (サイドカーモード) のインストール
- オブザーバビリティのため kube-prometheus を用いた Prometheus と Grafana のインストール(または、このガイドを使用して Amazon Managed Prometheus と Amazon Managed Grafana をセットアップすることもできます)
- Slack での受信ウェブフックの設定(このステップでは、無料の Slack アカウントを使用できます)
デモンストレーション
以下の手順で、このソリューションについて説明していきます。
サンプルアプリケーション用の Istio ネットワークの設定
まず、関連する Istio リソースを設定してデプロイし、サンプルアプリケーションが外部からのネットワークリクエストを受信できるようにします。そのためには、まず Istio Ingress ゲートウェイを設定する必要があります。Ingress ゲートウェイはサービスメッシュへのエントリポイントであり、メッシュ内のワークロードを保護し、メッシュに流入するトラフィックを制御する役割を果たします。Istio Ingress ゲートウェイは、開くポートとそれに関連する仮想ホストを指定するゲートウェイリソースを作成することで設定できます。
ゲートウェイ
ネットワークトラフィックが Ingress ゲートウェイを経由してサービスメッシュに入ったら、正しい宛先にルーティングする必要があります。このルーティングプロセスの管理は VirtualService リソースが行います。
Virtual Service
次のステップでは、サンプルアプリケーションをデプロイします。
複数の Pod レプリカを実行して AZ 間に分散させる
アプリケーションの複数のインスタンスを実行し、それを複数の AZ に分散させると、耐障害性と可用性の両方が向上します。トポロジー分散の制約を使用すると、アプリケーションが事前に静的安定性を持つように設定できます。これにより、AZ に障害が発生した場合でも、トラフィックの急増や急増が発生しても直ちに対処できる十分な数のレプリカが正常な AZ に保持されます。
最初のステップとして、アプリケーションインスタンスを配置する ecommerce 名前空間を作成します。その後、名前空間に適切なラベルを付けて、その名前空間内で実行されるすべてのアプリケーションにサイドカープロキシを挿入することを Istio が認識できるようにする必要があります。
これらのステップを完了すると、次のコードを使用してサンプルの支払いアプリケーションをデプロイできます。最適に分散 (またはレプリカを分布) させるには、他のレプリカがすでに起動して実行されてからアプリケーションを段階的にスケーリングする必要があります。これにより、スケジューラは特定の AZ のワーカーノードで実行されているレプリカを確認して、ユーザーが定義したスケジューリング制約に従うようにすることができます。
前述のリソースを適用すると、Pod がクラスターで期待どおりに実行されていることを確認できます。次のスクリーンショットは、K9s を使用したビューを示しています。
アプリケーションをデプロイしたら、次のコマンドを入力して Istio Ingress ゲートウェイが認識している payments アップストリームクラスターを一覧表示することで、さまざまな AZ 間でのアプリケーションの分布を確認できます。結果には、Pod エンドポイントと、それらが存在する各 AZ が表示されます。
次に、アプリケーションが期待どおりに動作していることをテストします。
まず、Istio Ingress ゲートウェイのホスト名を取得し、そのホスト名に /v1/payments というパスを追加し、ターミナル、ブラウザ、または API クライアントツールで GET リクエストを実行します。
次のスクリーンショットのような結果が表示されます。
Istio サイドカープロキシを監視するための Prometheus のセットアップ
ソリューション概要で詳しく説明されているように、各ゾーンのアプリケーションサイドカープロキシによって処理されるアップストリームリクエストへの応答を評価することで、AZ の状態を判断します。そのためには、まず Istio サイドカープロキシを持つ Pod からメトリクスを取得するように Prometheus を設定する必要があります。
前述のリソースを適用したら、次のコマンドを実行して Prometheus ダッシュボードにアクセスできます。
次に、Prometheus でメトリクスを確認できるように、サンプルアプリケーションのトラフィックを生成する必要があります。そのためには、ターミナルで以下のコマンドを実行します。これにより、支払いアプリケーションに 150 回の GET リクエストが入力されます。クエリの総数は必要に応じて調整できます。
その後、Prometheusダッシュボードを再度開き、次のスクリーンショットに示すように、特定のAZのEnvoyクラスターのメトリクス結果を検索できます。
af-south-1a – envoy_cluster_zone_af_south_1a__upstream_rq
af-south-1b – envoy_cluster_zone_af_south_1b__upstream_rq
af-south-1c – envoy_cluster_zone_af_south_1c__upstream_rq
Grafana ダッシュボードの作成
次に、Grafana でダッシュボードを作成し、関連データをより整理された形式で視覚化します。作成される Grafana パネルのデータソースとして Prometheus を使用します。
ブラウザで Grafana にアクセスするには、次のコマンドを実行します。
kube-prometheus でオブザーバビリティスタックをインストールしてから初めて Grafana を起動する場合は、admin ユーザーを使用し、次のコマンドを使用してパスワードを取得できます。
認証情報を取得したら、Grafana にログインします。デフォルトでは、kube-prometheus には Grafana インストールのデータソースとして Prometheus と Alertmanager があらかじめ設定されています。ただし、Prometheus をデータソースとして設定する必要がある場合は、以下の手順に従うことができます。
- 左側のメニューで [接続] を選択
- [接続] で [新しい接続を追加] を選択
- 検索バーに「プロメテウス」と入力
- 表示されたものを選択
- 右上の [新しいデータソースを追加] を選択
データソースを設定するには、次のスクリーンショットに示すように、接続の名前を入力し、Prometheus サーバーの URL を入力する必要があります。
kube-prometheus の Prometheus サーバー URL は ” http://prom-kube-prometheus-stack-prometheus.prometheus:9090/ ” です。
Prometheus データソースへ正常に接続できたら、Grafana でダッシュボードを作成できます。ダッシュボードに追加する各パネルは、前のセクションと同じメトリクス (envoy_cluster_zone_af_south_1a__upstream_rq など) を使用する EKS クラスターの AZ を表しています。次のスクリーンショットのように、クラスター内の AZ ごとにこのステップを繰り返します。
このプロセスを完了すると、パネル構成によっては、次のスクリーンショットのようなものが表示されるはずです。
EKS クラスター内の AZ 用に Grafana アラートを設定する
このセクションでは、Grafana アラートの設定に焦点を当てます。ここまでの手順により、ある AZ における Pod からのネットワーク応答に基づいて対象の AZ の状態を監視できるように EKS クラスター環境が設定されました。ただし、アラートのルールを定義する際には、次の点を考慮する必要があります。
何をもって AZ で問題が発生していると見なすか?
問題が発生した場合、誰に通知すべきか?
通知はどのように行われるか?
この例では、特定の AZ 内でサーバー側のエラーが急増している場合、その AZ に何か問題が起きているという兆候であるとします。レイテンシーや、リクエストのタイムアウト、接続障害など、他の指標を使用することもできます。ダッシュボードパネルで行ったように、AZ ごとにアラートルールを作成する必要があります。
まず、Alert Rules の欄で、次のスクリーンショットのように、直近の 30 分(30分前から現在まで)のデータを使用するようにアラートルールを設定します。次に、各 AZ のサーバー側のエラー (5xx) を追跡できるルールを設定できます。
envoy_cluster_zone_af_south_1a__upstream_rq{response_code_class=”5xx”}
その後、設定した条件を Grafana に評価させる頻度を設定し、通知ポリシーのアラートにラベルを割り当てます。
次に、Contact Point の欄でアラート通知を受け取るSlackチャンネルの連絡先を設定し、次のスクリーンショットのように期待どおりに機能することをテストします。
最後に、Notification Policy の欄で、次のスクリーンショットに示すように、各ルールに追加したラベルに基づいてGrafanaがアラートを適切な連絡先と照合できるようにポリシーを作成します。
アラート通知システムが期待どおりに機能していることをテストするには、いずれかの AZ (この例では af-south-1c) のアラート条件を変更して、リクエストが正常に送信されたとき (response_code_class= ”2xx” ) に Grafana が代わりに通知できるようにします。さらに、結果を確認するために長時間待たなくても済むように、評価間隔を短くすることもできます。
そのためには、アラートルールのメトリックスとラベルフィルターを更新して、アラートをテストしたい AZ の条件を以下のように設定します。
envoy_cluster_zone_af_south_1c__upstream_rq{response_code_class=”2xx”}
その後、テスト目的でカウントのしきい値を減らし、アラートルールの評価間隔を更新できます。Grafana でプレビューを選択すると、どの値がアラートを発するか確認できます。次のスクリーンショットは、アラートルールのプレビュー例を示しています。
アラートルール設定を保存したら、次のスクリーンショットに示すように、アプリケーションに多数のクエリを入力してアラートルールのしきい値を超えるようにすることで、通知システムをテストできます。
Amazon EKS でのゾーンシフトを実行する
EKS クラスター内の AZ に異常または障害があるというアラートを受け取った場合は、ARC ゾーンシフトを使用して影響を受ける AZ からネットワークトラフィックを遠ざけることで対応できます。Amazon EKS でゾーンシフトをトリガーすると、次のステップが自動的に適用されます。
- 影響を受けた AZ のノードは封鎖されます。これにより、Kubernetes スケジューラが異常な AZ のノードに新しい Podをスケジューリングすることを防ぎます。
- マネージドノードグループを使用している場合、AZ のリバランシングは中断され、Auto Scaling グループ (ASG) が更新されて、新しい EKS データプレーンノードが正常な AZ でのみ起動されるようになります。
- 異常な AZ のノードは終了されず、Pod もこれらのノードから削除されません。これは、ゾーンシフトの期限が切れたりキャンセルされたりしたときに、まだ十分なキャパシティのある AZ にトラフィックを安全に戻せるようにするためです。
- EndpointSlice コントローラーは、障害のある AZ 内の Pod エンドポイントを見つけ、関連する EndpointSlice から削除します。これにより、正常な AZ 内の Pod エンドポイントのみがネットワークトラフィックの受信対象になるようになります。ゾーンシフトがキャンセルされるか期限が切れると、EndpointSlice コントローラーは EndpointSlice を更新して、復元された AZ のエンドポイントを追加します。
次のコマンドを使用して、クラスターのゾーンシフトを開始できます。
次のスクリーンショットに示すように、リソースがデプロイされているリージョンに存在する AZ の情報で前述のスクリプトを更新することを忘れないでください。
影響を受けたエンドポイントがトラフィックを受信できなくなったことを確認するには、次のコマンドを実行して、支払いアプリケーションに関連付けられた Envoy クラスターを取得します。
前のスクリーンショットでわかるように、支払いアプリケーションに使用できるアップストリームクラスターは af-south-1a と af-south-1b のクラスターだけです。
次に、支払いアプリケーションにクエリを実行して、他の AZ (af-south-1a と af-south-1b) で実行されている Pod からのネットワーク応答に基づいて、そのアプリケーションが引き続き利用可能で期待どおりに機能していることを確認できます。
クリーンアップ
これ以上のコストが発生しないように、この記事で詳しく説明した例に関連してプロビジョニングしたインフラストラクチャを必ず削除してください。チュートリアルで Kubernetes マニフェストファイルの保存に使用したファイル名を忘れずに使用してください。
アプリケーションのリソース削除
kubectl delete -f sample-application-manifest.yaml
Envoy サイドカー監視用の Prometheus カスタムリソースの削除
kubectl delete -f pod-monitoring-manifest.yaml,service-monitoring-manifest.yaml
Prometheus のアンインストール
helm uninstall <release-name> -n <namespace> -f values.yaml
Istio のアンインストール
おわりに
この投稿では、Istio、Prometheus、Grafana、ARC ゾーンシフトを使用して Amazon EKS クラスター内の AZ 障害を監視し、回復を自動化するための実践的なアプローチについて説明しました。Amazon EKS の ARC ゾーンシフトとゾーンオートシフトの詳細については、ドキュメントをご覧ください。
翻訳はソリューションアーキテクトの松本が担当しました。原文はこちらです。