Въведение
В последно време популярността на Kubernetes нараства стремително - все повече проекти внедряват тази технология. Аз обаче искам да се спра на оркестратора Nomad: той е отличен за проекти, в които вече се използват други решения от компанията HashiCorp, например, Vault и Consul, и самите проекти не са сложни по отношение на инфраструктурата. В този материал ще бъде предоставена инструкция за инсталиране на Nomad, свързване на две ноди в клъстер, както и интеграция на Nomad с Gitlab.

Тестов стенд
Няколко подробности за тестовата среда: използват се три виртуални сървъра с характеристики 2 CPU, 4 RAM, 50 Gb SSD, свързани в обща локална мрежа. Имената и IP адресите им са:
- nomad-livelinux-01: 172.30.0.5
- nomad-livelinux-02: 172.30.0.10
- consul-livelinux-01: 172.30.0.15
Инсталиране на Nomad и Consul. Създаване на Nomad клъстер
Нека да започнем с базовата инсталация. Въпреки че инсталацията е проста, ще я опиша за цялостност: всъщност тя бе създадена от чернови и бележки за бърз достъп при необходимост.
Преди да преминем към практиката, нека обсъдим теоретичната част, тъй като на този етап е важно да разберем бъдещата структура.
Имаме две ноди на Nomad и искаме да ги обединим в клъстер, а също така за бъдещето ще ни е необходим автоматичен скейлинг на клъстера - за това ни е нужен Consul. С помощта на този инструмент клъстеризацията и добавянето на нови ноди стават много просто: създадената нода Nomad се свързва с Consul агента, след което извършва свързването с съществуващия Nomad клъстер. Затова първо ще инсталираме Consul сървър, ще настроим основна http авторизация за уеб панела (по подразбиране е без авторизация и може да бъде достъпна по външен адрес), а също така и самите Consul агенти на Nomad сървърите, след което ще започнем с Nomad.
Инсталирането на инструментите на компанията HashiCorp е много просто: всъщност просто преместим бинарния файл в директорията bin, настройваме конфигурационния файл на инструмента и създаваме неговия сервисен файл.
Сваляме бинарния файл на Consul и го разархивираме в домашната директория на потребителя:
root@consul-livelinux-01:~# wget https://releases.hashicorp.com/consul/1.5.0/consul_1.5.0_linux_amd64.zip
root@consul-livelinux-01:~# unzip consul_1.5.0_linux_amd64.zip
root@consul-livelinux-01:~# mv consul /usr/local/bin/Сега имаме готов бинарен файл consul за по-нататъшна настройка.
За работа с Consul трябва да създадем уникален ключ с помощта на командата keygen:
root@consul-livelinux-01:~# consul keygen
Преминаваме към настройката на конфигурацията на Consul, създаваме директория /etc/consul.d/ със следната структура:
/etc/consul.d/
├── bootstrap
│ └── config.jsonВ директорията bootstrap ще се намира конфигурационният файл config.json — в него ще зададем настройките на Consul. Съдържанието му:
{
"bootstrap": true,
"server": true,
"datacenter": "dc1",
"data_dir": "/var/consul",
"encrypt": "your-key",
"log_level": "INFO",
"enable_syslog": true,
"start_join": ["172.30.0.15"]
}Да разгледаме поотделно основните директиви и техните стойности:
- bootstrap: true. Включваме автоматичното добавяне на нови нодове при тяхното свързване. Ще отбележа, че не указваме тук точния брой на очакваните нодове.
- сървер: true. Включваме режим на сървър. Consul на тази виртуална машина в момента ще бъде единственият сървър и мастер, а ВМ на Nomad ще бъдат клиенти.
- datacenter: dc1. Указваме името на датацентъра за създаване на клъстера. То трябва да бъде идентично както на клиентите, така и на сървърите.
- encrypt: your-key. Ключ, който също трябва да бъде уникален и да съвпада на всички клиенти и сървъри. Генерира се с помощта на командата consul keygen.
- start_join. В този списък указваме списък с IP адреси, към които ще се осъществява свързване. В момента оставяме само собствения адрес.
На този етап можем да стартираме консул с помощта на командния ред:
root@consul-livelinux-01:~# /usr/local/bin/consul agent -config-dir /etc/consul.d/bootstrap -uiТова е добър начин за отстраняване на грешки в момента, но не може да се използва постоянно по очевидни причини. Ще създадем файл за услуги за управление на Consul чрез systemd:
root@consul-livelinux-01:~# nano /etc/systemd/system/consul.service
Съдържанието на файла consul.service:
[Unit]
Description=Consul Startup process
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c '/usr/local/bin/consul agent -config-dir /etc/consul.d/bootstrap -ui'
TimeoutStartSec=0
[Install]
WantedBy=default.targetСтартираме Consul чрез systemctl:
root@consul-livelinux-01:~# systemctl start consul
Проверяваме: нашият сървис трябва да е стартиран, а при изпълнение на командата consul members трябва да видим нашия сървър:
root@consul-livelinux:/etc/consul.d# consul members
consul-livelinux 172.30.0.15:8301 alive server 1.5.0 2 dc1Следващият етап: инсталиране на Nginx и настройка на прокси, http авторизация. Инсталираме nginx чрез пакетния мениджър и в директорията /etc/nginx/sites-enabled създаваме конфигурационния файл consul.conf със следното съдържание:
upstream consul-auth {
server localhost:8500;
}
server {
server_name consul.doman.name;
location / {
proxy_pass http://consul-auth;
proxy_set_header Host $host;
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Password-protected Area";
}
}Не забравяйте да създадете .htpasswd файл и да генерирате потребителско име и парола за него. Тази стъпка е необходима, за да не бъде уеб панелът достъпен за всеки, който знае домейна ни. Въпреки това, при настройката на Gitlab ще трябва да се откажем от това - иначе няма да можем да внедрим приложението си в Nomad. В моя проект и Gitlab, и Nomad се намират само в защитената мрежа, така че тук такъв проблем няма.
На другите два сървъра инсталираме агентите на Consul според следващите инструкции. Повтаряме действията с бинарния файл:
root@nomad-livelinux-01:~# wget https://releases.hashicorp.com/consul/1.5.0/consul_1.5.0_linux_amd64.zip
root@nomad-livelinux-01:~# unzip consul_1.5.0_linux_amd64.zip
root@nomad-livelinux-01:~# mv consul /usr/local/bin/По аналогия с предишния сървър създаваме директория за конфигурационните файлове /etc/consul.d със следната структура:
/etc/consul.d/
├── client
│ └── config.jsonСъдържание на файла config.json:
{
"datacenter": "dc1",
"data_dir": "/opt/consul",
"log_level": "DEBUG",
"node_name": "nomad-livelinux-01",
"server": false,
"encrypt": "your-private-key",
"domain": "livelinux",
"addresses": {
"dns": "127.0.0.1",
"https": "0.0.0.0",
"grpc": "127.0.0.1",
"http": "127.0.0.1"
},
"bind_addr": "172.30.0.5", # локален адрес на виртуалната машина
"start_join": ["172.30.0.15"], # отдалечен адрес на консул сървъра
"ports": {
"dns": 53
}Запазваме промените и преминаваме към настройката на файла за услугата, съдържанието му:
/etc/systemd/system/consul.service:
[Unit]
Description="HashiCorp Consul - решение за мрежови услуги"
Documentation=https://www.consul.io/
Requires=network-online.target
After=network-online.target
[Service]
User=root
Group=root
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d/client
ExecReload=/usr/local/bin/consul reload
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.targetСтартираме consul на сървъра. Сега, след стартирането, трябва да видим конфигурирана услугата в nsul members. Това ще означава, че успешно се е свързал с клъстера като клиент. Повторете същото на втория сървър и след това можем да започнем с инсталацията и настройката на Nomad.
По-подробната инсталация на Nomad е описана в официалната му документация. Има два традиционни метода за инсталация: изтегляне на бинарен файл и компилиране от изходен код. Аз ще избера първия метод.
Забележка: проектът се развива много бързо, често излизат нови обновления. Може да се случи до момента на завършване на статията да излезе нова версия. Затова препоръчвам преди прочитане да проверите актуалната версия на Nomad в момента и да изтеглите именно нея.
root@nomad-livelinux-01:~# wget https://releases.hashicorp.com/nomad/0.9.1/nomad_0.9.1_linux_amd64.zip
root@nomad-livelinux-01:~# unzip nomad_0.9.1_linux_amd64.zip
root@nomad-livelinux-01:~# mv nomad /usr/local/bin/
root@nomad-livelinux-01:~# nomad -autocomplete-install
root@nomad-livelinux-01:~# complete -C /usr/local/bin/nomad nomad
root@nomad-livelinux-01:~# mkdir /etc/nomad.dСлед като разархивираме, ще получим бинарен файл на Nomad с размер 65 MB — необходимо е да го преместим в /usr/local/bin.
Ще създадем директория data за Nomad и ще редактираме файла за услугата му (вероятно такъв файл не съществува в началото):
root@nomad-livelinux-01:~# mkdir --parents /opt/nomad
root@nomad-livelinux-01:~# nano /etc/systemd/system/nomad.serviceВмъкнете следните редове:
[Unit]
Description=Nomad
Documentation=https://nomadproject.io/docs/
Wants=network-online.target
After=network-online.target
[Service]
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/nomad agent -config /etc/nomad.d
KillMode=process
KillSignal=SIGINT
LimitNOFILE=infinity
LimitNPROC=infinity
Restart=on-failure
RestartSec=2
StartLimitBurst=3
StartLimitIntervalSec=10
TasksMax=infinity
[Install]
WantedBy=multi-user.targetНо не бързайте да стартирате nomad — все още не сме създали конфигурационния файл:
root@nomad-livelinux-01:~# mkdir --parents /etc/nomad.d
root@nomad-livelinux-01:~# chmod 700 /etc/nomad.d
root@nomad-livelinux-01:~# nano /etc/nomad.d/nomad.hcl
root@nomad-livelinux-01:~# nano /etc/nomad.d/server.hcl
Крайна структура на директорията ще бъде следната:
/etc/nomad.d/
├── nomad.hcl
└── server.hclФайлът nomad.hcl трябва да съдържа следната конфигурация:
datacenter = "dc1"
data_dir = "/opt/nomad"Съдържание на файла server.hcl:
server {
enabled = true
bootstrap_expect = 1
}
consul {
address = "127.0.0.1:8500"
server_service_name = "nomad"
client_service_name = "nomad-client"
auto_advertise = true
server_auto_join = true
client_auto_join = true
}
bind_addr = "127.0.0.1"
advertise {
http = "172.30.0.5"
}
client {
enabled = true
}Не забравяйте да промените конфигурационния файл на втория сървър — ще е нужно да промените стойността на директорията http.
Последната стъпка на този етап е да настроите Nginx за прокси и да инсталирате http авторизация. Съдържание на файла nomad.conf:
upstream nomad-auth {
server 172.30.0.5:4646;
}
server {
server_name nomad.domain.name;
location / {
proxy_pass http://nomad-auth;
proxy_set_header Host $host;
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Защитена зона с парола";
}
}Сега можем да имаме достъп до уеб панела през външната мрежа. Свързваме се и преминаваме на страницата servers:

Изображение 1. Списък на сървърите в клъстера Nomad
И двата сървъра успешно се показват в панела, същото ще видим и в резултата от командата nomad node status:

Изображение 2. Резултат от командата nomad node status
А какво става от страна на Consul? Нека да видим. Преминаваме към контролния панел на Consul, на страницата nodes:

Изображение 3. Списък на нодовете в клъстера Consul
Сега имаме настроен Nomad, работещ в комбинация с Consul. В последния етап ще преминем към най-интересното: ще настроим доставката на Docker контейнери от GitLab в Nomad, а също така ще обсъдим и някои от неговите отличителни характеристики.
Създаване на GitLab Runner
За деплой на Docker образи в Nomad ще използваме отделен Runner с бинарния файл на Nomad вътре (между другото, може да се отбележи още една характеристика на приложенията на Hashicorp — те самостоятелно представляват единичен бинарен файл). Заредете го в директорията на Runner-а. За него ще създадем прост Dockerfile със следното съдържание:
FROM alpine:3.9
RUN apk add --update --no-cache libc6-compat gettext
COPY nomad /usr/local/bin/nomad
В този проект създаваме .gitlab-ci.yml:
variables:
DOCKER_IMAGE: nomad/nomad-deploy
DOCKER_REGISTRY: registry.domain.name
stages:
- build
build:
stage: build
image: ${DOCKER_REGISTRY}/nomad/alpine:3
script:
- tag=${DOCKER_REGISTRY}/${DOCKER_IMAGE}:latest
- docker build --pull -t ${tag} -f Dockerfile .
- docker push ${tag}В резултат на това ще имаме наличен образ на Nomad Runner в GitLab Registry, сега можем да преминем директно към репозитория на проекта, да създадем Pipeline и да настроим nomad job на Nomad.
Настройка на проекта
Нека започнем с файла job’s за Nomad. Моят проект в тази статия ще бъде доста примитивен: той ще се състои от една задача. Съдържанието на .gitlab-ci ще бъде следното:
variables:
NOMAD_ADDR: http://nomad.address.service:4646
DOCKER_REGISTRY: registry.domain.name
DOCKER_IMAGE: example/project
stages:
- build
- deploy
build:
stage: build
image: ${DOCKER_REGISTRY}/nomad-runner/alpine:3
script:
- tag=${DOCKER_REGISTRY}/${DOCKER_IMAGE}:${CI_COMMIT_SHORT_SHA}
- docker build --pull -t ${tag} -f Dockerfile .
- docker push ${tag}
deploy:
stage: deploy
image: registry.example.com/nomad/nomad-runner:latest
script:
- envsubst '${CI_COMMIT_SHORT_SHA}' job.nomad
- cat job.nomad
- nomad validate job.nomad
- nomad plan job.nomad || if [ $? -eq 255 ]; then exit 255; else echo "success"; fi
- nomad run job.nomad
environment:
name: production
allow_failure: false
when: manualТук деплой се извършва ръчно, но можете да го настроите да се променя при промяна на съдържанието в директорията на проекта. Pipeline също се състои от два етапа: изграждане на образа и неговия деплой в Nomad. В първия етап изграждаме Docker образа и го натискаме в нашия Registry, а на втория стартираме нашата работа в Nomad.
работа "monitoring-status" {
центрове_данни = ["dc1"]
миграция {
макс_паралел = 3
проверка_здравето = "checks"
мин_здравословно_време = "15s"
здравословен_краен_срок = "5m"
}
група "zhadan.ltd" {
брой = 1
актуализация {
макс_паралел = 1
мин_здравословно_време = "30s"
здравословен_краен_срок = "5m"
краен_срок_прогрес = "10m"
автоматично_възстановяване = true
}
задача "service-monitoring" {
драйвер = "docker"
конфигурация {
изображение = "registry.domain.name/example/project:${CI_COMMIT_SHORT_SHA}"
задължително_изтегляне = true
удостоверяване {
потребителско_име = "gitlab_user"
парола = "gitlab_password"
}
карта_порт {
http = 8000
}
}
ресурси {
мрежа {
порт "http" {}
}
}
}
}
}Обърнете внимание, че имам затворен Registry и за успешното изтегляне на docker изображение ми е необходимо да се удостоверя. Най-доброто решение в този случай е да запиша логина и паролата във Vault, с последваща интеграция с Nomad. Nomad поддържа Vault нативно. Но първо в самия Vault ще настроим необходимите политики за Nomad, те могат да бъдат заредени:
# Download the policy and token role
$ curl https://nomadproject.io/data/vault/nomad-server-policy.hcl -O -s -L
$ curl https://nomadproject.io/data/vault/nomad-cluster-role.json -O -s -L
# Write the policy to Vault
$ vault policy write nomad-server nomad-server-policy.hcl
# Create the token role with Vault
$ vault write /auth/token/roles/nomad-cluster @nomad-cluster-role.jsonСега, след като създадохме необходимите политики, ще добавим интеграция с Vault в блока задача на файла job.nomad:
vault {
активирано = true
адрес = "https://vault.domain.name:8200"
токен = "token"
}Използвам удостоверяване с токен и го прописвам директно тук, също така има вариант за указване на токена като променлива при стартиране на nomad agent:
$ VAULT_TOKEN= nomad agent -config /path/to/config
Сега можем да използваме ключовите стойности с Vault. Принципът на работа е прост: създаваме файл в работата на Nomad, който ще съдържа стойностите на променливите, например:
template {
data = <<EOH
{{with secret "secrets/pipeline-keys"}}
REGISTRY_LOGIN="{{ .Data.REGISTRY_LOGIN }}"
REGISTRY_PASSWORD="{{ .Data.REGISTRY_LOGIN }}{{ end }}"
EOH
цел = "secrets/service-name.env"
env = true
}С такъв прост подход можем да настроим доставянето на контейнери в кластер Nomad и да работим с него по-късно. Аз лично смятам, че в известен смисъл предпочитам Nomad — той е по-подходящ за малки проекти, където Kubernetes може да създаде допълнителни усложнения и няма да реализира своя потенциал напълно. Освен това, Nomad е перфектен за начинаещи — лесно се инсталира и конфигурира. Въпреки това, при тестване на някои проекти се сблъсквам с проблеми в ранните версии — много базови функции просто липсват или не работят коректно. Въпреки това, вярвам, че Nomad ще продължи да се развива и в бъдеще ще придобие необходимите функции.
Автор: Илия Андреев, под редакцией Алексей Жадан и екипът на «Лайв Линукс»
Източник: habr.com
