Недавно разработчики Ansible анонсировали новый проект Ansible Container. Проект нас очень сильно заинтриговал, и мы решили рассмотреть его поближе.
Ansible уже давно стал незаменимым инструментом в вопросах создания, сборки, деплоя образов docker-контейнеров и самих docker-контейнеров, благодаря соответствующему модулю.
Ранее для провиженинга docker-контейнеров с помощью Ansible необходим был запущенный в контейнере sshd, но в версии 2.1 в Ansible был добавлен Docker connection plugin, благодаря которому стало возможно запускать плейбуки не только на физических/виртуальных машинах, но и внутри docker-контейнеров и отпала необходимость использования sshd внутри docker-контейнера.



Ещё одна из причин, по которым разработчики начали работу над ansible-container — это формат Dockerfile. Наверное, многие знают, что из себя представляет Dockerfile — не более, чем shell-скрипт со своими инструкциями. Не знаю, как вам, но лично я предпочту описать содержимое контейнера в yaml-формате, чем городить портянку из shell-скрипта, в котором потом ещё не каждый сможет разобраться. Таким образом, нам дали ещё одну крутую возможность — сборку docker-образа при помощи ansible-плейбука!

Ещё один из приятных бонусов — это возможность оркестрации контейнеров в формате docker-compose.
Также есть возможность закидывать и скачивать образы в Docker registry (в том числе в приватный), и разворачивать приложения в кластере Kubernetes и в облаке OpenShift.

Давайте проведём небольшое знакомство с ansible-container.
В качестве хост-машины будем использовать CentOS 7.

Установка Docker.



sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF


sudo yum install docker-engine


Установка Ansible.



Установка ansible прекрасно описана в официальной документации.

Подключим репозиторий EPEL (в нём доступная последняя стабильная версия Ansible 2.1), установим ansible, git и python-pip для управления пакетами python.
yum install epel-release
yum install ansible git python-pip


Установка ansible-container
Здесь всё довольно просто. Пока что доступна только сборка из исходников, т. к. проект находится на стадии ранней разработки и в репозитории его ещё не выкладывали.

git clone https://github.com/ansible/ansible-container.git
cd ansible-container
pip install --upgrade setuptools
python ./setup.py install


Настройка



Правим юнит (For ansible-container to work the Docker daemon must be set to listen on an IP address assigned to the host NOT 127.0.0.1. This is because the daemon must be accessible remotely from the Ansible build container.):
По-умолчанию, docker-демон слушает UNIX-сокет. Для использования Ansible Container необходимо перевесить демон на TCP-сокет.

vi /etc/systemd/system/docker.service


Меняем в строке *ExecStart* IP-адрес на актуальный:

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/docker daemon -H fd:// -H tcp://0.0.0.0:2375
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes

[Install]
WantedBy=multi-user.target


Также рекомендуется настроить TLS для docker-демона. В тестовой среде мы опустили этот момент.

перезапускаем docker-демон
systemctl daemon-reload
systemctl restart docker

не забываем выставить переменную DOCKER_HOST для работы с docker-демоном по TCP-сокету.

export DOCKER_HOST=tcp://0.0.0.0:2375


после установки ansible и ansible-container нужно создать новый проект
ansible-container init


после этого у нас создастся директория «ansible» с тремя файлами внутри

ansible
|-- container.yml
|-- main.yml
`-- requirements.txt


Файл container.yml — это описание запуска проекта, его контейнеров и приложений внутри них. Формат очень схож с docker-compose v 1.

К примеру, у нас есть парочка сферических ролей в вакууме.
+-- container.yml
+-- main.yml
+-- requirements.txt
L-- roles
    +-- dumb-init
    ¦   L-- tasks
    ¦       L-- main.yml
    +-- nginx
    ¦   +-- defaults
    ¦   ¦   L-- main.yml
    ¦   +-- files
    ¦   ¦   L-- nginx.repo
    ¦   +-- handlers
    ¦   ¦   L-- main.yml
    ¦   +-- tasks
    ¦   ¦   L-- main.yml
    ¦   L-- templates
    ¦       L-- nginx.conf
    +-- php-fpm
    ¦   +-- handlers
    ¦   ¦   L-- main.yml
    ¦   +-- tasks
    ¦   ¦   L-- main.yml
    ¦   +-- templates
    ¦   ¦   L-- php.ini
    ¦   ¦   L-- app.conf
    ¦   L-- vars
    ¦       L-- main.yml


файл container.yml

version: "1"
services:
  nginx:
    image: centos:7
    ports:
      - "80:80"
    links:
      - php
    command: ['/usr/bin/dumb-init', '/usr/sbin/nginx', '-c', '/etc/nginx/nginx.conf' ]
    volumes:
      - /var/www:/usr/share/nginx/html

  php:
    image: centos:7
    ports:
      - "9000:9000"
    command: ['/usr/bin/dumb-init', '/usr/sbin/php-fpm', '-y', '/etc/php-fpm.d/app.conf']
    volumes:
      - /var/www:/usr/share/nginx/html


Файл main.yml — это ничто иное, как ansible-плейбук, который описывает конфигурацию docker-контейнеров. Именно по этому сценарию будет выполняться сборка docker-образов. Нам больше не нужна куча папок и Dockerfile'ов. Сборку всех образов можно описать в одном-единственном файле.

- hosts: all
  gather_facts: false

  roles:
    - dumb-init

- hosts: nginx
  roles:
    - nginx

- hosts: php
  roles:
    - php-fpm


Собираем образы командой:
ansible-container build


И запускаем контейнеры:

ansible-container run


Таким образом, двумя командами мы можем собрать, запустить полноценное докерезированное приложение, не утруждая себя в написании Dockerfile и не вводя кучу параметров в командной строке при запуске docker-контейнеров.

Проект ещё достаточно молодой, находится на стадии активной разработки, но, на мой взгляд, имеет огромный потенциал, хотя и имеется ещё ряд недостатков. К примеру, я не смог найти как запустить контейнеры с опцией detach (аналог docker-compose up -d) или возможность отладки плейбуков. И сборка образов мне показалась слишком долгой, в отличии от сборки образов традиционным Dockerfile.

Спасибо за внимание. Удачной автоматизации!
Автор: DevOps-администратор Southbridge — Виктор Батуев.
Поделиться с друзьями
-->

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


  1. theo
    27.07.2016 09:40
    +3

    Cпасибо за статью. В случае, если Dockerfile мы пишем сами, то у нас есть возможность управлять слоями образа, путем объединения команд под одной инструкцией (например: RUN yum update && yum install… ) и тем самым экономя на размере однотипных образов, как это делать в случае с ansible-container?

    P.S. В вашем примере containers.yml не стоит выкидывать порт 9000 на 0.0.0.0 интерфейс, для nginx это не нужно, а вот весь «прогрессивный» мир будет рад увидеть доступный php-fpm для выполнения :)


  1. dmitry_ch
    27.07.2016 10:20
    -1

    Фото котика зеркально повернуто по горизонтали? Надпись Nestle зеркальная. Неудивительно, что у него такое выражение мордочки )


  1. foxmuldercp
    27.07.2016 13:31

    А я сейчас на рельсах пишу свою панель управления для хостингом приложений, основанную на docker, потому как текущие существующие решения, ээм, немного в этом плане отстали.


  1. dostigai
    27.07.2016 15:22
    +2

    Благодарность Виктору и всему проекту!


  1. Gular
    27.07.2016 17:04

    Разработчикам Ansible (Red Hat) нужно было назвать этот инструмент «Yet Another Docker Orchestration Tool», потому что, честно говоря, существует так много инструментов для работы над уровнем Docker. :-| Kubernetes, CoreOS, инструменты от Hashicorp, RacherOS.
    Что будет, если Docker сделает Dockerfile deprecated?


  1. umputun
    27.07.2016 20:41
    +4

    Что-то я упускаю прелесть этой идеи. В моем понимании построение контейнера, это часть построения сервиса/программы, которое создает артифакты в виде docker image и пушит, и все это происходит в CI системе и, строго говоря, никакого отношения к asnible не имеет. Именно тут нужен Dockerfile, и он нужен на уровне сервиса а не на уровне композа, т.е. каждый сервис строится со своим собственным Dockerfile и никакой зависимости с прочими частями, типа nginx ему не надо.

    Сам деплоймент никакого отношения к этим Dockerfile не имеет, он их даже не видит. Все, что ему надо это docker-compose.yml в котором прописано все сервисы, порты, зависимости и прочее. Это (деплоймент) можно делать с помощью ansible (я так и делаю) но никакой хитрости для этого не надо, просто доставить compose файл плюс что надо еще (конфиги, например) и дернуть docker-compose.

    В какой модели удобно использовать подход описанный здесь, я не могу себе представить. Это если строить на боевом сервер контейнер? И в этом, странном случае, это можно делать с помощью compose. Единственный, но на мой взгляд сомнительный, плюс это разбиение на роли для сборки образов, но я не очень вижу зачем, например dumb-init иметь в виде роли, но не базовым контейнером.

    Кроме того, реализация своего сборщика, это дело муторное и требующее постоянной гонки за обновлениями docker. Даже они сами не поспевают с этим, и compose иногда обновляется сильно позже чем та или иная фича добавилась в докер. А тут теперь надо будет ждать пока и ansible это добавит.


    1. theo
      28.07.2016 10:39

      В статье прямо пишут о том «зачем» это было придуманно: "...Dockerfile — не более, чем shell-скрипт со своими инструкциями. Не знаю, как вам, но лично я предпочту описать содержимое контейнера в yaml-формате...". Авторам и адептам, «так» легче :)


      1. umputun
        28.07.2016 23:33

        Dockerfile примерно такой же «shell-script» как и ансибловый yaml. Ну да, там в RUN пиши что надо, но примерно с тем же успехом можно сказать, что и ansible это такой «shell-script» с ssh запускалкой.

        Короче, как по мне, так очень странная затея. Понятно, почему это надо ansible, но как (а главное зачем) этим будут пользоваться живые люди я все еще не могу понять. Мотивация «этот язык описания мне нравится больше» мне кажется какой-то неубедительной для введения такого сомнительного велосипеда в свой процесс построения контейнеров.


        1. skandyla
          31.07.2016 08:50

          Также, никто не мешает запускать плейбук и в самом docker контейнере, предварительно установив там ansible или взяв уже готовый image c ansible.


          RUN  yum -y install epel-release      && yum -y install ansible      && echo -e "[local]\nlocalhost" > /etc/ansible/hosts
          RUN  ansible-galaxy install example-role
          RUN  ansible-playbook site.yml -c local

          полагаю, что идея(использования ansible-container) приобретает ценность, когда при помощи ansible-container производится только сборка и push в registry. В то время как делать ansible-container run видится актуальным для каких-то тестов разве что...


          1. umputun
            31.07.2016 09:18
            +1

            идея запускать плейбук и в самом docker контейнере мне кажется еще более … диковинной, мягко говоря. Если вдруг по каким-то, совершенно непонятным мне причинам, хочется делать такие странные, полуготовые и мутабельные докер контейнеры и деплоить внутрь код с помощью ansible, то совсем непонятно зачем тут docker вообще, и почему бы не делать это прямо на хост.

            > полагаю, что идея(использования ansible-container) приобретает ценность, когда при помощи ansible-container производится только сборка и push в registry

            С трудом могу себе представить эту ценность. Возможно, для этого нужны какие-то совсем дикие многофункциональные контейнеры, которые муторно и сложно описать обычным образом, но мне это видится кривой дорогой — я за контейнер-на-сервис, а не контейнер-как-легкая-vm.


            1. skandyla
              31.07.2016 21:36

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


              В целом я с вами солидарен, преимущества от использования ansible-container для меня не очевидны, если не сказать спорны.


            1. TimsTims
              01.12.2016 18:55

              Спасибо, juDGe, я помню вас :) Вы играли еще с кем-то из VSOP, вам было двое как минимум.

              > когда нынешние именитые киберспортсмены типа Нски, Лоста или Пгг могли играть с тобой в обычном клозе
              Да, только они позволяли себе такие вольности, как послать всех к чертям и выйти из игры )) А pgg вообще начинал как модератор на QDL :)

              > появившийся позже iccup не ваших рук дело?
              Нет, но этот проект стал мне очень симпатичен


              1. xxxTy3uKxxx
                03.12.2016 13:56
                +1

                Под «Зря Вы так» я имел в виду то, что не надо так категорично говорить, что никто не понимал суть успеха доты. Насчет клонов и подобий — изюминкой доты был хороший баланс (не знаю как сейчас), непрекращающийся интерес со стороны игроков и, конечно же, киберспорт. Увы, на мапмейкерской сцене есть только один громкий проект — TKoK. И та является РПГ картой. Но какой…