【GKE/Kubernetes】Node、Podのスケールアウト


Kubernetesのスケールアウト

スケーラビリティを担保することは、システムにとって非常に重要なことです。
例えば、急なトラフィックの増大にも柔軟に対応できるシステム設計が求められることは言うまでもないことです。
今回は、 そのスケーラビリティの手法の一つであるスケールアウトをkubernetes(GKE)でどう実現するかについて記載していきたいと思います。

環境

GKE

スケーラビリティとは

負荷が増大したとしても、パフォーマンスを保つことができる機能を備えていることを指します。

参考:
データ指向アプリケーションデザイン ―信頼性、拡張性、保守性の高い分散システム設計の原理

スケーリングの種類

スケーリングには主に2つの種類が存在しています。

スケールアウト

アクセスが集中して、既存のサーバがアクセスをさばき切れない場合などに、サーバーを増やしていく手法です。
これにより、大量のトラフィックでも対応することができるようになります。

用語集|スケールアウト

スケールアップ

サーバー自体の性能をあげる手法のことを指します。
具体的には、CPU、メモリやなどのリソースを拡張するを指します。

スケールアウト、スケールアップどちらを使用するか

スケールアウトが使用される場合

更新データの整合性維持に対する要件があまり厳しくないケースに適している。すなわち、高い並列性を実現しやすい場合

つまりほとんどのデータのアクセスが、リードオンリー(GET)が想定されるのであれば、スケールアウトで問題ないと判断できます。
GETであれば整合性を高く持つ必要がないので、サーバーを増やしても問題にはなりません。

スケールアウトとスケールアップ:サーバ処理能力向上の2つのアプローチ

スケールアップが使用される場合

データベースに対して頻繁に更新が発生する場合が有効とされています。
具体的には、オンライントランザクション処理があげられます。
ここでのオンラインは、リアルタイムでの処理を指し、そこでトランザクション処理が行われる場合は、高い整合性が求められます。
仮にスケールアウトをしてしまうと、アクセスしたサーバーごとに持っているデータが違うことが発生するので、適切ではありません。
そのため高い整合性が求められる場合には、スケールアップの方が適切であると言えます

OLTPとは?OLAPやDWHとの違いをわかりやすく解説
オンライン トランザクション処理 (OLTP)

Kubernetesでのスケールアウト(GKE)

今回は、スケールアウト、スケールアップのうち、スケールアウトに関して書いていきます
Kubernetesでスケールアウトさせる対象は主に2つあり、NodeとPodが対象になります。

Cluster AutoScaler(Nodeのスケールアウト)

Kubernetesクラスタ自体のオートスケーリングを意味しています。
PodをスケジュールできるNodeが存在しない場合に、Nodeの数を自動的に増やしてくれます。
GKEの場合、クラスタを作成する際に、--enable-autoscalingをつけることで設定を行うことができます。

下記では、example-clusterという名前でクラスタを作成します。
オートスケールを有効にし、最大のNode数を4と最小のNode数を1と設定しています。

gcloud container clusters create example-cluster \
--zone us-central1-a \
--node-locations us-central1-a,us-central1-b,us-central1-f \
--num-nodes 2 --enable-autoscaling --min-nodes 1 --max-nodes 4

クラスタ構築後の変更

Cluster AutoScalerは、後からでも変更が可能です。
「default-pool」を選択します。

「編集」ボタンをクリックし、「自動スケーリング」を有効にし、ノードの数を設定することができます。

クラスタ オートスケーラー
GKEでPodとNodeをAutoscaling する

Horizontal Pod AutoScaler(Podのスケールアウト)

Podのスケールアウトです。
PodをCPU負荷などの条件によって自動的にスケールアウトできます。
CPU使用率の基準値を設定し、その基準値が超えたタイミングでPodを増やしてくれます。

またスケールアウトの条件式もあるようです。
avg(Podの現在のCPU使用率) / targetAverageUtilazation > 1.1
このtargetAvrageUtilazationは、すべてのPodのCPU使用率の平均を表します。
avg(Podの現在のCPU使用率)の数値の決定は、負荷試験を行なってから決めることになりそうです。

マニフェストファイルで作成

スケールアウトを実装するためには、新しくマニフェストファイルを作成する必要があります。
下記のようなファイルを作成すれば完了です。


apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler # 水平スケールを設定
metadata:
  name: hpa-worker
spec:
  maxReplicas: 10 # 最大Pod数
  minReplicas: 1 # 最小Pod数
  targetCPUUtilizationPercentage: 70 # スケールする際の基準
  scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment
    name: test-name # スケール対象のDeploymentの名前

コマンドで設定

kubectl autoscale deployment hello-web --cpu-percent=70 --min=1 --max=10

horizontalpodautoscaler.autoscaling/hpa-worker created

kubectl get hpaを実行

NAME        REFERENCE              TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
hello-web   Deployment/hello-web   0%/70%    1         10        1          22s

ちなみにコマンドで作成するとマニフェストは下記のように作成されました。

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  annotations:
    autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2019-11-23T09:03:16Z","reason":"ScaleDownStabilized","message":"recent
      recommendations were higher than current one, applying the highest recent recommendation"},{"type":"ScalingActive","status":"True","lastTransitionTime":"2019-11-23T09:03:16Z","reason":"ValidMetricFound","message":"the
      HPA was able to successfully calculate a replica count from cpu resource utilization
      (percentage of request)"},{"type":"ScalingLimited","status":"False","lastTransitionTime":"2019-11-23T09:03:16Z","reason":"DesiredWithinRange","message":"the
      desired count is within the acceptable range"}]'
    autoscaling.alpha.kubernetes.io/current-metrics: '[{"type":"Resource","resource":{"name":"cpu","currentAverageUtilization":0,"currentAverageValue":"0"}}]'
  creationTimestamp: "2019-11-23T09:03:01Z"
  name: hello-web
  namespace: default
  resourceVersion: "9016531"
  selfLink: /apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/hello-web
  uid: 0d7167e3-0dd0-11ea-9fa0-42010a800108
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment
    name: hello-web
  targetCPUUtilizationPercentage: 70
status:
  currentCPUUtilizationPercentage: 0
  currentReplicas: 1
  desiredReplicas: 1

Node Podのスケールアウトの流れ

上記でみてきたPodとNodeのスケールアウトを確認するためには、負荷試験を行うことをお勧めします。

私が負荷試験を行なった際は、下記のような順番でスケールアウトしていました。
1. アクセスが増える
2. Podがスケールアウトする(増える)
3. 新規のPodがどこのNodeにも配置できなくなる
4. Nodeがスケールアウトする

また負荷試験に関しては、以下のGoogleのドキュメントを使えば、GKE環境下でスケールアウトを確認することができます。
ぜひ検証してみてください!
Google Kubernetes Engine を使用した負荷分散テスト

参考にした記事

KubernetesのPodとNodeのAuto Scalingについて
GKEでPodとNodeをAutoscaling する