Как-то в комментах задавали вопрос, чем участие в Слёрме отличается от чтения мануалов по Кубернетес. Я попросил Павла Селиванова, спикера Слёрм-2 и МегаСлёрм, дать небольшой пример того, что он будет рассказывать на Слёрмах. Передаю слово ему.
Я администрирую кластер Кубернетес. Недавно мне понадобилось обновить версию k8s и, в том числе, перезапустить все машины в кластере. Я начал процесс в 12:00, и к концу рабочего дня все было готово. Причем в первый раз я еще следил за ходом обновления, а во второй — ушел на обед на 1,5 часа (справедливости ради, прихватив ноутбук). Кластер обновился сам, без моего участия и незаметно для клиентов, разработка ничего не заметила, деплои продолжались, сервис работал как обычно.
Как это выглядело.
Вероятные проблемы
При ребуте машин есть два плохих сценария.
- Разработчик запустил приложение/redis в один инстанс. Как аккуратно ни выводи машину из обслуживания, случится даунтайм.
- Есть 2 реплики приложения, и в одну идет деплой. Она погасла, осталась единственная реплика, и тут приходит админ и гасит последнюю реплику. Опять же, пока не поднимется реплика после деплоя, будет даунтайм.
Я бы мог согласовать ребут с разработкой, мол, остановите деплой, проверьте инстансы, я буду перезапускать машины, но мне по душе идея DevOps, что человеческое общение нужно свести к минимуму. Лучше один раз настроить автоматизацию, чем каждый раз согласовывать свои действия.
Условия задачи
Я пользуюсь Амазоном с его удобством и стабильностью. Все автоматизировано, можно создавать и гасить виртуалки, проверять их доступность и т.д.
Кластер Кубернетес разворачивается, управляется и обновляется через утилиту kops, которую я очень люблю.
При обновлении kops автоматически дрейнит ноду (kubectl drain node), дожидается, пока все будет эвакуировано с этой ноды, удаляет ее, создает в Амазоне новую ноду с нужной версией компонентов Кубернетес, присоединяет ее к кластеру, проверяет, что нода хорошо въехала в кластер, и так со всеми нодами по кругу, пока везде не будет нужная версия Кубернетес.
Решение
В CI я при помощи kube-lint проверяю все манифесты, которые будут запущены в Кубернетес. Helm Template выкидывает все, что собирается запускать, я на выгрузку натравливаю линтер, который все оценивает по заданным правилам.
Например, одно из правил гласит, что для любого приложения в кластере Кубернетес количество реплик должно быть не меньше 2.
Если реплик нет вообще (что по дефолту равняется 1), их 0 или 1, kube-lint запрещает деплой в кластер, чтобы избежать проблем в будущем.
Допустим, деплой by design устроен так, что остается одна реплика. На этот случай есть pod disruption budget, где для приложения, запущенного в Кубернетес, устанавливается max_unavailable и min_available. Если нужно, чтобы всегда была хотя бы 1 реплика, ставим min_available = 1.
Было 2 реплики, запустился деплой, 1 реплика умерла, осталась 1. На машине, где реплика живет, админ запускает kubectl drain node. По идее Кубернетес должен начать эту живую реплику удалять и перевозить на другую ноду. Но срабатывает pod disruption budget. Кубернетес говорит админу: извини, тут живет реплика, если мы ее удалим, то нарушим pod disruption budget. Умный drain node висит до истечения таймаута и пытается задрейнить ноду. Если деплой окончен и обе реплики стали доступны, реплика на этой ноде будет выведена.
На МегаСлёрме я покажу полный набор правил, который позволяет мне пить кофе в кафешке, пока кластер Кубернетес обновляется с рестартом всех нод.
Мои темы на Слёрме:
- Знакомство с Kubernetes, основные компоненты
- Устройство кластера, основные компоненты, отказоустойчивость, сеть k8s
- Продвинутые абстракции Kubernetes
- Логирование и мониторинг
Мои темы на МегаСлёрме:
- Процесс создания отказоустойчивого кластера изнутри
- Авторизация в кластере при помощи внешнего провайдера
- Безопасные и высокодоступные приложения в кластере
- Реализация стратегий деплоя отличных от RollingUpdate
- Траблшутинг в Kubernetes