ビビリフクロウの足跡

いつもお世話になっているインターネットへの恩返し

API Aggregationを有効化してPrometheusのメトリクスからHorizonPodAutoscalerでPodのオートスケールをする

やたら長いタイトルですが…

KubernetesではAPI Aggregationといって、Custom Metrics API Serverを用意しkube-apiserverと連携することでAPIを拡張することができます。例えば今回のタイトルにもある通り、Prometheusが取得したメトリクスをAPIから取得できるようにすることができます。この記事では以下を可能とするKubernetesの設定を説明します。

  • API Aggregationの有効化
  • Prometheus用のCustom Metrics API Serverの構築とkube-apiserverとの連携

API Aggregationの有効化

API Aggregationを有効化するにはkube-apiserverkube-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.crtserving.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が増えていく様が見て取れるはずです。