Тема: 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