HashiCorp Nomad. Installation guide and example

Nomad от HashiCorp это очередной scheduler для управления/ жизненным циклом различных задач запускаемых на группе серверов. Из коробки Nomad имеет драйверы для запуска Docker, rkt, LXC контейнеров и виртуальных машин QEMU-KVM. Так же поддерживается запуск отдельных процессов. Перечень драйверов и их описание.
Лично я рассматриваю Nomad как средство оркестрации Docker-контейнерами. Меня пугает монструозный Kubernetes а нативный Docker-swarm навязывает слишком много своих правил, например не всегда нужные overlay-сети и механизмы балансировки на базе LVS или dns-rr. Пока, что мы используем Puppet для деплоя docker-контейнеров описанных в yaml-файле. Puppet хорошо справляется с задачей создания\обновления\удаления контейнеров но при отказе сервера перераспределить контейнеры на другие ноды уже сложнее, это все такие не его стезя. В общем, мы периодически посматриваем на другие решения и надеемся найти, что то, что даст максимум свободы и при этом не будет иметь переусложненную архитектуру. Nomad — потенциальный  кандидат 🙂

Коротко о архитектуре

Nomad как и большинство продуктов от HashiCorp поставляется в виде одного бинарного файла. Как и во многих проектах написанных на Go, Nomad может быть запущен с разными ключами и выполнять различные роли.
server — в производственной среды должно быть не меньше трех экземпляров на с ролью server. Экземпляры с этой ролью поддерживают кворум и реплицируют между собой всю информацию о кластере, задачах в нем и т.д. Собственно задача на выполнения(job) передается серверам а те в свою очередь запускают ее на серверах с ролью client.
сlient — рабочие лошадки кластера. Они подключаются к серверам, регистрируются и затем на них выполняются различные задачи запускаемые в кластере.
dev — эта специальная роль совмещающая в себе и server и client. Подходит для дебага или тестирования.
Nomad Client and Server Requirements

Quorum серверов

Интересно, что nomad позиционируется как средство позволяющее управлять миллионом контейнеров на тысячах серверов но при этом на оф. сайте нет информации по настройке производственной среды. Все что есть на тему настройки в их документации это vagrant up. Я не использую vagrant  и по этой причине я и решил написать заметку по настройке похожего на производственный кластера.

Итак, я использую CentOS 7.3 но это совершенно не принципиально в данном случае.

Роль серверов у меня будут выполнять три ноды:

dh01
dh02
dh03

Роль клиентов:
dh04
dh05

Собственно скачиваем любым способом zip с nomad.
Распаковываем и кладем бинарь в /usr/bin/ на всех серверах.

Генерим ключ для авторизации серверов и шифрования передаваемых ими данных:

nomad keygen

vvCQqXZoMcPWJtq63D/Zwg==

Далее, я буду использовать systemd-юниты для демонизации и управления процессами nomad.

systemd-юнит для серверов:

vim /usr/lib/systemd/system/nomad-server.service


[Unit]
Description=Nomad-server
After=network.target

[Service]
StartLimitInterval=20
StartLimitBurst=5
TimeoutStartSec=0

ExecStartPre=/usr/bin/mkdir -p /var/lib/nomad
ExecStart=/usr/bin/nomad agent -server -data-dir=/var/lib/nomad -encrypt=vvCQqXZoMcPWJtq63D/Zwg== -bootstrap-expect=3
ExecStop=/usr/bin/kill $MAINPID

[Install]
WantedBy=multi-user.target

Данный unit написан мной самостоятельно и опции запуска nomad тоже выбраны эмпирическим путем, в силу отсутствия документации.
Поясню только, что  -bootstrap-expect=3  указывает количество серверов которых нужно дождаться прежде чем конфигурить кластер и выбирать лидера.

Запускам созданный сервис на трех серверах с ролью server:

systemctl daemon-reload
systemct start nomad-server

Собираем кластер(выполнить на одном из серверов с запущенным сервисом nomad-server):

[root@dh01] nomad server-join 10.200.77.32 10.200.77.30

10.200.77.32 10.200.77.30 — ip dh02,dh03

Проверяем состояние кластера:

nomad server-members


Name                     Address       Port  Status  Leader  Protocol  Build  Datacenter  Region
dh01.ruden.local.global  10.200.77.29  4648  alive   false   2         0.5.5  dc1         global
dh02.ruden.local.global  10.200.77.30  4648  alive   false   2         0.5.5  dc1         global
dh03.ruden.local.global  10.200.77.32  4648  alive   true    2         0.5.5  dc1         global

Подключение клиентов

systemd-юнит для серверов с ролью client:

cat /usr/lib/systemd/system/nomad-client.service 


[Unit]
Description=Nomad-server
After=network.target

[Service]
StartLimitInterval=20
StartLimitBurst=5
TimeoutStartSec=0

ExecStartPre=/usr/bin/mkdir -p /var/lib/nomad
ExecStart=/usr/bin/nomad agent -client -data-dir=/var/lib/nomad -servers dh01 dh02 dh03
ExecStop=/usr/bin/kill $MAINPID

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemct start nomad-client

Клиенты автоматически подключаются к кластеру:

nomad node-status


ID        DC   Name              Class   Drain  Status
f3b0df4b  dc1  dh05.ruden.local  <none>  false  ready
1f889694  dc1  dh04.ruden.local  <none>  false  ready

 Запуск задачи

Генерация скелета файла-описания задачи в котором используется docker-драйвер и запускается контейнер с redis:

nomad init

Example job file written to example.nomad

 Запуск задачи:

nomad run example.nomad

 Статус задач:

nomad status

ID       Type     Priority  Status
example  service  50        running

 Естественно на серверах с ролью client в данном конкретном случае должен работать docker-engine )

К сожалению я особо не успел поработать с nomad и не могу пока говорить о плюсах, минусах, надежности и прочем. Пока все на стадии «потыкать палочкой».