Привет, это Марат Сахабетдинов, руководитель группы развития инфраструктуры ITSM 365.
Основная цель нашей компании — создание надежного, удобного и гибкого ПО для автоматизации операционных бизнес-процессов в облаке по модели SaaS. Сервис построен на базе функциональной low-code платформы.
Три года назад мы приняли решение сменить облачную инфраструктуру и перейти с виртуальных машин на контейнеризацию в Kubernetes.
О причинах, выборе провайдера и по какому плану действовали — в этой статье.
Как мы работали до Kubernetes
Как раньше, так и сейчас каждому клиенту мы выдаем выделенный инстанс платформы.
В целом, архитектура платформы является классической: реверс-прокси, приложение, база данных, файловое хранилище. На деле за входящий трафик отвечает Nginx. Само приложение — монолит на Java с нативными мобильными клиентами для Android и iOS. В качестве СУБД выступает PostgreSQL, а файлы расположены отдельно в S3-совместимом хранилище облачного провайдера.
До перехода на Kubernetes наша инфраструктура в основном размещалась на виртуальных машинах. Все стандартные операции, такие как деплой или обновление были автоматизированы. Ядро автоматизации в такой инфраструктуре представляет собой систему на базе платформы, сервисов на Python, набора плейбуков Ansible и bash-скриптов. При этом, управление частью конфигураций приложений осуществлялось не централизованно и в полуручном варианте.
Почему решили переехать
Во время работы мы сталкивались с определенными особенностями, которые впоследствии стали причинами для перехода на Kubernetes. Основные моменты, которые можно выделить:
Дрифт конфигурации. Из-за отсутствия инструментов для управления конфигурацией, часть параметров приложения мы правили вручную. В конечном итоге дрифт стал отрицательно влиять практически на все аспекты эксплуатации приложения.
Нестабильность обновления. Процесс обновления приложения на мажорные версии может включать в себя немало операций, а это, в свою очередь, увеличивает шанс на непредвиденный исход. Также со временем увеличивается продолжительность процесса, что отрицательно сказывается на итоговом результате.
Сложность управления балансировщиком. Для Nginx была необходимость в создании достаточно развитой системы управления конфигурацией.
Важно отметить, что у команды был положительный опыт работы с Docker и Docker Compose и немного Kubernetes. На момент принятия решения, Kubernetes в своей области уже был стандартом, поэтому выбор был не сложным, хотя предварительно мы ознакомились с Nomad и Mesos.
Критерии выбора провайдера
Мы рассматривали как решения от облачных провайдеров, так и self-hosted — установку приложения на свой сервер.
Основным функциональным требованием было наличие подключаемых дисков, persistent volume, так как приложение хранит часть данных рядом на диске. Для self-hosted понадобилось бы использовать программную систему хранения данных, например, ceph, и значительно погружаться в её администрирование. К тому же, появились бы дополнительные сложности с вводом в эксплуатацию новых нод. Поэтому, мы решили сделать выбор в пользу облачных провайдеров.
Проанализировав российский рынок, а выбор на тот момент был небольшой, мы приняли решение воспользоваться услугами VK Cloud (на тот момент Mail Cloud Solution) и перенести небольшую часть общей инфраструктуры.
Как проходил «переезд» на Kubernetes
Первоначально мы занимались декомпозицией задачи: пошагово продумали, что и как хотим провести, разделили задачу на этапы и подзадачи, продумали риски и изучили опыт коллег.
В результате весь процесс мы разделили на четыре этапа.
Этап 1. Подготовка к запуску демо-стендов
На этом этапе нам нужно было подготовить основные элементы для работы в кластере, подробнее о каждом шаге:
Выпуск образов
Образы в Kubernetes — основной элемент в контейнеризации, в котором заключены как просто программные зависимости, необходимые для функционирования приложения, так и целые процессы. В нашем случае задача была не самой сложной, так как на базе прошлого опыта образы были частично готовы.
В этом же этапе мы добавили возможность запуска кастомных скриптов из директории /entrypoint.d перед стартом приложения. Это в будущем помогло нам экспериментировать с недостающей функциональностью в образе и оперативно её добавлять.
Подготовка манифестов
Когда мы приступили к этому шагу, перед нам встал выбор: генерировать манифесты с помощью клиентской python-библиотеки или helm-чарта. В итоге мы выбрали чарт из-за относительной простоты старта и возможности передать опыт за пределы нашего проекта. Чарт получился вполне стандартным, хотя определенные сложности вызвало написание правил для Ingress Nginx Controller, учитывающих наши потребности в фильтрации трафика по разным условиям.
Далее в процессе эксплуатации Ingress Nginx Controller выяснилась неприятная особенность в порядке применения ingress-правил. При наличие двух (и более) правил для одного домена с разными значениями параметра whitelist-source-range, будет применено ограничение whitelist-source-range для запросов к Default Backend только из одного правила. Сортировка будет осуществляться по timestamp, а затем сравнением строк. В итоге теряется декларативность, так как необходимо учитывать порядок применения правил.
Настройка автоматизации
В этом шаге мы реализовали базовые операции: создание, остановку и обновление стенда. Скрипты автоматизации стали проще, потому что сложность распределилась на образ и чарт.
Доработка мониторинга
Всю инфраструктуру мы уже мониторили с помощью Prometheus и собственного инструмента NDAP, поэтому при переезде схема особо не изменилась. Единственное, мы добавили через федерацию новый сервер Prometheus и убрали шероховатости в лейблах.
В схеме оповещений об инцидентах никаких изменений не произошло. Alertmanager отправляет алерты на почту, в телеграм и корпоративный сервис, отвечающий за дозвон дежурному инженеру.
Оформление документации
В этом шаге мы зафиксировали новую схему в документации и описали стандартные операции, в том числе дебаг приложения.
Итог: у нас появилась возможность запускать, останавливать и обновлять стенды, предназначенные исключительно для внутреннего использования.
Этап 2. Подготовка к запуску триальных стендов
Когда завершилась основная подготовка, мы перешли к следующему этапу. Нам нужно было посмотреть на реакцию стендов и добавить некоторые сервисы:
Перенос стендов
Перенесли на Kubernetes несколько стендов для внутренних нужд. Начиная с этого момента, начали получать первый реальный опыт эксплуатации нашего приложения в Kubernetes.
Настройка Network Policy
Разграничили и актуализировали сетевые доступы. Кстати, сделать это на Kubernetes стало однозначно проще и надежнее. До этого нам приходилось раскатывать правила iptables на ВМ с помощью ansible-плейбуков, которые требовали больших усилий в поддержке.
Организация логирования
У нас уже был не самый удачный опыт эксплуатации стека ELK (EFK), поэтому выбор пал на не самую популярную в тот период связку Loki и Promtail. Скромные системные требования, хранение логов в S3 и просмотр логов в Grafana сыграли решающую роль в принятии решения.
Итог: мы смогли запускать триальные стенды, для которых уровень критичности понижен.
Этап 3. Подготовка к запуску продуктивных стендов
После того, как мы посмотрели на процесс переноса и функционирования внутренних приложений в Kubernetes, мы начали активно готовиться к запуску клиентских стендов. В этот этап вошли:
Доработка автоматизации
Продолжили процесс реализации стандартных операций — на очереди ресайз стенда.
Настройка Default Backend
В этом шаге мы подготовили сервис, который выдаёт страницу ошибки при недоступности стенда. Впоследствии, этот сервис оброс дополнительной функциональностью: появились персональные клиентские страницы и кастомизируемый текст ошибки в зависимости от статуса обслуживания.
Перенос стендов
В этом шаге мы перенесли первую небольшую группу стендов реальных клиентов в новую инфраструктуру и внимательно следили за работой и реакцией.
Доработка дебага
Завершили начальную подготовку инженеров. Для облегчения процесса написали небольшую утилиту для стандартных операций в процессе дебага приложения.
Итог: смогли запустить продуктивные стенды с небольшими ограничениями: не были реализованы некоторые стандартные операции и разместили не всю информацию для дебага приложений.
Этап 4. Задачи на развитие
В финальном этапе переезда мы спланировали и реализовали вот такие шаги:
Доработка автоматизации
Продолжили процесс реализации стандартных операций — приостановка и возобновление стенда.
Мониторинг
Скорректировали дашборды с учетом новых лейблов Prometheus в Kubernetes.
Перенос стендов
По результату предыдущего опыта приняли решение перенести еще одну группу стендов.
Доработка дебага
Разработали решение для периодического снятия стеков потоков с приложения. Данные стали отправляться в Loki аналогично логам, а мы смогли смотреть в Grafana метрики, логи и стеки.
Сроки и объём работы
Переезд от декомпозиции до момента переноса стендов в заключительном этапе занял чуть больше двух месяцев работы 1.5 человек.
Как работаем сейчас
Особенностью для команды стало то, что «переехали» не полностью. Часть стендов осталась на виртуальных машинах по причине значительных трудозатрат на согласование миграции.
Благодаря текущему опыту работы в гибридной инфраструктуре: в классической и Kubernetes, мы получили возможность постоянно сравнивать два решения на всех этапах работы.
Через год мы подобрали альтернативного провайдера — Yandex Cloud. Для перехода была оперативно подготовлена инфраструктура и запущены новые стенды. Расширение прошло относительно легко и безболезненно. Сейчас мы можем легко переехать в любой кластер Kubernetes, потому что мы не привязаны к каким-то особенностям конкретного провайдера, (кроме наличия persistent volumes.
Вывод и общие впечатления
В результате перехода на Kubernetes:
Решились проблемы с дрифтом.
Изменилась и была доработана система управления конфигурацией. Попутно улучшили её за счет новых подходов, характерных для Kubernetes.
Процесс обновления стал более гладким. Избавились от проблем с зависимостями.
С балансировщиком хотя и остались сложности, но в целом решена проблема конфигурирования.
В целом, получили больше инструментов для декларативного управления инфраструктурой и описания в виде кода.
Для компании, которая работает с облачным продуктом, современный формат облачной инфраструктуры Kubernetes — это стандарт. Переход дал нам экспертность в области Kubernetes и запуске нашего продукта — платформы в рамках Kubernetes.