2024.04.08

EKSでAZダウンのリスクを最小限に抑える

こんにちは、次世代システム研究室のT.Iです。今回はEKSでAZダウンを対策を行ったためそれについて解説をします。

・環境

今回の環境は以下の通りとなっています。

EKS:1.27以上

Nodeの管理:Karpenter

他にも色々ありますが、今回の内容は上記に依存するため最低限の環境だけ記載します。

 

・Podの分散スケジューリング

AZダウンのリスクを最小限にするためには各AZに均等にPodを分散させる必要があります。今回は2つのAZに分散させることを考えます。

Podを複数のAZに分散して配置するためにはkubernetesの機能であるTopologySpreadConstraintsを使用する必要があります。

今回は以下のように設定を行いました。
topologySpreadConstraints:
- maxSkew: 1
    topologyKey: "topology.kubernetes.io/zone"
    whenUnsatisfiable: ScheduleAnyway
    labelSelector:
        matchLabels:
              ${app-label}
- maxSkew: 1
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule
    minDomains: 2
    labelSelector:
        matchLabels:
              ${app-label}
TopologySpreadConstraintsはPodの分散スケジューリングするための機能です。(すでに動いているPodは再スケジューリングされません)

分散条件はNodeとPodのラベルをベースに設定していきます。各設定項目について解説します。

maxSkew:対象のNodeごとにスケジューリングされた対象のPodの最小数と最大数の差をどこまで許容するか(1以上)

topologyKey:どのNodeのラベルをもとに分散させるか

whenUnsatisfiable:分散させるNodeがない場合にどうするか

LabelSelector:どのラベルのPodを分散させるか

minDomains:分散するNodeの最小数(EKSの1.27以上でないと使用できないので注意)

 

・設定について

ここでは前章でも記載した今回のTopologySpreadConstrainsでの設定値について解説します。

まず以下の一つ目の設定からです。
- maxSkew: 1
    topologyKey: "topology.kubernetes.io/zone"
    whenUnsatisfiable: ScheduleAnyway
    labelSelector:
        matchLabels:
              ${app-label}
topologyKeyの”topology.kubernetes.io/zone”についてですが、こちらはEKSのManagedNodeGroupやKarpenterを使用するとAZごとに異なる値がNodeごとに「topology.kubernetes.io/zone:${value}」という形で自動で付与されます。そのため、AZごとに分散させるような設定となります。

次にwhenUnsatisfiableのScheduleAnywayは条件のあうNodeが存在しない場合は設定の条件に合わなくても存在するNodeにスケジューリングするような設定となっています。これによりAZダウン時は片方のAZに必要な数のPodをスケジューリングすることができます。

ここでKarpenter公式ReferenceによるとTopologySpreadConstraintsに対応しているので全体のリソースが足りなくてどちらにしてもNodeを別で用意しなくてはならない場合は優先的にTopologySpreadConstraintsの設定に合うNodeをプロビジョニングしてくれます。

つまり、AZごとのPod数の差分を1以下に抑えるようにスケジューリングを行うが、条件のあうNodeにスケジューリングできない場合は合わないNodeにスケジューリングするというソフトな設定となっています。

 

次に二つ目の設定についてです。
- maxSkew: 1
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule
    minDomains: 2
    labelSelector:
        matchLabels:
              ${app-label}
こちらはtopologyKeyがkubernetes.io/hostnameとなっています。これはhostごとにユニークな値が付与されるラベルなのでhost、つまりNode単位で分散させる設定となっています。

またwhenUnsatisfiableがDoNotScheduleとなっており、これは必ず条件のあうNodeにスケジューリングする設定なので条件のあるNodeがプロビジョニングされるまではPodはスケジューリングステータスのまま保留されます。

つまり、必ずNodeごとの差分を1以下に抑えつつ2つ以上のNodeに分散させるというハードな設定となっています。

TopologySpreadConstraintsは複数設定していた場合、全ての条件に合わせて動作するためこれらの二つの設定により2つのAZに均等にPodがスケジューリングされるようになります。

 

・復旧について

AZダウンでもし片方のAZの機能全てが停止した場合は残った方の二つ以上のNodeにPodが偏ることとなります。そのためAZが復旧した際には再度Podを配置しなおす必要があります。

ここで、TopologySpreadConstraintsはスケジューリングの際に機能するものだったので、Deschedulerなどの条件指定でPodをEvictするようなツールを使用して再度スケジューリングすることで再度TopologySpreadConstraintsに沿ってスケジューリングされるので自動で複数のAZにPodを分散しなおすことが可能です。

ここでは紹介しませんが、先述したDeschedulerはTopologySpreadConstraintsに沿っていないPodをEvictするように設定することは可能です。

 

さいごに

次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。インフラ設計、構築経験者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。 皆さんのご応募をお待ちしています。

  • Twitter
  • Facebook
  • はてなブックマークに追加

グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

 
  • AI研究開発室
  • 大阪研究開発グループ

関連記事