Предлагаю ознакомиться с расшифровкой доклада Александра Сигачева Service Discovery в распределенных системах на примере Consul.


Service Discovery создан для того, чтобы с минимальными затратами можно подключить новое приложение в уже существующее наше окружение. Используя Service Discovery, мы можем максимально разделить либо контейнер в виде докера, либо виртуальный сервис от того окружения, в котором он запущен.



Я всех приветствую! Я Сигачев Александр, работаю в компании Inventos. И сегодня я вас познакомлю с таким понятием как Service Discovery. Рассмотрим мы Service Discovery на примере Consul.



Какие проблемы решает Service Discovery?


Service Discovery создан для того, чтобы с минимальными затратами можно подключить новое приложение в уже существующее наше окружение. Используя Service Discovery, мы можем максимально разделить либо контейнер в виде докера, либо виртуальный сервис от того окружения, в котором он запущен.


Как это выглядит? На классическом п��имере в вебе – это фронтенд, который принимает запрос пользователя. Дальше выполняет маршрутизацию его на backend. На данном примере – это load-balancer балансирует на два backend.



Здесь мы видим, что мы запускаем третий экземпляр приложения. Соответственно, когда приложение запускается, оно производит регистрацию в Service Discovery. Service Discovery уведомляет load-balancer. Load-balancer меняет свой конфиг автоматически и уже новый backend подключается в работу. Таким образом могут добавляться backend, либо, наоборот, исключаться из работы.



Что еще удобно делать при помощи Service Discovery?


В Service Discovery могут храниться конфиги nginx, сертификаты и список активных backend-серверов.



Также Service Discovery позволяет обнаружить сбой, обнаружить отказы.


Какие возможны схемы при обнаружении отказов?


  • Это приложение, которое мы разработали, само уведомляет Service Discovery, что оно еще до сих пор работоспособно.
  • Service Discovery со своей стороны опрашивает приложение на факт доступности.
  • Или же используется сторонний скрипт или приложение, которое проверяет наше приложение на доступность и уведомляет Service Discovery, что все хорошо и можно работать, или, наоборот, что все плохо и необходимо этот экземпляр приложения исключить из балансировки.

Каждая из схем может применяться в зависимости от того, какое ПО мы используем. Например, мы только начали разрабатывать новый проект, то мы без про��лем можем обеспечить схему, когда наше приложение уведомляет Service Discovery. Либо можем подключить, что Service Discovery проводит проверку.


Если же приложение досталось нам в наследство или разработано кем-то сторонним, то здесь подходит третий вариант, когда мы пишем обработчик, и все это встает в нашу работу автоматически.



Это один из примеров. Load-balancer в виде nginx перезагружается. Это дополнительная утилита, которая предоставляется вместе с Consul. Это consul-template. Мы описываем правило. Говорим, что используем шаблон (Шаблонизатор Golang). При совершении событий, при уведомлениях, что произошли изменения, он перегенерируется и Service Discovery присылается команда «reload». Простейший пример, когда по событию переконфигурируется nginx и перезапускается.



Что такое Consul?


  • Прежде всего – это Service Discovery.


  • Он имеет механизм проверки доступности – Health Checking.


  • Также он имеет KV Store.


  • И в его основу заложено возможность использовать Multi Datacenter.



Для чего все это можно использовать? В KV Store мы можем хранить примеры конфигов. Health Checking мы можем проводить проверку локального сервиса и уведомлять. Multi Datacenter используется для того, чтобы можно было построить карту сервисов. Например, Amazon имеет несколько зон и маршрутизирует трафик наиболее оптимально, чтобы не было лишних запросов между дата-центрами, которые тарифицируются отдельно от локального трафика, и, соответственно, имеют меньшую задержку.



Немножко разберемся с терминами, которые в Consul используются.


  • Consul – сервис, написанный на Go. Одним из преимуществ программы на Go – это 1 бинарный файл, который ты просто скачал. Запустил из любого места и у тебя никаких зависимостей нет.
  • Дальше при помощи ключей мы можем запустить этот сервис либо в режиме клиента, либо в режиме сервера.
  • Также атрибут «datacenter» позволяет поставить флаг к какому дата-центру принадлежит данный сервер.
  • Consensus – базируется на протоколе raft. Если кому интересно, то об этом можно прочитать поподробнее на сайте Consul. Это протокол, который позволяет определить лидера и определить какие денные считать валидными и доступными.
  • Gossip – это протокол, который обеспечивает взаимодействие между нодами. Причем эта система является децентрализованной. В рамках одного дата-центра все ноды общаются с соседями. И, соответственно, передается друг другу информация об актуальном состоянии. Можно сказать, что это сплетни между соседями.
  • LAN Gossip – локальный обмен данных между соседями в рамках одного дата-центра.
  • WAN Gossip – используется, когда нам необходимо синхронизировать информацию между двумя дата-центрами. Информация идет между нодами, которые помечены как сервер.
  • RPC – позволяет выполнять запросы через клиента на сервере.

Описание RPC. Допустим, на виртуальной машине или физическом сервере запущен Consul в виде клиента. К нему локально обращаемся. А дальше локальный клиент запрашивает информацию у сервера и синхронизируется. Информация в зависимости от настроек может выдаваться из локального кэша, либо может быть синхронизирована с лидером, с мастером сервера.


У этих двух схем есть как плюсы, так и минусы. Если мы работаем с локальным кэшем, то это быстро. Если мы работаем с данными, которые хранятся на сервере, то это дольше, но получаем более актуальную информацию.



Если это изобразить графически, то вот такая картинка сайта. Мы видим, что у нас запущено три мастера. Один звездочкой помечен как лидер. В данном примере три клиента, которые между собой обмениваются локально информацией по UDP/TCP. А информация между дата-центрами передается между серверами. Здесь клиенты взаимодействуют между собой локально.



Какой API предоставляет Consul?


Для того чтобы получить информацию, есть два вида API у Consul.


Это DNS API. По умолчанию Consul запускается на 8600 порту. Мы можем настроить проксирование запроса и обеспечить доступ через локальный резолвинг, через локальный DNS. Мы можем запросить по домену и получим в ответ информацию об IP-адресе.


HTTP API – либо мы можем локально на 8500 порту запросить информацию о конкретном сервисе и получим JSON ответ, какой IP имеет сервер, какой host, какой порт зарегистрирован. И дополнительная информация может быть передана через token.



Что нужно, чтобы запустить Consul?


В первом варианте мы в режиме разработчика указываем флаг, что это режим раз��аботчика. Agent стартует как сервер. И всю функцию выполняет уже самостоятельно на одной машине. Удобно, быстро и никаких практически дополнительных настроек для первого старта не требуется.


Второй режим – это запуск в production. Здесь запуск немного усложняется. Если у нас нет ни одной версии консула, то мы должны привести в bootstrap первую машину, т. е. эта машина, которая возьмет на себя обязанности лидера. Мы поднимаем ее, затем мы поднимаем второй экземпляр сервера, передавая ему информацию, где у нас находится мастер. Третий поднимаем. После того, как у нас поднято три машины, мы на первой машине из запущенного bootstrap, перезапускаем ее в обычном режиме. Данные синхронизируются, и начальный кластер уже поднят.


Рекомендуется запускать от трех до семи экземпляров в режиме сервера. Это обуславливается тем, что если количество серверов растет, то увеличивается время на синхронизацию информации между ними. Количество нод должно быть нечетным, чтобы обеспечить кворум.



Как обеспечиваются Health Checks?


В директорию для конфигурации Consul мы в виде Json пишем правило проверки. Первый вариант – это доступность в данном примере домена google.com. И говорим, что через интервал в 30 секунд нужно выполнять эту проверку. Таким образом мы проверяем, что наша нода имеет доступ во внешнюю сеть.


Второй вариант – это проверка себя. Мы обычным curl дергаем localhost по указанному порту с интервалом в 10 секунд.


Эти проверки суммируются и поступают в Service Discovery. На основании доступности эти ноды либо исключаются, либо появляются в списке доступных и корректно работающих машинок.



Также Consul предоставляет UI-интерфейс, который с отдельным флагом запускается и будет доступен на машинке. Это позволяет просматривать информацию, а также можно вносить некоторые изменения.


В данном примере открыта вкладка «Сервис». Показано, что запущено три сервиса, один из них Consul. Количество выполненных проверок. И имеются три дата-центра, в которых находятся машинки.



Это пример вкладки «Nodes». Видим, что у них составные имена с участием дата-центров. Здесь также показано, какие сервисы запущены, т. е. мы видим, что теги не заданы. В этих дополнительных тегах можно задать какую-то информацию, которую разработчик может использовать для указания дополнительных параметров.


Также можно передавать информацию в Consul о состоянии дисков, о средней загрузке.


Вопросы


Вопрос: У нас есть докер-контейнер, как его использовать с Consul ?


Ответ: Для докер-контейнера есть несколько подходов. Один из самых распространенных – это использовать сторонний докер-контейнер, отвечающий за регистрацию. При запуске ему прокидывается сокет докера. Все события по регистрации и депубликации контейнера заносятся в Consul.


Вопрос: Т. е. Consul сам запускает докер-контейнер?


Ответ: Нет. Мы запускаем докер-контейнер. И при конфигурации указываем – слушай такой-то сокет. Это примерно так же, как идет работа с сертификатом, когда мы прокидываем информацию, где и что у нас лежит.


Вопрос: Получается, что внутри докер-контейнера, который мы пытаемся подключить к Service Discovery должна быть какая-то логика, которая умеет отдавать данные Consul?


Ответ: Не совсем. Когда он стартует, то мы через переменное окружение передаем переменные. Допустим, сервис name, сервис порт. В регистре слушает эту информацию и заносит в Consul.


Вопрос: У меня еще по UI вопрос. Мы развернули UI, допустим, на production-сервере. Что с безопасностью? Где хранятся данные? Можно ли как-то аккумулировать данные?


Ответ: В UI как раз данные из базы и из Service Discovery. Пароли мы ставим в настройках самостоятельно.


Вопрос: Это можно публиковать в интернет?


Ответ: По умолчанию Consul стартует на localhost. Чтобы публиковать в это интернет, надо будет поставить какой-то proxy. За правила безопасности мы отвечаем сами.


Вопрос: Исторические данные из коробки выдает? Интересно посмотреть статистику по Health Checks. Можно же диагностировать проблемы, если сервер часто выходит из строя.


Ответ: Я не уверен, что там есть детали проверок.


Вопрос: Не столько важно текущее состояние, сколько важна динамика.


Ответ: Для анализа – да.


Вопрос: Service Discovery для докера Consul лучше не использовать?


Ответ: Я бы не рекомендовал его использовать. Цель доклада – познакомить, что есть такое понятие. Исторически он проделал путь, по-моему, до 1-ой версии. Сейчас уже есть более полноценные решения, например, Kubernetes, который все это имеет под капотом. В составе Kubernetes Service Discovery уступает Etcd. Но я с ним не так плотно знаком, как с Consul. Поэтому Service Discovery я решил сделать на примере Consul.


Вопрос: Схема с сервером лидером не тормозит старт приложения в целом? И как Consul определяет нового лидера, если этот лежит?


Ответ: У них описан целый протокол. Если интересно, то можно почитать.


Вопрос: Consul у нас выступает полноценным сервером и все запросы летают через него?


Ответ: Он выступает не полноценным сервером, а берет определенную зону. Она, как правило, оканчивается service.consul. И дальше мы уже по логике идем. Мы не используем в production доменные имена, а именно внутреннюю инфраструктуру, которая обычно прячется за кэширование сервера, если мы работаем по DNS.


Вопрос: Т. е. если мы хотим обратиться к базе данных, то мы в любом случае будем дергать Consul, чтобы найти эту базу сперва, правил��но?


Ответ: Да. Если работаем по DNS, то это работает как без Consul, когда используем DNS имена. Обычно современные приложения не в каждом запросе дергают доменное имя, потому что мы connect установили, все работает и в ближайшее время мы практически не используем. Если connect разорвался, то – да, мы опять спрашиваем, где у нас лежит база и идем к ней.