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);
    • пароли в секретах (видны только тем, кому прямо предоставлен доступ к паролям);
    • удобно делать дополнительные окружения (для разработки, тестов и др) внутри единой инфраструктуры.
    Southbridge
    351,48
    Обеспечиваем стабильную работу серверов
    Поделиться публикацией

    Комментарии 8

      +1
      Битрикс, Kubernetes, Сeph — найди лишнее.
      Скажите, но зачем распихивать код одной платной сторонней CMS по разным контейнерам? Прочитал введение, дочитал до
      с необходимостью реализации микросервисности определились

      И по-моему, всё-таки эта часть выпала из повествования. Почему это необходимо?
        0
        потому, я думаю, что битрикс из коробки не работает так, как бы хотелось клиенту… и разработчики видимо сами не знают как же сделать сей продукт быстрее и поворотлевее. А то для WP достаточно дохлого хостинга, а для битрикса и VPS за 1к рубль порой не достаточно!
          0
          Погонял конфигуратор Firstvds — да, для старых и измученных bitrix на PHP 5.3 порой и сервера за 3500/месяц не хватает. Если PHP не 7.0, стоит нанять программиста, пусть посмотрит slow.log БД и перепишет свой код под PHP 7.0/7.1, это будет более разумным вложением, чем заваливать старое ПО железом.
          Или хотя бы memcached добавить да агенты на cron перевести.
          +1
          Возможно, будет правильнее сказать так — «если с необходимостью реализации микросервисности вы определились, делаем ...»
          0
          А каким макаром кубернетес и цеф поможет ускорить битрикс? По моему нужно просто уметь настраивать битрикс24 и серверное окружение для него и не нужен сервер за 1к и тем более цеф и кубернетес, имхо.
            +1
            В случае Kubernetes, как правило, речь про суммы на порядки больше 1000 р/мес :)
            Это нужно, если есть желание добиваться аптайма с большим числом «девяток», поддерживать работу сайта на большом числе серверов, делать десятки апдейтов кода в день, иметь много копий сайта (для разработчиков, автоматических тестов и др.) и т.д… Если строить такую инфраструктуру без Кубернетес и подобных технологий, «руками» управлять серверами, ее поддержка становится сложнее, чем с Кубернетес и другими оркестраторами.
              +1
              Kubernetes & Ceph не ускоряют работу сайта. Из-за сетевых задержек (разные части сайта в разных контейнерах) скорость работы даже немного упадет. Но зато владелец сайта получит большую надежность и инфраструктуру, которая может выдержать много апдейтов кода, изменений в структуре, отключений любого из серверов без даунтайма.
              0
              в идеале конечно просто вычеркнуть битрикс из этого списка

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое