はじめに
以下の記事にもあるように、Kubernetes(k8s)ではノードと呼ばれるマシンにポッドを展開し、そのポッドの中にコンテナが格納されています。
そんなPodはマニフェストに記載することで冗長に展開することができますが、複数のPodが同一ノードに展開されてしまった場合はノード障害が単一障害点になってしまいます。
それを防ぐ仕組みにAntiAffinityがあるので分かりやすく解説します。
Anti-Affinityとは?
そもそも英語の「affinity」には以下のような意味があり「くっつく」というニュアンスがあります。
affinity
〔人や物への〕親しみ、親近感、一体感
〔人や物同士の〕類似[共通]性[点]
その「anti」ということからも想起できるように同じノードに同じポッドを配置しないようにすることができます。
要はノードXにルールYを満たすPodがすでに稼働している場合はこのPodはノードXで稼働させないといった指定ができます。
ちなみに逆の場合(あえて同じノードで稼働させたい場合)はInter-Pod Affinityと呼びます。
実際の例
例えば以下のようなマニフェストファイルだった場合は
spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - hoge topologyKey: "kubernetes.io/hostname"
「app=hoge であるPod」という条件をlabelSelectorで提示し、この条件を運用する対象を
topologyKey: "kubernetes.io/hostname"
で指定しています。
ちなみに、このkubernetes.io/hostnameは全てのノードを指しています。
つまり「app=hoge であるPodがデプロイされていないノードにデプロイする」ということを上のファイルでは指定しており、この記載によって結果的に全ノードの中でhogeがすでに稼働している場合はそのPodではhogeを稼働させない」ことを実現しています。
これによって、ノード障害が発生した場合も別ノードでPodが機能します。
こんな便利なAntiAffinityにも注意点があります。
AntiAffinityの注意点
replica数が配置されない場合がある
マニフェストに記載したレプリカ数よりもノード数が少ない場合は、Podはデプロイされません。
つまりreplicaよりもAntiAffinityのルールを優先します。
パフォーマンスに影響がある
Kubernetesの公式文書には以下のような但し書きがあります。
Inter-pod affinity and anti-affinity require substantial amount of processing which can slow down scheduling in large clusters significantly. We do not recommend using them in clusters larger than several hundred nodes.
要約すると「パフォーマンスに影響があるので大規模クラスターでは推奨しない」ということです。細かな制御であるため、管理を行うにはリソースを食うのかもしれません。
終わりに
素朴な疑問であるPodを複数に展開しても同一ノードに展開されていたらノード障害時に冗長性が担保されないのでは?に対して「Anti-Affinity」という機能を解説しました。
他にもnodeSelectorなどといったPodを展開する条件を指定する手法はあるので興味がある方はぜひそちらも調べてみてください。
以上、ご参考になれば幸いです。