Добро пожаловать в серию кратких руководств по Kubernetes. Это регулярная колонка с самыми интересными вопросами, которые мы получаем онлайн и на наших тренингах. Отвечает эксперт по Kubernetes.
Сегодняшний эксперт — Даниэль Поленчик (Daniele Polencic). Даниэль работает инструктором и разработчиком ПО в Learnk8s.
Если вы хотите получить ответ на свой вопрос в следующем посте, свяжитесь с нами по электронной почте или в Твиттере: @learnk8s.
Пропустили предыдущие посты? Ищите их здесь.
Как соединить кластеры Kubernetes в разных дата-центрах?
Кратко: скоро выходит Kubefed v2, а еще советую почитать о Shipper и проекте multi-cluster-scheduler.
Довольно часто инфраструктура реплицируется и распределяется по разным регионам, особенно в контролируемых средах.
Если один регион недоступен, трафик перенаправляется в другой, чтобы избежать перебоев.
С Kubernetes можно использовать схожую стратегию и распределять рабочие нагрузки по разным регионам.
У вас может быть один или несколько кластеров на команду, регион, среду или на комбинацию этих элементов.
Ваши кластеры могут размещаться в различных облаках и в локальной среде.
Но как спланировать инфраструктуру для такого географического разброса?
Нужно создать один большой кластер на несколько облачных сред по единой сети?
Или завести много маленьких кластеров и найти способ контролировать и синхронизировать их?
Один руководящий кластер
Создать один кластер по единой сети не так-то просто.
Представьте, у вас авария, потеряна связность между сегментами кластера.
Если у вас один мастер-сервер, половина ресурсов не смогут получать новые команды, потому что им не удастся связаться с мастером.
И при этим у вас старые таблицы маршрутизации (kube-proxy
не может загрузить новые) и никаких дополнительных pod’ов (kubelet не может запрашивать обновления).
Что еще хуже, если Kubernetes не видит узел, он помечает его как потерянный и распределяет отсутствующие pod’ы по существующим узлам.
В итоге pod’ов у вас в два раза больше.
Если вы сделаете по одному мастер-серверу на каждый регион, будут проблемы с алгоритмом достижения консенсуса в базе данных etcd. (прим. ред. — На самом деле база данных etcd не обязательно должна находится на мастер-серверах. Ее можно запустить на отдельной группе серверов в одном регионе. Правда, получив при этом точку отказа кластера. Зато быстро.)
etcd использует алгоритм raft, чтобы согласовать значение, прежде чем записать его на диск.
То есть большинство экземпляров должны достичь консенсуса, прежде чем состояние можно будет записать в etcd.
Если задержка между экземплярами etcd резко вырастает, как в случае с тремя экземплярами etcd в разных регионах, требуется много времени, чтобы согласовать значение и записать его на диск.
Это отражается и на контроллерах Kubernetes.
Менеджеру контроллеров нужно больше времени, чтобы узнать об изменении и записать ответ в базу данных.
А раз контроллер не один, а несколько, получается цепная реакция, и весь кластер начинает работать очень медленно.
etcd настолько чувствителен к задержке, что в официальной документации рекомендуется использовать SSD вместо обычных жестких дисков.
Сейчас не существует хороших примеров большой сети для одного кластера.
В основном, сообщество разработчиков и группа SIG-cluster пытаются понять, как оркестрировать кластеры так же, как Kubernetes оркестрирует контейнеры.
Вариант 1: федерация кластеров с kubefed
Официальный ответ от SIG-cluster — kubefed2, новая версия исходного клиента и оператора kube federation.
Впервые управлять коллекцией кластеров как единым объектом пробовали с помощью инструмента kube federation.
Начало было хорошим, но в итоге kube federation так и не стал популярным, потому что поддерживал не все ресурсы.
Он поддерживал объединенные поставки и сервисы, но, к примеру, не StatefulSets.
А еще конфигурация федерации передавалась в виде аннотаций и не отличалась гибкостью.
Представьте себе, как можно описать разделение реплик для каждого кластера в федерации с помощью одних аннотаций.
Получился полный беспорядок.
SIG-cluster проделали большую работу после kubefed v1 и решили подойти к проблеме с другой стороны.
Вместо аннотаций они решили выпустить контроллер, который устанавливается на кластерах. Его можно настраивать с помощью пользовательских определений ресурсов (Custom Resource Definition, CRD).
Для каждого ресурса, который будет входить в федерацию, у вас есть пользовательское определение CRD из трех разделов:
- стандартное определение ресурса, например деплой;
- раздел
placement
, где вы определяете, как ресурс будет распределяться в федерации; - раздел
override
, где для конкретного ресурса можно переопределить вес и параметры из placement.
Вот пример объединенной поставки с разделами placement и override.
apiVersion: types.federation.k8s.io/v1alpha1
kind: FederatedDeployment
metadata:
name: test-deployment
namespace: test-namespace
spec:
template:
metadata:
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
placement:
clusterNames:
- cluster2
- cluster1
overrides:
- clusterName: cluster2
clusterOverrides:
- path: spec.replicas
value: 5
Как видите, поставка распределена по двум кластерам: cluster1
и cluster2
.
Первый кластер поставляет три реплики, а у второго указано значение 5.
Если вам нужно больше контроля над количеством реплик, kubefed2 предоставляет новый объект ReplicaSchedulingPreference, где реплики можно распределять по весу:
apiVersion: scheduling.federation.k8s.io/v1alpha1
kind: ReplicaSchedulingPreference
metadata:
name: test-deployment
namespace: test-ns
spec:
targetKind: FederatedDeployment
totalReplicas: 9
clusters:
A:
weight: 1
B:
weight: 2
Структура CRD и API еще не совсем готовы, и в официальном репозитории проекта ведется активная работа.
Следите за kubefed2, но помните, что для рабочей среды он пока не годится.
Узнайте больше о kubefed2 из официальной статьи о kubefed2 в блоге о Kubernetes и в официальном репозитории проекта kubefed.
Вариант 2: объединение кластеров в стиле Booking.com
Разработчики Booking.com не занимались kubefed v2, зато придумали Shipper — оператор для поставки на нескольких кластерах, в нескольких регионах и в нескольких облаках.
Shipper чем-то похож на kubefed2.
Оба инструмента позволяют настраивать стратегию развертывания на нескольких кластерах (какие кластеры используются и сколько у них реплик).
Но задача Shipper — снизить риск ошибок при поставке.
В Shipper можно определить ряд шагов, которые описывают разделение реплик между предыдущим и текущим деплоем и объем входящего трафика.
Когда вы отправляете ресурс в кластер, контроллер Shipper пошагово развертывает это изменение по всем объединенным кластерам.
А еще Shipper очень ограничен.
Например, он принимает Helm-чарты как входные данные и не поддерживает vanilla ресурсы.
В общих чертах, Shipper работает следующим образом.
Вместо стандартной поставки нужно создать ресурс приложения, включающий Helm-чарт:
apiVersion: shipper.booking.com/v1alpha1
kind: Application
metadata:
name: super-server
spec:
revisionHistoryLimit: 3
template:
chart:
name: nginx
repoUrl: https://storage.googleapis.com/shipper-demo
version: 0.0.1
clusterRequirements:
regions:
- name: local
strategy:
steps:
- capacity:
contender: 1
incumbent: 100
name: staging
traffic:
contender: 0
incumbent: 100
- capacity:
contender: 100
incumbent: 0
name: full on
traffic:
contender: 100
incumbent: 0
values:
replicaCount: 3
Shipper неплохой вариант для управления несколькими кластерами, но его тесная связь с Helm только мешает.
А вдруг мы все перейдем с Helm на kustomize или kapitan?
Узнайте больше о Shipper и его философии в этом официальном пресс-релизе.
Если хотите покопаться в коде, отправляйтесь в официальный репозиторий проекта.
Вариант 3: "магическое" объединение кластеров
Kubefed v2 и Shipper работают с федерацией кластеров, предоставляя кластерам новые ресурсы через пользовательское определение ресурсов.
Но вдруг вы не хотите переписывать все поставки, StatefulSets, DaemonSets и т. д. для объединения?
Как включить существующий кластер в федерацию, не меняя YAML?
multi-cluster-scheduler — это проект Admirality, который занимается рабочими нагрузками планирования в кластерах.
Но вместо того, чтобы придумывать новый способ взаимодействия с кластером и оборачивать ресурсы в пользовательские определения, multi-cluster-scheduler внедряется в стандартный жизненный цикл Kubernetes и перехватывает все вызовы, которые создают поды.
Каждый создаваемый под сразу заменяется на пустышку.
multi-cluster-scheduler использует веб-hooks для модификации доступа, чтобы перехватить вызов и создать бездействующий pod-пустышку.
Исходный pod проходит через еще один цикл планирования, где после опроса всей федерации принимается решение о размещении.
Наконец, pod поставляется в целевой кластер.
В итоге у вас лишний pod, который ничего не делает, просто занимает место.
Преимущество в том, что вам не пришлось писать новые ресурсы для объединения поставок.
Каждый ресурс, создающий pod, автоматически готов для объединения.
Это интересно, ведь у вас вдруг появляются поставки, распределенные по нескольким регионам, а вы и не заметили. Впрочем, это довольно рискованно, ведь здесь все держится на магии.
Но если Shipper старается, в основном, смягчить последствия поставок, multi-cluster-scheduler выполняет более общие задачи и, возможно, лучше подходит для пакетных заданий.
У него нет продвинутого механизма постепенных поставок.
Больше о multi-cluster-scheduler можно узнать на странице официального репозитория.
Если хотите прочитать о multi-cluster-scheduler в действии, у Admiralty есть интересный случай применения с Argo — рабочими процессами, событиями, CI и CD Kubernetes.
Другие инструменты и решения
Соединение нескольких кластеров и управление ими — сложная задача, универсального решения не существует.
Если вы хотите подробнее изучить эту тему, вот вам несколько ресурсов:
- Submariner от Rancher — инструмент, соединяющий оверлей-сети разных кластеров Kubernetes.
- Розничная сеть Target использует Unimatrix в сочетании Spinnaker, чтобы оркестировать деплой на нескольких кластерах.
- Попробуйте использовать IPV6 и единую сеть в нескольких регионах.
- Можно использовать service mesh, например Istio для соединения нескольких кластеров.
- Cilium, плагин интерфейса сети контейнеров, предлагает функцию cluster mesh, которая позволяет сочетать несколько кластеров
Вот и все на сегодня
Спасибо, что дочитали до конца!
Если вы знаете, как эффективнее соединить несколько кластеров, расскажите нам.
Мы добавим ваш способ к ссылкам.
Особая благодарность Крису Несбитту-Смиту (Chris Nesbitt-Smith) и Венсану де Сме (Vincent De Smet) (инженеру по надежности в swatmobile.io) за то, что прочитали статью и поделились полезной информацией о том, как работает федерация.