Slide 1

Slide 1 text

AWS EKSでClusterAutoscalerを使うときは NodeGroupの分け⽅に気をつけろ︕ Jul 19th, 2023 Shota Nishino(Morix) Rakuten Group, Inc.

Slide 2

Slide 2 text

2 ⾃⼰紹介 • 名前 • ⻄野 翔太 • 所属 • 楽天グループ株式会社 • ラクマ開発課 SREチーム • Twitter • @morix1500

Slide 3

Slide 3 text

3 話すこと • NodeGroupはアベイラビリティゾーン(AZ)ごとに分けよう︕ • NodeGroupをAZごとに分けるときの注意点

Slide 4

Slide 4 text

4 NodeGroupとは︖ EKSクラスターのNode(EC2)のプロビジョニングやライフサイクル管理をしてくれるもの。 AZやインスタンスタイプを複数指定することができる。 ClusterAutoscalerを使⽤してNodeのオートスケールを⾏いたい場合、以下のような制限がある。 • 1つのNodeGroup内のインスタンスタイプはすべて同⼀のvCPUとMemoryである必要がある • 例) c5.largeは vCPU: 2 Memory: 4GB なので、c5a.largeやc6.largeを⼀緒に指定できる

Slide 5

Slide 5 text

5 NodeGroupはAZごとに分けよう︕ 理由: • うまくPodのスケジューリングができなくなる場合がある • Podの Topology Spread Constraints を使うときに問題が起きるときがある︕

Slide 6

Slide 6 text

6 Topology Spread Constraintsとは Podの分散配置を⾏える機能。ゾーンやノード単位などで分散⽅法を指定できる。 引⽤元: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/

Slide 7

Slide 7 text

7 どんなときに問題が起きるのか︖ ・NodeGroupに複数のAZを紐づけている ・NodeGroupが複数ある ・PodのTopologySpreadConstraintsがZone分散かつ whenUnsatisfiable: DoNotScheduleのとき

Slide 8

Slide 8 text

8 スケールアウト対象のNodeGroupの選定ロジック ClusterAutoscaler(CA)はPodがスケジューリング可能なNodeGroupを探す。 CAはひとつのNodeGroup内のNodeを同⼀スペックとみなしている。 そのためTemplateNodeというものをNodeGroupの中のNodeから1台選び、そのNodeの情報を保持する。 CA NodeGroup1 Node1 AZ: a c5.large Node2 AZ: c c5a.large NodeGroup2 Node3 AZ: d c5.large Node4 AZ: c c5a.large NodeGroup1: AZ=a InstanceType: c5.large NodeGroup2: AZ=c InstanceType: c5a.large

Slide 9

Slide 9 text

9 スケールアウト対象のNodeGroupの選定ロジック その後expanderの設定に従って数を増やすNodeGroupを選定する。 CA NodeGroup1 Node1 AZ: a c5.large Node2 AZ: c c5a.large NodeGroup2 Node3 AZ: d c5.large Node4 AZ: c c5a.large NodeGroup1の数を増やそう︕

Slide 10

Slide 10 text

10 うまくいかないパターン あるアプリケーションのPodのTopologySpreadConstraintsをZone分散してるとき、 aとcゾーンにPodを配置してる場合は、次はdゾーンにPodを配置したい。けど空きがないのでNodeを増やす 必要がある。 CA NodeGroup1 Node1 AZ: a c5.large Node2 AZ: c c5a.large NodeGroup2 Node3 AZ: d c5.large Node4 AZ: c c5a.large NodeGroup1: AZ=a InstanceType: c5.large NodeGroup2: AZ=c InstanceType: c5a.large Pod Pod Pod もうPod置けません︕ dに ⾏きたい

Slide 11

Slide 11 text

11 うまくいかないパターン この場合CAは、NodeGroup1はaゾーン、NodeGroup2はcゾーンとみなすので dゾーンのNodeGroupは存在しないものと⾒てスケールアウトをしない。 CA NodeGroup1 Node1 AZ: a c5.large Node2 AZ: c c5a.large NodeGroup2 Node3 AZ: d c5.large Node4 AZ: c c5a.large NodeGroup1: AZ=a NodeGroup2: AZ=c dないじゃん︕うーん、むり︕ Pod Pod Pod そんなー

Slide 12

Slide 12 text

12 NodeGroupをAZごとに分けるときの注意点︕ • NodeGroupを増やしすぎるとスケールアウトの速度に影響が出る可能性がある • 単純にAZごとにNodeGroupを分けてもうまくバランシングをしてくれない

Slide 13

Slide 13 text

13 NodeGroupを増やしすぎるとスケールアウトの速度に影響が出る可能性がある Reducing the number of Node Groups Minimizing the number of node groups is one way to ensure that the Cluster Autoscaler will continue to perform well on large clusters. This may be challenging for some organizations who structure their node groups per team or per application. While this is fully supported by the Kubernetes API, this is considered to be a Cluster Autoscaler anti-pattern with repercussions for scalability. There are many reasons to use multiple node groups (e.g. Spot or GPUs), but in many cases there are alternative designs that achieve the same effect while using a small number of groups. ノードグループの数を減らす ノードグループの数を最⼩限に抑えることは、⼤規模なクラスタでもCluster Autoscalerのパフォーマンスを維 持できるようにする1つの⽅法です。これは、チームごとまたはアプリケーションごとにノードグループを構成 する組織によっては難しいかもしれません。これはKubernetes APIによって完全にサポートされていますが、 スケーラビリティに影響を与えるCluster Autoscalerのアンチパターンと考えられています。複数のノードグ ループ(SpotやGPUなど)を使⽤する理由はたくさんありますが、多くの場合、少数のグループを使⽤しなが ら同じ効果を達成する代替設計があります。 引⽤元: https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/#reducing-the-number-of-node-groups

Slide 14

Slide 14 text

14 単純にAZごとにNodeGroupを分けてもうまくバランシングしてくれない CAの起動オプションの --balance-similar-node-groups を必ず指定する︕ このオプションを指定すると、Nodeを増やす際に選択したNodeGroupと似ているNodeGroupを探し、それら のNodeGroupのNodeを増やしてくれる。 この似ているというのがクセモノで・・・デフォルトだと以下のような定義になっている。 • 各リソース(CPU・Memoryなど)のCapacityが⼀緒 • 割当可能(Allocatable)なリソースの差が5%以内 • 空きリソース(AllocatableからDaemonSetやkube-proxyが使⽤するリソースを引いたもの)が5%以内 • 同じLabelを持っている(zone/hostname除く)

Slide 15

Slide 15 text

15 NodeにはたくさんLabelがついている EKSのNodeにはたくさんLabelがついている。 そのなかにinstanceTypeのラベルもある・・・

Slide 16

Slide 16 text

16 うまくバランシングしてくれないケース Node4台分を起動したいとする。 NodeGroup1と2は同⼀のCPU・Memoryを持つので、バランスよく2台ずつ起動してほしい。 CA NodeGroup1 Node1 AZ: a c5.large Node2 AZ: c c5a.large NodeGroup2 Node3 AZ: d c5.large Node4 AZ: c c5a.large 4台増やしたい・・・ 似ているNodeGroupはどこかな︖

Slide 17

Slide 17 text

17 うまくバランシングしてくれないケース CAはTemplateNodeを元にNodeGroupの情報を保持している。 ここにはInstanceTypeも含まれているため TemplateNodeのInstanceType = そのNodeGroupのInstanceTypeとみなしてしまう CA NodeGroup1 Node1 AZ: a c5.large Node2 AZ: c c5a.large NodeGroup2 Node3 AZ: d c5.large Node4 AZ: c c5a.large NodeGroup1: InstanceType: c5.large NodeGroup2: InstanceType: c5a.large

Slide 18

Slide 18 text

18 うまくバランシングしてくれないケース NodeGroup1の数を増やす選択をした場合、似ているNodeGroupを探すがInstanceTypeが同⼀なNodeGroupは 存在しないため、NodeGroup1で4台起動してしまう。 CA NodeGroup1 Node1 AZ: a c5.large Node2 AZ: c c5a.large NodeGroup2 Node3 AZ: d c5.large Node4 AZ: c c5a.large NodeGroup1: InstanceType: c5.large NodeGroup2: InstanceType: c5a.large NodeGroup1と⼀致するラベルを 持つNodeGroupはいない︕

Slide 19

Slide 19 text

19 どうすれば︖--balancing-label をつけよう︕ CAの起動オプションに –balancing-label を指定する。 このオプションを付与するとどのLabelをもって似ているNodeGroupとみなすか指定できる︕ CPUとMemoryが⼀緒であれば似ているNodeGroupとみなしてほしいのであれば --balancing-label=example.com/cpu --balancing-label=example.com/memory と指定しておけば、NodeのこれらのLabelのみ参照して似ているNodeGroupを探す動きをしてくれる。 Nodeに以下のLabelを付与すればいい感じにバランシングしてくれる。 • example.com/cpu: 2 • example.com/memory: 4

Slide 20

Slide 20 text

20 まとめ • EKSのNodeGroupはアベイラビリティゾーンごとに分ける • NodeGroupが1種類だけでいい規模なら必要なし • 単純に分けただけじゃClusterAutoscalerはバランシングをうまくできないので以下のオプションをつけよう • --balance-similar-node-groups • --balancing-label