Southbridge в Челябинске и Битрикс в Kubernetes

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В Челябинске проходят митапы системных администраторов Sysadminka, и на последнем из них я делал доклад о нашем решении для работы приложений на 1С-Битрикс в Kubernetes.


Битрикс, Kubernetes, Сeph — отличная смесь?


Расскажу, как мы из всего этого собрали работающее решение.


Поехали!



Митап прошел 18 апреля Челябинске. Про наши митапы можно почитать в Timepad и посмотреть на ютубе.


Если хотите прийти к нам с докладом или как слушатель — велкам, пишите на vadim.isakanov@gmail.com и в Телеграм t.me/vadimisakanov.


Мой доклад


Видео доклада о Битрикс в Kubernetes


Слайды


Решение «Битрикс в Kubernetes, версия Southbridge 1.0»


Я расскажу о нашем решении в формате «для чайников в Kubernetes», как это было сделано на митапе. Но предполагаю, что слова Битрикс, Docker, Kubernetes, Ceph вам известны хотя бы на уровне статей в Википедии.


Что вообще есть готового про Битрикс в Kubernetes?


Во всем интернете очень мало информации о работе приложений на Битрикс в Kubernetes.
Я нашел только такие материалы:


Доклад Александра Сербула, 1С-Битрикс, и Антона Тузлукова из Qsoft:



Рекомендую послушать его.


Разработка собственного решения от пользователя serkyron на Хабре.
Нашел еще такое решение.


Ииии… собственно, все.


Предупреждаю, качество работы решений по ссылкам выше мы не проверяли :-)
Кстати, при подготовке нашего решения я общался с Александром Сербулом, тогда его доклада еще не было, поэтому в моих слайдах есть пункт «Битрикс не пользуется Kubernetes».


Но зато готовых Docker образов для работы Битрикс в Docker уже много: https://hub.docker.com/search?q=bitrix&type=image


Достаточно ли этого для создания полноценного решения для Битрикс в Kubernetes?
Нет. Есть большое количество проблем, которые нужно решить.


В чем проблемы с Битрикс в Kubernetes?


Первая — готовые образы из Dockerhub не подходят для Kubernetes


Если мы хотим построить микросервисную архитектуру (а в Kubernetes мы обычно хотим), приложение в Kubernetes нужно разделять на контейнеры и добиваться того, чтобы каждый контейнер выполнял одну маленькую функцию (и делал это хорошо). Почему только одну? Если кратко — чем проще, тем надежнее.
Если подлиннее —- посмотрите эту статью и видео, пожалуйста: https://habr.com/ru/company/southbridge/blog/426637/


Docker образы в Dockerhub в основном построены по принципу «все в одном», поэтому нам пришлось все-таки делать свой велосипед и даже образы делать с нуля.


Вторая — код сайта правится из админ-панели


Создали новый раздел на сайте — обновился код (добавилась директория с названием нового раздела).


Изменили свойства компонента из админ-панели — изменился код.


Kubernetes «по умолчанию» с таким работать не умеет, контейнеры должны быть не изменяемыми (Stateless).


Причина: каждый контейнер (под) в кластере обрабатывает только часть трафика. Если изменить код только в одном контейнере (поде), то в разных подах код будет разным, сайт будет работать по-разному, разным пользователям будут показываться разные версии сайта. Так жить нельзя.


Третья — нужно решать вопрос с деплоем


Если у нас монолит и один «классический» сервер, все совсем просто: разворачиваем новую кодовую базу, проводим миграцию БД, переключаем трафик на новую версию кода. Переключение происходит мгновенно.
Если у нас сайт в Kubernetes, распилен на микросервисы, контейнеров с кодом много — ой. Нужно собирать контейнеры с новой версией кода, выкатывать их вместо старых, правильно выполнять миграцию БД, и в идеале делать это незаметно для посетителей. Благо, в этом Kubernetes нам помогает, поддерживая целую тучу разных видов деплоя.


Четвертая — нужно решать вопрос с хранением статики


Если ваш сайт весит «всего лишь» 10 гигабайт и вы развернете его целиком в контейнерах, вы получите контейнеры весом в 10 гигабайт, которые будут деплоиться вечность.
Нужно хранить самые «тяжелые» части сайта вне контейнеров, и встает вопрос, как правильно это делать


Чего нет в нашем решении


Совсем весь код Битрикс на микрофункции/микросервисы не разрезан (так, чтобы регистрация отдельно, модуль интернет-магазина отдельно, и т.п.). Всю кодовую базу мы храним в каждом контейнере целиком.


Базу в Kubernetes также не храним (я все же реализовывал решения с базой в Kubernetes для окружений разработчиков, но не для продакшн).


Администраторам сайта все-таки будет заметно, что сайт работает в Kubernetes. Функция «проверка системы» работает некорректно, для редактирования кода сайта из админ-панели нужно сначала нажимать кнопку «хочу отредактировать код».


С проблемами определились, с необходимостью реализации микросервисности определились, цель ясна — получить работающую систему для работы приложений на Битрикс в Kubernetes, сохранив и возможности Битрикс, и преимущества Kubernetes. Начинаем реализацию.


Архитектура


Много «рабочих» подов с вебсервером (worker'ы).
Один под с крон-тасками (обязательно только один).
Один upgrade под для редактирования кода сайта из админ-панели (также обязательно только один).



Решаем вопросы:


  • Где хранить сессии?
  • Где хранить кэш?
  • Где хранить статику, не размещать же гигабайты статики в куче контейнеров?
  • Как будет работать база данных?

Docker образ


Начинаем со сборки Docker образа.


Идеальный вариант — у нас один универсальный образ, на его основе мы получаем и worker-поды, и поды с кронтасками, и upgrade поды.


Мы сделали как раз такой образ.


В него включен nginx, apache/php-fpm (можно выбрать при сборке), msmtp для отправки почты, и cron.


При сборке образа в директорию /app копируется полная кодовая база сайта (за исключением тех частей, что мы вынесем в отдельный shared storage).


Микросервисность, сервисы


worker поды:


  • Контейнер с nginx + контейнер apache/php-fpm + msmtp
  • msmtp вынести в отдельный микросервис не вышло, Битрикс начинает возмущаться, что не может напрямую отправить почту
  • В каждом контейнере полная кодовая база.
  • Запрет на изменение кода в контейнерах.

cron под:


  • контейнер с apache, php, cron
  • в комплекте полная кодовая база
  • запрет на изменение кода в контейнерах

upgrade под:


  • контейнер с nginx + контейнер apache/php-fpm + msmtp
  • запрета на изменение кода в контейнерах нет

хранилище сессий


хранилище кэша Битрикс


Еще важно: пароли для подключения ко всему, от базы данных до почты, мы храним в kubernetes secrets. Получаем бонус, пароли видны только тем, кому мы даем доступ к секретам, а не всем, у кого есть доступ к кодовой базе проекта.


Хранилище для статики


Можно использовать что угодно: ceph, nfs (но nfs не рекомендуем для продакшн), network storage от «облачных» провайдеров, etc.


Хранилище нужно будет подключать в контейнерах в /upload/ директорию сайта и другие директории со статикой.


База данных


Для простоты рекомендуем выносить базу за пределы Kubernetes. База в Kubernetes — отдельная сложная задача, она сделает схему на порядок сложнее.


Хранилище сессий


Используем memcached :)


Он хорошо справляется с хранением сессий, кластеризуется, «нативно» поддерживается как session.save_path в php. Такая система много раз отработана еще в классической монолитной архитектуре, когда мы строили кластеры с большим числом веб-серверов. Для деплоя мы используем helm.


$ helm install stable/memcached --name session

php.ini — здесь в образе заданы настройки для хранения сессий в memcached


Мы использовали Environment Variables для передачи данных о хостах с memcached https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/.
Это позволяет использовать один и тот же код в окружениях dev, stage, test, prod (имена хостов memcached в них будут отличаться, поэтому в каждое окружение нам нужно передавать уникальное имя хостов для сессий).
Хранилище кэша Битрикс


Нам нужно откаузостойчивое хранилище, в которое все поды могли бы писать и из которого могли бы читать.


Также используем memcached.
Это решение рекомендуется самим Битрикс.


$ helm install stable/memcached --name cache

bitrix/.settings_extra.php — здесь в Битрикс задается, где у нас хранится кэш


Так же используем Environment Variables.


Кронтаски


Есть разные подходы к выполнению кронтасков в Kubernetes.


  • отдельный deployment с подом для выполнения кронтасков
  • cronjob для выполнения кронтасков (если это web app — с wget https://$host$cronjobname, или kubectl exec внутрь одного из worker подов, и т.п.)
  • etc.

Можно спорить о наиболее правильном, но в этом случае мы выбрали вариант "отдельный deployment с подами для кронтасков"


Как это сделано:


  • крон-таски добавляем через ConfigMap либо через файл config/addcron
  • в одном экземпляре запускаем контейнер, идентичный worker-поду + разрешаем выполнение крон-тасков в нем
  • используется та же кодовая база, благодаря унификации сборка контейнера проста

Что хорошего получаем:


  • имеем работающие кронтаски в окружении, идентичном окружению разработчиков (docker)
  • кронтаски не нужно "переписывать" для Kubernetes, они работают в том же виде и в той же кодовой базе, что и раньше
  • крон-таски могут добавлять все члены команды с правами commit в production ветку, а не только админы

Модуль Southbridge K8SDeploy и редактирование кода из админ-панели


Мы ведь говорили про upgrade под?
А как направлять туда трафик?
Ура, мы написали для этого модуль на php :) Это небольшой классический модуль для Битрикс. Его еще нет в открытом доступе, но мы планируем его открыть.
Модуль устанавливается как обычный модуль в Битрикс:



И выглядит вот так:



Он позволяет задать cookie, которая идентифицирует администратора сайта и позволяет Kubernetes отправлять трафик на upgrade под.


Когда изменения завершены, нужно нажать git push, изменения кода будут отправлены в git, далее система соберет образ с новой версией кода и «раскатает» ее по кластеру, заменив старые поды.


Да, несколько костыльно, но при этом мы сохраняем микросервисную архитектуру и не забираем у пользователей Битрикс любимую возможность поправить код из админки. В конце концов, это опция, можно задачу правки кода решить по-другому.


Helm чарт


Для сборки приложений в Kubernetes мы, как правило, используем пакетный менеджер Helm.
Для нашего решения Битрикс в Kubernetes Сергей Бондарев, наш ведущий системный администратор, написал специальный Helm чарт.


Он выполняет сборку worker, ugrade, cron подов, настраивает ingress'ы, сервисы, передает переменные из Kubernetes secrets в поды.


Код мы храним в Gitlab, и сборку Helm также запускаем из Gitlab.


Если кратко, это выглядит так


$ helm upgrade --install project .helm --set image=registrygitlab.local/k8s/bitrix -f .helm/values.yaml --wait --timeout 300 --debug --tiller-namespace=production

Helm также позволяет делать «бесшовный» откат, если вдруг при деплое что-то пошло не так. Приятно, когда не вы в панике «фиксите код по фтп, потому что прод упал», а Kubernetes делает это автоматически, причем без даунтайма.


Деплой


Да, мы фанаты Gitlab & Gitlab CI, используем его :)
При коммите в Gitlab в репозитарий проекта Gitlab запускает пайплайн, который выполняет разворачивание новой версии окружения.


Этапы:


  • build (собираем новый Docker образ)
  • test (тестируем)
  • clean up (удаляем тестовое окружение)
  • push (отправляем его в Docker registry)
  • deploy (разворачиваем приложение в Kubernetes через Helm).


Ура, готово, внедряем!
Ну или задаем вопросы, если они есть.


Итак, что мы сделали


С технической точки зрения:


  • докеризировали Битрикс;
  • «разрезали» Битрикс на контейнеры, каждый из которых выполняет минимум функций;
  • добились stateless состояния контейнеров;
  • решили проблему с обновлением Битрикс в Kubernetes;
  • все функции Битрикс продолжили работать (почти все);
  • отработали деплой в Kubernetes и откат между версиями.

С точки зрения бизнеса:


  • отказоустойчивость;
  • инструменты Kubernetes (простая интеграция с Gitlab CI, бесшовный деплой, etc);
  • пароли в секретах (видны только тем, кому прямо предоставлен доступ к паролям);
  • удобно делать дополнительные окружения (для разработки, тестов и др) внутри единой инфраструктуры.
Источник: https://habr.com/ru/company/southbridge/blog/456608/


Интересные статьи

Интересные статьи

Can I just once again state my love for [WireGuard] and hope it gets merged soon? Maybe the code isn't perfect, but I've skimmed it, and compared to the horrors that are OpenVPN and IPS...
На митапе Михаил Кабанов из DINS расскажет, как DevOps-инженеры могут влиять на прибыль компании, а Павел Селиванов из Mail.ru Cloud Solutions объяснит, какие возможности есть у names...
Для Kubernetes есть несколько вариантов обновления ресурсов: apply, edit, patch и replace. С тем, что каждый из них делает и когда их применять, есть путаница. Давайте разберемся. ...
Всем привет! Сегодня мы хотим пригласить вас принять участие в осеннем митапе Moscow Kubernetes Meetup в Acronis, который будет полностью посвящен технологиям Kubernetes, а также практикам исполь...
Этот пост будет из серии, об инструментах безопасности, которые доступны в Битриксе сразу «из коробки». Перечислю их все, скажу какой инструмент в какой редакции Битрикса доступен, кратко и не очень р...