Дисклеймер: Данная статья не несёт в себе практических описаний того, как реализовать выкладку вашего приложения в Kubernetes. Какую конечную версию решения и какие инструменты будете использовать — решать только вам.
Контейнеризированные приложения продолжают захватывать мир. Та революция, которую начал Docker, будет приобретать всё большие масштабы. После Docker к нам в 2014 году, а если брать версию 1.0 — в 2015, пришёл Kubernetes, и, давайте скажем честно, он классный. Он позволяет решать кучу задач в автоматическом режиме, из-за которых вы, скорее всего, как OPS-инженер могли плохо спать по ночам. Kubernetes принёс нам новый уровень абстракций над контейнеризированными приложениями. И сейчас большинство компаний стремятся перетащить в него свою рабочую нагрузку и управлять через него своими приложениями. А там, где есть приложения, нам надо продумать, как мы будем их выкатывать. Об этом сегодня и поговорим.
Модели доставки кода в кластер
И вот тут я должен сделать первое и главное для нас уточняющее разъяснение. На мой взгляд, существует две модели доставки кода в кластер — условные Pull и Push. В модели Pull мы передаём новое желаемое состояние кластера путём применения манифестов через kubectl, Helm, Kustomize или любым другим методом. В модели Push реализован подход GitOps.
В кластере Kubernetes есть механизм, который следит за Git-репозиторием, и в случае изменения в нём кода, этот механизм приводит кластер в состояние, чётко описанное этим кодом. Почему это хорошо? Потому что у вас есть один источник правды — SST (Single Source of Truth). Допустим, ручное изменение количества ReplicaSet c двух до трёх не будет сохранено на долгое время, так как механизм согласования вернёт кластер в состояние, описанное в Git-репозитории.
Деплой манифестов. Модель Pull
Взглянем на изображение ниже.
Разработчик пушит изменения в Git-репозиторий, в данном случае это GitLab, но может быть Bitbucket или GitHub, это неважно. В этом репозитории также хранится ваше описание Kubernetes, это могут быть Helm-чарты или просто манифесты YAML — решать вам в зависимости от ваших предпочтений. Вы можете хранить файлы описания в отдельном репозитории. Но тогда в случае, например, с GitLab, нужно будет воспользоваться хуками для активации выкладки с изменёнными параметрами после сборки образа.
Продолжим. Изменения в коде триггерят активацию пайплайна сборки. Как вы будете собирать изменения тоже неважно — Jenkins, GitLab CI/CD или любой другой механизм. Главное — понять концепцию. Активация пайплайна заставляет сборщик собрать новый образ приложения и опубликовать его в реестре контейнеров. Используйте теги или переменные окружения для версионирования образов.
Далее наш собранный образ проходит автоматические тесты. Затем мы разворачиваем наш релиз — в примере с помощью Helm — в наш кластер Kubernetes. Не забываем про встроенную возможность сделать rollback. В общем, так выглядит стандартная схема деплоя приложения в кластер. Обязательно продумайте, как у вас будет выполняться миграция, как эффективно убрать даунтайм приложения или то, как и куда будут попадать пользователи во время деплоя.
GitOps подход. Модель Push
Давайте взглянем на схему реализации push-модели.
Данный подход предполагает использование двух репозиториев. В первом репозитории мы храним код нашего приложения. Там же мы храним Docker-файлы для сборки, но не храним Helm-чарты или описания желаемого состояния кластера в простых манифестах или с применением kustomize. Триггер сборки активирует пайплайн, который собирает и тестирует новый образ приложения, а также пушит его в registry.
Затем вносятся изменения в репозиторий с манифестами, которые описывают желаемое состояние кластера. Далее оператор синхронизации — в данном случае представлен Argo CD, однако вы можете использовать Flux2 — определяет, что текущее состояние не соответствует описанному состоянию в репозитории, и приводит кластер к этому состоянию. Оператор синхронизации является приложением, предварительно задеплоенным в кластер. Хранение манифестов в отдельном репозитории с их синхронизацией упрощает ваш CI-пайплайн, избавляя его от задач выката приложения.
Сегодня мы рассмотрели две основные модели CI/CD-доставки кода в кластер Kubernetes. Надеюсь, после этой статьи стало немного понятнее, как реализовать выкладку вашего приложения. По какой модели лучше работать — решать вам. Всё будет зависеть от тех задач, которые выполняет приложение, и от того, из каких компонентов оно состоит. Важно использовать Kubernetes с умом и не забывать, что мы используем инструменты для достижения цели, а не ставим цели, чтобы для них подходили конкретные инструменты.
Читайте также нашу прошлую статью «Пошаговая настройка Kube-Prometheus-Stack для мониторинга Kubernetes»