オートスケールの設計
GKE + k8sにおいて、オートスケールには2種類存在する。
- Horizontal Pod Autoscaling(水平Podオートスケール)
- Cluster Autoscaler
前者がPodをスケールさせ、後者がクラスタをスケールさせる。スケール速度はPodであれば一瞬、クラスタノードは起動までに30秒前後かかる。また、k8sの再起動がはいる。
CPUリソースなどの使用状況をk8sが監視し(デフォルト30秒)、設定されたオートスケール閾値を超えたら新しくPodをたてたり、クラスタを増やしたりする。当然、負荷が下がったら自動で減る。
戦略
基本は2つのオートスケールを組み合わせ使う感じが良いだろうと思う。
- Horizontal Pod Autoscaling・Cluster Autoscalerを設定
- 最小起動数は予測できるトラフィックに合わせる
- ノード数についてはデプロイ時のPod数も考慮に入れる
- 最小起動数は予測できるトラフィックに合わせる
- トラフィックが増加すると、まずPodが立ち上がる
- CPUリソースなどが足りずPodが起動できないと、ノードが立ち上がる
- 新規ノードにPodが立ち上がる
- トラフィックが減少すると、Podが減り、順次ノードも減る
- CPUリソースなどが足りずPodが起動できないと、ノードが立ち上がる
また、k8sの監視がデフォルトだと30秒間隔なので、トラフィックが増加してからスケールするまでに1分弱くらいのタイムラグがある。これが許容できない場合はk8sの設定を変更することで間隔を短くできるようだ(未検証)。
kube-controller-manager
の --deployment-controller-sync-period
オプションで設定できる。
設定方法
kubectl
コマンドを使った設定方法。
手動でPodの数を設定する
$ kubectl scale deployment <POD_NAME> --replicas=3
Horizontal Pod Autoscaling
CPUが70%以上使われていた場合、最大3個までPodをたてるという設定例。
$ kubectl autoscale deployment <POD_NAME> --cpu-percent=70 --min=1 --max=3
設定内容を修正したい場合は edit
でviが立ち上がるので、そこで値を修正する。
$ kubectl edit hpa <POD_NAME>
削除はこちら。
$ kubectl delete hpa <POD_NAME>
また、各ノードのCPUリソース利用状況を抜き出すコマンド例。 describe
がJSONをサポートしていないのでちょっとダルい。
$ kubectl describe nodes | grep % | grep -v kube-system | grep -v default
Cluster Autoscaler
オートスケールの設定は、ノードプールに設定する。
$ gcloud container clusters update <CLUSTER_NAME> --enable-autoscaling --min-nodes=3 --max-nodes=20 --node-pool <NODEPOOL_NAME>
ノードプール名は指定していなかったら default-pool
と思われる。
また、Cluster Autoscaler自体はまだベータ版(2017/06/16時点)。
これは Cluster Autoscaler のベータ版です。この機能はサービスレベル契約(SLA)または非推奨ポリシーの対象ではなく、バージョン アップ時に下位互換性が維持されない可能性があります。
公式ドキュメントにはこのような注意書きが書かれているので、運用する際はそのつもりで。
実際に試してみたところ、特に問題なく動いた。が、負荷がなくリソースも圧迫していないのに、なぜかノード数が最小まで減少しない現象が発生した。設定の問題かもしれないが。
YAMLファイルの記述例
実際はYAMLで記述することが多いと思うので、記述例も記載しておく。この場合、最低1個・最高40個でCPUが70%以上という感じ。ちなみにメモリを閾値にするのはサポートされていない。
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: <NAME>
spec:
maxReplicas: 40
minReplicas: 1
targetCPUUtilizationPercentage: 70
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: <DEPLOYMENT_NAME>