2021年3月14日日曜日

複数の deployment で podAntiAffinity を使う場合は対象の namespace を指定する必要がある

概要

podAntiAffinity は Pod をノードにデプロイする際のルールを指定することができる
podAffinity と似ていますが podAntiAffinity の場合は特定の条件に合致する Pod とは別のノードにデプロイしたい場合に使うルールになります
通常 Deployment で使い replicas で複数の Pod をデプロイする場合にそれらの Pod を異なるホストにデプロイしたい場合に使います
しかし複数の Deployment 定義を YAML ファイルでしている場合にはそれぞれの YAML ファイルを横断して affinity ルールを適用する必要があります
その場合にはルールを適用する対象の namespace を指定することで横断的に affinity ルールを適用することができます

環境

  • k8s 1.19.3

普通に podAntiAffinity を使う

まずは普通に podAntiAffinity を使う例を紹介します
1 つの Deployment 内で各ノードに 1 つ Pod をデプロイしたい場合には replicas をノード数分指定し podAntiAffinity を使います
今回は 6 ノードあるクラスタに対してデプロイするので replicas:6 を指定しています

  • vim pod_anti_affinity.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-multi
spec:
  selector:
    matchLabels:
      app: web
  replicas: 6
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-multi
        image: nginx:latest
  • kubectl apply -f pod_anti_affinity.yaml

これでデプロイすると確かに各ノードに 1 つずつ重複することなくデプロイされることが確認できます

  • kubectl get pod -o wide | grep web-multi
web-multi-db6d7cd4f-2b559 1/1 Running 0 11s 10.233.2.31 tt9lr <none> <none> web-multi-db6d7cd4f-7ql5h 1/1 Running 0 11s 10.233.5.14 ifov6 <none> <none> web-multi-db6d7cd4f-cqq4l 1/1 Running 0 11s 10.233.4.8 qdhf7 <none> <none> web-multi-db6d7cd4f-hm4sm 1/1 Running 0 11s 10.233.3.7 1rfxw <none> <none> web-multi-db6d7cd4f-m76ck 1/1 Running 0 11s 10.233.0.31 00wcr <none> <none> web-multi-db6d7cd4f-w9wbx 1/1 Running 0 11s 10.233.1.24 bdzss <none> <none>

異なる namespace 間で podAntiAffinity を使う場合

本題です
例えば以下のように Deployment の定義が複数ある場合を考えます
そういった場合には namespaces を追加して affinity ルールを横断的に適用する namespace を指定します

  • vim pod_anti_affinity_with_ns.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: web1
spec:
  selector:
    matchLabels:
      app: web
  replicas: 1
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: "kubernetes.io/hostname"
            namespaces:
              - web2
              - web3
      containers:
      - name: web
        image: nginx:latest

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: web2
spec:
  selector:
    matchLabels:
      app: web
  replicas: 1
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: "kubernetes.io/hostname"
            namespaces:
              - web1
              - web3
      containers:
      - name: web
        image: nginx:latest

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: web3
spec:
  selector:
    matchLabels:
      app: web
  replicas: 1
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: "kubernetes.io/hostname"
            namespaces:
              - web1
              - web2
      containers:
      - name: web
        image: nginx:latest

こうすることで

web1 は web2 と web3 によってデプロイされた app=web というラベルを持つ Pod とは異なるノードにデプロイされる

といったルール付けをすることができるようになります
試しに何度かデプロイしてみると必ずそれぞれの Pod が別のノードにデプロイされるのが確認できると思います

  • kubectl get pod --all-namespaces -o wide | grep -e web[1-3]
web1 web-86d5665f89-2fb54 1/1 Running 0 9s 10.233.3.14 1rfxw <none> <none> web2 web-78b54b56fd-cj2tn 1/1 Running 0 9s 10.233.4.16 qdhf7 <none> <none> web3 web-c9469f65-v87cb 1/1 Running 0 9s 10.233.5.20 ifov6 <none> <none>

おまけ: 特定のノードに固定した場合は nodeSelector を使う

piVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      name: web
  template:
    metadata:
      labels:
        name: web
    spec:
      nodeSelector:
        kubernetes.io/hostname: pool2-tt9lr
      containers:
        - image: nginx:latest
          name: web

最後に

  • podAffinity は条件に合致する Pod があるホストやゾーンと同じノードにデプロイする
  • podAntiAffinity は条件に合致する Pod がないホストやゾーンのノードにデプロイする

と覚えておけば良いと思います

参考サイト

0 件のコメント:

コメントを投稿