Коли сервісів на серверах стає більше десятка, файл /etc/hosts і захардкоджені IP-адреси в конфігах перестають працювати: адреси змінюються при перестворенні VPS, а оновлювати їх вручну на кожному сервері — гарантована помилка рано чи пізно. Consul від HashiCorp вирішує це через service discovery: сервіси реєструються самі, а інші знаходять їх за іменем через DNS чи HTTP API, без єдиного файлу з адресами.
Що робить Consul і коли він потрібен
Consul зберігає три речі: каталог сервісів з їхніми адресами і портами, статус health check для кожного інстансу і розподілене key-value сховище для конфігурації. Застосунок питає не «яка IP-адреса у сервісу billing», а «дай мені живу адресу сервісу billing» — і отримує тільки ті інстанси, які пройшли перевірку здоров'я.
Consul варто ставити, коли серверів більше 5-6 і вони змінюються: додаються репліки, перестворюються VPS, змінюються IP після міграції. На двох постійних серверах з одним сервісом на кожному Consul — зайва складність, вистачить DNS-запису чи рядка в конфігу.
Архітектура: сервер, агент, каталог сервісів
Consul server і кворум
Серверні вузли зберігають стан кластера через протокол Raft і домовляються про кворум. Для відмовостійкості потрібна непарна кількість серверів: 3 сервери переживають втрату одного, 5 — втрату двох. Один сервер годиться тільки для тесту, у продакшені це точка відмови всього кластера.
Consul agent на кожному вузлі
Агент у режимі client ставиться на всі інші сервери — він не зберігає стан кластера, а тільки реєструє локальні сервіси і опитує їхній health check, передаючи дані серверним вузлам через gossip-протокол.
| Роль | Скільки вузлів | Завдання |
|---|---|---|
| Consul server | 3 чи 5 | Кворум, зберігання стану, Raft |
| Consul agent (client) | По одному на кожен робочий сервер | Реєстрація сервісів, health check |
| Consul DNS interface | Вбудований у кожен агент | Резолвінг service.consul |
Встановлення і запуск кластера Consul
Пакет consul ставиться з офіційного репозиторію HashiCorp, окремо для серверних вузлів і для агентів.
curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
apt update && apt install -y consul
consul version
Мінімальний конфіг серверного вузла задає режим server, кількість серверів у кворумі і адресу для gossip-протоколу між вузлами.
{
"server": true,
"bootstrap_expect": 3,
"datacenter": "dc1",
"data_dir": "/var/lib/consul",
"bind_addr": "10.10.0.1",
"retry_join": ["10.10.0.1", "10.10.0.2", "10.10.0.3"]
}
Реєстрація сервісу і перевірка здоров'я
Сервіс реєструється файлом визначення в каталозі /etc/consul.d — агент підхоплює його під час старту чи за командою consul reload.
{
"service": {
"name": "billing-api",
"port": 8080,
"check": {
"http": "http://localhost:8080/health",
"interval": "10s",
"timeout": "2s"
}
}
}
Якщо health check тричі поспіль повертає помилку, Consul позначає інстанс як critical і перестає віддавати його адресу у відповідях DNS і API — балансувальник чи сусід дізнаються про падіння сервісу за 30 секунд, а не за фактом зростання 5xx у клієнтів.
Service discovery через DNS і розподілена конфігурація через KV
Будь-який вузол із працюючим агентом резолвить ім'я billing-api.service.consul через вбудований DNS-інтерфейс на порту 8600 — достатньо прописати Consul як resolver для домену .consul у systemd-resolved чи dnsmasq. Сховище ключ-значення consul kv put/get заміняє окремий конфіг-сервер: feature-прапорці і параметри на кшталт ліміту з'єднань із базою читаються застосунком під час старту і оновлюються без деплою.
Consul зазвичай піднімають поверх уже готової приватної мережі — наприклад, WireGuard mesh між вузлами, щоб gossip-трафік і API не йшли через публічний інтернет. Разом із Nomad Consul закриває і service discovery, і розподіл завдань по кластеру одним і тим самим набором агентів.
Чек-лист перед продакшеном
- Непарна кількість серверних вузлів (3 чи 5), gossip і RPC-порти закриті від публічного інтернету.
- ACL увімкнені хоча б у мінімальному режимі — Consul без ACL за замовчуванням довіряє будь-кому, хто дістався до API.
- Health check налаштований для кожного сервісу, а не тільки сама реєстрація — без нього мертвий інстанс продовжує отримувати трафік.
- Резервне копіювання consul snapshot save налаштоване за розкладом — стан кластера не відновити з нізвідки.
Часті питання
Чому кількість серверних вузлів Consul має бути непарною, а не парною?
Протоколу Raft потрібна чітка більшість голосів, щоб домовитися про стан кластера, а за парної кількості серверів мережа під час розриву може поділитися на дві однакові за розміром групи, і жодна з них не набере більшості для безпечної роботи. Непарна кількість завжди дає чітку більшість на одному боці, тому кластер продовжує працювати і лишається узгодженим навіть після втрати вузла.
Чи замінює Consul балансувальник навантаження, чи перед сервісами все одно потрібен окремий проксі?
Ні, Consul відстежує, які інстанси живі і де вони перебувають, але сам трафік не маршрутизує і не балансує. Зворотному проксі, API-шлюзу чи клієнтській бібліотеці все одно доводиться читати цей каталог і вирішувати, який інстанс обробить конкретний запит — Consul лише віддає актуальний перелік, а саме рішення про маршрутизацію лишається поза ним.
Як швидко Consul перестає надсилати трафік на сервіс після того, як той почав провалювати health check?
Щойно перевірка поспіль повідомляє про помилку, а не один раз випадково, Consul позначає інстанс як critical і одразу прибирає його адресу з відповідей DNS і API. Усе, що покладається на свіжий запит — проксі, балансувальник, інший сервіс, — просто перестає отримувати цей інстанс, і перемикання відбувається автоматично, без того, щоб людина спершу помітила збій за зростанням помилок у клієнтів.
Чи обов'язкова приватна мережа на кшталт VPN-mesh для роботи Consul, чи агенти можуть спілкуватися напряму через публічний інтернет?
Суворо обов'язковою вона не є, проте робота через відкритий інтернет ризикована без ретельно налаштованих списків доступу і шифрування, оскільки gossip-трафік і API спершу не розраховані на публічний інтернет. Запуск агентів поверх уже приватної мережі, наприклад mesh-VPN між вузлами, — стандартний безпечний підхід, який повністю прибирає цей трафік із публічного інтернету.