Тема: Consul как простой DNS балансер
Вот и появилась минутка поделится чем-то новым и полезным, на повестки дня Consul.io продукт старый, сделан в лучших традициях devops культуры (мы наговнокодили, он точно работает, но как ставить и запускать, твое дело) По сути ничего сложного и проблемного в этом нет, просто я не люблю когда производитель не дает конечного продукта, а надо что-то допиливать...
Так вот, консул это dns балансер (он же failover) и key-value хранилище. Его можно растянуть как на несколько регионов так и оставить в приделе одного имея хороший кластер который может решить проблему auto-discovery и арбитра во многих случаях, особенно полезно иметь что-то такое если используются микросервисы.
Конфиг клавтера (один на все сервера) примерно такой
# cat /srv/consul/consul.d/config.json
{
"client_addr": "0.0.0.0",
"bootstrap_expect": 3,
"domain": "discovery.domain.com",
"server": true,
"datacenter": "dc1",
"data_dir": "/srv/consul/data",
"encrypt": "J/FNc4hTx3n2ZTipHOUrXQ==",
"dns_config": {
"allow_stale": true,
"max_stale": "15s"
},
"retry_join": [
"10.0.1.1",
"10.0.1.2",
"10.0.1.3"
],
"retry_join_wan": [
"10.0.0.1",
"10.0.0.2",
"10.0.0.3"
],
"retry_interval": "10s",
"retry_max": 100,
"skip_leave_on_interrupt": true,
"leave_on_terminate": false,
"ports": {
"dns": 53,
"http": 80
},
"ui_dir": "/srv/consul/web",
"rejoin_after_leave": true,
"addresses": {
"http": "0.0.0.0",
"dns": "0.0.0.0"
},
"service": {
"name": "consul-web-ui",
"tags": [
"dc1"
],
"port": 80,
"check": {
"id": "web",
"name": "WEB UI on port 80",
"tcp": "localhost:80",
"interval": "10s"
}
}
}
Если надо растянуть на несколько DC то просто добавляются отдельные сервера (3-5) в каждом новом DC и их IP прописываются в wan список. Получается что есть локальные сервер, это мой кластер, и все остальные. Из других кластеров я могу делать выборку данных, что упрощает работу с несколькими регионами, так как я могу сделать запрос и получить список регионов и сделать выборку из какова-то конкретного, ниже будит пример.
Конфигурация клиента
# cat /srv/consul/consul.d/config.json
{
"client_addr": "0.0.0.0",
"datacenter": "dc1",
"data_dir": "/srv/consul/data",
"ui_dir": "/srv/consul/web",
"encrypt": "J/FNc4hTx3n2ZTipHOUrXQ==",
"rejoin_after_leave": true,
"retry_join": [
"10.0.1.1",
"10.0.1.2",
"10.0.1.3"
],
"service": {
"name": "www-http-80",
"tags": ["dc1"],
"port": 80,
"check": {
"name": "WWW on port 80",
"tcp": "localhost:80",
"interval": "5s"
}
}
}
В этом примере у меня на сервере где есть клиент установлен web сервер и его проверяет клиент на работоспособность (простейший тест, есть возможность усложнить сценарий)
Настройка DNS примерно такая, вообще идеально если в зависимости от клиента работает geo-dns и к тому же домену подставляются правильные адреса...
discovery.domain.com. 3600 IN NS ns3-discovery.domain.com.
discovery.domain.com. 3600 IN NS ns2-discovery.domain.com.
discovery.domain.com. 3600 IN NS ns1-discovery.domain.com.
ns3-discovery.domain.com. 3600 IN A 10.0.1.1
ns2-discovery.domain.com. 3600 IN A 10.0.1.2
ns1-discovery.domain.com. 3600 IN A 10.0.1.3
Собственно говоря все, на наш домен который выдает консул делаем cname нужного домена и все работает.
Список к кому обращаться
$ dig +short consul.service.discovery.domain.com
10.0.1.1
10.0.1.2
10.0.1.3
IP из другого DC
$ dig +short consul.service.dc2.discovery.domain.com
10.0.0.1
10.0.0.2
10.0.0.3
Можно какой-то параметр положить и получить
# curl -s http://consul.service.dc1.discovery.domain.com/v1/kv/example 2>&1 | jq
[
{
"LockIndex": 0,
"Key": "example",
"Flags": 0,
"Value": "dmFsdWUx",
"CreateIndex": 62251,
"ModifyIndex": 62251
}
]
# echo "dmFsdWUx" | base64 -d
value1
А вот так можно по DC раскидать сервис
$ dig +short www-http-80.service.discovery.domain.com
10.0.0.219
10.0.0.22
10.0.1.220
$ dig +short dc1.www-http-80.service.discovery.domain.com
10.0.0.22
10.0.0.219
$ dig +short dc2.www-http-80.service.discovery.domain.com
10.0.1.220