Consul - configurare servicii si autodiscovery

Postat la Tue 10 December 2019 in tutoriale, consul

Intr-o infrastructura dinamica - unde microserviciile ruleaza pe instante cu durata de viata scurta - interconectarea serviciilor se rezolva prin service discovery oferita de Consul.

Acest serviciu foloseste un registru (baza de date) pentru a cunoaste in timp real lista de servicii, locatia lor si starea lor de sanatate. Clienti interogeaza acest registru pentu descoperirea locatiei pentru serviciile necesare (alte microservicii, baze da date, cache etc..). Acest lucru permite scalarea in sus/jos fara necesitatea uni proxy.

Definirea serviciilor se face cu instantele client Consul. De exemplu pentru definirea unui servciu de api creem fisierul /etc/consul/shop.json:

{
  "service": {
    "name": "shop",
    "tags": [
      "shop",
      "urlprefix-/shop"
    ],
    "port": 80,
    "check": {
      "id": "shop-check",
      "name": "Shop App Status",
      "http": "http://localhost/status.html",
      "interval": "10s"
    }
  }
}

Unde:

  • name - numele serviciului;
  • tags - etichete atasate serviciului;
  • port - portul pe care ruleaza serviciul;
  • check - metoda de verificare a servciului

Metodele de verificare for fi de mai multe feluri (exemple):

  • script de verificare;
  • call HTTP/HTTPS;
  • verificarea unui port (TCP/UDP).

Mesajul de rapuns nu conteaza singura cerinta e codul de raspuns:

  • 0 - functionare normala;
  • 1 - necesita atentie;
  • alt cod - verificarea nu a functionat/serviciu nefunctional;

Notificam instanta agent sa preia noua configuratie

consul reload

Serviciul apare in scurt timp si in interfata de admin:

Informatii despre acest servciu poate fi descoperite prin 2 metode:

  • prin API propriu oferit de consul pe portul 8500:
curl http://localhost:8500/v1/catalog/service/shop
[
  {
    "ID": "064e26c0-0a21-b886-73fd-8972a8bbb155",
    "Node": "consul-node1",
    "Address": "10.209.214.170",
    "Datacenter": "lxd",
    "TaggedAddresses": {
      "lan": "10.209.214.170",
      "wan": "10.209.214.170"
    },
    "NodeMeta": {
      "consul-network-segment": ""
    },
    "ServiceKind": "",
    "ServiceID": "shop",
    "ServiceName": "shop",
    "ServiceTags": [
      "shop",
      "urlprefix-/shop"
    ],
    "ServiceAddress": "",
    "ServiceWeights": {
    "Passing": 1,
    "Warning": 1
    },
    "ServiceMeta": {},
    "ServicePort": 80,
    "ServiceEnableTagOverride": false,
    "ServiceProxy": {
      "MeshGateway": {},
      "Expose": {}
    },
    "ServiceConnect": {},
    "CreateIndex": 11442,
    "ModifyIndex": 11442
  }
]
  • prin interogare DNS.

Agentul client Consul expune pe portul 8600 un servicu DNS prin care se pot interoga nodurile (<nume_nod>.node.consul) sau serviciu (<nume_serviciu>.service.consul) sau tag (<tag>.<nume_serviciu>.service.consul):

dig @127.0.0.1 -p 8600 shop.service.consul

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

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;shop.service.consul.           IN      A

;; ANSWER SECTION:
shop.service.consul.    0       IN      A       10.209.214.170

;; ADDITIONAL SECTION:
shop.service.consul.    0       IN      TXT     "consul-network-segment="

;; Query time: 1 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Mon Dec 09 17:36:02 UTC 2019
;; MSG SIZE  rcvd: 100

Dupa cum banuiti metoda a doua este cea mai usor de folosit in configuratii. Pentru asta avem nevoie de un server local de DNS - de ex dnsmasq - ce se poate conecta pe consul pe portul 8600 pentru actualizari.

Instalam pachetul dnsmasq:

apt install dnsmasq

Oprim serviciul systemd-resolved

systemctl stop systemd-resolve
systemctl disable systemd-resolve
rm -f /etc/resolv.conf

Adaugam urmatorul fisier /etc/dnsmasq.d/10-consul:

# Enable forward lookup of the 'consul' domain:
server=/consul/127.0.0.1#8600

# Upstream DNS server:
server=1.1.1.1

Pornim si activam serviciul dnsmasq:

systemctl start dnsmasq
systemctl enable dnsmasq

Si acum putem da ping la orice serviciu ca la un domeniu

# ping -c 2 static.service.consul
PING static.service.consul (10.209.214.214) 56(84) bytes of data.
64 bytes from consul-node3.lxd (10.209.214.214): icmp_seq=1 ttl=64 time=0.048 ms

# ping -c 2 static.service.consul
PING static.service.consul (10.209.214.169) 56(84) bytes of data.
64 bytes from consul-node4.lxd (10.209.214.169): icmp_seq=1 ttl=64 time=0.037 ms

In exemplul de mai sus primim 2 IP diferite penru ca sunt 2 instante iar consul face si balansare:

# dig  static.service.consul

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> static.service.consul
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40113
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;static.service.consul.         IN      A

;; ANSWER SECTION:
static.service.consul.  0       IN      A       10.209.214.214
static.service.consul.  0       IN      A       10.209.214.169

;; ADDITIONAL SECTION:
static.service.consul.  0       IN      TXT     "consul-network-segment="
static.service.consul.  0       IN      TXT     "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Dec 09 18:00:29 UTC 2019
;; MSG SIZE  rcvd: 154

Suplimentar Consul poate oferi informatia legata de portul pe care functioneaza servciul (SRV record):

# dig  static.service.consul SRV

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> static.service.consul SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11406
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;static.service.consul.         IN      SRV

;; ANSWER SECTION:
static.service.consul.  0       IN      SRV     1 1 8080 consul-node3.node.lxd.consul.
static.service.consul.  0       IN      SRV     1 1 8080 consul-node4.node.lxd.consul.

;; ADDITIONAL SECTION:
consul-node3.node.lxd.consul. 0 IN      A       10.209.214.214
consul-node3.node.lxd.consul. 0 IN      TXT     "consul-network-segment="
consul-node4.node.lxd.consul. 0 IN      A       10.209.214.169
consul-node4.node.lxd.consul. 0 IN      TXT     "consul-network-segment="

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Dec 09 18:15:48 UTC 2019
;; MSG SIZE  rcvd: 250

In PHP putem optine informatia referitoare la port usor:

<?php
$record = dns_get_record('static.service.consul', DNS_SRV);
print_r($record);

si rapunsul ca:

Array
(
  [0] => Array
    (
      [host] => static.service.consul
      [class] => IN
      [ttl] => 0
      [type] => SRV
      [pri] => 1
      [weight] => 1
      [port] => 8080
      [target] => consul-node3.node.lxd.consul
    )
  [1] => Array
    (
      [host] => static.service.consul
      [class] => IN
      [ttl] => 0
      [type] => SRV
      [pri] => 1
      [weight] => 1
      [port] => 8080
      [target] => consul-node4.node.lxd.consul
    )
)