Как создать отказоустойчивый кластер Kubernetes?

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

Ответ

Отказоустойчивость кластера Kubernetes достигается за счет избыточности на всех уровнях и правильной настройки объектов. Вот как я это делаю:

1. Архитектура Control Plane: Разворачиваю минимум 3 master-ноды, распределенные по разным зонам доступности (AZ). Использую managed-сервисы (EKS, GKE, AKS), так как они берут на себя отказоустойчивость etcd и API-сервера. При самоуправляемом развертывании (kubeadm) обязательно настраиваю внешний, кластеризованный etcd.

2. Рабочие ноды (Worker Nodes):

  • Использую группы нод (Node Groups) в разных AZ.
  • Настраиваю Cluster Autoscaler для автоматического добавления нод при нехватке ресурсов.
  • Применяю PodDisruptionBudgets (PDB) для критичных приложений, чтобы не допустить одновременного вывода из строя слишком многих подов при обслуживании нод.
    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: my-app-pdb
    spec:
      minAvailable: 2  # Гарантирует, что всегда будет доступно минимум 2 пода
      selector:
        matchLabels:
          app: my-critical-app

3. Настройка самих приложений (Pods/Deployments):

  • Anti-affinity: Распределяю поды одного приложения по разным нодам и AZ.
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - my-app
            topologyKey: kubernetes.io/hostname # Разные ноды
            # topologyKey: topology.kubernetes.io/zone # Разные зоны
  • Readiness/Liveness Probes: Корректно настраиваю пробы, чтобы kubelet и Service могли точно определять состояние пода.
  • Resource Requests/Limits: Обязательно указываю, чтобы планировщик мог правильно распределять нагрузку и избегать "шумного соседа".
  • Horizontal Pod Autoscaler (HPA): Настраиваю автоматическое масштабирование приложения на основе CPU/Memory или кастомных метрик.

4. Сеть и хранение:

  • Выбираю сетевой плагин (Calico, Cilium), поддерживающий Network Policies для изоляции трафика.
  • Для stateful-приложений использую отказоустойчивые решения для хранения (например, облачные managed-диски с репликацией между AZ или операторы вроде Rook для Ceph).

5. Мониторинг и восстановление: Разворачиваю стек мониторинга (Prometheus, Grafana) с алертами на здоровье нод, нехватку ресурсов и сбои приложений. Настраиваю автоматические реакции, где это возможно (например, перезапуск пода при падении через restartPolicy: Always).