Introducción a Nomad para gestionar aplicaciones y microservicios

Escrito por el , actualizado el .
planeta-codigo programacion software
Comentarios

En las aplicaciones basadas en microservicios dado el número de ellos y de instancias tienen han de gestionarse como si fuesen ganado en vez como si fuesen animales de compañía. Nomad es un orquestador de servicios que a diferencia de Docker Swarm permite gestionar servicios con otros sistemas de ejecución además de contenedores docker y a diferencia de Kubernetes es más sencillo.

Nomad
Consul
HashiCorp

En las arquitecturas de aplicaciones basadas en microservicios cada microservicio o simplemente servicio es una aplicación distinta e independiente, son varias aplicaciones que hay que gestionar y desplegar de forma individual o de forma coordinada.

Dado su número hay que automatizar todas las tareas para tratar de conseguir la menor intervención manual, ningún proceso manual si es posible. Para que no sean inmanejables han de tratarse como ganado de forma masiva en vez de como animales de compañía que requieran atención individual para continuar generando valor en un proyecto con el tiempo disponible en vez de dedicarlo a tareas que no lo aportan.

Dado que cada microservicio puede emplear una tecnología diferente es necesario algo que permita tratarlos a todos por igual, esta tecnología son los contenedores que hacen un papel similar al que hacen en el transporte de mercancías en barcos.

Hay varias tecnologías para orquestar o gestionar los microservicios y crear clusters de máquinas en las que desplegarlos, una de ellas es Docker Swarm sencilla e integrada con Docker pero no con tantas funcionalidades como otra de las populares que es Kubernetes y para usarlo en una máquina local minikube, ofrece mas funcionalidad pero añade una complejidad significativa que para algunos casos de uso no compensa además requiere mas tiempo para dominarla. Una solución intermedia conservando la sencillez pero con mas funcionalidad es Nomad de HashiCorp. Otra de sus características destacadas es que el cluster de Nomad puede estar formado en diferentes centros de datos y proveedores de la nube al mismo tiempo, por ejemplo en AWS, GCP entre otros o centros de datos híbridos en la nube y propios. En la sección Nomad vs. Other Software de su documentación se compara con otras opciones.

Nomad es distribuido, con alta disponibilidad y escalable a cientos de nodos en múltiples centros de datos y regiones. No es una solución completa por si sola pero se integra con otras. No ofrece descubrimiento de servicios pero se integra muy bien con Consul. No es un balanceador de carga pero se integra con Nginx, Fabio, Traefik y HAproxy automatizando su configuración desde Consul. No integra un gestor de secretos pero se integra con Vault. No soporta escalado y no integra de por sí varias de estas funcionalidades como Kubernetes pero es más simple.

Nomad a diferencia Docker no solo puede gestionar contenedores docker sino también tareas del sistema y otras como máquinas virtuales qemu o contenedores con rkt, a diferencia de Kubernetes es mucho mas sencilla pero conservando funcionalidad suficiente para muchos casos de uso. Nomad requiere de otra de las herramientas de HashiCorp que es Consul para el registro y descubrimiento y para la configuración del cluster, también se integra con otras de sus herramientas como Vault para guardar cifrados datos sensibles como contraseñas y certificados. Con Connect es capaz de proporcionar conexión TLS con autenticación mutua de forma transparente para los servicios.

Los jobs son la unidad de trabajo que contienen la definición de los servicios, se definen en un archivo de configuración donde los elementos son el nombre, los grupos de tareas, las tareas y en cada tarea el driver que usa dependiendo del cual se proporciona la configuración apropiada. El driver determina como es gestionada el tipo de tarea puede ser un conteendor de docker, un proceso del sistema, una máquina virtual de qemu o un contenedor rkt, a diferencia de Docker Swarm que solo puede gestionar contenedores docker. Se pueden configurar variables de entorno, memoria asignada a cada tarea, propiedades de red y CPU.

Nomad y Nomad cada uno son un binario ejecutable sin ninguna otra dependencia. Basta con descargarlos e incluirlos en el path del sistema. En este ejemplo hay definido un job compuesto por una tarea de un contenedor docker de nginx configurado en un puerto aleatorio y con 1 GB de memoria para cada una de las dos instancias del servicio. Dado que lo usa es necesario instalar Docker.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
job "nginx" {
  datacenters = ["localhost"]

  type = "service"

  update {
    stagger      = "30s"
    canary       = 2
    max_parallel = 2
  }

  group "services" {
    count = 2

    task "nginx" {
      driver = "docker"

      config {
        image = "nginx:alpine"
        port_map {
          http = 80
        }
      }

      resources {
        memory = 1024 # MB

        network {
          port "http" {}
        }
      }
    }
  }
}

Nomad y Nomad se ejecutan con los siguientes comandos en modo desarrollo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ consul agent -dev -datacenter localhost
==> Starting Consul agent...
==> Consul agent running!
           Version: 'v1.4.4'
           Node ID: '1934d5b2-0f3f-ffdd-8378-7ab8a6207bb1'
         Node name: 'archlinux'
        Datacenter: 'localhost' (Segment: '<all>')
            Server: true (Bootstrap: false)
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
      Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false

$ sudo nomad agent -dev -dc localhost
[sudo] password for picodotdev: 
==> No configuration files loaded
==> Starting Nomad agent...
==> Nomad agent configuration:

       Advertise Addrs: HTTP: 127.0.0.1:4646; RPC: 127.0.0.1:4647; Serf: 127.0.0.1:4648
            Bind Addrs: HTTP: 127.0.0.1:4646; RPC: 127.0.0.1:4647; Serf: 127.0.0.1:4648
                Client: true
             Log Level: DEBUG
                Region: global (DC: localhost)
                Server: true
               Version: 0.9.0

Iniciados se pueden enviar jobs y ver su estado, dirección y puerto asignado así como los logs generados.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
$ nomad job plan nginx.nomad
$ nomad job run nginx.nomad
==> Monitoring evaluation "b2b07746"
    Evaluation triggered by job "nginx"
    Allocation "60f3d102" created: node "58823be1", group "services"
    Allocation "6e12ae8f" created: node "58823be1", group "services"
    Evaluation within deployment: "0dddab79"
    Allocation "6e12ae8f" status changed: "pending" -> "running" (Tasks are running)
    Allocation "60f3d102" status changed: "pending" -> "running" (Tasks are running)
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "b2b07746" finished with status "complete"

$ nomad job status nginx
ID            = nginx
Name          = nginx
Submit Date   = 2019-04-14T13:31:53+02:00
Type          = service
Priority      = 50
Datacenters   = localhost
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group  Queued  Starting  Running  Failed  Complete  Lost
services    0       0         2        0       0         0

Latest Deployment
ID          = 0dddab79
Status      = running
Description = Deployment is running

Deployed
Task Group  Desired  Placed  Healthy  Unhealthy  Progress Deadline
services    2        2       2        0          2019-04-14T13:42:04+02:00

Allocations
ID        Node ID   Task Group  Version  Desired  Status   Created  Modified
60f3d102  58823be1  services    0        run      running  12s ago  1s ago
6e12ae8f  58823be1  services    0        run      running  12s ago  1s ago

$ nomad alloc status 60f3d102
ID                  = 60f3d102
Eval ID             = b2b07746
Name                = nginx.services[1]
Node ID             = 58823be1
Job ID              = nginx
Job Version         = 0
Client Status       = running
Client Description  = Tasks are running
Desired Status      = run
Desired Description = <none>
Created             = 56s ago
Modified            = 45s ago
Deployment ID       = 0dddab79
Deployment Health   = healthy

Task "nginx" is "running"
Task Resources
CPU        Memory           Disk     Addresses
0/100 MHz  820 KiB/1.0 GiB  300 MiB  http: 127.0.0.1:28421

Task Events:
Started At     = 2019-04-14T11:31:54Z
Finished At    = N/A
Total Restarts = 0
Last Restart   = N/A

Recent Events:
Time                       Type        Description
2019-04-14T13:31:54+02:00  Started     Task started by client
2019-04-14T13:31:53+02:00  Task Setup  Building Task Directory
2019-04-14T13:31:53+02:00  Received    Task received by client

$ nomad alloc logs 60f3d102
172.17.0.1 - - [14/Apr/2019:11:33:17 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-"
172.17.0.1 - - [14/Apr/2019:11:33:17 +0000] "GET /favicon.ico HTTP/1.1" 404 154 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-"

También poseen una interfaz web integrada en la que consultar la misma información, la de Consul está en el puerto 8500 y la de Nomad en el 4646 donde ver el estado de los jobs y el progreso de los despliegues.

Interfaces web de Consul y Nomad

Nomad permite varias estrategias para actualizar los jobs a una nueva versión de un servicio, basta modificar la configuración del job, volverlo a enviar a Nomad y este se encarga de actualizar las instancias siguiendo la estrategia rolling, blue/green o canary definida en el job, pero eso lo muestro mas detalladamente en otro artículo.

La documentación de Nomad, Nomad y otros productos de HashiCorp dedicados a la infraestructura en la nube esta muy bien explicada y detallada, este artículo solo es un resumen de las partes básicas para conocer como empezar a usarlo. En el siguiente vídeo se hace una pequeña explicación y demostración.