Как грамотно распределить поды по разным нодам в разных дата-центрах в Kubernetes?

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

Ответ

Для распределения подов по нодам в разных зонах доступности (AZ) используются Pod Topology Spread Constraints и Pod Anti-Affinity. Это обеспечивает отказоустойчивость и высокую доступность.

Пример манифеста с комбинацией стратегий:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 6
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      topologySpreadConstraints:
        # Распределение по зонам доступности
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: my-app
        # Распределение по хостам внутри зоны
        - maxSkew: 2
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: my-app
      affinity:
        podAntiAffinity:
          # Жесткое правило: не размещать два пода с одним лейблом на одной ноде
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  app: my-app
              topologyKey: kubernetes.io/hostname

Ключевые параметры:

  • topologyKey: Определяет домен распределения (zone, hostname, region).
  • maxSkew: Максимально допустимая разница в количестве подов между топологическими доменами. Значение 1 означает максимально равномерное распределение.
  • whenUnsatisfiable: DoNotSchedule (не планировать, если правило не выполняется) или ScheduleAnyway (планировать, стараясь минимизировать skew).

Практика: Для критичных приложений я всегда настраиваю spread constraints по зонам с maxSkew: 1 и DoNotSchedule, чтобы гарантировать выживаемость при падении целой AZ.