company_banner

Centos-admin.ru: познаем Ansible

    image

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

    Итак, не так давно у нас появился новый клиент. У него было несколько нетипичных для нас требований: использовать для конфигурирования серверов ansible, контент сайта хранится в git, каждый сайт находится на своей виртуальной машине. Все это не сулило ничего хорошего, так как совсем не укладывалось в стандартную схему «Клиент всегда прав!», и мы начали разрабатывать новую схему. Но обо всем по порядку.

    Исходные данные: есть клиент, у которого более 30 сайтов которые надо перенести на нашу площадку. Каждый сайт должен располагаться в отдельном контейнере (мы используем OpenVZ контейнеры). Используется только один внешний IP. Для конфигурирования серверов используется ansible. Для каждого сайта есть архив с конфигурационными файлами. Контент сайта находится в git.

    И мы начали творить… Что у нас получилось, можно посмотреть под катом. Забегая вперед, скажу, разворот нового сайта сводится к нескольким командам.

    У нас есть несколько шаблонов для разворачивания новых контейнеров, в виде архивов. Для начала мы внесли некоторые изменения в эти шаблоны, а точнее добавили пользователя ansilble и ключи. Это позволило сразу после разворота, без дополнительных действий настраивать контейнер с помощью ansible.

    В ansible у нас было создано несколько ролей, не буду описывать их все, только про самые интересные:
    • create_vm
    • content_update


    create_vm это роль, которая, собственно, и создает вм и и конфигурирует ее.

    Чуть подробнее.

    Эта роль применяется к хостовой машине на которой будет установлен контейнер. Сразу оговорюсь, везде активно используются host_vars. У хостовой машине в host_vars, есть только одна переменная vm_number. Эта переменная содержит номер последнего контейнера +1, после выполнения playbook этот номер будет увеличен на 1. Так же в playbook для это роли используются «vars_promt». Это первое, что нам показалось интересным и мало где описанный механизм. vars_promt позволяет интерактивно задавать переменные при выполнении playbook и в дальнейшем к этим переменным можно обращаться в шаблонах, заданиях и тд. Мы вынесли в эти переменные такие уникальные данные для каждого сайта как имя сайта, репозитарий git (где хранится контент сайта) и адрес, где расположены конфигурационные файлы для сайта.

    Получилось примерно так:
    <spoiler title="new_vm.yml">
    - name: Create new vm
      hosts: ds
      remote_user: ansible
      sudo: true
     
      roles:
       - new_vm
      vars_prompt:
        conf_url: "Введите url c архивов конфигов который приложен к заданию"
        area_fqdn: "Введите имя сайта"
        git_repo: "Введите адрес git репозитария"
    </spoiler>
    



    Описание самих тасков приводить не буду, так как получились достаточно длинными. Если кому-то будет интересно можем прислать.

    А дальше все очень просто, ansible подключается к хосту, выкачивает архив шаблона, проверяет что вм с таким номером нет и создает вм, задает ей IP и имя, на этом все процедуры на хосте заканчиваются.

    Дальше очень полезным оказался модуль ansible local_action, который позволяет выполнять действия на хосте откуда запускается playbook. Asible выкачивает файлы конфигурации для сайта (nginx, apache и т.д.), по ссылке которую мы задаем в интерактивной переменной, создает структуру каталогов в ansible, добавляет новый контейнер к ролям в ansible и раскладывает конфиги. А также создается host_vars для нового контейнера, в которых задается имя сайта и git репозитарий, это пригодится в дальнейшем, это нам потребуется в дальнейшем. На этом создание контейнера закончено.


    Как было сказано в начале, есть только один белый ip для всех сайтов. Не проблема, был создан контейнер с проксирующим nginx. Для новых контейнеров надо добавлять правила проксирования. И тут нам на помощь пришли шаблоны и все те же интерактивные переменные. Также локально из шаблона создаётся файл конфигурации прокси для нового контейнера.

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

    Вкратце о роли content_update. Ansible делает клон git репозитария и потом с помощью скрипта раскладывает контент сайта в нужные директории с нужными правами. На этом, собственно, подготовка контейнера почти закончена, остается запустить playbook для применения конфигурации для нового контейнера и все, контейнер можно передавать заказчику.

    Автор: системный администратор компании Magvai69
    Southbridge
    521,86
    Обеспечиваем стабильную работу highload-проектов
    Поделиться публикацией

    Похожие публикации

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

      0
      У вас spoiler не сработал
      Сам первое что пробовал — Ansible, вот уже пол года активно пользуюсь и радуюсь. Но тут захотел попробовать Puppet, но что то модель pull мне совершенно не нравится
        0
        Кстати, судя по гитхабу и багтрекеру ансибл-модуля «докер», который бы Вам пригодился, Этот ансибл модуль докера я бы пока в продакшен не выпускал.
        а так — я бы на Вашем месте реально подумал про Docker — полноценная виртуалка требует больше внимания на администрирование.
          –1
          Удел докера, это быстрое создание лёгкого окружения разработчика, а отнюдь не контейнерная виртуализация для продакшена.
          Хоть и декларируется, что «Docker is an open platform for developers and sysadmins of distributed applications.», сисадминам удобнее использовать полноценные виртуальные машины с большей изоляцией, и полноценной операционкой.

          Поддерживать в продакшене докер контейнеры не проще, наоборот — это редкостный геморрой, на самом-то деле. Можно запихать в каждый образ ssh, пакетный менеджер, клиент системы мониторинга и.т.п., но при этом он уже и не будет отличаться от других контейнеров при этом имея проблемы с изоляцией той же. А без этих инструментов для продакшена он просто не годится, т.к. без обновлений, мониторинга и.т.п. вы далеко в продакшене не уплывёте.

          Обратите внимание на страничку www.docker.com/resources/usecases — для чего крупные компании используют докер — в основном это " testing and deployment"
            +3
            Простите, но Вы кажется не очень понимаете идеологию Docker'а.
            Попробую объяснить на примере тот самый Demployment, который вы упомянули в конце комментария, в противоречие своим же словам «продакшене докер контейнеры», Вот, допустим, я пишу свой какойнить бложек на Perl + Mojolicious. у меня туева хуча зависимостей из Cpan, компилирующихся в ~blog/.perl… Чтобы не засырать этими сборками систему, я пишу нечто вроде:
            RUN apt-get update && apt-get install -y make gcc postgresql-server-dev-all cpanminus &&\
             apt-get clean && apt-get autoremove -y && apt-get autoclean &&\
             cpanm -n Mojolicious DBI DBD::Pg Mojolicious::Plugin::Database Mojolicious::Plugin::I18N Date::Parse&&\
             mkdir /opt/panel
            COPY pmblog /opt/panel/
            EXPOSE 8080
            VOLUME  ["/opt/panel"]
            ENTRYPOINT ["/usr/local/bin/hypnotoad","-f","/opt/panel/script/pm_blog"]
            


            после чего говорю какому-нить скрипту или mesos'у — эй, чувак, наплоди мне на вон том списке хостов стопицот контейнеров из этого образа.
            после чего мне достаточно натравить на этот зоопарк nginx.

            какой ssh, какое пакетный менеджер, Вы о чем?
            идеология контейнеров как раз в том, что Вы в них не лезете и у Вас повторимость, хоть на CoreOS, хоть на Ubuntu, да хоть на Debian 7, хоть еще гдё.

            С учётом того, что логи отправляются на какойнить Sentry для аналитики, живущий в контейненре из рядом лежащего образа.

            Ну или про сборку/тесты — можно пойти например путём — собираем образ из нужных нам gcc/cpp/make с apt-get|yum install (нужный_список_библиотек) с точкой входа — скрипт компиляции. Про запуске контейнера делаем mount /src и /out на каталоги хост системы. После окончания работы контейнера получаем в /out собранный софт/библиотеки/пакеты. Ну, или в случае тестов получаем лог passed/failed тестов.
              0
              Про deployment опечатка, прошу прощения.Подразумевалось, конечно, development.

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

              «после чего говорю какому-нить скрипту или mesos'у — эй, чувак, наплоди мне на вон том списке хостов стопицот контейнеров из этого образа.»
              И что должен сделать админ, при нахождении критической уязвимости в любой софтине/библиотеке вашего образа? Пересобрать его?
              Или по вашему цикл разработки вечен, и разработчик будет выкатывать каждый раз новые образы? В большинстве случаев, это и близко не так.

              Логи и мониторинг это несколько разные вещи. Или вы считаете, что вообще не важно, что делается в конкретном контейнере?
              Искать проблемы потом по логам, возможно, будет проблематично…

              «и у Вас повторимость, хоть на CoreOS, хоть на Ubuntu, да хоть на Debian 7»
              А так-ли это нужно в реальности — в рамках одного проекта такой зоопарк держать всё равно не будет никто. А если распространять приложение как образ контейнера для внешнего использования, то возникнет масса других проблем, частично описанных выше. Частично с доверием к вашему образу.
                0
                Админ — в случае уязвимости — да, пересобрать образ.
                ssh и rdp — нужны для виртуалок на lxc/openvz/hyper-v. Виртуалок. полных.
                А у контейнера другая задача — запускать ОДНО конкретное приложение, висеть на хосте и молотить что надо после аппаратного балансера или nginx'а какого.

                Логи и ошибки должны собираться каким-нить Sentry, Elastix'ом и тикетной системой из почты.
                Вот у меня на крайнем проекте было полсотни лезвий, apache kafka обрабатывал 5-6 миллионов запросов в секунду от всех.
                Скорость добавления записей в логи — сколько-то сотен метров в секунду на все молотилки.
                Вы думаете у Вас получится гигабайты логов в сутки, а самое главное — зачем, Если все события должны быть к чему-то привязаны, и могут происходить на разных лезвиях в рамках одной сесии.

                Насчет что делается внутри контейнера — нет, не важно. Если там внутри приложение, то оно делает исключительно то, что написали программисты. Или не делает, Но это обычно должно отсекаться разными вариантами тестов.

                Насчёт cpan — Ну нет нужных мне модулей в пакетном менеджере репозитория, нету. Не, вру. часть — есть, часть, кхм, устарела. Но часть требует сборки — Вы мне предлагаете сделать еще один образ для сборки cpan модуля в deb, и во втором образе подсовывать его из личного репозитория.
                А повторимость нужна не только Вам. Вот у меня был проект из нескольких офисов — в Далласе CoreOS исторически, в Лондоне — debian, в Киеве — centos.
                  0
                  «Админ — в случае уязвимости — да, пересобрать образ.»
                  Ну вот это первое большое неудобство с точки зрения администрирования.

                  «ssh и rdp — нужны для виртуалок на lxc/openvz/hyper-v. Виртуалок. полных.»
                  hyper-v тут лишнее, остальное, это та же контейнерная виртуализация, обычно, действительно, с более полным окружением, но запустить в таком контейнере можно и 1 процесс init, вообще без какого-либо окружения.
                  rdp обычно излишне, а вот ssh полезен хотя бы для того, чтобы автоматизировать что-либо тем же ansible на уровне контейнера.

                  «запускать ОДНО конкретное приложение, висеть на хосте и молотить что надо после аппаратного балансера»
                  Что точно также, но с большей изоляцией, часто, как раз и реализуется на тех же lxc/openvz.

                  Или не делает, Но это обычно должно отсекаться разными вариантами тестов.
                  В идеальном мире это так.

                  Насчёт cpan — Ну нет нужных мне модулей в пакетном менеджере репозитория, нету. Не, вру. часть — есть, часть, кхм, устарела. Но часть требует сборки — Вы мне предлагаете сделать еще один образ для сборки cpan модуля в deb, и во втором образе подсовывать его из личного репозитория.
                  Ну во-первых, оно где-то наверняка есть и поддерживается уже кем-то, в виде пакета, но если действительно нет, то да, поддерживать собственный репозиторий. Или не гоняться за последними версиями модулей при разработке, что тоже часто разумно, например, с точки зрения стабильности и поддерживаемости, о которой программисты часто забывают.
                    0
                    Всё-таки вы неправильно различаете полноценные окружения вроде lxc/openvz и docker.
                    Идеология докера как раз в том. что в него не вмешиваются. Настроил образ, собрал, наплодил контейнеров и понеслась. всё. точка.
                    Как раз для того, чтобы я мог написав свой перлобложек просто выложить Dockerfile и любой мог этот докерфайл собрать и получить готовый к работе бложик.
                    В случае обновлений — просто его пересобрать.
                      0
                      Я честно смотрел на Докер и думал, как его прикрутить себе в проект. Не нашел возможности.
                      Для общего уровня развития — как происходит выкладка нового кода с контейнерами? Вот есть у меня фронт, за ним 6 апстримов… Что будет в момент перевыкладывания?..
                        0
                        Пока билдится новая версия образа бложика старое работает. После успешного билда поднимаю новые контейнеры, прописываю в конфиг нгинкса апстримы, передергиваю нгинкс, тушу старые контейнеры, грохаю старый образ. CI в общем-то.

                        У меня это все пошло немного дальше, я докер в условиях кластерного шаредхостинга хочу использовать, интересный опыт в процессе ковыряния получаю.
              0
              Во многом согласен. Для себя выбрал lxc.
                0
                Как минимум он, как openvz уже в ядре, и не требует 2.6.32 с тонной патчей.
                у меня на одном и том же хосте соседствую как lxc, так и docker для разных целей. за год проблем не было
            0
            Про vars_promt даже не слышал, попробую. Очень интересная возможность
              0
              про Jinja2 тоже почитайте… конфиги под ситуацию править
                0
                Я уже давно использую ansible в продакшене, конфиги всякие доводилось мастерить :)
                А вот про интерактив с запуском плейбука услышал впервые :)
                  0
                  А как Вы себе представляете программирование без переменных?
                    0
                    Никак не представляю :) В том же var файле для плейбуков этих переменных вагон.
                    Я отметил тот факт, что о возможности СПРАШИВАТЬ у пользователя переменные в момент выполнения плейбука я не знал. До этого все жестко прописывал в конфиге, ну или через ключ -е
                      0
                      В официальной доке же есть пример для ввода пароля, например. не в -е же его вводить.
                        0
                        «век живи — век учись»
                          0
                          Есть ещё удобный способ через ansible-vault, но что он, что vars_prompt появились не сразу.

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

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