kubeadm out of beta: разворачиваем первый production-кластер Kubernetes на bare-metal
kubeadm выходит из beta в Kubernetes 1.8 и становится рекомендованным способом поднять кластер. Разворачиваем HA на трёх master-нодах через keepalived и haproxy - и сразу упираемся в пробелы документации.
kubeadm выходит из beta в Kubernetes 1.8 и становится официально рекомендованным инструментом развёртывания кластера на bare-metal и VM
С выходом Kubernetes 1.8 kubeadm официально покинул статус beta. Это не просто смена лейбла в документации - команда Kubernetes прямо говорит: kubeadm является рекомендованным способом поднять кластер на bare-metal и VM. Мы взяли это за отправную точку и развернули первый полноценный production-кластер для одного из клиентов целиком через kubeadm. Опыт получился показательным.
Зачем вообще bare-metal
У клиента - собственный датацентр, несколько стоек, никакого желания перекладывать данные в облако. Задача: запустить managed-кластер Kubernetes поверх имеющегося железа. До этого мы работали с кластерами на облачных VM через kops и kubeadm в тестовом режиме. Здесь впервые - чистый bare-metal, production, и сразу HA-схема.
HA на трёх master-нодах - это минимум для того, чтобы etcd имел кворум и потеря одной ноды не роняла весь control plane. Схема выглядит понятно на бумаге: keepalived держит виртуальный IP, haproxy балансирует запросы к apiserver на всех трёх мастерах, etcd кластеризован между ними же.
VIP (keepalived)
|
HAProxy
/ | \
API API API
| | |
etcd-etcd-etcd
На практике эта схема потребовала примерно вдвое больше времени, чем мы планировали.
Что не описано в документации
kubeadm в 1.8 умеет инициализировать первый мастер и добавлять рабочие ноды - это всё хорошо документировано. HA-сценарий с несколькими мастерами в официальной документации на момент выхода 1.8 описан как «экспериментальный» и дан очень бегло. Конкретные грабли:
Первое - kubeadm init и advertise-address. При инициализации первого мастера нужно передать --apiserver-advertise-address равный виртуальному IP keepalived, а не реальному IP ноды. Иначе сертификаты генерируются под реальный адрес, и когда VIP переезжает на другую ноду при failover, клиенты начинают получать ошибку TLS. Это нигде прямо не написано - вывели из принципа работы TLS и нескольких часов отладки.
Второе - etcd на тех же нодах. kubeadm по умолчанию поднимает etcd как static pod на той же ноде. При добавлении второго и третьего мастера через kubeadm join нужно вручную добавлять каждый новый узел в кластер etcd до того, как kubeadm завершит настройку. Порядок операций важен, и если его перепутать - получаешь etcd без кворума, который молчаливо отказывается принимать новые ноды.
Третье - haproxy и health checks. haproxy нужно настроить с корректными health check-ами к /healthz на каждом apiserver. Казалось бы очевидно, но дефолтный TCP-check в нашем случае давал ложноположительные результаты при рестарте apiserver в процессе обновления. Переключились на HTTP check - стало нормально.
Четвёртое - keepalived и VRRP. Если все три ноды в одном L2-сегменте (у нас так), keepalived работает без проблем. Если ноды в разных VLAN - VRRP-пакеты нужно пропускать отдельно, и это зависит от конфигурации коммутаторов, а не от Kubernetes.
Как в итоге прошли инициализацию
Схема, которая сработала:
- Поднять keepalived на всех трёх нодах, убедиться что VIP работает и переезжает при отключении ноды.
- Поднять haproxy на всех трёх нодах, настроить балансировку на локальные apiserver с HTTP health check.
kubeadm initна первом мастере с--apiserver-advertise-address=<VIP>и--apiserver-cert-extra-sans=<VIP>,<real-ip-1>.- Вручную добавить ноды 2 и 3 в etcd-кластер через
etcdctl member add. - Скопировать PKI с первого мастера на второй и третий (kubeadm не делает это автоматически).
kubeadm joinна нодах 2 и 3 с флагом--experimental-control-plane.- Только после этого -
kubeadm joinдля рабочих нод.
Каждый шаг звучит несложно. Вместе - это пол-дня осторожной работы с постоянными проверками состояния etcd и кворума.
Состояние kubeadm сегодня
Инструмент явно дозрел по сравнению с тем, что было в 1.6. Генерация сертификатов, настройка RBAC, kubeconfig для admin - всё это kubeadm берёт на себя и делает правильно. Базовый сценарий «один мастер плюс N рабочих нод» действительно работает из коробки и занимает минут двадцать.
HA-сценарий пока требует дополнительных рук. Флаг --experimental-control-plane в названии содержит честное предупреждение - команда сама его так назвала. Мы рассчитываем что в следующих минорных версиях этот путь обрастёт нормальной документацией и, возможно, большей автоматизацией со стороны самого kubeadm.
Сеть и CNI
Отдельная история - выбор CNI-плагина. На bare-metal без overlay-поддержки со стороны провайдера мы остановились на Calico: он работает в BGP-режиме без encapsulation, что даёт нормальную производительность на физических интерфейсах. Weave и Flannel тоже рассматривали, но Calico лучше ложится на то, что у клиента есть в плане сетевого оборудования.
Установка Calico через kubeadm - стандартный kubectl apply -f после инициализации кластера. Единственный нюанс: нужно передать --pod-network-cidr в kubeadm init заранее, иначе controller-manager не знает о podCIDR и Calico ведёт себя странно.
Итог
Кластер работает. Три мастера, keepalived проверили в бою - убивали ноды по очереди, VIP переезжал за секунды, kubectl продолжал работать. Рабочие ноды добавляются стандартным kubeadm join без каких-либо сюрпризов.
kubeadm как инструмент - хороший выбор для тех, кто разворачивает кластер вручную на своём железе. Только нужно понимать, что документация HA-сценария идёт сильно позади реальных возможностей инструмента. Мы всё это записали в виде runbook-а - при следующем развёртывании будет сильно быстрее.
- Kubernetes 1.8: RBAC стабилен, CRD в beta - смотрим на операторы · 2 октября 2017