KubernetesでDatadog + Horizontal Pod Autoscalerをやってみた

KubernetesでDatadog + Horizontal Pod Autoscalerをやってみた:


概要


TL;DR

Datadogのmetricsを使ってHorizontal Pod Autoscalerを設定したらとても便利だった(設定も簡単だった)
https://www.datadoghq.com/blog/autoscale-kubernetes-datadog/


背景

KubernetesでHorizontal Pod Autoscalerを使っている人も多いと思いますが、どのような値を使ってAutoscalingしてますでしょうか?

我々も元々はCPUやメモリでやっていたのですが、段々満足できず色々なmetricsを使いたくなりました。custom metricsを利用可能なのでそちらを使おうと思ったのですが、調べるとPrometheusを使った方法が良く紹介されています。元々Prometheusを使っている人はPrometheusで良いですが、我々はそうではなかったのでHPAのためにPrometheus入れるのもなーと思い悩みました。

Custom Metrics APIの仕様は公開されているので自分で作ることも可能なのですが、結構手間なので決断できずにいました。
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/custom-metrics-api.md

さらに調べるとexternal metricsといって外部のmetricsを利用したHPAも設定可能なことが分かりました。我々のプロジェクトでは既にDatadogを導入していたため、Datadogのmetrics使えないかなという視点で調べ始めたところドンピシャのやり方がDatadogの公式で紹介されてました。
https://www.datadoghq.com/blog/autoscale-kubernetes-datadog/

なのでそれを使ってHPA設定してみたら簡単に出来てとても便利になったというのがこの記事の趣旨です。


詳細

上の記事に書いてあるとおりなので、その通りにやってもらえばよいのですが今回はさらに簡単なやり方を紹介しておきます。

DatadogをExternal Metrics Providerとして動かすためにはDatadog Cluster Agentの導入やAPIServiceの登録が必要です。

そのYAMLは以下でexampleが公開されているのでkubectl applyしていけば動くものが出来上がります。
https://github.com/DataDog/datadog-agent/tree/9ceedbd0efb1efbf4de3f1f6d9f34206f2928f5b/Dockerfiles/manifests/cluster-agent

Datadog Cluster Agentについては以下に説明が書いてあります。
https://docs.datadoghq.com/agent/kubernetes/cluster/

Datadogは通常nodeごとにagentがデプロイされますが、それだとクラスタのmetricsを取得するためにnodeのagentにk8s APIの権限を渡さないといけないし、Datadog Cluster Agentがいれば1つでクラスタの情報を取得すればいいから負荷も軽減されるということのようです。さらにHPAでDatadogのmetricsを使うときのmetrics APIサーバとしても動いてくれるようです(多分)。


Helm Chart

上にYAMLのリポジトリを貼りましたが、Helmであればオプションを渡すだけで導入可能です。
https://github.com/helm/charts/tree/master/stable/datadog#enabling-the-datadog-cluster-agent

$ helm install --name datadog-monitoring \ 
    --set datadog.apiKey=YOUR-API-KEY-HERE \ 
    --set datadog.appKey=YOUR-APP-KEY-HERE \ 
    --set clusterAgent.enabled=true \ 
    --set clusterAgent.metricsProvider.enabled=true \ 
    stable/datadog 
これだけでDatadog Cluster Agentもデプロイされ、APIServiceの登録等もされます。

つまりもうHPAが使える状態です!

$ kubectl get pods | grep datadog 
datadog-cluster-agent-74f88b78d6-t9nrl        1/1     Running     0          1h 
datadog-datadog-k9fdl                         1/1     Running     0          1h 
datadog-datadog-qqm42                         1/1     Running     0          1h 
datadog-kube-state-metrics-5db89d6d78-qzlgc   1/1     Running     0          1h 
datadog-cluster-agentがあればOKです。kube-state-metricsは既にデプロイ済みなので不要な人とかのためのオプションもありますし、他に細かい設定をしたい人はChartのオプションを見てみて下さい。


HPA

nginxのリクエスト数でAutoScalingする場合のexampleは以下にあります。
https://github.com/DataDog/datadog-agent/blob/9ceedbd0efb1efbf4de3f1f6d9f34206f2928f5b/Dockerfiles/manifests/cluster-agent/hpa-example/hpa-manifest.yaml

同じだと芸がないので、Redisのkey lengthでスケールしてみます。

我々のプロジェクトではCeleryというタスクキュー用のツールを使っています。

このツールではRedisをキューとして使うことが出来るのですが(SQSとかも使えます)、 celery というkeyでtaskを管理します。

つまりkey lengthがtask数を指します。今回はtask数が多い時にworkerをスケールさせたいというケースでやってみます。

デフォルトだとRedisのkey lengthが取得されないのでDatadog Agentの設定を少しいじります。values.yamlに以下のように設定します。

clusterAgent: 
  enabled: true 
  metricsProvider: 
    enabled: true 
 
datadog: 
  confd: 
    redisdb.yaml: |- 
      init_config: 
      instances: 
        - host: "redis.local" 
          port: 6379 
          keys: 
            - celery 
上のvalues.yamlを適用します。

$ helm upgrade -f values.yaml datadog-monitoring stable/datadog 
ここではRedisのhost名を指定してkeyの長さを取得するようにしています。Datadogの設定についてはここでは細かくは触れません。

Datadogの画面からmetrics: redis.key.lengthのtag: key:celeryで値が取得できていることを確認します。

無事に取得できていればあとはHPAの設定をするだけです。

apiVersion: autoscaling/v2beta1 
kind: HorizontalPodAutoscaler 
metadata: 
  name: celery-worker 
spec: 
  minReplicas: 2 
  maxReplicas: 5 
  scaleTargetRef: 
    apiVersion: apps/v1 
    kind: Deployment 
    name: celery-worker 
  metrics: 
  - type: External 
    external: 
      metricName: redis.key.length 
      metricSelector: 
        matchLabels: 
            key: celery 
      targetAverageValue: 4 
ここではcelery-workerというDeploymentのAutoScalingの設定をしています。

targetAverageValueは全Podの数で割った数がその値に近づくように動くという目標値です(自分の理解では)。

詳細はドキュメント見て下さい。
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details

上のYAMLをapplyしましょう。

$ kubectl apply -f hpa.yaml 
hpaの設定を見てみます。

$ kubectl get hpa 
NAME                         REFERENCE                   TARGETS             MINPODS   MAXPODS   REPLICAS   AGE 
celery-worker                Deployment/celery-worker    4/4 (avg)   2         5         2          1m 
今はキューに8つのtaskが登録されてる状態です。replicasが2のため、分子が8/2=4になっています。分母の4はtargetAverageValueの値。

もしこの状態で新たに4つtaskが登録されたとします(8+4=12)。そうすると以下のようになります。

$ kubectl get hpa 
NAME                         REFERENCE                   TARGETS             MINPODS   MAXPODS   REPLICAS   AGE 
celery-worker                Deployment/celery-worker    6/4 (avg)   2         5         2          2m 
今はPodが2つなので12/2=6になっています。

こうするとtargetAverageValueが4になるようにPodがAutoScalingされます。

そのため、Podが1つ増えます。そうすると12/3=4になるので以下のようになります。

$ kubectl get hpa 
NAME                         REFERENCE                   TARGETS             MINPODS   MAXPODS   REPLICAS   AGE 
celery-worker                Deployment/celery-worker    4/4 (avg)   2         5         3          5m 
replicasが3になっています。もしtaskの数が減ればscale-inされます。

ということで終わりです。

今回はRedisのkeyでやりましたが、SQSのメッセージ数でAutoScalingとかも可能ですし、ALBのレスポンスタイムとかを見て増やしたりとかも可能です。Datadogのmetricsが使えるとなると可能性は無限大です。


まとめ

Datadogのmetricsを使ってHorizontal Pod Autoscalerを設定したらとても便利だった(設定も簡単だった)

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)