Обновить
Комментарии 8
При вводе нового узла в кластер, нам необходимо знать адрес любого узла в кластере. Выполнив команду:
consul join node_ip_address
Лучше в конфиг файле прописать список всех серверов, используя start_join:
"start_join": ["10.x.x.1", "10.x.x.2", "10.x.x.3"]


Вообще, настройку лучше не ручками делать. У нас, к примеру, всё это через Ansible. Используем плейбук вроде этого.
Да, несомненно это так. Просто в статье мы описывали не особенности конфигурации консула, а, скорее, применимость его для discovery в целом. Мы описали ситуацию, которую можно воспроизвести как “посмотреть на его возможности”.
Получается, каждый сервис должен знать IP, по которому доступен?
Нет, не совсем так. Каждый сервис регистрируется в консуле, как раз для того, чтобы не знать свой IP. Агент консула запускается рядом с каждым сервисом и берет на себя всю работу по распространению информации по кластеру.
Строго говоря, часто ip этого сервиса должен знать тот, кто его регистрирует, а это не обязательно сам сервис. Вот запускается у меня сервис в своём netns, где у него на условном eth0 ip 172.17.0.22, стучится в консул на бридже 172.17.0.1. В netns, где работает консул есть три адаптера: eth0 (внешний с условным ip 203.0.113.12), tap0 (vpn с условным 10.8.0.33) и бридж с 172.17.0.1. Если что, описанный setup — модель хоста с сервисом, запущенным в docker/systemd.

Какой из ip адресов должен быть указан в консуле? Каким образом он его выберет? Тот же registrator решает эту проблему явным указанием адреса, на который надо регистрировать сервисы.
Да, вы правы. Прелесть консула в его децентрализованности, то есть нужды держать discovery на бридже у вас нет, агент консула всегда доступен для вашего сервиса на локальном интерфейсе. Если вы запускаете сервис в контейнере, то там будет всего два интерфейса — локальный и внешний, консул успешно разместится на обоих:

root@2bc788f155da:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:02
          inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:14 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1156 (1.1 KB)  TX bytes:578 (578.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
root@2bc788f155da:~# ./consul agent -data-dir /tmp/consul/
==> Starting Consul agent...
==> Starting Consul agent RPC...
==> Consul agent running!
         Node name: '2bc788f155da'
        Datacenter: 'dc1'
            Server: false (bootstrap: false)
       Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
      Cluster Addr: 172.17.0.2 (LAN: 8301, WAN: 8302)
    Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
             Atlas: <disabled>

Посмотрите на Cludter Addr — это именно тот интерфейс, который будет доступен для кластера Consul извне
Теперь попробуем запустить консул на хост-машине, там явно больше двух интерфейсов

docker@consul:/mnt/sda1/tmp$ ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:7A:86:C8:9D
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:7aff:fe86:c89d/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:536 (536.0 B)  TX bytes:648 (648.0 B)

eth0      Link encap:Ethernet  HWaddr 08:00:27:89:88:DF
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe89:88df/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:883 errors:0 dropped:0 overruns:0 frame:0
          TX packets:573 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:128760 (125.7 KiB)  TX bytes:104274 (101.8 KiB)

eth1      Link encap:Ethernet  HWaddr 08:00:27:A2:68:2C
          inet addr:192.168.99.100  Bcast:192.168.99.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fea2:682c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:165 errors:0 dropped:0 overruns:0 frame:0
          TX packets:112 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:21390 (20.8 KiB)  TX bytes:22364 (21.8 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1376 (1.3 KiB)  TX bytes:1376 (1.3 KiB)

veth01e9663 Link encap:Ethernet  HWaddr 6A:0F:14:E9:35:D2
          inet6 addr: fe80::680f:14ff:fee9:35d2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:648 (648.0 B)  TX bytes:1296 (1.2 KiB)
docker@consul:/mnt/sda1/tmp$ ./consul agent -data-dir=/tmp/cns
==> Starting Consul agent...
==> Error starting agent: Failed to get advertise address: Multiple private IPs found. Please configure one.

Не стартует. Необходимо явно указать адрес, на который будет биндиться интерфейс кластера

docker@consul:/mnt/sda1/tmp$ ./consul agent -data-dir=/tmp/cns -bind=172.17.0.1
==> Starting Consul agent...
==> Starting Consul agent RPC...
==> Consul agent running!
         Node name: 'consul'
        Datacenter: 'dc1'
            Server: false (bootstrap: false)
       Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
      Cluster Addr: 172.17.0.1 (LAN: 8301, WAN: 8302)
    Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
             Atlas: <disabled>

Вот теперь все ок.
Дальше кейс использования очень простой. Ваш сервис (или то, что его запускает :) ) всегда знает, что на локальном интерфейсе есть API консула, а консул дальше распространяет эту информацию по кластеру
Этот подход имеет четыре недостатка:

  • не работает, если у вас больше одного хоста (или требует ручного геморроя с подсетями для бриджа), т. к. адрес сервиса 172.17.0.22 абсолютно не говорит о том, как к этому сервису обращаться, если он реально на другом хосте;
  • требует ухода от SRP, модификации образов контейнеров и запуска связки супервизор+консул+сервис в каждом контейнере;
  • резко увеличивает поверхность атаки, т. к. статические ключи для serf'овского gossip'а и ключи+сертификаты для tls будут присутствовать в каждом контейнере;
  • требует внесения изменений во все сервисы, что трудоёмко и не всегда возможно.

Мне больше импонирует подход с вынесением этого счастья на уровень инфраструктуры (вышеупомянутый registrator, подход с systemd unit'ом с BindsTo.
Возможно, в вашем случае все описанные недостатки существенны и имеют место быть. В таком случае вы правы и вам действительно лучше выбрать другой подход и другие инструменты.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.