Ansible и Docker, почему и зачем?

http://thechangelog.com/ansible-docker/
  • Перевод
Достаточно много интереса проявляется среди технического сообщества к Docker и Ansible, я надеюсь, что после прочтения данной статьи, вы тоже разделите этот интерес. Вы так же получите навыки практического применения Ansible и Docker в настройке сервера и окружения для Rails приложения.

«Почему бы просто не взять и использовать Heroku?», спросите вы.
Прежде всего, я могу запустить Docker и Ansible на любой машине, с любым хостинг провайдером. Во вторых, я предпочитаю гибкость, удобству. Я могу, таким же образом, запускать все что угодно, не только web приложения. Ну и напоследок, потому что я эксперементатор в душе, я получаю удовольствие от понимания того как оно все вместе работает. Фундаментальная основа Heroku это Linux контейнер. Та же технология лежит и в основе Docker'a. На самом деле, одним из девизов Docker'a является «Контейнеризация это новая виртуализация»

Почему Ansible?


После 4 лет активного использования Chef, инфраструктура как код стала действительно утомительной для меня. Я проводил больше времени за кодом, который управлял моей инфраструктурой, но не за самой инфраструктурой. Любое изменение, не важно насколько маленькое, потребует большое количество усилий для незначительной выгоды.

С Ansible, с одной стороны есть данные описывающие инфраструктуру, с другой ограничения между взаимодействием других компонентов. Эта модель намного проще, она позволяет намного быстрее двигаться дальше, позволяя сосредоточится на том, что делает моя инфраструктура. Как и в Unix модели, Anisible предоставляет модули с единичной ответственностью, которые могут быть объедены бесконечным множеством способов.

Ansible не имеет зависимостей кроме как Python и SSH. Ей не нужно устанавливать агентов на удаленные машины, она не оставляет всякого рода мусора после своей работы. Более того, она поставляется со стандартной библиотекой модулей для управления всем чем угодно, начиная от пакетного менеджера в облаке, заканчивая базами данных.

Почему Docker?


Docker позиционирует себя как самый надежный и удобный способ развертывания процесса на машине. Это может быть все что угодно, от mysqld до redis, заканчивая Rails приложением. Таким же эффективным способом, как git снимки и распределение кода, Docker делает тоже самое с процессами. Он гарантирует, что будет предоставлено все, что нужно для запуска этого процесса, независимо от машины на которой он запущен.

Основная, но понятная ошибка, сравнивание Docker контейнера с VM. Здесь применяется принцип единственной ответственности, запуск одного процесса на контейнер дает простоту изменяемости и поддержки. Эта модель выдержала испытание временем в философии Unix, это дает прочный фундамент для действий.

Настройка


Не покидая свой терминал, я могу получить от Ansible настроенную машину на одном из следующих хостингов: AWS, Linode, Rackspace или DigitalOcean. Если быть более конкретным, я с помощью Ansible создаю новый дроплет с 2ГБ памяти на DigitalOcean в регионе Amsterdam 2 за 1 минуту 25 секунд. В течение еще 1 минуты и 50 секунд я могу получить настроенную систему с Docker'ом и некоторыми другими установками. Теперь, имея базовую систему, я могу развернуть свое приложение. Заметьте, я не настраивал какой либо язык программирования или базу данных. Docker сам позаботился об этом.

Ansible исполняет все команды на удаленных машинах через SSH. Мои SSH ключи, лежащие в локальном ssh-agent'е будут удаленно расшарены через SSH сессию Ansible. Когда, на удаленной машине, код моего приложения будет клонирован или обновлен никаких данных для авторизации в git не потребуется, для авторизации будет использован проброшенный ssh-agent с локальной машины.

Docker и зависимости приложения


Я нахожу забавным тот факт, что большинство разработчиков точно указывают версию ЯП, модули для Python, Ruby гемы или node.js модули, нужные для их приложения, но когда дело доходит до чегото важного, к примеру сервер БД или сервер очередей, они используют то что доступно на данный момент. Я думаю это одна из причин DevOps движения, разработчики берут на себя ответственность за окружение в котором они запускают приложение. Docker делает эту задачу легче и проще, добавляя дольку прагматизма и уверенности к существующим практикам.

Мое приложение определяет зависимости от процессов, таких как MySQL 5.5 и Redis 2.8 включая .docker_container_dependencies файл
gerhard/mysql:5.5
gerhard/redis:2.8


Ansible playbook увидит этот файл и скажет Docker'у взять правильные образа из индекса образов и запустить их как контейнеры. Также эти контейнеры слинкуются в контейнер моего приложения. Если вы хотите подробностей о работе линковки контейнеров, загляните в анонс Docker 0.6.5

Мое приложение так же идет с Dockerfile, который специфичен для Ruby Docker образа. Когда образ будет установлен, шаги в Dockerfile гарантируют, что будет установлена правильная версия Ruby.

FROM howareyou/ruby:2.0.0-p353

ADD ./ /terrabox

RUN \
  . /.profile ;\
  rm -fr /terrabox/.git ;\
  cd /terrabox ;\
  bundle install --local ;\
  echo '. /.profile && cd /terrabox && RAILS_ENV=test bundle exec rake db:create db:migrate && bundle exec rspec' > /test-terrabox ;\
  echo '. /.profile && cd /terrabox && export RAILS_ENV=production && rake db:create db:migrate && bundle exec unicorn -c config/unicorn.rails.conf.rb' > /run-terrabox ;\
# END RUN

ENTRYPOINT ["/bin/bash"]
CMD ["/run-terrabox"]

EXPOSE 3000


Первый шаг — это скопировать весь код моего приложения в образ Docker'a и загрузить глобальные переменные окружения, добавленные предыдущими образами. Образ Ruby Docker, например, добавляет в PATH пути для корректной загрузки правильной версии Ruby.

Далее, я удаляю историю git, поскольку она не нужна в данном контексте. Я устанавливаю все гемы и затем создаю /test-terrabox файл, который запускается только для тестов. Целью всего этого является иметь «canary» версию, которая проверяет приложение и все его зависимости, что все Docker контейнеры слинкованы правильно и все тесты пройдены успешно, перед актуальным запуском приложения.

Команда, которая вызывается при запуске нового контейнера, определена в шаге CMD.
Запуск /run-terrabox команды, определен как часть процесса сборки, сразу после процесса запуска тестов.

Последняя инструкция в Dockerfile пробрасывает порт 3000 изнутри Docker контейнера на хост машину из под которой запущен Docker. Который могут использовать сервер или балансировщик нагрузки для проксирования запросов в мое приложение контейнера.

Запуск Rails приложения внутри Docker контейнера


Для среднего Rails приложения, с где-то примерно 100 гемами и множеством интеграционных тестов, запускаемых из под Rails, запуск всего этого занимает 8 минут 16 секунд на 2GB и 2 ядерной машине, без каких либо локальных Docker образов. Если у меня уже есть Ruby, Mysql и Redis образа на этой машине, это займет 4 минуты 45 секунд. Более того, если у меня уже есть эталонный образ моего приложения, то это занимает 2 минуты 23 секунды. Если посмотреть, в перспективе, развертывание нового Rails приложения, включая такие зависимости как MySQL и Redis занимает не более 2 минут.

Так же следует заметить, что развертывание приложения включает в себя запуск всех тестов, которые занимают, впритык, минуту времени.
Без преувеличений, Docker становится простым средством непрерывной интеграции, которое оставляет за собой только тестовые контейнеры для исследования, если тесты не проходят, или стартует новый контейнер приложения с последней версией, когда тесты проходят. Внезапно, я могу проверить новый код с моими заказчиками за минуты, который гарантированно будет изолирован от других версий приложения на уровне операционной системы. В отличии от традиционных VM, которые загружаются за минуты, Docker на это тратит секунды. Более того, раз создав образ Docker'a и убедившись, что все тесты пройдены для специфичной версии моего приложения, я могу залить образ в приватный реестр, который в свою очередь, может быть загружен другими машинами с Docker'ом и запущен как новый контейнер, и все это за секунды.

Заключение


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

Получить с нуля полностью настроенное Rails приложение за каких то 12 минут это впечатляюще для любого стандарта. Получить базовую Continuous Integration систему бесплатно с возможностью предпросмотра разных версий приложении бок о бок, без затрагивания «рабочей» версии, запущенных на той же машине, это невероятно мощно. Это делает меня радостным, и достигнув конца статьи, я могу только надеяться, что вы разделите мою радость со мной.
Метки:
Поделиться публикацией
Похожие публикации
Комментарии 25
  • 0
    Сколько не смотрел на докер, меня все время смущает тот факт, что я не понимаю, как работает создание образа: это бинарный слепок или образ наподобие livecd с последующими загрузкай в облоко и скачиванием?
    • +1
      Оно, нет?
      Не очень понимаю, правда, какое это имеет в сути значение.
      • 0
        Я понимаю, как создаются контенеры и как они наслаиваются друг на друга. Я спрашивал про механиз создания самого образа для общего репозитория. Грубо говоря, что происходит под капотом при создании gerhard/mysql:5.5 в общей репо и последующем распространении.
      • +1
        Там есть начальный слепок, например, чистая операционная система и специальная файловая система AuFS, которая прозрачно наслаивает снимки на это слепок. Поэтому переключение между контейнерами это что-то типа git checkout. Меня вот в докере смущает тот факт, что например, порт SSH всегда динамический в большом диапазоне значений и этот диапазон жестко зафиксирован в коде: github.com/dotcloud/docker/blob/master/runtime/networkdriver/portallocator/portallocator.go
        • 0
          Это тоже все понятно, меня больше интересует вопрос, что представляет собой этот самый слепок. Или снимок, если хотите. Просто кусок файловой системы наподобие брэнча svc или кусой файловой системы наподобие образа iso, etc… При этом это какой-то свой формат или один из распространненных форматов (так как может работать и с aufs + снимки btrfs or lvm или вообще без всего этого)
          Все, что выше — это понятно из сайта докера, мана aufs и тому подобного…
          • +2
            Это сделано специально, т. к.:
            The range 49152–65535 – above the registered ports – contains dynamic or private ports that cannot be registered with IANA.
            .
            • +2
              Можно же самому выбрать фиксированный:
              docker run -p 10500:22…
          • +1
            Заходим на docs.docker.io/en/latest/ и читаем:
            Please note Docker is currently under heavy development. It should not be used in production (yet).
            Так что безусловно интересно, но пока не для продакшн даже несмотря на то, что Яндекс.Cocaine работает на нем.
            • +2
              Да я думаю все это читали. Однако кроме яши, на этом сидит еще и OpenShirt и вроде как отлично работает. Думаю за подобными решениями недалекое будущее.

              Что касается управления инфраструктурой, то тут мне сильно ближе salt state. Хотя он и требует агента, за то не требует ssh.
              • +1
                Тут основной выигрыш — скорость. Если через Salt на чистую машину можно ставить пакеты несколько минут, то контейнеры поднимаются за доли секунды.
                • +2
                  да я в общем ansible сравнивал с salt а не docker
            • +2
              Как вы переносите данные из одного редис контейнера в другой? Такой же вопрос про базу.
              Если для тестов все понятно, то как вы решаете эти вопросы в продакшене?
              • 0
                По идее база данных живет в отдельном контейнере, так что при выкатке очередной версии в прод, у вас сначала поднимается контейнер с новой версией, затем накатываются миграции в базу (тут видимо важно что бы изменения в базе не влияли на работоспособность предыдущей версии), и просто подменяется контейнер с текущего на новый.
                • 0
                  Собственно такой подход можно применить к любому случаю, когда у вас должно использоваться какое-то постоянное хранилище. Причем любой контейнер при необходимости сможет получить к этим данным доступ.
                  • +1
                    Вы говорите про рельсовую часть, как я понял.
                    Если вы подменяете контейнеры с базами — как вы поддерживаете их актуальность?
                    • 0
                      контейнеры с базой и не нужно подменять, они как висят себе так и висят. Просто в момент апдейта у нас два контейнера с приложением, которые работают с одним контейнером базы. Как только накатятся миграции для новой версии, можно подменять контейнеры и тушить старый.
                      • 0
                        «конфиг капистраны в студию»
                        • 0
                          Я пока только обкатываю данный метод развертывания на «домашних» проектах. Да и капистрану я не использую… Да и пишу я на php. У меня сборка через phing идет, а потом в дело вступают ансибл.
                          • 0
                            я про абстрактную систему деплоя. Капистрано или еще что-то — смысл сильно не меняется. Было бы интересно глянуть хоть на баш скрипты
                • +1
                  С двумя годами работы с Chef у меня такое же впечатление от работы с ним, что на писание кода для чефа уходит больше времени, чем на инфраструктуру. Надо будет попробовать ansible.
                • 0
                  Кто нибудь знает как запустить Docker на 32 битной машине?
                  • +3
                    Пользуюсь Chef.
                    По началу казалось, что разработка инфраструктуры с chef — это не просто долго, это вечность!
                    Когда побольше разобрался в нём — дела пошли куда быстрее.
                    Хотя, от этого он не перестаёт быть сложным и медленным (в плане разработки).

                    Однако, в защиту Chef могу сказать, что сообщество очень быстро адаптируется и меняется в лучшую сторону.
                    Появляется всё больше удобных инструментов, которые существенно ускоряют процесс разработки. Потихоньку вырабатываются best practice/chef patterns для работы с cookbooks. Качество community cookbooks (они же library cookbooks) быстро растёт. К моменту выхода chef 12 картина должна существенно улучшиться.

                    Мой «джентльменский набор» сейчас такой: Chef Zero, Test-Kitchen, Berkshelf, Docker (test kitchen driver for docker), chefspec, bats, serverspec.

                    Основная причина по которой остаюсь на Chef это orchestration: работа с кластерами, зависимости между серверами.
                    Конечно, есть тот же etcd который может частично решить проблему.

                    А вообще, Docker мне очень понравился, отличная идея, отличный проект. Подумываю над тем, чтобы серверами-болванками управлять через Chef, раскатывать проект через Docker (есть cookbook: github.com/bflad/chef-docker), настраивать опять же Chef-ом или каким-нибудь другим сервисом.
                    • +1
                      Абсолютно с вами согласен.
                      Когда есть устоявшаяся методология и понимание процесса разработки и дейплоймента — chef прекрасно ложиться на Technical Operations.
                      Вот кстати тоже интересная ссылка по теме, про интеграцию docker с chef docs.deis.io/en/latest/gettingstarted/concepts/#concepts
                    • 0
                      Очень хотел увидеть примеры того, как Вы объединили Docker и Ansible, но вместо этого увидел рассказ о том, как всё круто сделано, но без конкретики. В духе Яндекса, кстати :)

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