Статьи

Микросервисы в микроконтейнерах с докером и консулом

После первого использования толстых Docker-контейнеров для создания PaaS-подобных возможностей ( http://www.slideshare.net/IlkkaAnttonen/open-slava-2014ilkkaanttonen ) я теперь переключился на более простые контейнеры. Размер основного контейнера составил более гигабайта, в то время как микроконтейнеры можно хранить очень маленькими, в мегабайтах или десятках мегабайт вместо сотен мегабайт.

Содержит отдельные услуги

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

Если контейнерная сеть предоставляется, например, Weave ( https://github.com/zettio/weave ), сервисы могут быть распределены по нескольким хостам или облачным провайдерам.

Бокс для микроконтейнеров

BusyBox обычно используется в качестве минимального образа Linux, например, в маршрутизаторах и встроенных системах. Очень хорошую реализацию Docker можно найти по адресу https://github.com/progrium/busybox . У него также есть проект, который можно использовать для создания нового базового образа BusyBox, но это совсем не тривиально с кучей опций конфигурации. Для этого упражнения достаточно предоставить изображение программы-контейнера в реестре Docker.io.

Образ Docker Progrium / busybox включает opkg в качестве менеджера пакетов. Существует довольно много пакетов, но наиболее активная разработка, похоже, направлена ​​на ARM, а не на архитектуру x86_64.

Начало работы узла в микроконтейнере

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

Поскольку виртуализированный образ Ubuntu, который я использую в качестве хоста Docker, имеет ту же архитектуру x86_64, что и контейнер BusyBox, можно использовать те же библиотеки и исполняемые файлы.

Проверка связанных библиотек

Связанные библиотеки исполняемого файла можно проверить с помощью команды ldd. Я установил узел на хосте, и запуск ldd там дает следующий результат:

vagrant@node1:~$ ldd /usr/bin/node
  linux-vdso.so.1 =>  (0x00007fffdd5fe000)
  libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f41e8f3f000)
  librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f41e8d37000)
  libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f41e8a32000)
  libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f41e872c000)
  libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f41e8516000)
  libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f41e82f7000)
  libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f41e7f31000)
  /lib64/ld-linux-x86-64.so.2 (0x00007f41e914b000)

Из них только libstdc ++ недоступен в каталоге BusyBox image / lib.

Методом проб и ошибок

Конечно, чтобы увидеть, работает ли исполняемый файл, нужно запустить его. После того, как Docker начнет поддерживать сборочные контейнеры, все станет намного проще, но на данный момент проще всего собирать программы на хосте и напрямую вызывать их из своей файловой системы, разделяя файловую систему хоста с контейнером. Следующая команда дает оболочку в контейнере и представляет файловую систему хоста как / host. Вы можете выйти из контейнера с помощью CTRL + D, и файловая система очищается после выхода.

vagrant@node1:~$ sudo docker run -v /:/host -ti --rm --name testbox progrium/busybox /bin/sh

Вы можете попробовать запустить исполняемый файл узла (обратите внимание, что довольно часто настоящий исполняемый файл находится за несколькими символическими ссылками):

/ # /host/usr/bin/nodejs
/host/usr/bin/nodejs: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

Как и ожидалось, исполняемый файл жалуется на отсутствующую библиотеку.

Добавление ссылки и повторная попытка

После добавления символической ссылки команду можно повторить:

/  # ln -s /host/usr/lib/x86_64-linux-gnu/libstdc++.so.6 /lib/libstdc++.so.6
/ # /host/usr/bin/nodejs
>

Узел запускается успешно. Теперь мы знаем, что, добавив библиотеку libstdc ++ к образу BusyBox, мы сможем запустить узел.

Делая изображения маленькими, разделяя среду выполнения

Я начал играть с идеей просто иметь код приложения в контейнере и хранить большие исполняемые файлы и библиотеки, чтобы микроконтейнеры могли делиться ими. Таким образом, обновление среды выполнения наподобие версии nodejs будет тривиальным.

Объемные контейнеры

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

Контейнер томов должен быть собран один раз на каждом хосте, но поскольку базовый образ может быть собран с помощью Dockerfile и, вероятно, доступен из реестра, сборка контейнера является однострочной. Хорошим базовым изображением для контейнера томов является tianon / true, который в основном является чистым изображением только с истинной командой на ассемблере.

Пример Dockerfile для контейнера томов

FROM tianon/true
MAINTAINER Ilkka Anttonen version: 0.1
VOLUME /opt/files
ADD consul /opt/files/consul
ADD libstdc++.so.6 /opt/files/libstdc++.so.6
ADD node /opt/files/node

Этот файл добавляет в контейнер исполняемые файлы Consul и node, а также библиотеку libstdc ++. Версию этого можно найти в Docker.io с именем sirile / filebox.

Контейнер приложений

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

Пример Dockerfile контейнера Nodebox

FROM progrium/busybox
MAINTAINER Ilkka Anttonen version: 0.1
RUN ln -s /opt/files/node /usr/bin/node
RUN ln -s /opt/files/libstdc++.so.6 /lib/libstdc++.so.6

Этот файл добавляет символические ссылки на месте. Это можно найти в Docker.io с именем sirile / nodebox.

Пример приложения

Пример приложения — это очень простое приложение node.js и экспресс-приложение, которое предоставляет ответ «Hello world» на запрос http.

Dockerfile для примера приложения

FROM sirile/nodebox
MAINTAINER Ilkka Anttonen version: 0.1
ADD express.js express.js
ADD node_modules node_modules
CMD "node" "express"

Этот файл добавляет модули узлов и основной файл Javascript на место и выполняет приложение. Это можно найти в Docker.io с именем sirile / nodeboxtest.

Построение контейнера объема

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

vagrant@node1:~$ sudo docker run --name filebox sirile/filebox

Это загружает образ из реестра Docker.io при необходимости.

Сборка и запуск контейнера демонстрационного приложения

Демонстрационное приложение можно запустить с помощью команды:

vagrant@node1:~$ sudo docker run --volumes-from filebox -ti --name testbox -p 3000:3000 --rm sirile/nodeboxtest
Example app listening at http://0.0.0.0:3000

Доступ к приложению можно получить с хост-порта 3000 с помощью браузера. Вы можете выйти из него, нажав CTRL + C.

Изображений

Размер изображений довольно маленький:

vagrant@node1:~$ sudo docker images
REPOSITORY  TAG  IMAGE ID  CREATED  VIRTUAL SIZE
sirile/nodeboxtest  latest  a52297dd66a1  5 hours ago  5.774 MB
sirile/filebox  latest  4fda74df99f9  5 hours ago  25.56 MB
progrium/busybox  latest  6f114d3139e3  3 weeks ago  4.808 MB
vagrant@node1:~$

Размер контейнера для демонстрационного приложения составляет 5,774 МБ. Это можно сделать еще меньше, но при таком размере контейнер предлагает достойную функциональность на тот случай, если к нему потребуется доступ для отладки.

Доступ к контейнеру

Если вам нужно присоединиться к запущенному сеансу и посмотреть, что происходит внутри контейнера, вы можете использовать:

sudo docker exec -ti nodeboxtest /bin/sh

Это открывает оболочку в работающем контейнере, после чего вы можете осмотреться и установить средства отладки и т. Д. Команда доступна начиная с версии Docker 1.3. Таким образом, запуск sshd не требуется в контейнере и nsenter не требуется.

Следующие шаги

Следующим шагом является добавление возможности регистрации услуги в микроконтейнер с помощью Consul. Один микроконтейнер на хост будет действовать как узел сервера Консул, и все микроконтейнеры (микросервисы) в этом узле будут регистрироваться на нем.

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