Folosind consul pentru descoperirea de servicii și alte sarcini, notele programatorului

Mulți au auzit că există un astfel de lucru numit Consul, creat în HashiCorp, compania care ia dat vagabondul mondial. Packer și o mulțime de alte lucruri minunate. Cineva chiar știe că consulul este destinat descoperirii serviciului, cum ar fi, de exemplu, etcd sau ZooKeeper. Dar nu toată lumea știe că, în afară de descoperirea serviciului, Consul are de asemenea un număr mare de alte caracteristici, de exemplu, monitorizarea integrată a serviciilor, Loks distribuite și altele. În acest articol ne vom familiariza cu consulul și vom învăța să folosim, deși nu toți, o parte esențială a funcționalității sale.

Pe scurt despre principal

Când spun "descoperirea serviciului", înseamnă că există un sistem care știe unde se află serviciul. De exemplu, folosiți PostgreSQL. Aveți mai multe fragmente din baza de date, fiecare șarpe are un maestru și o mulțime de replici. Când maestrul scade, un faylover este executat manual sau automat, ca urmare a faptului că una dintre fostele replici devine maestru. Cu alte cuvinte, rolul maestrului este în plină desfășurare. În plus, numărul de replici nu este neapărat constant. Deci, descoperirea serviciului este un lucru care poate răspunde cererii dvs. la întrebările "cine este acum stăpânul shard N?" Sau "dați-mi o listă cu toate replicile shard N".

Desigur, puteți stoca în mod stupid toate aceste informații în config. Dar, în cazul în care există o mulțime de servere și aplicații pe ele, varianta cu descoperirea de servicii devine mai convenabil. Cel puțin, deoarece toate datele sunt într-un singur loc și, prin urmare, nu se îndepărtează și deoarece configurația este actualizată mult mai repede decât atunci când configurați toate serverele cu scp. De asemenea, atunci când utilizați platforme de tip cluster, cum ar fi Kubernetes, Mesos sau Nomad, nu știți în prealabil ce mașini sunt exact ce servicii sunt în desfășurare și câte sunt acum, plus de multe ori se pot deplasa de la o mașină la alta. Deci, nu le veți găsi fără să aveți o soluție cum ar fi consulul la îndemână.

Concret, consulul pentru misiunea de descoperire a serviciului oferă un API REST. De asemenea, are un server DNS încorporat, care vă permite să îl utilizați chiar și în aplicații care nu cunosc nimic despre un consul. În acest caz, consulul poate scala la mai multe centre de date și, spre deosebire, de exemplu, de la etcd, funcționează nu numai pe Linux și MacOS, dar și pe FreeBSD și chiar pe Windows. Încă inspiră încrederea că HashiCorp testează Consul cu ajutorul lui Jepsen.

În Consul, informațiile despre serviciile existente se numesc un director. Directorul este stocat pe mai multe servere Consul care comunică între ele folosind protocolul Raft. În plus față de servere, există și agenți. Agenții sunt instalați pe toate mașinile în care serviciile se rotesc și informează serverele Consul despre starea actuală a mașinii și a serviciilor pe care le utilizează, folosind protocolul de bârfe. Astfel, dacă mașina se blochează sau unul dintre servicii devine rău, serverele Consul vor afla despre acest lucru și informațiile despre serviciile relevante nu vor mai fi date clienților. De asemenea, serverele pot fi utilizate ca agenți.

Pe lângă descoperirea și monitorizarea serviciului, Consul are și multe alte funcții utile. Cu unii avem încă timp să ne cunoaștem mai departe.

Instalarea și configurarea consulului

Toate acțiunile descrise au fost verificate de mine pe Ubuntu 14.04 LTS, care rulează în trei containere LXC. Cel mai probabil, pe alte distribuții Linux și versiuni Ubuntu, situația nu va fi mult diferită. Mai mult, se presupune că toate mașinile sunt în rețea 10.0.3 / 24.

Consulul este scris în limba Go și este distribuit ca un singur binar (și codurile sursă.) Inutil să spun. Din păcate, HashiCorp nu oferă pachete gata pentru Debian / Ubuntu sau CentOS / RHEL. Aici, o persoană bună a creat un depozit, prin care puteți construi singur un pachet deb. De asemenea, a reușit să găsească PPA. deși nu cu cea mai recentă versiune a consulului. Cu toate acestea, nu există nimic care să împiedice Consulul să utilizeze acest PPA și, dacă este necesar, să înlocuiască binarul.

sudo apt-get update
sudo apt-get instala software-proprietăți-comune
sudo apt-add-repository ppa: bcandrea / consul
sudo apt-get update
sudo apt-get instalare consul consul-web-ui dnsutils curl jq

Dacă vrem cel mai mult svezhak, executăm de asemenea comenzi precum:

sudo apt-get instala unzip
wget https: // releases.hashicorp.com / cale / către / consul.zip
dezarhiva consul_VER_linux_amd64.zip
sudo service consul opri
sudo mv / usr / bin / consul / usr / bin / consul.backup
sudo mv consul / usr / bin / consul

Editați fișierul /etc/consul.d/20-agent.json cumva:

"server": true,
"datacenter": "dc1",
"bootstrap_expect": 3,
"date_dir": "/ opt / consul";
"log_level": "INFO"
>

... făcând serverul consul în sine, nu agentul.

sudo service consul restart

Pe alte noduri facem același lucru. Apoi combinați-le cu maestrul:

consul se alăture 10.0.3.223 10.0.3.224

curl-s http: // 10.0.3.224: 8500 / v1 / catalog / service / postgresql-replica \
| | JQ.

[
"ModifyIndex": 804,
"CreateIndex": 802,
"Nod": "postgresql-sclav",
"Adresa": "10.0.3.223",
"ServiceID": "postgresql-replica-1";
"ServiceName": "postgresql-replica",
"ServiceTags": [
"Postgresql"
]
"ServiceAddress": "10.0.3.223",
"ServicePort": 5432,
"ServiceEnableTagOverride": false
>
"ModifyIndex": 842,
"CreateIndex": 841,
"Nod": "postgresql-slave-2",
"Adresa": "10.0.3.224",
"ServiceID": "postgresql-replica-2";
"ServiceName": "postgresql-replica",
"ServiceTags": [
"Postgresql"
]
"ServiceAddress": "10.0.3.224",
"ServicePort": 5432,
"ServiceEnableTagOverride": false
>
]

Pentru a vă spune adevărul, nu înțeleg pe deplin de ce sunt necesare două domenii - adresa și adresa de serviciu. Bănuiesc că acest lucru este în cazul în care dorim să monitorizăm serviciile terților de către agenții noștri.

Lista de servicii pe mașina dată:

curl-uri http: // 10.0.3.224: 8500 / v1 / catalog / nod / postgresql-slave | JQ.

"Servicii": "postgresql-replica-1": "ModifyIndex": 804,
"CreateIndex": 802,
"EnableTagOverride": false,
"Port": 5432,
"Adresa": "10.0.3.223",
"Etichete": [
"Postgresql"
]
"Serviciu": "postgresql-replica";
"ID": "postgresql-replica-1"
>
"consul": "ModifyIndex": 72,
"CreateIndex": 4,
"EnableTagOverride": false,
"Port": 8300,
"Adresa": "",
"Etichete": [],
"Serviciu": "consul",
"ID": "consul"
>
>
"Nod": "ModifyIndex": 804,
"CreateIndex": 4,
"Adresa": "10.0.3.223",
"Nod": "postgresql-slave"
>
>

Ștergerea unui serviciu de la un agent:

curl http: // localhost: 8500 / v1 / agent / serviciu / deregister / postgresql-master

Pentru a verifica dacă serviciul este în viață, puteți face acest lucru:

curl-uri http: // localhost: 8500 / v1 / health / service / postgresql-replica | JQ.

Răspunsul în acest caz este destul de mare, deci aici nu este dat.

Descoperirea de servicii utilizând DNS

dig @ 127.0.0.1 -p 8600 postgresql-replica.service.consul

;; ÎNTREBĂRI SECȚIUNE:
; postgresql-replica.service.consul. IN A

;; RĂSPUNS SECȚIUNEA:
-replica.service.consul PostgreSQL. 0 IN A 10.0.3.223
-replica.service.consul PostgreSQL. 0 IN A 10.0.3.224

Puteți solicita o înregistrare SRV astfel încât răspunsul să includă și numerele de porturi:

salvați srv @ 127.0.0.1 -p 8600 postgresql-replica.service.consul

Răspunsul în acest caz este:

;; ÎNTREBĂRI SECȚIUNE:
; postgresql-replica.service.consul. IN SRV

;; RĂSPUNS SECȚIUNEA:
-replica.service.consul PostgreSQL. 0 în SRV 1 1 5432
postgresql-sclav-2.node.dc1.consul.
-replica.service.consul PostgreSQL. 0 în SRV 1 1 5432
-slave.node.dc1.consul PostgreSQL.
;; SECȚIUNEA SUPLIMENTARĂ:
postgresql-sclav-2.node.dc1.consul. 0 IN A 10.0.3.224
-slave.node.dc1.consul PostgreSQL. 0 IN A 10.0.3.223

Zero în ambele răspunsuri este TTL, adică răspunsul DNS nu trebuie să fie stocat în cache.

S-ar putea să fi observat că cel mai mare la primirea informațiilor despre servicii, Consul nu ne-a spus dacă aceste servicii lucrează acum sau nu.

Pentru a primi informațiile despre o condiție de serviciu și gazda acestuia, este posibil prin intermediul unui astfel de mâner:

curl-uri http: // 10.0.3.224: 8500 / v1 / sănătate / serviciu / postgresql-master | JQ.

[
"Verificări": [
"ModifyIndex": 13148,
"CreateIndex": 13148,
"Nod": "postgresql-master";
"CheckID": "serfHealth",
"Nume": "Starea de sănătate a serpilor";
"Stare": "trecere",
"Note": "",
"Output": "Agent viu și accesibil";
"ServiceID": "",
"ServiceName": ""
>
"ModifyIndex": 13155,
"CreateIndex": 13150,
"Nod": "postgresql-master";
"CheckID": "serviciu: postgresql-master";
"Nume": "Serviciu" postgresql-master "check",
"Stare": "critică",
"Note": "",
"Output": "9.5 / main (portul 5432): în jos \ n",
"ServiceID": "postgresql-master";
"ServiceName": "postgresql-master"
>
]
"Service": "ModifyIndex": 13155,
"CreateIndex": 13150,
"EnableTagOverride": false,
"Port": 5432,
"Adresa": "10.0.3.245",
"Etichete": [
"Postgresql"
]
"Serviciu": "postgresql-master";
"ID": "postgresql-master"
>
"Nod": "ModifyIndex": 13155,
"CreateIndex": 13148,
"Adresa": "10.0.3.245",
"Nod": "postgresql-master"
>
>
]

În acest exemplu, serviciul se află.

Și astfel puteți afla statutul de gazdă și serviciile pe care acesta le oferă:

curl-s http: // 10.0.3.224: 8500 / v1 / sănătate / nod / postgresql-slave- 2 | JQ.

[
"ModifyIndex": 12827,
"CreateIndex": 12827,
"Nod": "postgresql-slave-2",
"CheckID": "serfHealth",
"Nume": "Starea de sănătate a serpilor";
"Stare": "trecere",
"Note": "",
"Output": "Agent viu și accesibil";
"ServiceID": "",
"ServiceName": ""
>
"ModifyIndex": 13147,
"CreateIndex": 12832,
"Nod": "postgresql-slave-2",
"CheckID": "serviciu: postgresql-replica-2";
"Nume": "Serviciu" postgresql-replica "check",
"Stare": "trecere",
"Note": "",
"Output": "9.5 / main (portul 5432): on-line, recuperare \ n",
"ServiceID": "postgresql-replica-2";
"ServiceName": "postgresql-replica"
>
]

Încercați să defaim serviciile sau gazdele și să vedeți cum helchecs-urile corespunzătoare își schimbă starea de la trecerea la critică. În consola web, gazdele și serviciile își schimbă culoarea de la verde la portocaliu. Este interesant faptul că atunci când serviciul este activat, acesta continuă să fie dat când solicită un director prin API-ul REST, deși serviciul este tăiat din răspunsul DNS. Acest comportament poate fi corectat prin adăugarea argumentului? Trecerea la interogare.

Informații despre alegeri de cluster și lider

Consulul vă permite să vedeți cine este în prezent în cluster:

curl-uri http: // localhost: 8500 / v1 / status / peers | JQ.

Și astfel puteți obține informații foarte detaliate despre agent, care conține, printre altele, IP-ul mașinii curente:

curl-s http: // localhost: 8500 / v1 / agent / auto | jq '.Member.Addr'

Există o dorință naturală de a încerca să obțineți alegerea liderului cu acest API pentru aplicația dvs. în 20 de linii de cod Python. Dar nu este deloc o idee bună. În primul rând, deoarece este ușor să creați curse și să obțineți doi lideri la un moment dat. Rezolvați această problemă așteptând ACK din partea majorității clusterului, iar în ACK ar trebui să includeți numărul termenului curent în Raft'e sau alt contor. În al doilea rând, într-un mod bun, în acest caz, este necesar să verificăm dacă suntem încă lideri în orice acțiune.

Cât de corect mi-a spus @ sum3rman. este mult mai ușor să folosiți o abordare diferită, denumită presupus un lider de leasing. Deoarece avem deja un magazin KV cu suport CAS, putem pur și simplu să-i scriem că mașina este un astfel de lider înainte de expirarea unui astfel de timp. În timp ce liderul trăiește și trăiește, el se poate extinde periodic de această dată. Dacă liderul moare, cineva îl va înlocui repede. În acest caz, este suficient să se sincronizeze timpul pe mașini cu ntpd și atunci când liderul efectuează orice acțiune, verificați dacă are suficient timp în stoc pentru a finaliza această acțiune.

O altă versiune interesantă a alegerilor de lider asupra Consulului este descrisă în documentația Consulului. El se bazează pe mecanismul de tip helschek deja familiar, precum și pe sesiune. Sesiunile sunt bucle distribuite în mod esențial, care sunt eliberate automat de TTL sau când serviciul este dezactivat. În cadrul acestei note, nu considerăm sesiunea. Dar această oportunitate este foarte interesantă și recomand cu tărie să o cunoaștem.

Notă privind siguranța

Rețineți că, în mod implicit, Consulul nu utilizează nici o criptare a traficului. De asemenea, având acces la o singură mașină din cluster, puteți aranja ușor DoS-ul întregii aplicații.

Cu toate acestea, trebuie făcute mai multe rezerve. În primul rând, totul depinde de modul în care folosiți consulul. De exemplu, dacă este folosit doar ca spațiu de stocare KV, accesul la acesta este foarte ușor de restricționat folosind Nginx și iptables. În al doilea rând, există un drept de a trăi punctul de vedere conform căruia accesul la unul dintre frontenduri este posibil ca atacatorul să aibă acces la baza de date, ceea ce înseamnă că va putea să aranjeze un DoS prin simpla scriere a nonsens în această bază de date. Prin urmare, este prea târziu să apărați în această etapă, de ce să creăm inconveniente inutile?

În orice caz, toate aceste întrebări depășesc sfera acestui post, însă, în concluzie, veți găsi câteva linkuri pe această temă.

concluzie

Și folosiți consulul și, dacă da, cum impresiile?

Adăugare: Un exemplu real de utilizare a consulului pe care îl puteți găsi în nota Stolon: creați un cluster PostgreSQL cu un expert automat.