Как в Kubernetes разместить два пода так, чтобы они гарантированно оказались на разных узлах (нодах)?

«Как в Kubernetes разместить два пода так, чтобы они гарантированно оказались на разных узлах (нодах)?» — вопрос из категории Kubernetes, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для гарантированного разделения подов по разным узлам используется Inter-Pod Anti-Affinity с жестким правилом (requiredDuringSchedulingIgnoredDuringExecution). Это критично для отказоустойчивости StatefulSet'ов (например, мастер-узлы БД) или сервисов, которые не должны простаивать из-за отказа одной ноды.

Пример манифеста Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - my-app
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: app
        image: nginx:alpine

Как это работает:

  • labelSelector определяет, к каким подам применяется правило (в данном случае ко всем с меткой app: my-app).
  • topologyKey: "kubernetes.io/hostname" указывает, что "доменом" для разделения является имя узла. Поды с одинаковыми метками не могут быть размещены на узлах с одинаковым значением этого ключа.
  • requiredDuringScheduling... — это жесткое требование. Если в кластере меньше двух узлов, второй под останется в статусе Pending.

Альтернатива (мягкое правило): Используйте preferredDuringSchedulingIgnoredDuringExecution, если разделение желательно, но не критично. Планировщик попытается выполнить правило, но разместит поды на одной ноде, если другого выбора нет.