本文の内容は、2019年12月18日にSysdigのCarlos Arillaが投稿したブログ(https://sysdig.com/blog/monitor-kubernetes-api-server/)を元に日本語に翻訳・再構成した内容となっております。
Kubernetes APIサーバーを監視する方法を学ぶことは、Kubernetesを運用環境で実行する際に非常に重要です。kube-apiserverを監視すると、待ち時間、エラーの検出およびトラブルシューティングを行い、期待どおりにサービスが実行されることを検証できます。kube-apiserverから最も重要なメトリクスを収集し、それらを使用してこのサービスを監視する方法を学ぶために是非ご一読いただければと思います。
Kubernetes APIサーバーは、Kubernetesコントロールプレーンの基本コンポーネントです。クラスター内で実行されているすべてのサービスは、このインターフェースを使用して相互に通信します。ユーザーインタラクション全体もAPIを介して処理されます。kubectlはAPIにリクエストを送信するラッパーです。kubectlはHTTPを使用してAPIサーバーに接続しますが、残りのコントロールプレーンコンポーネントはgRPCを使用します。 実は、両方のチャネルを監視する準備はすでに整っています。
他のマイクロサービスと同様に、Kubernetes APIサーバーの健全性とパフォーマンスを監視するためにゴールデンシグナルアプローチを採用します。
- レイテンシー
- リクエストレート
- エラー
- サチュレイション(飽和)
では、それぞれの意味を説明する前に、これらの指標を取得する方法を見ていきましょう。
kube-apiserverを監視するためのメトリクスの取得
APIサーバーはデフォルトでPrometheusメトリクスをは装備・公開しています。レイテンシ、リクエスト、エラー、etcdキャッシュステータスなどのモニタリングメトリクスを提供しています。このエンドポイントは簡単にスクレイピングでき、追加のスクリプトやエクスポーターを必要とせずに有用な情報を取得できます。
APIサーバーでは、/metricsエンドポイントへの要求を行うために認証が必要なので、そのための特権を持つ認証情報を取得する必要があります。クラスター内でPrometheusを実行している場合、ClusterRoleにバインドされたサービスアカウントを使用して認証し、GETリクエストを/metricsエンドポイントに許可します。
これは、Prometheusが使用するClusterRoleに1つのルールを追加することで実行できます。
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app: monitor component: server name: monitor rules: - nonResourceURLs: - /metrics verbs:
- get
このように、ポッド内の/var/run/secrets/kubernetes.io/serviceaccountにあるサービスアカウントからbearerトークンを使用して/metricsエンドポイントにアクセスできます。
Prometheusポッド内からこのシェルコマンドを実行して、認証をテストできます。
#curl https://kubernetes.default.svc/metrics -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -vvv --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Prometheusメトリクスの長いリストが返されます(ここでは省略されています)。
# TYPE APIServiceOpenAPIAggregationControllerQueue1_adds counter APIServiceOpenAPIAggregationControllerQueue1_adds 108089 # HELP APIServiceOpenAPIAggregationControllerQueue1_depth Current depth of workqueue: APIServiceOpenAPIAggregationControllerQueue1 # TYPE APIServiceOpenAPIAggregationControllerQueue1_depth gauge APIServiceOpenAPIAggregationControllerQueue1_depth 0 # HELP APIServiceOpenAPIAggregationControllerQueue1_queue_latency How long an item stays in workqueueAPIServiceOpenAPIAggregationControllerQueue1 before being requested. # TYPE APIServiceOpenAPIAggregationControllerQueue1_queue_latency summary APIServiceOpenAPIAggregationControllerQueue1_queue_latency{quantile="0.5"} 15
...
Kubernetes APIサーバーエンドポイントをスクレイプするようにPrometheusを構成するには、ターゲットに1つのジョブを追加します。
- job_name: 'kubernetes-apiservers' kubernetes_sd_configs: - role: endpoints scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep
regex: default;kubernetes;https
Kubernetes APIサーバーの監視:何を見るべきでしょうか?
ゴールデンシグナルを使用してKubernetes APIサーバーを監視できます。ゴールデンシグナルは、消費者(ここではkubectlユーザーと内部クラスターコンポーネント)に対するサービスのパフォーマンスに関する洞察を提供する多数のメトリクスを通じてサービスを監視するために使用される手法です。これらのメトリクスは、レイテンシー、リクエスト、エラー、およびサチュレイション(サーバーが現在のリソースで最大容量に向かってどれだけビジーであるか)です。
免責事項:APIサーバーのメトリクスはKubernetesのバージョンによって異なる場合があります。 ここでは、Kubernetes 1.15を使用しました。Kubernetesリポジトリ(1.15.3バージョンのリンク)で、ご使用のバージョンで利用可能なメトリクスを確認できます。
レイテンシー:レイテンシーは、apiserver_request_duration_secondsヒストグラムバケットから抽出できます。
# TYPE apiserver_request_latencies histogram apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="125000"} 2 apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="250000"} 2 apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="500000"} 2 apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="1e+06"} 2 apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="2e+06"} 2 apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="4e+06"} 2 apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="8e+06"} 2 apiserver_request_duration_seconds{resource="adapters",scope="cluster",subresource="",verb="LIST",le="+Inf"} 2 apiserver_request_duration_seconds_sum{resource="adapters",scope="cluster",subresource="",verb="LIST"} 50270
apiserver_request_duration_seconds_count{resource="adapters",scope="cluster",subresource="",verb="LIST"} 2
レイテンシの広がりを理解するには、パーセンタイルを使用することをお勧めします。
histogram_quantile(0.99, sum(rate(apiserver_request_latencies_count{job=\"kubernetes-apiservers\"}[5m])) by (verb, le))
リクエストレート:メトリクスapiserver_request_totalを使用して、サービスへの要求を、要求元、サービス、アクション、および成功したかどうかを監視できます。
# TYPE apiserver_request_count counter apiserver_request_total{client="Go-http-client/1.1",code="0",contentType="",resource="pods",scope="namespace",subresource="portforward",verb="CONNECT"} 4 apiserver_request_total{client="Go-http-client/2.0",code="200",contentType="application/json",resource="alertmanagers",scope="cluster",subresource="",verb="LIST"} 1 apiserver_request_total{client="Go-http-client/2.0",code="200",contentType="application/json",resource="alertmanagers",scope="cluster",subresource="",verb="WATCH"} 72082
apiserver_request_total{client="Go-http-client/2.0",code="200",contentType="application/json",resource="clusterinformations",scope="cluster",subresource="",verb="LIST"} 1
たとえば、次のようにサービス全体で成功したすべてのリクエストを取得できます。
sum(rate(apiserver_request_total{job=\"kubernetes-apiservers\",code=~\"2..\"}[5m]))
エラー:リクエストレートに使用したものと同じクエリを使用できますが、400および500のエラーコードをフィルタリングできます。
sum(rate(apiserver_request_total{job=\"kubernetes-apiservers\",code=~\"[45]..\"}[5m]))
サチュレーション:このサービスのCPU、メモリ、ネットワークI/Oなどのシステムリソース使用メトリクスによってサチュレーションを監視できます。
APIサーバー関連のメトリクスに加えて、他の関連するメトリクスにアクセスできます。 APIサーバーが提供するもの:
controller-managerから:
- ワークキューの追加率:コントローラーが実行する新しいアクションをスケジュールする速度。これらのアクションには、クラスター内のリソース(ワークロード、configmap、service...)の追加、削除、および変更を含めることができます。
- ワークキューの待ち時間:コントローラーマネージャーがこれらのアクションを実行する速度はどれくらいですか?
- ワークキューの深さ:実行を待機しているアクションの数。
etcdから:
- etcdキャッシュエントリ:いくつのクエリ結果がキャッシュされましたか?
- etcdキャッシュのヒット/ミス率:キャッシュは有用ですか?
- etcdキャッシュ期間:キャッシュ結果はどのくらいの期間保存されますか?
課題例
APIへのリクエストでレイテンシーの増加を検出します。
これは通常、APIサーバーの過負荷の兆候です。 おそらく、クラスターには多くの負荷がかかり、APIサーバーをスケールアウトする必要があります。
リクエストのタイプ、リソース、またはverbごとにメトリクスをセグメント化できます。これにより、問題の場所を検出できます。 たぶん、etcdの読み取りまたは書き込みに問題があり、修正する必要があります。
作業キューの深さと待ち時間の増加を検出します。
アクションのスケジューリングに問題があります。スケジューラが機能していることを確認する必要があります。一部のノードが過負荷になっていて、クラスターをスケールアウトする必要がある場合があります。 おそらく、1つのノードに問題があり、それを交換する必要があるかも知れません。
Sysdig MonitorでのKubernetes APIサーバーメトリクスの監視
Sysdig Monitorを使用してKubernetes APIサーバーにおけるPrometheusメトリクスを監視する場合は、Sysdigエージェントのyaml設定ファイルにいくつかのセクションを追加するだけです。
#Enable prometheus metrics metrics_filter: # beginning of kube-apiserver - include: "apiserver_request_total" - include: "apiserver_request_duration_seconds*" - include: "workqueue_adds_total" - include: "workqueue_depth" - include: "workqueue_queue_duration_seconds*" - include: "etcd_helper_cache_entry_total" - include: "etcd_helper_cache_hit_total" - include: "etcd_helper_cache_miss_total" - include: "etcd_request_cache_get_duration_seconds*" - include: "etcd_request_cache_add_duration_seconds*" - include: "go_goroutines" # end of kube-apiserver prometheus: enabled: true histograms: true max_metrics: 3000 max_metrics_per_process: 3000 process_filter: - include: kubernetes.pod.label.k8s-app: kube-apiserver port: 8080 conf: tags: kubernetes.component.name: kube-apiserver host: 127.0.0.1 port: 8080 use_https: false
auth_token_path: "/var/run/secrets/kubernetes.io/serviceaccount/token"
metrics_filter部分を使用すると、メトリクスの制限に達した場合にこれらのメトリクスが破棄されないようにできます。次のように、このリストにないAPIサーバーが提供する他のメトリクスを追加できます。
metrics_filter: - include: "apiserver_request_total" ...
- include: "go_goroutines"
次に、Sysdigエージェントがメトリクスをスクレイピングする方法を構成し、ラベルkube-apiserverを持つKubernetesポッドを検索し、ポート8080を介してlocalhostでスクレイピングします。Sysdigエージェントは、ネットワークコンテキストを切り替えて、そのままポッドに接続できるため ローカルホストでは、httpsを使用する必要はありません。また、メトリクスエンドポイントにアクセスするためにエージェントが使用する認証トークンを指定する必要があります。
prometheus: enabled: true ... process_filter: - include: kubernetes.pod.label.k8s-app: kube-apiserver port: 8080 conf: tags: kubernetes.component.name: kube-apiserver host: 127.0.0.1 port: 8080 use_https: false
auth_token_path: "/var/run/secrets/kubernetes.io/serviceaccount/token"
その後、これらのメトリクスを使用してカスタムダッシュボードを構築できます。 興味をお持ちの場合は、事前に作成したダッシュボードを共有できます。
まとめ
Kubernetes APIサーバーの監視は、クラスター操作の重要な部分であるため、基本です。 クラスターコンポーネント間のすべての通信は、kube-apiserverを介して行われます。
APIサーバーの問題を検出することは、Kubernetesクラスターの問題を修正するための重要な要素となります。コントロールプレーンコンポーネントで何が行われているかを認識し、問題が発生した場合にそれを活用する方法を学ぶ必要があります。
すべてのKubernetesコンポーネントを適切に監視することは、クラスター内で実行されているワークロードとアプリケーションを監視することと同じくらい重要です。コントロールプレーンを監視することを忘れないでください!