導入
Kubernetesで運用を行う際、すべてのPodを「どのノードに配置しても良い」状態で運用するのは理想的ですが、実務ではそうもいきません。特定のGPU搭載ノードに機械学習Podを割り当てたり、冗長化のために同じアプリのPodが物理的に異なるノードに散らばるように制御したりする必要があります。これらを実現する「Node Affinity」と「Pod Anti-Affinity」は、システムの信頼性とハードウェア効率を最大化するために必須の知識です。
基礎知識
Kubernetesのスケジューラは、デフォルトではリソースの空き状況に基づいて自動配置を行います。これを制御する仕組みが「Affinity(親和性)」です。
・Node Affinity: Podを特定の条件を持つノード(例:SSD搭載、特定のリージョンなど)に配置させるための設定です。
・Pod Anti-Affinity: 特定のPodが既に存在するノードには、新しいPodを配置しないようにする設定です。これにより、単一障害点(SPOF)を回避し、ノード障害時にサービス全体がダウンするリスクを低減できます。
実装/解決策
Node Affinityには、条件を満たさないと配置が失敗する「requiredDuringSchedulingIgnoredDuringExecution(ハード制約)」と、条件を満たすノードを優先する「preferredDuringSchedulingIgnoredDuringExecution(ソフト制約)」の2種類があります。実務では、可用性を担保するためにAnti-Affinityを活用し、Podをノード間で分散させる設定をYAMLに記述するのが一般的です。
サンプルプログラム
以下の設定は、同じアプリのPodが同じノードに固まらないようにするための「Pod Anti-Affinity」の例です。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAntiAffinity:
# 同じノードに配置しないためのハード制約(必須)
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
- key: app
- nginx
- name: nginx
応用・注意点
1. topologyKeyの選択: 「kubernetes.io/hostname」を指定するとノード単位で分散されますが、より広範囲に分散させたい場合は「topology.kubernetes.io/zone」を指定することで、AZ(アベイラビリティゾーン)をまたいだ分散が可能になります。
2. パフォーマンスのトレードオフ: Anti-Affinityを厳しく設定しすぎると、ノード数に対してPod数が上回った場合にPodが「Pending」状態で起動できなくなる可能性があります。リソース計画とセットで検討してください。
3. デバッグのコツ: 設定が正しく機能しない場合は、kubectl describe pod コマンドを実行し、「Events」セクションでスケジューリングの拒否理由を確認するのが定石です。

コメント