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するように設定することは可能です。