ADG Оставить заявку
Блог DevOps 4 мин чтения

KubeFed v2 beta: пилот с двумя кластерами в разных ЦОД и почему это оказалось сложнее, чем выглядело

KubeFed v2 вышел в beta: запустили пилот на двух кластерах в разных ЦОД. Single API для федерированных Deployment-ов работает, но ценой нетривиальной настройки.

Контекст момента

KubeFed v2 (Kubernetes Federation v2) достигает beta: управление политиками и рабочими нагрузками в нескольких кластерах через единый API

В июле мы писали про Kubernetes 1.15, и там одной строчкой упомянули, что тема федерации - это отдельный разговор. Вот этот разговор.

KubeFed v2 вышел в beta в рамках sig-multicluster, и мы решили не ждать GA, а запустить пилот прямо сейчас: два кластера на Kubernetes 1.16, в двух разных ЦОД одного из клиентов, задача - DR без ручной синхронизации манифестов.

Контекст задачи

У клиента два ЦОД с разным железом, оба с собственными кластерами Kubernetes. До последнего времени DR выглядел классически: второй кластер держат «тёплым», манифесты синхронизируют через отдельный GitOps-пайплайн, при переключении меняют DNS вручную. Работает, но при обновлении конфигурации приложения нужно помнить про оба кластера - и рано или поздно они расходятся.

Идея KubeFed v2: единый API-слой поверх нескольких кластеров, который сам распределяет ресурсы по кластерам согласно политикам. Звучит ровно как наш сценарий.

Что такое KubeFed v2 на практике

Ключевые объекты, с которыми пришлось разобраться:

  • FederatedDeployment. Это не просто Deployment с дополнительными полями - это отдельный CRD, который содержит шаблон (template), переопределения для каждого кластера (overrides) и политику размещения (placement). Всё в одном объекте.
  • KubeFedCluster. Регистрация кластера в федерации со своими kubeconfig-секретами и health-check-ом. Без этого кластер невидим для федерационного контроллера.
  • ReplicaSchedulingPreference. Политика распределения реплик по кластерам - можно задать минимумы, максимумы и вес. Вещь полезная, но с нюансами.

Установка через Helm в host-кластер. Контроллер федерации живёт в одном из кластеров и управляет остальными через API. В нашем случае host-кластером стал основной ЦОД.

Что оказалось сложнее ожидаемого

Предполагали, что сложность будет в концепциях. На деле концепции легли понятно, а сложность оказалась операционной.

Первое - управление kubeconfig-секретами. Для каждого кластера в федерации нужен отдельный ServiceAccount с правами в целевом кластере, сертификат, endpoint. Всё это хранится в секрете в host-кластере. При ротации сертификатов или изменении endpoint нужно обновлять вручную - автоматики нет. Это не баг, это просто beta.

Второе - namespace federation. Namespace нужно явно включать в федерацию через FederatedNamespace. Если забыл - ресурсы просто не уйдут в целевой кластер, и контроллер об этом сообщит не сразу и не слишком громко. Потеряли минут сорок на этом при первой попытке.

Третье - CRD нужно синхронизировать отдельно. Если в кластерах есть кастомные ресурсы, их CRD нужно создавать в каждом кластере самостоятельно - KubeFed v2 не распространяет CRD автоматически. Для нашего пилота с обычными Deployment-ами это не проблема, но для реального продакшна с несколькими операторами - заметный пробел.

Четвёртое - observability федерационного слоя. Метрики контроллера есть, Prometheus-эндпоинт поднят, но понять почему конкретный FederatedDeployment не синхронизируется - это kubectl describe плюс логи контроллера. Нормального статуса в духе «вот что происходит с каждым кластером прямо сейчас» у объекта нет. Есть условия (conditions), но их набор скромный.

Что работает хорошо

При этом то, ради чего затеяли пилот, работает.

Один FederatedDeployment в host-кластере - и Deployment появляется в обоих ЦОД с нужными параметрами. Обновили образ в шаблоне - обновилось в обоих кластерах. Для DR-сценария без кастомных CRD это закрывает главную боль: манифесты больше не расходятся, потому что источник истины один.

ReplicaSchedulingPreference позволила задать минимум реплик для DR-кластера независимо от основного. Если основной перегружен или недоступен, федерационный контроллер может перераспределить реплики - логика рабочая, хотя мы её пока тестируем в нагрузочном стенде, не в живом трафике.

apiVersion: scheduling.kubefed.io/v1alpha1
kind: ReplicaSchedulingPreference
metadata:
  name: app-backend
  namespace: production
spec:
  targetKind: FederatedDeployment
  targetName: app-backend
  clusters:
    dc1:
      minReplicas: 3
      maxReplicas: 10
      weight: 70
    dc2:
      minReplicas: 1
      maxReplicas: 5
      weight: 30

Overrides для специфики кластеров - тоже работают. У нас в ЦОД разные storage class-ы и разные node selector-ы под часть подов, это решается через поле overrides в FederatedDeployment без дублирования всего манифеста.

Где мы сейчас

Пилот работает вторую неделю на managed-инфраструктуре в режиме «наблюдаем». Основной трафик по-прежнему через старый GitOps-пайплайн, KubeFed v2 управляет несколькими некритичными сервисами. Хотим поймать хотя бы один реальный failover прежде чем перекладывать туда что-то важное.

Главный вывод пока такой: концепция федерации через единый API работает, и для DR без кастомных операторов - это рабочий инструмент уже сейчас. Но beta есть beta: операционная часть требует ручного труда там, где хотелось бы автоматики, а прозрачность состояния федерационного слоя оставляет желать лучшего. Если идти в production - нужен нормальный runbook для нескольких сценариев отказа, которые мы сейчас и составляем.

В любом случае альтернатива - поддерживать два независимых набора манифестов вручную - хуже. Так что продолжаем.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.