Amazon EKS API サーバーのモニタリング
オブザーバビリティのベストプラクティスガイドのこのセクションでは、API サーバーのモニタリングに関連する以下のトピックについて詳しく説明します:
- Amazon EKS API サーバーのモニタリングの概要
- API サーバートラブルシューターダッシュボードの設定
- API トラブルシューターダッシュボードを使用した API サーバーの問題の理解
- API サーバーへの無制限のリスト呼び出しについて
- API サーバーへの不適切な動作の停止
- API の優先順位と公平性
- 最も遅い API 呼び出しと API サーバーのレイテンシーの問題の特定
はじめに
Amazon EKS マネージドコントロールプレーンのモニタリングは、EKS クラスターの健全性に関する問題を事前に特定するための重要な Day One の運用活動です。 Amazon EKS コントロールプレーンのモニタリングは、収集したメトリクスに基づいて事前対策を講じるのに役立ちます。 これらのメトリクスは、API サーバーのトラブルシューティングと、根本的な問題の特定に役立ちます。
このセクションでは、Amazon EKS API サーバーのモニタリングに Amazon Managed Service for Prometheus (AMP) を、メトリクスの可視化に Amazon Managed Grafana (AMG) を使用してデモンストレーションを行います。 Prometheus は、強力なクエリ機能を提供し、さまざまなワークロードを幅広くサポートする人気のオープンソースモニタリングツールです。 Amazon Managed Service for Prometheus は、完全マネージド型の Prometheus 互換サービスで、Amazon EKS、Amazon Elastic Container Service (Amazon ECS)、Amazon Elastic Compute Cloud (Amazon EC2) などの環境を安全かつ確実にモニタリングすることができます。 Amazon Managed Grafana は、オープンソースの Grafana 向けの完全マネージド型で安全なデータ可視化サービスで、お客様は複数のデータソースからアプリケーションの運用メトリクス、ログ、トレースを即座にクエリ、相関付け、可視化することができます。
まず、Amazon Managed Service for Prometheus と Amazon Managed Grafana を使用してスターターダッシュボードを設定し、Prometheus を使用し た Amazon Elastic Kubernetes Service (Amazon EKS) API サーバーのトラブルシューティングを支援します。 続くセクションでは、EKS API サーバーのトラブルシューティング時の問題の理解、API の優先順位と公平性、不適切な動作の停止について詳しく説明します。 最後に、最も遅い API 呼び出しと API サーバーのレイテンシーの問題を特定する方法を詳しく説明し、Amazon EKS クラスターの状態を健全に保つためのアクションを取れるようにします。
API サーバーのトラブルシューティング用ダッシュボードのセットアップ
Amazon Elastic Kubernetes Service (Amazon EKS) の API サーバーのトラブルシューティングを支援するための初期ダッシュボードを、AMP を使用してセットアップします。 これを使用して、本番環境の EKS クラスターのトラブルシューティング時にメトリクスを理解できるようにします。 Amazon EKS クラスターのトラブルシューティング時に、収集されたメトリクスの重要性をより深く理解できるように説明していきます。
まず、ADOT コレクターをセットアップして、Amazon EKS クラスターから Amazon Manager Service for Prometheus にメトリクスを収集します。 このセットアップでは、EKS ADOT アドオンを使用します。これにより、EKS クラスターの起動後いつでも ADOT をアドオンとして有効にすることができます。 ADOT アドオンには、最新のセキュリティパッチとバグ修正が含まれており、Amazon EKS で動作することが AWS によって検証されています。 このセットアップでは、EKS クラスターに ADOT アドオンをインストールし、クラスターからメトリクスを収集する方法を説明します。
次に、最初のステップでセットアップした AMP をデータソースとして使用するために、Amazon Managed Grafana ワークスペースをセットアップします。 最後に、API トラブルシューターダッシュボードをダウンロードし、Amazon Managed Grafana に移動して API トラブルシューター用のダッシュボード JSON をアップロードし、トラブルシューティングのためのメトリクスを可視化します。
API トラブルシューティングダッシュボードを使用した問題の理解
クラスターにインストールしたい興味深いオープンソースプロジェクトを見つけたとします。 そのオペレーターは、クラスターに DaemonSet をデプロイしますが、不正な形式のリクエストを使用したり、不必要に多くの LIST コールを行ったり、あるいは 1,000 ノードすべてにある DaemonSet が、クラスター上の 50,000 個の Pod のステータスを毎分リクエストしたりする可能性があります! このようなことは本当によく起こるのでしょうか?はい、実際によく起こります! このような状況がどのように発生するのか、簡単に見ていきましょう。
LIST と WATCH の理解
クラスター内のオブジェクトの状態を理解する必要があるアプリケーションがあります。例えば、機械学習 (ML) アプリケーションでは、Completed ステータスになっていない Pod の数を把握することでジョブのステータスを知る必要があります。Kubernetes では、WATCH と呼ばれる適切な方法と、Pod の最新ステータスを確認するためにクラスター上のすべてのオブジェクトをリストアップするという、あまり適切ではない方法があります。
適切な WATCH の使用
Kubernetes でアップデートを行う最もスケーラブルな方法は、WATCH またはプッシュモデルを介してアップデートを受信する単一の長期接続を使用することです。簡単に説明すると、システムの完全な状態を要求し、そのオブジェクトに対する変更を受信したときにのみキャッシュ内のオブジェクトを更新し、定期的に再同期を実行してアップデートの漏れがないことを確認します。
以下の画像では、apiserver_longrunning_gauge
を使用して、両方の API サーバーにおけるこれらの長期接続の数を把握しています。
図: apiserver_longrunning_gauge
メトリクス
このような効率的なシステムでも、良いものを使いすぎることがあります。たとえば、API サーバーと通信する必要がある 2 つ以上の DaemonSet を使用する非常に小さなノードを多数使用する場合、システムの WATCH 呼び出しの数が不必要に大幅に増加する可能性があります。例として、8 つの xlarge ノードと 1 つの 8xlarge ノードの違いを見てみましょう。ここでは、システムの WATCH 呼び出しが 8 倍に増加しているのが分かります。
図: 8 つの xlarge ノード間の WATCH 呼び出し
これらは効率的な呼び出しですが、もし先ほど言及した不適切な呼び出しだったらどうでしょうか?1,000 個のノードそれぞれの 上記の DaemonSet の 1 つが、クラスター内の合計 50,000 個の Pod それぞれのアップデートを要求していると想像してみてください。次のセクションでは、この無制限のリスト呼び出しについて詳しく見ていきます。
続ける前に注意点があります。上記の例のような統合は細心の注意を払って行う必要があり、多くの要因を考慮する必要があります。システムの限られた数の CPU を争う多数のスレッドの遅延、Pod の変更率、ノードが安全に処理できるボリュームアタッチメントの最大数など、すべてが関係します。しかし、私たちの焦点は、問題の発生を防ぎ、場合によっては設計に新しい洞察を与えてくれる実行可能なステップにつながるメトリクスに置かれます。
WATCH メトリクスはシンプルですが、WATCH の数を追跡し、それが問題である場合は削減するために使用できます。以下は、この数を減らすために検討できるいくつかのオプションです:
- Helm が履歴を追跡するために作成する ConfigMap の数を制限する
- WATCH を使用しないイミュータブルな ConfigMap とシークレットを使用する
- 適切なノードのサイジングと統合
API サーバーへの無制限のリストコールについて
これまで話してきた LIST コールについて説明します。リストコールは、オブジェクトの状態を理解する必要がある度に、Kubernetes オブジェクトの完全な履歴を取得します。この場合、キャッシュには何も保存されません。
これはどの程度の影響があるのでしょうか?これは、データをリクエストするエージェントの数、リクエストの頻度、リクエストするデータ量によって異なります。クラスター全体のデータを要求しているのか、それとも単一の名前空間だけなのでしょうか?それは毎分、すべてのノードで発生しているのでしょうか?例として、ノードから送信される各ログに Kubernetes のメタデータを追加するロギングエージェントを考えてみましょう。これは、大規模なクラスターでは膨大な量のデータになる可能性があります。エージェントがリストコールを通じてそのデータを取得する方法は多数ありますので、いくつか見てみましょう。
以下のリクエストは、特定の名前空間からポッドを要求しています。
/api/v1/namespaces/my-namespace/pods
次に、クラスター上の 50,000 個のポッドすべてを、一度に 500 個ずつのチャンクで要求します。
/api/v1/pods?limit=500
次のコールは最も破壊的です。クラスター全体の 50,000 個のポッドを一度に取得します。
/api/v1/pods
これは現場で頻繁に発生し、ログで確認することができます。
API サーバーの不適切な動作を停止する
クラスター をこのような不適切な動作から保護するにはどうすればよいでしょうか?Kubernetes 1.20 以前では、API サーバーは 1 秒あたりに処理される インフライト リクエストの数を制限することで自身を保護していました。etcd は一度に処理できるリクエスト数に限りがあるため、etcd の読み取りと書き込みを適切なレイテンシー範囲内に保つために、1 秒あたりのリクエスト数を制限する必要があります。残念ながら、この記事の執筆時点では、これを動的に行う方法はありません。
以下のチャートでは、読み取りリクエストの内訳を示しています。API サーバーあたりのインフライトリクエストのデフォルトの上限は 400、同時書き込みリクエストのデフォルトの上限は 200 です。デフォルトの EKS クラスターでは、2 つの API サーバーがあり、合計で 800 の読み取りと 400 の書き込みが可能です。ただし、アップグレード直後などの特定の時期には、これらのサーバーに非対称な負荷がかかる可能性があるため、注意が必要です。
図:読み取りリクエストの内訳を示す Grafana チャート
上記の方式は完璧ではないことが判明しました。例えば、新しくインストールした不適切な動作をするオペレーターが API サーバーのインフライト書き込みリクエストをすべて使用し、ノードのキープアライブメッセージなどの重要なリクエストを遅延させる可能性があるのを、どのように防ぐことができるでしょうか?