This is fine


Я хочу рассказать история, как запускали приложение в Openshift. Так же по ходу пьесы рассмотрим утилиты для управления приложением внутри Openshift. Это расшифровка выступления на kubernetes SPB meetup #3..


Цель


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


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


Пререквизиты


Deploy


Приложение должно работать в совершенно разных окружениях. Как результат наша документация по установке, весьма, обширная. Но если посмотреть свысока, то ничего сложного:


  • Применить схему БД.
  • Настроить сервер приложений.
  • Установить лицензию.
  • Настроить приложение и интеграции с внешними системами.

Deploy


Но мир жесток, у нас был ряд ограничений:


  • Приложение можно собирать только на специально Jenkins, который занимается подписанием. И только там.
  • Нет доступа из клиентского Openshift в окружение для разработки.
  • По ряду идеологических причин Не было возможности переиспользовать существующие Docker образы для разработки.
  • У нас есть ansible playbooks для установки и настройки приложения на серверах.

Ansible-container demo


Ansible-container


Ansible container это открытое программное обеспечение, которое преследует цель автоматизации сборки контейнеров, деплоя и управления процессом. Как можно догадаться из названия. для сборки контейнеров используется Ansible. У нас уже были написано Ansible роли для инсталляции и развертывания приложения поверх серверов, так что мы решили не изобретать велосипед и переиспользовать их. Не то что бы это идеальный инструмент, но быстрое переиспользование существующих ролей оказалось решающим фактором для демо.


По большому счету, что бы сделать сделать демо мы взяли существующие роли, настраивающие всё и вся, и сделали "монолитный контейнер". Что собрать контейнер не было особых проблем, т.к. у Openshift есть замечательные рекомендации, но отдельно отмечу:


  • Роли было необходимо было доработать, т.к. мы используем systemd.
  • По умолчанию, в целях безопасности в openshift запрещено использовать некоторые syscall. Как следствие будут нюансы с chroot, sudo. Привет CVE-2019-5736.
  • Аналогично из соображений безопасности контейнер запускается из под пользователя со случайным ID, это так же настраиваемое поведение.

Основная идея в этом пункте, что мы сделали демо ооочень быстро.


Multiple containers demo


Multiple containers


Демо контейнер выполнил свою роль и мы распилили его на отдельные составляющие:


  1. Наше приложение.
  2. База данных.
  3. Внешние сервисы итд...

Multiple containers


Первое с чем столкнулись, как инициализировать базу данных? Понятно что используем миграции, но когда и как их применять? Тут стоит дать ссылку на замечательную статью описывающие устройство POD: PODs life. По большому счету есть несколько подходом:


  • Использовать init-container
  • Использовать системы оркестрации, которые определят порядок развертывания сервисов и накатят миграции когда надо.

Мы решили пойти по пути Init-container. Т.е. в POD нашего приложение, до старта нашего приложения, стартует контейнер, который катит миграции. Но как сконфигурировать само приложение и внешние интеграции?


Initialize the application


Multiple containers


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


  • Использовать системы оркестрации, которые определят порядок развертывания сервисов и применять конфигурацию после старта приложения.
  • Передавать через переменные окружения контейнеру как настроиться.
  • Использовать start hook.
  • Сделать отдельный контейнер, который содержит конфигурацию и применит ее к приложению. Грубо аналог миграция для БД.

Мы выбрали последний подход, т.к. он позволяет делать конфигурацию воспроизводимой и самодостаточной. Только зачем-то изначально сделали этот контейнер в отдельном replication controller с фактором 1.


Multiple containers


Ок, почитаем документацию снова.


A pod (as in a pod of whales or pea pod) is a group of one or more containers (such as Docker containers), with shared storage/network, and a specification for how to run the containers.

POD это группа контейнеров. В итоге наш под состоял из 3 контейнеров


  1. Init container для инициализации a PostgreSQL.
  2. Контейнер с приложение.
  3. Контейнер с конфигурацией приложения.

Инструментарий


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



Openshift templates


Openshift templates


Openshift templates


Плюсы:


  • Нативно и у них отличная документация.

Минусы:


  • Еще один шаблонизатор.
  • Длинные и ужасные YAML файлы.
  • Если у вас есть зависимости между сервисами и их очередностью старта, то будет сложно.

Scripts and template


Custom scripts


Плюсы:


  • Можете использовать отличные инструменты и всю мощь ООП.

Минусы:


  • Костыли, которые поддерживать. И не только вам.

Terraform k8s provider


Terraform k8s provider


Terraform k8s provider


Плюсы:


  • Вы не беспокоитесь об очередности создания элементов инфраструктуры.
  • Можно переиспользовать код инфраструктуры как модули.
  • Можно добавить логику инициализации приложения.

Минусы:


  • Нет поддержки Openshift, только k8s.
  • Иногда устаревшая дока и модули.
  • Еще одна тула в вашей команде.

Ansible-container


Ansible-container


Ansible-container


Плюсы:


  • Make CM, no bash
  • Можно переиспользовать код в виде ролей.
  • В нашем случае один инструмент для всего.

Минусы:


  • Огромные образы, т.к. идут одним слоем.
  • Выглядит покинутым и не поддерживаемым. Был заменен Ansible bender.

Ansible k8s module


Ansible k8s module


Ansible + k8s module


Плюсы:


  • Один плэйбук для описания все инфраструктуры проекта внутри Openshift.
  • Переиспользование кода в виде ролей.
  • Можно добавить логику инициализации приложения.

Минусы:


  • Нет поддержки прокси.
  • Вы заботитесь об удаление. Если объект больше не нужен надо описать его удаление.
  • Вы сами описываете очередность создания элементов инфраструктуры.

Ansible Playbook Bundle


Ansible Playbook Bundle


Утилита Ansible Playbook Bundle (APB) предлагает подход: а давайте запакуем ansible роли для развертывания приложения внутри k8s/openshift в контейнер и будем запускать внутри k8s/openshift.


Плюсы:


  • Всё свое ношу с собой.
  • Тестируемо и воспроизводимо.
  • Интеграция с Service catalogue(дружелюбный веб интерфейс для запуска приложений).

Минусы:


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

Result


Result


Не хочется быть последний инстанцией, но поделюсь своими умозаключениями:



P.S.


Комментарии (23)


  1. amarao
    27.02.2019 16:02
    +1

    С потрясающим интересом прочитал обзор, поскольку прямо сегодня с совещания мы думали о том, как нам «объединять» несколько плейбук из разных репозиториев. К сожалению, каждое из описанных решений слишком openshift/docker-centric (насколько я увидел), и вместо того, чтобы быть инструментом, каждый из них тащит в качестве полиси использование больших монстров…
    Увы.


    1. ultral Автор
      27.02.2019 16:04

      Но создание своего решения, далеко не факт что приведет вас к счастью. Если не секрет к чему склоняетесь?


      1. amarao
        27.02.2019 21:56

        Пока что я после нескольких часов обсуждений придумал терминологию и описал проблему яснее. У ансибла нет абстракции выше playbook'и, а хочется. Мы их назвали facilities и будем вендорить. Каждая facility в своём каталоге. Инструментария не нашёл, увы. Вот неотвеченный вопрос на SO по этому поводу: stackoverflow.com/questions/54906261/integration-level-for-anisble-between-roles-and-playbooks


        1. gecube
          27.02.2019 22:29

          По-русски, плиз, тезка. Че-то слишком сложно объясняете. Ну, и можно всегда в телеграмме обсудить поднятый вопрос.
          p.s. кстати, плюсанул на SO — не знаю, кто там минусанул, но среда там менее токсичная, чем здесь.


        1. ultral Автор
          28.02.2019 08:42

          мы для этого используем «мета роли». Это специальный вид ролей, который инклюдает другие роли с параметрами. Мы в них собираем конфигурацию из кирпичиков.

          Приведу пример. Пусть есть базовые роли
          — install java
          — install oracle
          — install postgresql
          — install wildfly
          — install glassfish

          Есть мета роль «install app 3.2.1.» установить наше приложение версии 3.2.1. поверх pg и установить такие-то пароли, она, условно инклюдает часть ролей передавая туда параметры при инклюде.

          далее мета роль применяем на сервера и радуемся жизни. проблемы начинаются когда это надо множить на несколько серверов… это решается не очень удобно тем, что есть playbook установи приложение версии 1.2.3 и там размазана логика по плэям.


          1. gecube
            28.02.2019 08:45

            Есть готовый пример на гитхабе/гитлабе?


            1. ultral Автор
              28.02.2019 10:16

              в паблике нет ничего что можно выложить. Сделал псевдо пример https://github.com/ultral/ansible-meta-roles-demo там есть роль ansible-dev можно на неё ориентироваться


          1. amarao
            28.02.2019 14:09

            Мета-роли, или роли-врапперы, это хорошо известная вещь. К сожалению, роль может работать только на тех хостах, куда её назначили, то есть роль не может определять список хостов, на которые надо выполнять задачи. И это проблема, если задача «меты» скоординировать несколько ролей на разных серверах.


            1. ultral Автор
              28.02.2019 14:23

              да, именно про эту проблему и говорил в комментарии про плэйбуки, что логику по плэям размазываем.


              1. amarao
                28.02.2019 14:54

                А дальше проблема: а как переиспользовать чужие плейбуки в проекте? Нет механизма, нет терминологии (нам же надо не только плейбука, но и её роли, а может быть, и её files/templates).

                Сейчас я думаю о том, как это вендорить. Терминологию уже придумали (facility) — но как именно её культурно вендорить надо думать.


                1. ultral Автор
                  28.02.2019 16:31

                  добавить новый слой вложености и генерировать плэйбуки на лету?


                  1. amarao
                    28.02.2019 16:33

                    Самомодифицирующиеся playbook'и — отличный метод увеличить сложность и снизить вероятность отладки.


                    1. ultral Автор
                      01.03.2019 08:06

                      снизить вероятность удачной отладки? или снизить вероятность самого процесса отладки?


                      1. amarao
                        01.03.2019 15:20

                        Я пострадал день, пострадал два. Моё текущее решение — git-vendor (гуглябельно). Не очень удобная структура получается, но всё-таки хоть что-то.


  1. gecube
    27.02.2019 18:20

    Очень интересный доклад и статья тоже.
    Жаль, что не рассмотрены альтернативные решения.
    Используем gitlab-ci и хотим использовать openshift. И желательно не как кубернетес на дрожжах. А именно опеншифт. Вот и интересно послушать мнение бывалых.


    1. ultral Автор
      28.02.2019 08:47

      Жаль, что не рассмотрены альтернативные решения.
      это какие? что упустил?

      про сборку:


      • Ansible bender — замена ansible container, форсится как замена ansible container
      • source2image — грубо ci/cd из коробки из опешифта

      про управление


      • operator — мб доберусь
      • Automation broker -мб доберусь
      • kustomize — вмерджен в kubectl, не актуально
      • helm — у нас опеншифт, извините


  1. mommys_little_hacker
    28.02.2019 08:32

    На тему шаблонизаторов для манифестов.

    Давно и крепко подсел на envsubst из пакета gettext. Все что он делает — заменяет в входном файле переменные окружения на их значения. Очень удобно использовать в связках с современными CICD фреймворками, т. к. они экспортируют все необходимые переменные в окружение. Получается просто один пайп, например:

    cat manifest-template.yml | envsubst | kubectl apply -f -


    Единственное неудобство — этот пакет надо ставить дополнительно, т. к. в минимальных образах он отсутствует по умолчанию, хотя есть во всех репах дистров (apt, apk, yum).


    1. gecube
      28.02.2019 08:34

      Может лучше jinja2 или gomplate? Минус в том, что их тоже нужно устанавливать дополнительно, а плюс в том, что они мощнее, чем envsubst.


      1. ultral Автор
        28.02.2019 08:54

        в моем обзоре это "Scripts and template". с этим жить можно но попахивает велосипедами. без понятно на то необходимости, не стал бы тащить.


        Зачем может такое понадобиться? ну предположим


        • мы хотим использовать мощь ООП, описать нашу инфраструктуру и потом перенести в реальный мир… ну ок… как потом поддерживать это не понятно… могут же и узнать домашний адрес после увольнения вашего. ^_^
        • более реальный случай, у нас есть некая СМДБ, с которой мы выгружаем нашу инфру(описание стэндов каких-нибудь?), генерим шаблон и катим…

        можно. но зачем?


      1. mommys_little_hacker
        28.02.2019 12:08

        Они безусловно мощнее, но у них и порог вхождения выше. Также, у них больше зависимостей. К тому же, мне сложно представить, зачем в манифесте нужна настолько сложная логика. Плюс envsubst в том, что он очевиден и понятен всем. Для 99% процентов случаев (подставить тег докер-образа, или какие-то данные разнящиеся на продовых и тестовых контурах) его возможностей достаточно.


        1. gecube
          28.02.2019 16:13

          Мне удобно, что


          • указанные шаблонизаторы позволяют выделять повторяющиеся блоки кода (так себе аргумент, но YAML anchor не очень удобны, все-таки jinja понятнее)
          • позволяют грузить переменные не только из env, но с stdin, другого файла (json, например) и пр. интересные штуки Это бывает полезно для отладки.


          1. mommys_little_hacker
            28.02.2019 17:26

            Буду честен, у меня такого юз-кейса не было. А еще я знаю только bash :)

            Но, возможно, вам имеет смысл подумать о написании полноценных helm чартов. ЕМНИП, они изначально задумывались для подобного.


            1. gecube
              28.02.2019 18:09

              Пока не будет HELM v3 — нет, увольте.