Добро пожаловать в серию кратких руководств по Kubernetes. Это регулярная колонка с самыми интересными вопросами, которые мы получаем онлайн и на наших тренингах. Отвечает эксперт по Kubernetes.
Сегодняшний эксперт — Даниэль Поленчик (Daniele Polencic). Даниэль работает инструктором и разработчиком ПО в Learnk8s.
Если вы хотите получить ответ на свой вопрос в следующем посте, свяжитесь с нами по электронной почте или в Твиттере: @learnk8s.
Пропустили предыдущие посты? Ищите их здесь.
Как соединить кластеры Kubernetes в разных дата-центрах?
Кратко: скоро выходит Kubefed v2, а еще советую почитать о Shipper и проекте multi-cluster-scheduler.
Довольно часто инфраструктура реплицируется и распределяется по разным регионам, особенно в контролируемых средах.
Если один регион недоступен, трафик перенаправляется в другой, чтобы избежать перебоев.
С Kubernetes можно использовать схожую стратегию и распределять рабочие нагрузки по разным регионам.
У вас может быть один или несколько кластеров на команду, регион, среду или на комбинацию этих элементов.
Ваши кластеры могут размещаться в различных облаках и в локальной среде.
Но как спланировать инфраструктуру для такого географического разброса?
Нужно создать один большой кластер на несколько облачных сред по единой сети?
Или завести много маленьких кластеров и найти способ контролировать и синхронизировать их?
Один руководящий кластер
Создать один кластер по единой сети не так-то просто.
Представьте себе разделение сети.
Если у вас одна мастер-сервер, половина ресурсов не смогут получать новые команды, потому что им не удастся связаться с мастером.
И при этим у вас старые таблицы маршрутизации (kube-proxy
не может загрузить новые) и никаких дополнительных pod’ов (kubelet не может запрашивать обновления).
Что еще хуже, если Kubernetes не видит узел, он помечает ее как потерянную и распределяет отсутствующие pod’ы по существующим нодам.
В итоге pod’ов у вас в два раза больше.
Если вы сделаете по одному мастер-серверу на каждый регион, будут проблемы с алгоритмом достижения консенсуса в базе данных 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) за то, что прочитали статью и поделились полезной информацией о том, как работает федерация.
Автор: nAbdullin