2021/08/17
[GKE]nodeAffinityを活用してDBとその他アプリケーションを別々のノードにデプロイする
GKEには、「自動スケーリング」という便利な機能がありますが、以下の点で注意が必要です。
GKEのノードが負荷を検知して、自動スケーリングする際に、既存のnodeを頻繁にシャットダウンしたり、新しいnodeを作成したりします。その際に、自動スケーリングに対応しているpoolにデプロイされているpodが再起動します。
Rest API Serverなどのステートレスなアプリケーションは、そのようなnode数の変更(再起動)にうまく対応してくれますが、PostgresqlやRedisなどのステートフルなアプリケーションが頻繁に再起動するのには(かなり)問題があります。
なので、ステートレスなアプリケーションをデプロイするノードプールとステートフルなアプリケーションをデプロイするノードプールとを分ける必要があり、それらに以下のようにして対応しました。
- 2つのノードプールを作成する
- 自動スケーリングがオフのノードプール
- 自動スケーリングがオンのノードプール
- affinity.nodeAffinityを使って、アプリケーションをデプロイする
- ステートフルなアプリケーションは自動スケーリングがオフのノードプールのノードにデプロイ
- ステートレスなアプリケーションは自動スケーリングがオンのノードプールのノードにデプロイ
※ 規模が大きいアプリケーションの場合は、Postgresql専用のノードプールを作るなど、アプリケーション毎に分けるのが最適かなと思いますが、私がよく対応する小〜中規模のものはステートレスかステートフルかを分けるくらいが管理が楽でちょうど良いのでそうしています。
概要図
以下のような感じになります
ノードプールの作成
- “fixed-sized-pool” という名前で、自動スケーリングがオフのノードプールを作成します。
- “app-pool” という名前で、自動スケーリングがオンのノードプールを作成します。
※ マシンタイプは実際に稼働させてみて、メモリ使用率やCPU使用率などをみて最適なものを選ぶと良いと思います。私の場合は、fixed-sized-poolにはちょっとスペックの良いものを選び、メモリがちょっと多めのものをよく選びます。逆にapp-poolではCPUが少し多めで、スペック自体はやや悪いものを選びます。(負荷が高まると複数のnodeが立ち上がるので、一つ一つはスペック悪めですが、負荷に応じてスケールアウトするような感じにしています。)
アプリケーションのデプロイ
ステートフルアプリケーションの場合
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
を活用してfixed-size-pool
という名前のノードプールのノードにしかデプロイされないように指定します。
以下のような感じです。
apiVersion: apps/v1
kind: StatefulSet
spec:
..中略..
template:
..中略..
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "cloud.google.com/gke-nodepool"
operator: In
values:
- fixed-size-pool
ステートレスアプリケーションの場合
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
を活用してapp-pool
という名前のノードプールのノードにしかデプロイされないように指定します。
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 3
..中略..
template:
..中略..
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "cloud.google.com/gke-nodepool"
operator: In
values:
- app-pool
Tips
ちなみにk8sクラスターのnodeをラベル付きで表示する場合は、以下のコマンドをうって確かめます。
$ kubectl get nodes --show-labels
上で記載した、cloud.google.com/gke-nodepool
のようなkey名もこのコマンドで確認できます。
こちらの構成で、運用がかなり安定しました。
以上です。
関連する記事
[小〜中規模向け]GKEにTiDBをデプロイする
MySQL互換のNewSQLであるTiDBをGKEにデプロイしてみました。
NATS JetStream Controllerを使ってNATSをGKEにデプロイする
helm chartのnackを使って、NATS JetStreamサーバーをデプロイして、Stream/Consumerをk8sリソースとして管理する
GKEにDragonflydbをデプロイする
redis互換のdragonflydbをGKEにデプロイしました
[GKE]Kafka Strimziをアップグレードする
GKEにデプロイしているKafka Strimzi 0.26.0を0.30.0にアップグレードする