

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Kubernetes アップストリーム SLOs
<a name="kubernetes_upstream_slos"></a>

Amazon EKS はアップストリーム Kubernetes リリースと同じコードを実行し、EKS クラスターが Kubernetes コミュニティで定義された SLOs 内で動作するようにします。Kubernetes [Scalability Special Interest Group (SIG)](https://github.com/kubernetes/community/tree/master/sig-scalability) は、スケーラビリティの目標を定義し、SLIs と SLOs。

SLIs は、システムの実行状況を判断するために使用できるメトリクスやメジャーなどのシステムを測定する方法です。たとえば、リクエストのレイテンシーやカウントなどです。SLOs「well」を実行しているときに予想される値を定義します。たとえば、リクエストのレイテンシーは 3 秒未満のままです。Kubernetes SLOs と SLIs は Kubernetes コンポーネントのパフォーマンスに焦点を当て、EKS クラスターエンドポイントの可用性に焦点を当てる Amazon EKS Service SLAs とは完全に独立しています。

Kubernetes には、CSI ドライバー、アドミッションウェブフック、自動スケーラーなどのカスタムアドオンまたはドライバーを使用してシステムを拡張できる多くの機能があります。これらの拡張機能は、さまざまな方法で Kubernetes クラスターのパフォーマンスに大きな影響を与える可能性があります。つまり、 を使用するアドミッションウェブフックは、ウェブフックターゲットが使用できない場合に K8s API リクエストにレイテンシーを追加する`failurePolicy=Ignore`可能性があります。Kubernetes Scalability SIG は、[「お約束します」フレームワーク](https://github.com/kubernetes/community/blob/master/sig-scalability/slos/slos.md#how-we-define-scalability)を使用してスケーラビリティを定義します。

次のことを約束する場合: - クラスターを正しく設定する - 「合理的に」拡張機能を使用する - クラスター内の負荷を推奨[制限](https://github.com/kubernetes/community/blob/master/sig-scalability/configs-and-limits/thresholds.md)内に維持する 

次に、クラスターがスケールすることを約束します。つまり、すべての SLOsが満たされます。

## Kubernetes SLOs
<a name="_kubernetes_slos"></a>

Kubernetes SLOs は、ワーカーノードのスケーリングやアドミッションウェブフックなど、クラスターに影響を与える可能性のあるプラグインや外部の制限をすべて考慮しているわけではありません。これらの SLOs [Kubernetes コンポーネント](https://kubernetes.io/docs/concepts/overview/components/)に焦点を当て、Kubernetes アクションとリソースが期待どおりに動作していることを確認します。SLOs、Kubernetes 開発者が Kubernetes コードを変更してもシステム全体のパフォーマンスが低下しないようにするのに役立ちます。

[Kuberntes Scalability SIG では、以下の公式 SLO/SLIsを定義します](https://github.com/kubernetes/community/blob/master/sig-scalability/slos/slos.md)。Amazon EKS チームは、これらの SLOs/SLIs の EKS クラスターでスケーラビリティテストを定期的に実行し、変更が行われ、新しいバージョンがリリースされたときにパフォーマンスの低下をモニタリングします。


| 目的 | 定義 | SLO | 
| --- | --- | --- | 
|  API リクエストのレイテンシー (変更)  |  過去 5 分間の 99 パーセンタイルとして測定される、すべての (リソース、動詞) ペアの単一オブジェクトに対する変更 API コールの処理のレイテンシー  |  デフォルトの Kubernetes インストールでは、仮想リソースと集計リソース、カスタムリソース定義を除くすべての (リソース、動詞) ペアについて、クラスター日あたり 99 パーセンタイル <= 1  | 
|  API リクエストのレイテンシー (読み取り専用)  |  過去 5 分間の 99 パーセンタイルとして測定される、すべての (リソース、スコープ) ペアの非ストリーミング読み取り専用 API コールの処理のレイテンシー  |  デフォルトの Kubernetes インストールでは、仮想リソースと集計リソースおよびカスタムリソース定義を除くすべての (リソース、スコープ) ペアについて、クラスター日あたり 99 パーセンタイル: (a) <= `scope=resource` (b) <= 30s それ以外の場合は 1s ( `scope=namespace`または の場合`scope=cluster`)  | 
|  ポッドの起動レイテンシー  |  スケジュール可能なステートレスポッドの起動レイテンシー。ポッド作成のタイムスタンプから、すべてのコンテナが開始と報告され、監視によって観測されるまでの、イメージをプルして init コンテナを実行する時間を除き、過去 5 分間で 99 パーセンタイルと測定されます。  |  デフォルトの Kubernetes インストールでは、クラスター日あたり 99 パーセンタイル <= 5s  | 

### API リクエストのレイテンシー
<a name="_api_request_latency"></a>

`kube-apiserver` は`1m0s`デフォルトで と`--request-timeout`定義されています。つまり、リクエストはタイムアウトしてキャンセルされる前に最大 1 分 (60 秒) 実行できます。レイテンシー用に定義された SLOs は、変更または読み取り専用のリクエストのタイプによって分類されます。

#### 変異
<a name="_mutating"></a>

Kubernetes でリクエストをミューテーションすると、作成、削除、更新など、リソースが変更されます。これらのリクエストは、更新されたオブジェクトが返される前に [etcd バックエンド](https://kubernetes.io/docs/concepts/overview/components/#etcd)に書き込む必要があるため、コストがかかります。[Etcd](https://etcd.io/) は、すべての Kubernetes クラスターデータに使用される分散キーバリューストアです。

このレイテンシーは、Kubernetes リソースの (リソース、動詞) ペアの 5 分間で 99 パーセンタイルとして測定されます。たとえば、これにより、ポッドの作成リクエストとノードの更新リクエストのレイテンシーが測定されます。SLO を満たすには、リクエストのレイテンシーが <= 1 秒である必要があります。

#### [Read-only]
<a name="_read_only"></a>

読み取り専用リクエストは、単一のリソース (Get Pod X など) またはコレクション (Get all Pods from Namespace X など) を取得します。はオブジェクトのキャッシュ`kube-apiserver`を保持するため、リクエストされたリソースはキャッシュから返されるか、最初に etcd から取得する必要がある場合があります。これらのレイテンシーも 5 分間で 99 パーセンタイルで測定されますが、読み取り専用リクエストには個別のスコープを含めることができます。SLO は 2 つの異なる目標を定義します。
+ *単一の*リソース ( など) `kubectl get pod -n mynamespace my-controller-xxx` に対して行われたリクエストの場合、リクエストのレイテンシーは <= 1 秒のままにする必要があります。
+ 名前空間またはクラスター ( など`kubectl get pods -A`) 内の複数のリソースに対して行われたリクエストの場合、レイテンシーは <= 30 秒のままにする必要があります

Kubernetes リソースのリストに対して行われたリクエストでは、リクエスト内のすべてのオブジェクトの詳細が SLO 内で返されることが予想されるため、SLO にはリクエストスコープごとに異なるターゲット値があります。大規模なクラスターや大量のリソースコレクションでは、レスポンスサイズが大きくなり、返すまでに時間がかかる場合があります。たとえば、JSON でエンコードされた各ポッドが約 1 KiB である数万個のポッドを実行しているクラスターでは、クラスター内のすべてのポッドを返すと 10MB 以上になります。Kubernetes クライアントは、[APIListChunking を使用してリソースの大規模なコレクションを取得することで、](https://kubernetes.io/docs/reference/using-api/api-concepts/#retrieving-large-results-sets-in-chunks)このレスポンスサイズを減らすのに役立ちます。

### ポッドの起動レイテンシー
<a name="_pod_startup_latency"></a>

この SLO は主に、Pod の作成からその Pod 内のコンテナが実際に実行を開始するまでの時間に関係します。これを測定するために、Pod に記録された作成タイムスタンプとの差を測定し、[その Pod の WATCH ](https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes)がコンテナの開始をレポートすると、コンテナが計算されます (コンテナイメージのプル時間と初期化コンテナの実行時間を除く）。SLO を満たすには、このポッド起動レイテンシーのクラスター日あたりの 99 パーセンタイルが <=5 秒のままである必要があります。

この SLO は、このクラスターにワーカーノードが既に存在しており、ポッドをスケジュールする準備が整っていることを前提としていることに注意してください。この SLO は、イメージのプルや初期化コンテナの実行を考慮しておらず、永続的ストレージプラグインを活用しない「ステートレスポッド」にテストを制限します。

## Kubernetes SLI メトリクス
<a name="_kubernetes_sli_metrics"></a>

Kubernetes は、これらの SLIs を経時的に追跡する Kubernetes コンポーネントに [Prometheus メトリクス](https://prometheus.io/docs/concepts/data_model/)を追加することでSLIs に関するオブザーバビリティも改善しています。[Prometheus クエリ言語 (PromQL)](https://prometheus.io/docs/prometheus/latest/querying/basics/) を使用すると、Prometheus や Grafana ダッシュボードなどのツールで SLI パフォーマンスを経時的に表示するクエリを構築できます。以下に、上記の SLOs の例をいくつか示します。

### API サーバーリクエストのレイテンシー
<a name="_api_server_request_latency"></a>


| メトリクス | 定義 | 
| --- | --- | 
|  apiserver\$1request\$1sli\$1duration\$1seconds  |  動詞、グループ、バージョン、リソース、サブリソース、スコープ、コンポーネントごとのレスポンスレイテンシー分布 (ウェブフック期間と優先度と公平性キューの待機時間はカウントされません）。  | 
|  apiserver\$1request\$1duration\$1seconds  |  verb、dry run 値、グループ、バージョン、リソース、サブリソース、スコープ、コンポーネントごとの、秒単位の応答遅延分布。  | 

**注記**  
`apiserver_request_sli_duration_seconds` メトリクスは Kubernetes 1.27 以降で使用できます。

これらのメトリクスを使用して、API Server の応答時間と、Kubernetes コンポーネントや他のプラグイン/コンポーネントにボトルネックがあるかどうかを調査できます。以下のクエリは[、コミュニティ SLO ダッシュボード](https://github.com/kubernetes/perf-tests/tree/master/clusterloader2/pkg/prometheus/manifests/dashboards)に基づいています。

 **API リクエストレイテンシー SLI (変更)** - 今回は、ウェブフックの実行やキューでの待機時間*は含まれません*。 `histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"CREATE|DELETE|PATCH|POST|PUT", subresource!~"proxy|attach|log|exec|portforward"}[5m])) by (resource, subresource, verb, scope, le)) > 0`

 **API リクエストレイテンシー合計 (変更)** - これはリクエストが API サーバーにかかった合計時間です。ウェブフック実行と API Priority and Fairness 待機時間が含まれているため、この時間は SLI 時間よりも長くなる可能性があります。 `histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"CREATE|DELETE|PATCH|POST|PUT", subresource!~"proxy|attach|log|exec|portforward"}[5m])) by (resource, subresource, verb, scope, le)) > 0`

これらのクエリでは、 `kubectl port-forward`や リクエスト (`subresource!~"proxy|attach|log|exec|portforward"`) など、すぐに返されないストリーミング API `kubectl exec`リクエストを除外し、オブジェクトを変更する Kubernetes 動詞 () のみをフィルタリングします`verb=~"CREATE|DELETE|PATCH|POST|PUT"`。次に、過去 5 分間のレイテンシーの 99 パーセンタイルを計算します。

読み取り専用 API リクエストに同様のクエリを使用できます。フィルタリングする動詞を変更して、読み取り専用アクション `LIST`と を含めるだけです`GET`。1 つのリソースの取得や多数のリソースの一覧表示など、リクエストの範囲に応じて異なる SLO しきい値もあります。

 **API リクエストレイテンシー SLI (読み取り専用)** - 今回は、ウェブフックの実行やキューでの待機時間*は含まれません*。単一のリソースの場合 (scope=resource、 threshold=1s) `histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"GET", scope=~"resource"}[5m])) by (resource, subresource, verb, scope, le))` 

同じ名前空間内のリソースのコレクション (scope=namespace、 threshold=5s) `histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"LIST", scope=~"namespace"}[5m])) by (resource, subresource, verb, scope, le))` 

クラスター全体のリソースのコレクションの場合 (スコープ = クラスター、しきい値 = 30 秒) `histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"LIST", scope=~"cluster"}[5m])) by (resource, subresource, verb, scope, le))` 

 **API リクエストレイテンシー合計 (読み取り専用)** - これはリクエストが API サーバーにかかった合計時間であり、ウェブフックの実行と待機時間が含まれているため、この時間は SLI 時間よりも長くなる可能性があります。単一のリソースの場合 (scope=resource、 threshold=1s) `histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"GET", scope=~"resource"}[5m])) by (resource, subresource, verb, scope, le))` 

同じ名前空間内のリソースのコレクションの場合 (スコープ = 名前空間、しきい値 = 5s) `histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"LIST", scope=~"namespace"}[5m])) by (resource, subresource, verb, scope, le))` 

クラスター全体のリソースのコレクションの場合 (スコープ = クラスター、しきい値 = 30 秒) `histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"LIST", scope=~"cluster"}[5m])) by (resource, subresource, verb, scope, le))` 

SLI メトリクスは、API Priority キューと Fairness キューでのリクエストの待機時間、アドミッションウェブフック、またはその他の Kubernetes 拡張機能の使用時間を除外することで、Kubernetes コンポーネントのパフォーマンスに関するインサイトを提供します。合計メトリクスは、アプリケーションが API サーバーからのレスポンスを待っている時間を反映するため、より包括的なビューを提供します。これらのメトリクスを比較すると、リクエスト処理の遅延が発生する場所を把握できます。

### ポッドの起動レイテンシー
<a name="_pod_startup_latency_2"></a>


| メトリクス | 定義 | 
| --- | --- | 
|  kubelet\$1pod\$1start\$1sli\$1duration\$1seconds  |  ポッドの作成タイムスタンプからすべてのコンテナが開始と報告され、監視によって観測されるまでに測定される、イメージをプルして init コンテナを実行する時間を除く、ポッドを開始するまでの秒単位の期間  | 
|  kubelet\$1pod\$1start\$1duration\$1seconds  |  kubelet がポッドを初めて確認してからポッドの実行が開始されるまでの秒単位の期間。これには、ポッドをスケジュールしたり、ワーカーノード容量をスケールアウトしたりする時間は含まれません。  | 

**注記**  
 `kubelet_pod_start_sli_duration_seconds` は Kubernetes 1.27 以降で利用可能です。

上記のクエリと同様に、これらのメトリクスを使用して、ノードスケーリング、イメージプル、初期化コンテナが Kubelet アクションと比較してポッドの起動を遅らせている時間に関するインサイトを得ることができます。

 **ポッドの起動レイテンシー SLI -** これは、ポッドが作成されてからアプリケーションコンテナが実行中と報告されるまでの時間です。これには、ワーカーノードの容量が利用可能になり、ポッドがスケジュールされるまでにかかる時間が含まれますが、イメージのプルや init コンテナの実行にかかる時間は含まれません。 `histogram_quantile(0.99, sum(rate(kubelet_pod_start_sli_duration_seconds_bucket[5m])) by (le))`

 **ポッドの起動レイテンシー合計 -** これは、kubelet がポッドを初めて起動するのにかかる時間です。これは、kubelet が WATCH 経由でポッドを受信したときから測定されます。これには、ワーカーノードのスケーリングまたはスケジューリングの時間は含まれません。これには、実行するイメージと初期化コンテナをプルする時間が含まれます。 `histogram_quantile(0.99, sum(rate(kubelet_pod_start_duration_seconds_bucket[5m])) by (le))`

## クラスターSLOs
<a name="_slos_on_your_cluster"></a>

EKS クラスター内の Kubernetes リソースから Prometheus メトリクスを収集している場合は、Kubernetes コントロールプレーンコンポーネントのパフォーマンスに関するより深いインサイトを得ることができます。

[パフォーマンステストリポジトリ](https://github.com/kubernetes/perf-tests/)には、テスト中のクラスターのレイテンシーと重要なパフォーマンスメトリクスを表示する Grafana ダッシュボードが含まれています。perf-tests 設定は、Kubernetes メトリクスを収集するように設定されたオープンソースプロジェクトである [kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) を活用しますが、[Amazon Managed Prometheus と Amazon Managed Grafana を使用することもできます。](https://aws-observability.github.io/terraform-aws-observability-accelerator/eks/)

`kube-prometheus-stack` または同様の Prometheus ソリューションを使用している場合は、同じダッシュボードをインストールしてクラスターの SLOs をリアルタイムで監視できます。

1. まず、 でダッシュボードで使用される Prometheus ルールをインストールする必要があります`kubectl apply -f prometheus-rules.yaml`。ルールのコピーは、https://github.com/kubernetes/perf-tests/blob/master/clusterloader2/pkg/prometheus/manifests/prometheus-rules.yaml からダウンロードできます。

   1. ファイルの名前空間が環境と一致することを確認してください。

   1. を使用している場合は、ラベルが `prometheus.prometheusSpec.ruleSelector` helm 値と一致することを確認します。 `kube-prometheus-stack`

1. その後、Grafana にダッシュボードをインストールできます。生成する JSON ダッシュボードと Python スクリプトは、https://github.com/kubernetes/perf-tests/tree/master/clusterloader2/pkg/prometheus/manifests/dashboards から入手できます。

   1.  [`slo.json` ダッシュボード](https://github.com/kubernetes/perf-tests/blob/master/clusterloader2/pkg/prometheus/manifests/dashboards/slo.json)には、Kubernetes SLOs

SLOs はクラスター内の Kubernetes コンポーネントのパフォーマンスに焦点を当てていますが、クラスターにさまざまな視点やインサイトを提供する追加のメトリクスを確認できます。[Kube-state-metrics](https://github.com/kubernetes/kube-state-metrics/tree/main) などの Kubernetes コミュニティプロジェクトは、クラスターの傾向をすばやく分析するのに役立ちます。Kubernetes コミュニティの最も一般的なプラグインとドライバーも Prometheus メトリクスを出力するため、オートスケーラーやカスタムスケジューラなどのことを調査できます。

[オブザーバビリティのベストプラクティスガイド](https://aws-observability.github.io/observability-best-practices/guides/containers/oss/eks/best-practices-metrics-collection/#control-plane-metrics)には、さらなるインサイトを得るために使用できる他の Kubernetes メトリクスの例が記載されています。