Wavefrontで学ぶHorizontal Pod Autoscaler Part-3

この文章は、Wavefrontで学ぶHorizontal Pod Autoscaler シリーズの第三回目です。

シリーズ

第一回 : 概要編
第二回 : Wavefront情報からスケールする
第三回 : サーバーレスもどきを実装する ← いまここ

始めに

前回の前提知識にもあったよう、Kubernetesは、HPAとして3つのAPIをサポートしています。

その中で、Wavefrontはexternal.metrics.k8s.ioを使った自由度の高いメトリクスの定義をサポートしています。

以下により詳細の説明があります。

https://github.com/wavefrontHQ/wavefront-kubernetes-adapter/blob/master/docs/introduction.md#externalmetricsk8sio

ここでのポイントが実質Wavefrontのメトリクスをどれでもつかって自由にHPAができるというものです。 今回はこれをつかって、「サーバーレスもどき」のアプリケーションを作ってみます。

検証方法

今回は以下の図示されているような構成で検証します。

つまり、Kubernetesとは別に稼働しているWebアプリ(/counter)に対して、リクエストを送信してスケールアップをするような構成です。特にリクエストがやってこない場合、徐々にスケールダウンしていきます。

なお、「サーバーレスもどき」と書いたわりに、必ず最低1つのPodが常に起動し続けます。 これは、HPAScaleToZeroとよばれるHPAのminインスタンスの値0を許可するが、執筆時点でまだAlphaの実装であり、GAとされていないためです。

https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features

これがGAされれば、より「サーバーレスもどき」に近づくのですが、今回は諦めます。

準備

前回の準備編インストールを参照してください。

アプリの準備

今回は、すでに持っているWavefrontのアカウントに対してMetricsを送付するようなアプリケーションを書きます。様々な方法がありますが、ここでは一番手っ取り早いSpring Bootを使ったアプリを作ります。

なお以下のアプリはWavefrontにアクセスできる端末であればどこで起動しても問題ないです。PC上でもいいです。最低限OpenJDKがインストールされている必要があります。

https://github.com/mhoshi-vm/wf-demanabu-hpa

このレポジトリーをクローンします。

1git clone https://github.com/mhoshi-vm/wf-demanabu-hpa
2cd wf-demanabu-hpa

そして以下のファイルを編集します。

1vi src/main/resources/application.properties

中身はWavefrontのアカウントとAPIキーを登録してください。

1wavefront.freemium-account=false
2management.metrics.export.wavefront.uri=https://<account>.wavefront.com
3management.metrics.export.wavefront.api-token=<API key>

準備ができたら起動します。

1./mvnw spring-boot:run

ただしく起動されたら、別のプロンプトでしばらく、URLへリクエストを送信します。

1curl localhost:8080/counter

Count Completeと出れば問題ないです。

この状態でWavefrontのUIにログインします。 そして以下のQueryを実行します。

1mdiff(5m, ts(custom.metrics.counter))

すると以下のように、curlを実行した回数分、5分間停滞するような画面になっていればOKです。

アプリは起動したままで次のステップに移ります。

HPAの準備

前回のゴミ掃除も兼ねて、作業用のネームスペースを再作成します。

1kubectl delete ns hpa
2kubectl create ns hpa

KubernetesのDeploymentを作成します。

1kubectl create deployment --image=nginx hpa-pods -n hpa

そして、今回は以下のHPAを作ります。

 1cat <<EOF | kubectl apply -n hpa -f -
 2apiVersion: autoscaling/v2beta1
 3kind: HorizontalPodAutoscaler
 4metadata:
 5  name: example-hpa-external-metrics
 6  annotations:
 7    wavefront.com.external.metric/scale_counter: 'mdiff(5m, ts(custom.metrics.counter))'
 8spec:
 9  minReplicas: 1
10  maxReplicas: 5
11  metrics:
12  - type: External
13    external:
14      metricName: scale_counter
15      targetAverageValue: 1
16  scaleTargetRef:
17    apiVersion: apps/v1
18    kind: Deployment
19    name: hpa-pods
20EOF

キモがいかです。

  • 参照したいメトリクスをAnnotationをつかって表現している。この場合は、wavefront.com.external.metric/scale_counter: 'mdiff(5m, ts(custom.metrics.counter))'
  • spec.metricsをAnnotationで指定した名前を定義します。この場合はscale_counter

定義としてはこれだけです、作成されたHPAをみてみましょう

1kubectl get hpa -n hpa
2NAME                           REFERENCE             TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
3example-hpa-external-metrics   Deployment/hpa-pods   0/1 (avg)   1         5         1          25m

この状態で、curl localhost:8080/counterを3回実行します。 しばらくするとTARGETSの値がCurlを実行した1に近い値に落ち着くと思います。またReplica数も3になります。

1kubectl get hpa -n hpa
2NAME                           REFERENCE             TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
3example-hpa-external-metrics   Deployment/hpa-pods   967m/1 (avg)   1         5         3          26m

これは、つまりPodに対する平均値が計算され、3(curlの回数) / 3(podの値) = 1となっているためです。

そして、5分後、また0になり、ゆっくりReplica数も1に近づいていくと思います。

1kubectl get hpa -n hpa
2NAME                           REFERENCE             TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
3example-hpa-external-metrics   Deployment/hpa-pods   0/1 (avg)   1         5         1          35m

まとめ

  • Wavefrontのexternal.metrics.k8s.ioを使えばどんなメトリクスをつかってもHPAができます。

全三回のシリーズから、Wavefront + HPAの実装がシンプルに実現できることが体験できました。