Introducció

Nomad és una aplicació distribuïda que gestiona contenidors, i pot garantit que si volem 5 apaches funcionant hi hauran 5 contenidors apache funcionant.

Altre cosa és on estaran aquests contenidors, per tant les IPs que haurem de fer servir, i en quin port estaran escoltant.

A més, les IPs no estan garantides; en qualsevol moment Nomad pot moure els contenidors de lloc.

Servei

Les arquitectures modernes es basen en la composició de serveis enlloc de grans aplicacions, serveis que cada cop tenen funcions més específiques i són més reduïts, que es poden replicar i modificar sense afectar al sistema.

Per poder-se comunicar, els serveis necessiten una manera de localitzar-se uns als altres, i Nomad no facilita gens la tasca.

La solució és fer servir noms que es resoldran a IPs, una solució que ja coneixes perquè has estudiat DNS.

En el nostre cas farem servir Consul, una pseudo base de dades distribuïda d’alta disponibilitat, que a més utilitza Envoy per crear una malla de serveis.

En el nostre desplegament, Nomad està integrat amb Consul.

Consul

Consul és una eina per localitzar i configurar i serveis. Les característiques principals de Consul inclouen la localització de serveis, verificar que estan actius, un sistema d’emmagatzematge clau-valor, i la capacitat de desplegar serveis en múltiples centres de dades de manera fiable.

Al integrar Nomad amb Consul, Nomad s’encarrega de manera automàtica de registrar els serveis (els contenidors) en el servei de localització que proporciona Consul, i de generar de manera dinàmica els fitxers de configuració i les variables d’entorn.

Consul Server

Per interactuar amb el servidor has de configurar el terminal.

$ export CONSUL_HTTP_ADDR="http://192.168.56.15:8500"

Si vols consulta els membres del cluster:

$ consul members

La resposta tindria que ser semblant a aquesta:

Node   Address              Status  Type    Build   Protocol  DC   Partition  Segment
box-1  192.168.56.101:8301  alive   server  1.14.4  2         dc1  default    <all>
box-5  192.168.56.105:8301  alive   client  1.14.4  2         dc1  default    <default>
box-7  192.168.56.107:8301  alive   client  1.14.4  2         dc1  default    <default>
box-8  192.168.56.108:8301  alive   client  1.14.4  2         dc1  default    <default>

També pots utilitzar la interfície gràfica: http://192.168.56.15:8500

Consul KV

Consul inclou un emmagatzematge clau/valor (KV) que pots fer servir per gestionar la configuració dels serveis.

Crea una clau db_port amb valor 5432:

$ consul kv put consul/configuration/db_port 5432
Success! Data written to: consul/configuration/db_port

A continuació, recupera el valor emmagatzemat:

$ consul kv get consul/configuration/db_port
5432

Consul DNS

Consul també proporcionar un servidor DNS que pots fer servir per resoldre les IPs dels teus serveis. Per defecte, el servi Consul DNS està configurat per escoltar al port 8600:

$ dig @127.0.0.1 -p 8600 consul.service.consul

Servei

Nomad està configurat perquè registri tots els serveis a Consul:

Per demostrar com funciona crearem un server nginx:

$ nano nginx.nomad

Perquè nomad registri el servei has de configurar el fitxer nomad, i afegir un block service tal com s’explica a Service Block - Job Specification

job "nginx" {
  datacenters = ["dc1"]
  group "nginx" {
    count = 1
    network {
      port "http" {
        to = 80
      }
    }
    task "nginx" {
      driver = "docker"
      config {
        image          = "nginx:1.22.1"
        ports          = ["http"]
        auth_soft_fail = true
      }
      service {
          name = "nginx"
          port = "http"
          provider = "consul"
      }
      resources {
        cpu    = 500
        memory = 256
      }
    }
  }
}

Registra la tasca a Nomad:

$ nomad job run nginx.nomad

Nomad crea un contenidor nginx i registra a Consul on està localitzat aquest servei:

Localitzar serveis mitjançant DNS

Una de les maneres de localitzar serveis a Consul és mitjançant una consulta DNS, enlloc de fer servir la API HTTP (que és el sistema que farien servir les aplicacions).

Per exemple, per saber on està el servei nginx, per tant, on estan alguns dels contenidors, pots fer servir el servei DNS de consul:

$ dig @127.0.0.1 -p 8600 nginx.service.consul ANY

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

;; ANSWER SECTION:
nginx.service.consul.   0       IN      A       192.168.56.15

Quan Consul rep aquesta consulta, busca tots els serveis registrats que proporcionin el servei nginx, i que estan actius.

Encara que pots conèixer la IP, una consulta DNS no et permet conèixer en quin port està escoltant el servei.

Per tant, una consulta DNS només té utilitat per aquelles consultes que es fan a serveis que estan a un port determinat, per exemple HTTP és el port 80 i HTTPS és el port 443.

Malla de serveis (pendent)

Fer servir DNS per localitzar serveis no és una opció, com tampoc és viable que les aplicacions facin servir l’API HTTP per localitzar serveis.

Per això fem servir un desplegament "sidecar", i configurem Consul perquè faci servir Envoy com un Connect Proxy.

Envoy s’encarrega de gestionar tota la complexitat de localitzar serveis, la seva disponibilitat, etc. i les aplicacions o contenidors que fan servir aquests serveis no s’han d’ocupar d’aquests problemes.

D’aquesta manera aconseguim l¡alta disponibilitat.

Continuarà

Pots crear un job d'exemple que fa servir Consul connect (i Envoy).

nomad job init -short -connect count.nomad
nomad job run count.nomad

Pendent: setup the plugins to make bridge networking work

CNI Plugins

Avaluació

01

1.- Desplega un servei nginx com el que està a la documentació.

2.- Para la màquina virtual on està el contenidor on està nginx, i verifica amb la comanda dig que el servei s’ha desplegat en un altre node.

Tarda una estona, no és immediat.

$ dig @127.0.0.1 -p 8600 nginx.service.consul ANY
;; ANSWER SECTION:
nginx.service.consul.   0       IN      A       192.168.56.107

3.- Modifica el fitxer nomad perquè enlloc d’un servei nginx hi hagin 3, i registra el job actualitzat a Nomad.

Localitza on estan aquest serveis amb la comanda dig.

Verifica amb la interfície gràfica de consul de que aquesta informació és correcta.

job "nginx" {
  datacenters = ["dc1"]
  group "nginx" {
    count = 3
    network {
      port "http" {
        to = 80
      }
    }
$ nomad job run nginx.nomad
$ dig @127.0.0.1 -p 8600 nginx.service.consul ANY
;; ANSWER SECTION:
nginx.service.consul.   0       IN      A       192.168.56.107
nginx.service.consul.   0       IN      A       192.168.56.108

02

1.- Modifica la configuració de network de nginx.nomad perquè es faci servir un port estàtic, el 80.

job "nginx" {
  datacenters = ["dc1"]
  group "nginx" {
    count = 3
    network {
      port "http" {
        static = 80
        to = 80
      }
    }

Registra el job actualitzat i verifica amb Consul que tots els serveis nginx estan al port 80.

2.- Fes una consulta DNS i obre el navegador a la primera IP que et retorni

$ dig @127.0.0.1 -p 8600 nginx.service.consul ANY

;; ANSWER SECTION:
nginx.service.consul.   0       IN      A       192.168.56.108
nginx.service.consul.   0       IN      A       192.168.56.107
nginx.service.consul.   0       IN      A       192.168.56.106

3.- Para dos màquines virtuals i verifica que només hi ha un contenidor actiu.

El motiu és que el job està configurat amb un port estàtic, i el port només el pot fer servir un contenidor.

03

1.- Elimina el job nginx i registra un job que desplegui només un contenidor apache i es registri a consul.

Fes servir d’exemple el job nginx.

$ nomad job stop -purge nginx
$ nano apache.nomad 
job "apache" {
  datacenters = ["dc1"]
  group "apache" {
    count = 1
    network {
      port "http" {
        to = 80
      }
    }
    task "apache" {
      driver = "docker"
      config {
        image          = "httpd:2.4.55"
        ports          = ["http"]
        auth_soft_fail = true
      }
      service {
          name = "apache"
          port = "http"
          provider = "consul"
      }
      resources {
        cpu    = 500
        memory = 256
      }
    }
  }
}
$ nomad job run apache.nomad

2.- Com que les respostes DNS tenen la limitació de que no ens diuen quin port fa servir el servei, farem servir l’endpoint /agent/service de l’agent local de Consul per obtenir la resposta.

Cada màquina virtual té un agent Consul executant-se, i aquest agent té una copia sincronitzada de tots els serveis del cluster, i pot donar una resposta immediata (no hi ha latència, ni problemes de xarxa).

Això és alta disponibilitat.

Consulta a totes les màquines client els serveis que tenen registrats, fins que trobis on està apache amb la petició de llistar serveis: Service - Agent - HTTP API

Per exemple:

$ curl http://192.168.56.101:8500/v1/agent/services | json_pp
$ curl http://192.168.56.105:8500/v1/agent/services | json_pp
...
$ curl http://192.168.56.108:8500/v1/agent/services | json_pp

Només afegeix captura de la consulta que l’ha trobat.

3.- Per saber tots els serveis que estan registrats en el nostre centre de dades dc1:, pots fer una consulta HTTP a l’API de Consul de qualsevol agent:

$ curl http://192.168.56.106:8500/v1/catalog/services
{"apache":[],"consul":[],"nomad":["http","serf","rpc"],"nomad-client":["http"]}
$ curl http://192.168.56.107:8500/v1/catalog/services
...

Pots consultar l'API a Catalog - HTTP API

4.- Però si tens un cluster de 100 màquines això és molta feina.

Per saber on estan els serveis apache pots consultar l'endpoint /catalog/service:

$ curl http://192.168.56.106:8500/v1/catalog/service/apache | json_pp