【ツール活用|実務向け】Kubernetesのスケジューリングを制御する:Node AffinityとAnti-Affinityによる可用性向上術

導入

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:
matchExpressions:
  • key: app
operator: In values:
  • nginx
# topologyKeyには、分散の単位を指定(kubernetes.io/hostnameはノード単位) topologyKey: "kubernetes.io/hostname" containers:
  • name: nginx
image: nginx:latest

応用・注意点

1. topologyKeyの選択: 「kubernetes.io/hostname」を指定するとノード単位で分散されますが、より広範囲に分散させたい場合は「topology.kubernetes.io/zone」を指定することで、AZ(アベイラビリティゾーン)をまたいだ分散が可能になります。
2. パフォーマンスのトレードオフ: Anti-Affinityを厳しく設定しすぎると、ノード数に対してPod数が上回った場合にPodが「Pending」状態で起動できなくなる可能性があります。リソース計画とセットで検討してください。
3. デバッグのコツ: 設定が正しく機能しない場合は、kubectl describe pod コマンドを実行し、「Events」セクションでスケジューリングの拒否理由を確認するのが定石です。

コメント

タイトルとURLをコピーしました