Как равномерно распределить поды приложения по нескольким зонам доступности?

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

Ответ

Для обеспечения отказоустойчивости и высокой доступности приложения его поды должны быть распределены по разным зонам доступности (Availability Zones, AZ). В Kubernetes для этого используются ограничения распространения по топологии (Pod Topology Spread Constraints) — это наиболее гибкий и рекомендуемый способ.

Основной метод: Pod Topology Spread Constraints Данное правило встраивается в спецификацию Pod, Deployment, StatefulSet и т.д.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 6
  selector: { ... }
  template:
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: my-app

Разбор параметров:

  • topologyKey: topology.kubernetes.io/zone: Указывает, что распределение должно происходить по метке узла, обозначающей зону доступности (эта метка обычно проставляется облачным провайдером).
  • maxSkew: 1: Определяет максимально допустимый дисбаланс. Значение 1 означает, что разница в количестве подов между самой загруженной и самой незагруженной зоной не может превышать 1 под. Для 6 реплик и 3 зон это даст распределение 2-2-2.
  • whenUnsatisfiable: DoNotSchedule: Директива, что делать, если условие нельзя выполнить. DoNotSchedule (по умолчанию) — не планировать под, ScheduleAnyway — запланировать с наименьшим нарушением.
  • labelSelector: Определяет, к каким подам применяется правило (обычно селектор самого приложения).

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

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchLabels:
          app: my-app
      topologyKey: topology.kubernetes.io/zone

Практика: Всегда проверяйте, что узлы в вашем кластере имеют корректные метки topology.kubernetes.io/zone. Для StatefulSet с упорядоченным развертыванием (podManagementPolicy: OrderedReady) распределение может быть затруднено, в таких случаях можно использовать podManagementPolicy: Parallel.