Consul - распределенная система обнаружения и мониторинга сервисов.
Распределенность достигается с помощью протокола gossip, что переводится как "сплетни". Концепцию распространения сплетен можно проиллюстрировать с помощью аналогии служащих распускающих слухи. Предположим, каждый час офисные работники собираются вокруг куллера. Каждая пара сотрудников встречается случайным образом и делится последними сплетнями. В начале дня, Алиса рассказывает новый слух: она комментирует Бобу, что она считает, что Чарли красит свои усы. На следующем заседании, Боб рассказывает это Дэйву, в это же время Алиса повторяет идею Еве. После каждого рандеву количество людей, которые слышали слух, увеличивается примерно в два раза (хотя это не учитывает рассказ сплетен дважды одному и тому же лицу. Возможно, Элис пытается рассказать эту историю Фрэнку, но Фрэнк уже слышал её от Дэйва). Компьютерные системы обычно реализуют этот тип протокола с формой случайного выбора "сверстников": с заданной частотой, каждая машина выбирает другую машину в случайном порядке и распространяют горячие слухи.
Обнаружение сервисов реализовано с помощью протокола DNS. Т.е. зарегистрированный сервис будет доступен по доменному имени. Например:
consul.service.domain.ltd
По мере роста инфраструктуры возникает проблема с обнаружением сервисов и организации взаимодействия между ними. Чем больше сервисов связаны между собой, тем маcштабнее она становится. Первое, что приходит в голову - использовать dns сервер. С помощью него, возможно сконфигурировать статическую инфраструктуру. Как же быть с динамической?
Ответ на этот вопрос попыталась дать компания HashiCorp. Consul - инструмент для обнаружения сервисов, балансировки нагрузки, мониторинга и согласованного хранилища данных (В виде ключ - значение).
В терминале перейдите в папку /usr/local/bin и загрузите Consul:
cd /usr/local/bin
wget https://releases.hashicorp.com/consul/0.7.1/consul_0.7.1_linux_amd64.zip
Теперь, распакуйте архив используя unzip, после чего удалите его:
unzip *.zip
rm *.zip
Начиная с версии 0.7.0 consul web ui включен в состав пакета. Параметр -ui активирует встроенный интерфейс.
На этом установка завершена и consul готов к настройке.
Consul возможно запустить в трех режимах: bootstrap, server, client. Для того, чтобы создать кластер хотя бы один сервер должен быть запущен в режиме boostrap. Разница между режимами server и client заключается в участии узла в consensus quorum при обновлении состояния кластера (Соответсвенно server учавствует, client - нет). Перейдем к базовой настройке:
Создайте папку /etc/consul:
mkdir /etc/consul
В ней будут храниться 3 файла кофигурации, по одному для каждого режима:
/etc/consul/bootstrap.conf:
{
"protocol": 3,
"bootstrap": true,
"server": true,
"data_dir": "/var/consul/",
"log_level": "INFO",
"leave_on_terminate": true,
}
/etc/consul/server.conf:
{
"protocol": 3,
"bootstrap": false,
"server": true,
"data_dir": "/var/consul",
"log_level": "INFO",
"leave_on_terminate": true,
"start_join": ["consul.service.domain.ltd"]
}
/etc/consul/client.conf:
{
"protocol": 3,
"bootstrap": false,
"server": false,
"data_dir": "/var/consul",
"log_level": "INFO",
"leave_on_terminate": true,
"start_join": ["consul.service.domain.ltd"]
}
Обновите список серверов доменных имен отредактировав файл /etc/resolv.conf:
nameserver IP_ADDRESS
nameserver BOOTSTRAP_SERVER_IP_ADDRESS
nameserver NET_PROVIDER_IP_ADDRESS
* Подставте ваши IP адреса следующим образом: IP_ADDRESS - локальный адрес сервера; BOOTSTRAP_SERVER_IP_ADDRESS - адрес сервера в режиме bootstrap; NET_PROVIDER_IP_ADDRESS - адрес доменного сервера вашего провайдера
Создайте пользователя consul используя команду:
adduser consul
Далее создайте директорию, в которой consul будет сохранять персистентную информацию и установите её владельцем ранее созданного пользователя:
mkdir /var/consul
chown consul:consul /var/consul
Последним шагом, необходимо создать systemd unit файл для запуска: consul.service:
[Unit]
Description=Consul Service Discovery
[Service]
User=consul
Environment="CONSUL_DOMAIN=domain.ltd"
Environment="CONSUL_DC=dev"
Environment="CONSUL_CONF_FILE=bootstrap.conf"
Restart=always
RestartSec=60
ExecStart=/usr/local/bin/consul agent -ui -domain ${CONSUL_DOMAIN} -dc ${CONSUL_DC} -client 0.0.0.0 -config-file /etc/consul/${CONSUL_CONF_FILE}
ExecStartPost=/bin/bash -c "until curl http://127.0.0.1:8500/v1/agent/services; do sleep 2; done"
ExecStop=/usr/local/bin/consul leave
[Install]
WantedBy=multi-user.target
В зависимости от количества серверов в кластере с помощью unit'а вы можете задавать необходимое количество узлов в режиме клиента и сервера, а также сколько из них должно учавствовать в создании кластера.
В таблице ниже указаны размеры кворума для кластеров различных размеров. Рекомендуемый размер от 3 до 5 серверов. Кластер с 1 узлом очень нестабилен и может привести к неконсистентности или потере данных в случае падений.
Узлы | Размер Кворума | Толерантность к неудачам |
1 | 1 | 0 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 3 |
7 | 4 | 3 |
Независимо от выбранного размера кластера первым делом необходимо выполнить bootstrap. Сделать это можно запустив на сервере с адресом указанным как BOOTSTRAP_SERVER_IP_ADDRESS unit consul.service с конфигурационым файлом bootstrap.conf. После выполнения этого шага можно запускать все остальные узлы и они автоматически подключатся к кластеру используя доменное имя consul.service.domain.ltd.
Если boostrap прошел успешно на http://IP_ADDRESS:8500/ui consul отобразит список сервисов:
Основная роль интерфейса - отображение актуального состояния кластера. Функционал по управлению сервисами в нем отсутствует.
Consul предоставляет REST API. По умолчанию оно доступно по адресу IP_ADDRESS:8500.
Регистрация сервиса производится по адресу http://IP_ADDRESS:8500/v1/agent/service/register с помощью PUT запроса:
{
"Datacenter": "dev",
"Node": "foobar",
"Address": "192.168.10.10",
"Service": {
"ID": "redis1",
"Service": "redis",
"Tags": [
"master",
"v1"
],
"Address": "127.0.0.1",
"Port": 8000
},
"Check": {
"Node": "foobar",
"CheckID": "service:redis1",
"Name": "Redis health check",
"Notes": "Script based health check",
"Status": "passing",
"ServiceID": "redis1"
}
}
или в более упрощенном варианте:
{
"ID": "regis1",
"Name": "regis1",
"Tags": ["master","v1"],
"Address": "192.168.10.10",
"Port": 8000
}
Полностью запрос регистрации с помощью утилиты curl возможно выполнить следующим образом:
curl -d '{"ID": "redis1","Name": "redis1","Tags": ["master","v1"],"Address": "192.168.10.10","Port": 8000}' http://IP_ADDRESS:8500/v1/agent/service/register
Дерегистрация сервиса производится по адресу http://IP_ADDRESS:8500/v1/agent/service/deregister с добавлением ID сервиса в конец. Например, чтобы дерегистрировать сервис redis1 с помощью утилиты curl:
curl http://IP_ADDRESS:8500/v1/agent/service/deregister/redis1
В случае, если на двух узлах будет зарегистрирован сервис с одинаковым названием consul будет использовать DNS round-robin. Причем IP адреса будут отдаваться базируясь на нагруженности, метрики и других показателях. Другими словами базовый load balancing доступен сразу и без дополнительных насторек.
В ходе использования consul на production системе, состоящей из 5 серверов выявлено было всего лишь 2 недостатка: