はじめに
独自メトリクスによるPodの水平スケール では独自メトリクスの種類と、設定方法、そして独自メトリクスを提供するためのAPIサーバをいくつか紹介しました。今回は、その1つであるPrometheus Adapterの概要と、これを利用したPodのオートスケールについて紹介します。
Prometheus Adapterとは
Prometheus Adapter1は、その名の通りPrometheusの任意のメトリクスをカスタム・外部メトリクスとして利用するためのAPIサーバです。また、現在はDirectXManの個人リポジトリで開発されていますが、現在kubernetes-sigsへの移行作業が進んでおり2、Kubernetes公式リポジトリの1つとなる予定です。
上の図は、Prometheus Adapterの大まかな構成です。Prometheus Adapterは、KubernetesとPrometheusの間をつなぐアダプターとしての役割を持っています。ConfigMapで設定したカスタムメトリクスのルールに合わせ、実際のメトリクスをPrometheusから取得し、メトリクスAPIフォーマットに合わせて値を整形・公開します。
インストール方法
Prometheus Adapterはインストール用のHelm Chart3を提供しています。Prometheusサーバのアドレスやこのあと説明するメトリクスのルールなど、各種設定はHelmのValuesファイル4から変更できます。各環境に合わせて修正してください。
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
$ helm repo update
$ helm install --name my-release prometheus-community/prometheus-adapter
正常に起動していれば、以下のようにカスタムメトリクスAPIのレスポンスが返ります。(メトリクスのルール設定に応じてresources
配列の中身は異なります。)
$ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"custom.metrics.k8s.io/v1beta1","resources":[]}
カスタムメトリクスのルール設定
次の順序つきリストはPrometheus Adapterの処理内容とその順序を示しています。まず、Prometheusから該当のメトリクスが存在するかを確認し、存在すれば実際のKubernetesリソースと紐づけます。そして、それをメトリクスAPIとして公開します。
- Discovery: 有効なメトリクスの確認
- Association: メトリクスとKubernetesリソースとの紐づけ
- Naming: カスタムメトリクスAPIとして公開するための名前づけ
- Quering: Prometheusからメトリクスを取得するためのクエリ実行
カスタムメトリクスの設定はConfigMapにconfig.yamlとして保存します。config.yamlのフォーマットは、先程説明したのPrometheus Adapterの動作に合わせ、大まかに4つに分かれています。また、ルールは複数個設定可能です。
rules:
# Discovery: Discovery対象のSeriesを指定する (関数は使えない)
- seriesQuery: 'http_request_duration_seconds_bucket{deploy_namespace!="",deploy_name!=""}'
# Association: メトリクスをマッピングするリソース設定、APIのパスになる
resources:
overrides:
deploy_name: {resource: "deployment", group: "apps"}
deploy_namespace: {resource: "namespace"}
# Naming: メトリクス名として公開する名前
name:
as: 'http_request_per_seconds'
# Quering: 公開するメトリクスをPrometheusから取得するためのクエリ
metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'
読み取り権限の付与
Prometheus AdapterにはPod以外のリソースの参照権限が付与されていないため、カスタムメトリクスに他のリソースを設定した場合は権限の付与が必要です。 読み取りリソースの権限はprometheus-adapter-resource-reader
というClusterRoleに定義されているので、ここに必要な設定を追加してください。例えば、Deploymentの参照権限を追加したい場合は以下のとおりです。
- apiGroups:
- "apps"
resources:
- deployments
verbs:
- get
- list
- watch
困ったときは
設定を間違えているとメトリクスAPIは空のresources配列を返します。Prometheus Adapterのリポジトリにもよくresourcesが空になるというIssueが作られていますが、多くの場合ユーザの設定ミスです。以下の点に注意して設定を見直しましょう。
- Prometheus AdapterのPodが正常に起動しており、エラーログを吐いていないか
- SeriesQueryに関数を使ってないか
- Namingで利用するラベルがメトリクスに含まれているか
- Prometheusでも該当のクエリ結果が正常に返るか
- 該当リソースを取得する権限がRBACで付与されているか
設定したカスタムメトリクスの確認
すべての設定が正常に完了すれば、設定したカスタムメトリクスAPIを叩くことができます。kubectl get
からAPIのルートを叩くと、登録されているカスタムメトリクスの一覧が表示されます。
$ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "namespaces/http_request_per_seconds",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "service/http_request_per_seconds",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
またnamespaceにはワイルドカード(*
)を使えませんが、nameには次のようにワイルドカードを利用できます。レスポンスのvalueは、このときのメトリクス値です。
$ kubectl get --raw '/apis/custom.metrics.k8s.io/v1beta1/namespaces/test_namespace/deployments.apps/*/http_request
_per_seconds'|jq
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {
"selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/test_namespace/deployments.apps/%2A/http_request_per_seconds"
},
"items": [
{
"describedObject": {
"kind": "Deployment",
"namespace": "test_namespace",
"name": "testapp",
"apiVersion": "apps/v1"
},
"metricName": "http_request_per_seconds",
"timestamp": "2020-11-22T08:40:47Z",
"value": "68",
"selector": null
}
]
}
カスタムメトリクスを使ったHPAの動作確認
カスタムAPIが正常に値を返すようになれば後はHPAにカスタムメトリクスを設定するだけです。(詳細な設定方法は前回の記事を参照してください。) 次のマニフェストは、HPAにhttp_request_per_seconds
というカスタムメトリクスを設定した例です。
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
name: testapp
spec:
scaleTargetRef:
kind: Deployment
name: testapp
metrics:
# Pod以外のカスタムメトリクスはObject
- type: Object
object:
describedObject:
apiVersion: apps/v1
kind: Deployment
name: testapp
metric:
name: http_request_per_seconds # カスタムメトリクス名
target:
type: Value # Value
value: "100" # しきい値
作成したHPAリソースを取得すると、.status.conditions
のScalingActive
タイプから正常にカスタムメトリクスが設定できるていることが確認できます。またheyコマンドあたりで負荷をかけると、しきい値を超えたところでスケールアウトしていることが確認できます。
$ kubectl get hpa.v2beta2.autoscaling testapp -n test_namespace -o yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
...
metrics:
- object:
describedObject:
apiVersion: apps/v1
kind: Deployment
name: testapp
metric:
name: http_request_per_seconds
target:
type: Value
value: "100"
type: Object
...
status:
conditions:
- lastTransitionTime: "2020-11-22T07:42:03Z"
message: the HPA was able to successfully calculate a replica count from object
metric http_request_per_seconds
reason: ValidMetricFound
status: "True"
type: ScalingActive
...
おわりに
今回は、まもなくkubernetes-sigsに取り込まれるであろうPrometheus Adapterについて解説しました。また、インストールのためのHelm Chartも、公式Stable Chartsリポジトリのアーカイブに合わせ既にPrometheus Communityに移管されています。メトリクス管理にPrometheusを利用している方にとっては、HPAカスタムメトリクスを利用する際の良い選択肢になるかと思います。
-
DirectXMan12/k8s-prometheus-adapter: An implementation of the custom.metrics.K8s.io API using Prometheus ↩
-
Migrate DirectXMan12/k8s-prometheus-adapter to kubernetes-sigs · Issue #2182 · kubernetes/org ↩
-
helm-charts/charts/prometheus-adapter at main · prometheus-community/helm-charts ↩
-
https://github.com/prometheus-community/helm-charts/blob/main/charts/prometheus-adapter/values.yaml ↩