Pull to refresh

Consul.io Часть 2

Reading time9 min
Views48K
В первой части мы подробно рассмотрели какие проблемы и задачи ставит перед нами распределенная архитектура приложения. Мы определили какие инструменты мы можем использовать для решения этих проблем и отметили важность реализации discovery на начальном этапе проекта. А также, выбрали Consul основным приложением на базе которого мы будем рассматривать реализацию discovery-сервиса.



В заключительной части мы рассмотрим как Consul работает с протоколом DNS, разберем основные запросы к HTTP API, посмотрим какие виды Health Checks мы можем использовать и, конечно, разберем для чего нужен K/V storage. И что самое важное, ближе познакомимся с некоторыми особенностями на практике.

Интерфейс DNS


Consul может отвечать на запросы по протоколу DNS, при этом можно использовать любой DNS-клиент для запросов. DNS-интерфейс доступен для компонентов на локальном хосте на порту 8600. Помимо прямых запросов к Consul, можно прописать его как resolver в системе и прозрачно использовать его для разрешения имен, проксируя все внешние запросы к вышестоящему “полноценному” DNS-серверу и разрешая запросы в приватной зоне .consul самостоятельно.
Для реализации примитивной DNS-балансировки в случае присутствия в каталоге нескольких сервисов с одинаковым именем и разными IP-адресами Consul случайно перемешивает IP-адреса в ответе.
Помимо прямого запроса на разрешение доменного имени в рамках кластера можно выполнять поиск (lookup). Поиск может быть выполнен как для сервиса (service lookup), так и для узла кластера (node lookup).
Формат доменного имени при DNS-запросе в рамках consul-кластера жестко определен и не подлежит изменению.

Узел кластера


Это обычный DNS-запрос, который вернет IP-адрес узла кластера по его имени (имя узла задается при старте агента при помощи параметра — node). Рассмотрим формат имени узла для DNS-запроса:
[node].node[.datacenter].[domain]
  • [node] — обязательная часть, имя узла;
  • .node — указатель на то, что мы выполняем node lookup;
  • [.datacenter] — необязательная часть, имя датацентра (consul “из коробки” может предоставлять discovery для нескольких датацентров в рамках одного кластера. По умолчанию используется имя dc1. Если имя датацентра не указано, то будет использован текущий ДЦ. То есть тот, в рамках которого запущен агент, к которому выполняется запрос);
  • .[domain] — обязательная часть, приватный домен Consul первого уровня. Имеет значение .consul по умолчанию.

Таким образом, доменное имя для узла с именем, например, nodeservice, будет выглядеть так:
nodeservice.node.consul.
Как мы видим название датацентра пропущенно, но имя можно построить еще и так:
nodeservice.node.dc1.consul.
Несколько узлов с одинаковым именем в рамках одного ДЦ не допускаются.

Сервис


Запрос на поиск сервиса по имени выполняется на всех узлах кластера. В отличии от запроса на разрешение имени узла, запрос на поиск сервиса предоставляет больше возможностей. Кроме, собственно, IP-адреса сервиса (то есть А-записи) вы можете выполнить запрос на получение SRV-записи и узнать порты, на которых запущен сервис.
Вот так выглядит обычный запрос на поиск всех узлов, на которых запущен сервис с именем rls:
root@511cdc9dd19b:~# dig @127.0.0.1 -p 8600 rls.service.consul.

; <<>> DiG 9.9.5-3ubuntu0.7-Ubuntu <<>> @127.0.0.1 -p 8600 rls.service.consul.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26143
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;rls.service.consul.		IN	A

;; ANSWER SECTION:
rls.service.consul.	0	IN	A	172.17.0.2
rls.service.consul.	0	IN	A	172.17.0.3

;; Query time: 4 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Thu Feb 18 07:23:00 UTC 2016
;; MSG SIZE  rcvd: 104

Из этого ответа можно увидеть, что в составе кластера присутствуют два узла, на которых запущен сервис с именем rls и то, что DNS-интерфейс Consul вернул IP-адреса всех узлов. Если мы повторим запрос несколько раз, то увидим, что записи периодически меняются местами, то есть первое место не закреплено за первым найденным сервисом. Это и есть пример простой DNS-балансировки, о которой мы говорили выше.
Если мы запросим SRV-запись, то ответ будет таким:

root@511cdc9dd19b:/# dig @127.0.0.1 -p 8600 rls.service.consul. SRV

; <<>> DiG 9.9.5-3ubuntu0.7-Ubuntu <<>> @127.0.0.1 -p 8600 rls.service.consul. SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8371
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;rls.service.consul.		IN	SRV

;; ANSWER SECTION:
rls.service.consul.	0	IN	SRV	1 1 80 agent-two.node.dc1.consul.
rls.service.consul.	0	IN	SRV	1 1 80 agent-one.node.dc1.consul.

;; ADDITIONAL SECTION:
agent-two.node.dc1.consul. 0	IN	A	172.17.0.3
agent-one.node.dc1.consul. 0	IN	A	172.17.0.2

;; Query time: 5 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Thu Feb 18 07:39:22 UTC 2016
;; MSG SIZE  rcvd: 244

В ANSWER SECTION перечислены доменные имена узлов в формате, требуемом Consul (обратите внимание, узлов, но не сервисов!) и порты, на которых запущен запрашиваемый сервис. IP-адреса узлов (и, соответственно, сервисов) перечислены в ADDITIONAL SECTION ответа.

Формат имени сервиса для DNS-запроса выглядит так:
[tag.][service].service[.datacenter].[domain]
  • [tag.] — необязательная часть. Используется для фильтрации сервиса по тегам. Если у нас есть сервисы с одинаковым именем, но разными тегами, то добавление названия тега поможет отфильтровать выдачу;
  • [service] — обязательная часть, имя сервиса;
  • .service — указатель на то, что мы выполняем service lookup;
  • [.datacenter] — необязательная часть, имя датацентра;
  • .[domain] — обязательная часть, приватный домен Consul первого уровня.

Таким образом, сервис с именем nginx и имеющий tag названный web, можно представить доменом:
web.nginx.service.consul

SRV-запросы на поиск сервисов в соответствии с RFC-2782

Помимо “обычного” построения доменного имени мы можем построить его по более строгим правилам RFC-2782 для выполнения запроса на получение SRV-записи. Формат имени выглядит так:
_service._tag.service[.datacenter].[domain]
Название сервиса и tag имеют underscore (_) в виде префикса. (В оригинальном RFC вместо tag должно стоять название протокола, это сделано для предотвращения коллизий при запросе).
В случае использования имени в формате RFC-2782, сервис с именем nginx и имеющий tag названный web, будет выглядеть так:
_web._nginx.service.consul

Ответ будет точно таким же, как и в случае “простого” запроса:
root@511cdc9dd19b:/# dig @127.0.0.1 -p 8600 _rls._rails.service.consul. SRV

; <<>> DiG 9.9.5-3ubuntu0.7-Ubuntu <<>> @127.0.0.1 -p 8600 _rls._rails.service.consul. SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26932
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;_rls._rails.service.consul.	IN	SRV

;; ANSWER SECTION:
_rls._rails.service.consul. 0	IN	SRV	1 1 80 agent-one.node.dc1.consul.
_rls._rails.service.consul. 0	IN	SRV	1 1 80 agent-two.node.dc1.consul.

;; ADDITIONAL SECTION:
agent-one.node.dc1.consul. 0	IN	A	172.17.0.2
agent-two.node.dc1.consul. 0	IN	A	172.17.0.3

;; Query time: 6 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Thu Feb 18 07:52:59 UTC 2016
;; MSG SIZE  rcvd: 268

По умолчанию, все доменные имена в рамках Consul имеют TTL = 0, то есть совсем не кешируются. Нужно иметь это в виду.

HTTP API


HTTP REST API является основным средством управления кластером Сonsul и предоставляет очень широкий диапазон возможностей. В рамках API реализовано 10 endpoints, каждый из которых предоставляет доступ к конфигурации определенного функционального аспекта Consul. Подробное описание всех edpoints есть в документации Consul, а мы кратко опишем каждый из них для представления о возможностях API:
  • acl — контроль доступа;
  • agent — управление агентом Consul;
  • catalog — управление узлами и сервисами кластера;
  • coordinate — сетевые координаты;
  • event — пользовательские события;
  • health — проверки доступности;
  • kv — Key/Value хранилище;
  • query — подготовленные запросы;
  • session — сессии;
  • status — статус системы.

acl
Как можно понять из названия, acl управляет контролем доступа к сервисам Consul. Мы можем регулировать доступ на получение и изменение данных о сервисах, узлах, пользовательских событиях, а также управлять доступом к k/v-хранилищу.

agent
Управление локальным агентом Consul. Все операции, доступные на этом endpoint, затрагивают данные локального агента. Можно получить информацию о текущем состоянии агента, его роли в кластере, а также получить доступ к управлению локальными сервисами. Изменения, выполненные над локальными сервисами, будут синхронизированы со всеми узлами кластера.

catalog
Управление глобальным реестром Consul. Здесь сосредоточена работа с узлами и сервисами. В рамках этого endpoint можно регистрировать и отключать сервисы и, в случае работы с сервисами, использование этого раздела более предпочтительно нежели работа через agent. Работа через catalog проще, понятнее и способствует анти-энтропии.

coordinate
Consul использует сетевую томографию для вычисления сетевых координат. Эти координаты используются для построения эффективных маршрутов в рамках кластера и многих полезных функций, таких как, например, поиск ближайшего узла с заданным сервисом или переключение на ближайший датацентр в случае аварии. Функции API в этом разделе используются только для получения информации о текущем состоянии сетевых координат.

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

health
Проверка текущего состояния узлов и сервисов. Данный endpoint используется только для чтения и возвращает текущее состояние узлов и сервисов, а также списки выполняемых проверок.

kv
Этот endpoint имеет только один метод и используется для управления данными в распределенном key/value-хранилище, предоставленным Consul. Единственный метод в этом endpoint выглядит так:
/v1/kv/[key]
Разница в обработке заключается в методе запроса. GET вернет значение по ключу, PUT сохранит новое значение или перезапишет старое, а DELETE удалит запись.

query
Управление подготовленными запросами (Prepared queries). Подобные запросы позволяют выполнять сложные манипуляции над конфигурацией Consul и могут быть сохранены и выполнены позже. Сохраненным запросам присваивается уникальный ID. C его помощью запрос может быть выполнен в любое время без необходимости повторной подготовки.

session
Механизм сессий в Consul используется для построения распределенных блокировок. Сессии представляют собой связующий слой между узлами, выполняемыми проверками и k/v-хранилищем. У каждой сессии есть имя и оно может быть сохранено в хранилище. Имя используется для реализации блокировок в рамках последовательных действий с узлами и сервисами в конкурентном режиме. Механизм работы сессий описан в документации Consul.

status
Этот endpoint используется для получении информации о статусе кластера. Здесь можно узнать текущего лидера и получить информацию обо всех участниках кластера.

Health Checks


Ранее мы говорили про равномерное распределение нагрузки с помощью DNS, а теперь рассмотрим механизм проверки состояния узлов и сервисов. Health check — это периодически выполняемая операция, по результатам которой можно определить состояние проверяемой системы. По факту это автоматический мониторинг, который поддерживает состояние кластера в работоспособном состоянии, вычищает неработающие узлы и сервисы и возвращает их в работу по факту восстановления работоспособности. Consul поддерживает несколько видов проверок:
  • Script check — запуск определенного скрипта на определенном узле с заданной периодичностью. В зависимости от кода выхода (любой отличный от нуля код будет означать, что проверка не прошла) включает или выключает узел или сервис.
  • HTTP Check — проверка, которая пытается загрузить указанный URL, и в зависимости от кода ответа включает или выключает проверяемый объект (любые 2xx — все нормально, код 429 Too Many Requests генерирует предупреждение, остальные коды говорят об ошибке).
  • TCP Check — проверка, которая пробует установить tcp-соединение с заданным интервалом к указанному адресу и порту. Невозможность установить соединение означает, что проверка не пройдена.
  • TTL Check — проверка, которая должна периодически обновляться через HTTP API. Суть ее в том, что если некий сервис не обновил эту проверку в рамках определенного интервала, то он помечается как неработающий. Это пассивная проверка, то есть сервис сам должен периодически отчитываться о том, что он работает. Если за заданный интервал отчет не поступил, то проверка считается не пройденной.
  • Docker Check — проверка для сервисов, работающих в docker-контейнерах. Consul, используя Docker Exec API, может выполнить скрипт, находящийся внутри контейнера. Результат проверки будет зависеть от кода выхода, любой отличный от нуля “провалит” проверку.

K/V storage


Хранилище, предоставляемое Consul является распределенной key-value базой данных и может использоваться для сохранения любых данных, доступных для любого участника кластера (в соответствии с правилами ACL, конечно же). Сервисы могут сохранять в этом хранилище данные, которые необходимы для других участников кластера. Это могут быть значения конфигурационных опций, результаты каких-либо вычислений или, как мы указали выше, k/v-хранилище может использоваться для реализации распределенных блокировок при помощи механизма сессий. Использование k/v-хранилища позволит нам сделать кластер более эффективным и уменьшить процент ручного вмешательства. Сервисы могут корректировать свое состояние в зависимости от информации в хранилище, гарантированно предоставленным кластером. Обратите внимание: не стоит сохранять в это хранилище какие-либо данные, связанные с бизнес-логикой ваших сервисов. Хранилище, предоставляемое Consul, используется для хранения и распространения метаинформации о состоянии участников кластера, а не о данных, которые они обрабатывают.

Заключение


Трудно переоценить роль discovery-сервиса в процессе построения распределенной архитектуры на больших проектах. Consul отлично подходит на эту роль. Продукт развивается и не стоит на месте, реализовано много полезного функционала, необходимого для безболезненного обслуживания системы с большим количеством компонентов. Кроме того, Consul написан на Go и распространяется в виде одного исполняемого файла, что делает процесс его обновления и поддержки очень удобным.
Tags:
Hubs:
Total votes 16: ↑14 and ↓2+12
Comments7

Articles