Ansible-container: новый шаг в управление контейнерами

  • Tutorial


Недавно разработчики 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
└── roles
    ├── dumb-init
    │   └── tasks
    │       └── main.yml
    ├── nginx
    │   ├── defaults
    │   │   └── main.yml
    │   ├── files
    │   │   └── nginx.repo
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    │       └── nginx.conf
    ├── php-fpm
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   ├── templates
    │   │   └── php.ini
    │   │   └── app.conf
    │   └── vars
    │       └── 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 — Виктор Батуев.
Southbridge
391.06
Обеспечиваем стабильную работу серверов
Share post

Comments 13

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

    P.S. В вашем примере containers.yml не стоит выкидывать порт 9000 на 0.0.0.0 интерфейс, для nginx это не нужно, а вот весь «прогрессивный» мир будет рад увидеть доступный php-fpm для выполнения :)
      –1
      Фото котика зеркально повернуто по горизонтали? Надпись Nestle зеркальная. Неудивительно, что у него такое выражение мордочки )
        0
        А я сейчас на рельсах пишу свою панель управления для хостингом приложений, основанную на docker, потому как текущие существующие решения, ээм, немного в этом плане отстали.
          +2
          Благодарность Виктору и всему проекту!
            0
            Разработчикам Ansible (Red Hat) нужно было назвать этот инструмент «Yet Another Docker Orchestration Tool», потому что, честно говоря, существует так много инструментов для работы над уровнем Docker. :-| Kubernetes, CoreOS, инструменты от Hashicorp, RacherOS.
            Что будет, если Docker сделает Dockerfile deprecated?
              +4
              Что-то я упускаю прелесть этой идеи. В моем понимании построение контейнера, это часть построения сервиса/программы, которое создает артифакты в виде docker image и пушит, и все это происходит в CI системе и, строго говоря, никакого отношения к asnible не имеет. Именно тут нужен Dockerfile, и он нужен на уровне сервиса а не на уровне композа, т.е. каждый сервис строится со своим собственным Dockerfile и никакой зависимости с прочими частями, типа nginx ему не надо.

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

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

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

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

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

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

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

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

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


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

                          0

                          Запускать ansible внутри контейнера очень даже можно и нужно. Но не для деплоя чего-то внутри, а для CI и тестов. Я тестирую свои публичные роли внутри докера(именно тот кейс, который вам кажется дикостью — полное разворачивание сервиса внутри докера) в travis'е. Закрытые плейбуки тестируются в докере и CD происходит изнутри контейнера.


                          А вот делать из ansible dockerfile + docker compose сомнительная вещь, согласен с вами.

                            0
                            Ну это ведь о другом. У меня тоже ansible используется из контейнера по понятным причинам — все зависимости, что ему нужны там, все скрипты и все ключи доступны и прочее. Тут ansible просто еще одна докерезированная штука которая мало отличается от любого другого сервиса. Мой комментарий относился к идее запускать плейбук и в самом docker контейнере для инициализации/создания этого контейнера и именно такой кейс я назвал диковинным.

                Only users with full accounts can post comments. Log in, please.