API Aggregationを有効化してPrometheusのメトリクスからHorizonPodAutoscalerでPodのオートスケールをする
やたら長いタイトルですが…
KubernetesではAPI Aggregationといって、Custom Metrics API Serverを用意しkube-apiserver
と連携することでAPIを拡張することができます。例えば今回のタイトルにもある通り、Prometheusが取得したメトリクスをAPIから取得できるようにすることができます。この記事では以下を可能とするKubernetesの設定を説明します。
API Aggregationの有効化
API Aggregationを有効化するにはkube-apiserver
とkube-controller-manager
に設定が必要になります。
まず、kube-controller-manager
に以下のオプションを設定して再起動します。
--horizontal-pod-autoscaler-use-rest-clients=true
次にkube-apiserver
の認証方式において、x509証明書認証を有効化するために、CA証明書を用意します。CA証明書のファイルパスを/etc/kubernetes/certs/ca.crt
とします。
さらにkube-apiserver
とCustom Metrics API Serverとが連携するために使うクライアント証明書と秘密鍵、そしてクライアント証明書の署名に使ったCAのCA証明書を用意します。それぞれのファイルパスを/etc/kubernetes/certs/proxy-client.crt
、/etc/kubernetes/certs/proxy-client.key
、/etc/kubernetes/certs/proxy-ca.crt
とします。
その後kube-apiserver
に以下のオプションを設定します
--client-ca-file=/etc/kubernetes/certs/ca.crt --requestheader-client-ca-file=/etc/kubernetes/certs/proxy-ca.crt --requestheader-allowed-names='' --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --proxy-client-cert-file=/etc/kubernetes/certs/proxy-client.crt --proxy-client-key-file=/etc/kubernetes/certs/proxy-client.key
最後にkube-apiserver
の再起動を行うのですが、もし既に--client-ca-file
の値を指定していて今回CA証明書を変更する場合、既にAPIサーバ間連携に使用するConfigMap extension-apiserver-authentication
ができてしまっているので、これをあらかじめ削除しておきます。
kubectl -n kube-system delete configmap extension-apiserver-authentication
その後、kube-apiserver
を再起動します。
これでAPI Aggregationの設定は完了です。
Prometheus用のCustom Metrics API Serverの構築とkube-apiserverとの連携
Prometheus用のCustom Metrics API Serverを構築し、kube-apiserverにAPIエンドポイントを作成してkube-apiserver
とCustom Metrics API Serverとを連携させます。
前提条件として名前空間kube-system
にPrometheusは構築済みであるとします。ここではPrometheusサーバ(port: 9090)のホスト名をprometheus-server
であるとします。
まずはCustom Metrics API Serverを構築するためのKubernetes Manifestをダウンロードします。
git clone https://github.com/DirectXMan12/k8s-prometheus-adapter cd k8s-prometheus-adapter
ダウンロードしてきたManifestの中にあるPrometheusサーバの指定を変更します。
sed -i 's/prometheus.prom.svc:9090/prometheus-server/g' deploy/manifests/custom-metrics-apiserver-deployment.yaml
また、Manifest内でリソースを作成する名前空間をkube-system
に変更します。
sed -i 's/namespace: custom-metrics/namespace: kube-system/g' deploy/manifests/*
さらにPullしてくるCustom Metrics API Serverコンテナイメージのタグを付与します。
sed -i 's/directxman12\/k8s-prometheus-adapter/directxman12\/k8s-prometheus-adapter:advanced-config/g' deploy/manifests/custom-metrics-apiserver-deployment.yaml
次にCustom Metrics API Serverのサーバ証明書と秘密鍵を作成します。ファイル名はそれぞれserving.crt
、serving.key
とします。
作成したサーバ証明書と秘密鍵を使用してSecret cm-adapter-serving-certs
を作成します。
kubectl -n kube-system create secret generic --from-file=serving.crt=serving.crt --from-file=serving.key=serving.key cm-adapter-serving-certs
最後にCustom Metrics API Serverを構築します。
kubectl create -f deploy/manifests/
構築がうまくいっていれば、APIを叩くと以下のような出力が得られると思います。
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [ { "name": "pods/fs_sector_writes", "singularName": "", "namespaced": true, "kind": "MetricValueList", "verbs": [ "get" ] }, <中略> { "name": "jobs.batch/kube_pod_status_phase", "singularName": "", "namespaced": true, "kind": "MetricValueList", "verbs": [ "get" ] } ] }
PrometheusのメトリクスからPodをオートスケールする
では実際に構築したCustom Metrics API Serverを使ってオートスケールを実現してみましょう。 まずはテスト用にDeployment、Serviceを作ります。
kubectl create deploy httpd --image httpd kubectl expose deploy httpd --port 80 kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd ClusterIP 172.16.132.62 <none> 80/TCP 10s kubernetes ClusterIP 172.16.0.1 <none> 443/TCP 56m
次にHorizontalPodAutoScalerをDeployment httpd
に対して作ります。
cat << EOF > hpa-httpd.yaml apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: httpd namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: httpd minReplicas: 1 maxReplicas: 8 metrics: - type: Pods pods: metricName: cpu_usage targetAverageValue: 1m EOF kubectl create -f hpa-httpd.yaml
HPAが作成出来たら、以下のスクリプトを実行してPodに負荷をかけます。
cat << EOF > hpa-test.sh #!/bin/sh count=1 while(true) do curl http://172.16.132.62 > /dev/null 2>&1 & echo access count = \$((count++)) done EOF chmod 755 hpa-test.sh ./hpa-test.sh
するとPodが増えていく様が見て取れるはずです。