OpenShiftでメモリでオートスケールをしてみる
OpenShift 全部俺 Advent Calendar 2017
まだAlpha機能ですが、CPUではなくメモリ利用量でオートスケールを設定することができます。
https://docs.openshift.org/3.11/dev_guide/pod_autoscaling.html#pod-autoscaling-memory
先に重要な点を書いておきますが、このメモリ利用量とはcgroupsのmemory.usage_in_bytes
であり、これはbuff/cacheを含みます。実際には解放できるディスクキャッシュなども使用中としてレポートされ、キャッシュが活用されている限りメモリ利用は常に高い状態をキープし、オートスケールであまり意味もなくPodが増えることになるので、メモリベースのオートスケールは現状あまり使い物にならないと思います。
追記: 上記記述は古いものであり、OpenShift 3.11以降など新しいバージョンはメモリ量としてmemory.usage_in_bytes
ではなくより一般的な利用量と呼ぶのにふさわしい値であるWorking set (memory.stat.rss + memory.stat.cache - memory.stat.inactive_file
) を返却するのでメモリオートスケールも普通に利用できます。
まずはドキュメントの通り以下の設定をmaster-config.yamlへ反映してmasterを再起動します。
apiServerArguments: runtime-config: - apis/autoscaling/v2alpha1=true
いつものRubyのサンプルを作成してrequests.memoryに64Miを指定します。
$ oc new-project test-memhpa $ oc new-app https://github.com/nekop/hello-sinatra $ oc set resources dc/hello-sinatra --requests=memory=64Mi $ cat <<EOF | oc create -f - apiVersion: autoscaling/v2alpha1 kind: HorizontalPodAutoscaler metadata: name: hpa-memory spec: scaleTargetRef: apiVersion: apps/v1 kind: DeploymentConfig name: hello-sinatra minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: memory targetAverageUtilization: 50 EOF
作成したHPAを再度取得するとAlpha機能であるため内容のほとんどは以下のようにアノテーション内に格納されていることがわかります。
$ oc get hpa hpa-memory -o yaml apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: annotations: autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2017-12-25T02:36:07Z","reason":"ReadyForNewScale","message":"the last scale time was sufficiently old as to warrant a new scale"},{"type":"ScalingActive","status":"True","lastTransitionTime":"2017-12-25T02:36:07Z","reason":"ValidMetricFound","message":"the HPA was able to succesfully calculate a replica count from memory resource utilization (percentage of request)"},{"type":"ScalingLimited","status":"False","lastTransitionTime":"2017-12-25T02:36:07Z","reason":"DesiredWithinRange","message":"the desired replica count is within the acceptible range"}]' autoscaling.alpha.kubernetes.io/current-metrics: '[{"type":"Resource","resource":{"name":"memory","currentAverageUtilization":24,"currentAverageValue":"16576512"}}]' autoscaling.alpha.kubernetes.io/metrics: '[{"type":"Resource","resource":{"name":"memory","targetAverageUtilization":50}}]' creationTimestamp: 2017-12-25T02:35:37Z name: hpa-memory namespace: test-memhpa resourceVersion: "4241124" selfLink: /apis/autoscaling/v1/namespaces/test-memhpa/horizontalpodautoscalers/hpa-memory uid: 4a2e8f4e-e91c-11e7-b3cf-001a4a40dc83 spec: maxReplicas: 10 minReplicas: 1 scaleTargetRef: apiVersion: apps/v1 kind: DeploymentConfig name: hello-sinatra status: currentReplicas: 1 desiredReplicas: 1
初期状態はメモリ16Mi利用しています。
$ oc adm top pod NAME CPU(cores) MEMORY(bytes) hello-sinatra-2-d9ft8 0m 16Mi
32MBのファイルを作ってcatしてディスクキャッシュに載せてみます。
$ oc rsh dc/hello-sinatra sh -c "dd if=/dev/zero of=/tmp/32mb bs=32M count=1; cat /tmp/32mb"
少し経過すると、メトリクスに反映されました。
$ oc adm top pod NAME CPU(cores) MEMORY(bytes) hello-sinatra-2-d9ft8 5m 48Mi
HPAによるスケールアウトがトリガーされ、Podが2つに増えました。
$ oc get pod NAME READY STATUS RESTARTS AGE hello-sinatra-2-b9hxt 1/1 Running 0 16s hello-sinatra-2-d9ft8 1/1 Running 0 5m $ oc adm top pod NAME CPU(cores) MEMORY(bytes) hello-sinatra-2-d9ft8 0m 48Mi hello-sinatra-2-b9hxt 0m 15Mi
動作に必要なメモリが足りなくなりそうな場合にスケールアウト、というのが欲しいところですが、今のところはこのように動作に不可欠ではない解放されるメモリもカウントされてオートスケールされてしまいますので、使い道はかなり限定されそうです。