Configurar un clúster Nomad usando Consul e integrarlo con Gitlab

introducción

Recientemente, la popularidad de Kubernetes ha aumentado rápidamente: cada vez más proyectos lo implementan. Quería hablar de un orquestador como Nomad: es perfecto para proyectos que ya utilizan otras soluciones de HashiCorp, por ejemplo, Vault y Consul, y los proyectos en sí no son complejos en términos de infraestructura. Este material contendrá instrucciones para instalar Nomad, combinar dos nodos en un clúster e integrar Nomad con Gitlab.

Configurar un clúster Nomad usando Consul e integrarlo con Gitlab

Banco de pruebas

Un poco sobre el banco de pruebas: se utilizan tres servidores virtuales con las características de 2 CPU, 4 RAM, 50 Gb SSD, unidos en una red local común. Sus nombres y direcciones IP:

  1. nomad-livelinux-01: 172.30.0.5
  2. nomad-livelinux-02: 172.30.0.10
  3. cónsul-livelinux-01: 172.30.0.15

Instalación de Nómada, Cónsul. Creando un clúster nómada

Comencemos con la instalación básica. Aunque la configuración fue simple, la describiré por el bien de la integridad del artículo: esencialmente se creó a partir de borradores y notas para un acceso rápido cuando sea necesario.

Antes de comenzar con la práctica, discutiremos la parte teórica, porque en esta etapa es importante comprender la estructura futura.

Tenemos dos nodos nómadas y queremos combinarlos en un clúster, y en el futuro también necesitaremos el escalado automático del clúster; para ello necesitaremos Consul. Con esta herramienta, agrupar y agregar nuevos nodos se convierte en una tarea muy simple: el nodo Nomad creado se conecta al agente Consul y luego se conecta al clúster Nomad existente. Por lo tanto, al principio instalaremos el servidor Consul, configuraremos la autorización http básica para el panel web (no tiene autorización por defecto y se puede acceder desde una dirección externa), así como los propios agentes Consul en los servidores Nomad, luego de lo cual Sólo procederemos a Nomad.

Instalar las herramientas de HashiCorp es muy simple: esencialmente, simplemente movemos el archivo binario al directorio bin, configuramos el archivo de configuración de la herramienta y creamos su archivo de servicio.

Descargue el archivo binario de Consul y descomprímalo en el directorio de inicio del usuario:

root@consul-livelinux-01:~# wget https://releases.hashicorp.com/consul/1.5.0/consul_1.5.0_linux_amd64.zip
root@consul-livelinux-01:~# unzip consul_1.5.0_linux_amd64.zip
root@consul-livelinux-01:~# mv consul /usr/local/bin/

Ahora tenemos un binario de cónsul listo para realizar más configuraciones.

Para trabajar con Consul, necesitamos crear una clave única usando el comando keygen:

root@consul-livelinux-01:~# consul keygen

Pasemos a configurar la configuración de Consul, creando un directorio /etc/consul.d/ con la siguiente estructura:

/etc/consul.d/
├── bootstrap
│   └── config.json

El directorio de arranque contendrá un archivo de configuración config.json; en él configuraremos la configuración de Consul. Su contenido:

{
"bootstrap": true,
"server": true,
"datacenter": "dc1",
"data_dir": "/var/consul",
"encrypt": "your-key",
"log_level": "INFO",
"enable_syslog": true,
"start_join": ["172.30.0.15"]
}

Veamos las directivas principales y sus significados por separado:

  • bootstrap: verdadero. Permitimos la adición automática de nuevos nodos si están conectados. Observo que no indicamos aquí el número exacto de nodos esperados.
  • servidor: verdadero. Habilite el modo servidor. El cónsul en esta máquina virtual actuará como el único servidor y maestro en este momento, la VM de Nomad serán los clientes.
  • centro de datos: pa1. Especifique el nombre del centro de datos para crear el clúster. Debe ser idéntico tanto en clientes como en servidores.
  • cifrar: tu llave. La clave, que también debe ser única y coincidir en todos los clientes y servidores. Generado usando el comando cónsul keygen.
  • iniciar_unirse. En este listado indicamos una lista de direcciones IP a las que se realizará la conexión. Por el momento dejamos sólo nuestra propia dirección.

En este punto podemos ejecutar cónsul usando la línea de comando:

root@consul-livelinux-01:~# /usr/local/bin/consul agent -config-dir /etc/consul.d/bootstrap -ui

Esta es una buena forma de depurar ahora; sin embargo, no podrá utilizar este método de forma continua por razones obvias. Creemos un archivo de servicio para administrar Consul a través de systemd:

root@consul-livelinux-01:~# nano /etc/systemd/system/consul.service

Contenido del archivo cónsul.service:

[Unit]
Description=Consul Startup process
After=network.target
 
[Service]
Type=simple
ExecStart=/bin/bash -c '/usr/local/bin/consul agent -config-dir /etc/consul.d/bootstrap -ui' 
TimeoutStartSec=0
 
[Install]
WantedBy=default.target

Inicie Consul a través de systemctl:

root@consul-livelinux-01:~# systemctl start consul

Comprobemos: nuestro servicio debe estar ejecutándose y al ejecutar el comando de miembros del cónsul deberíamos ver nuestro servidor:

root@consul-livelinux:/etc/consul.d# consul members
consul-livelinux    172.30.0.15:8301  alive   server  1.5.0  2         dc1  <all>

Siguiente etapa: instalar Nginx y configurar el proxy y la autorización http. Instalamos nginx a través del administrador de paquetes y en el directorio /etc/nginx/sites-enabled creamos un archivo de configuración consul.conf con el siguiente contenido:

upstream consul-auth {
    server localhost:8500;
}

server {

    server_name consul.doman.name;
    
    location / {
      proxy_pass http://consul-auth;
      proxy_set_header Host $host;
      auth_basic_user_file /etc/nginx/.htpasswd;
      auth_basic "Password-protected Area";
    }
}

No olvide crear un archivo .htpasswd y generar un nombre de usuario y contraseña para él. Este elemento es requerido para que el panel web no esté disponible para todos los que conocen nuestro dominio. Sin embargo, al configurar Gitlab, tendremos que abandonar esto; de lo contrario, no podremos implementar nuestra aplicación en Nomad. En mi proyecto, tanto Gitlab como Nomad solo están en la web gris, por lo que no existe tal problema aquí.

En los dos servidores restantes instalamos agentes Consul de acuerdo con las siguientes instrucciones. Repetimos los pasos con el archivo binario:

root@nomad-livelinux-01:~# wget https://releases.hashicorp.com/consul/1.5.0/consul_1.5.0_linux_amd64.zip
root@nomad-livelinux-01:~# unzip consul_1.5.0_linux_amd64.zip
root@nomad-livelinux-01:~# mv consul /usr/local/bin/

Por analogía con el servidor anterior, creamos un directorio para archivos de configuración /etc/consul.d con la siguiente estructura:

/etc/consul.d/
├── client
│   └── config.json

Contenido del archivo config.json:

{
    "datacenter": "dc1",
    "data_dir": "/opt/consul",
    "log_level": "DEBUG",
    "node_name": "nomad-livelinux-01",
    "server": false,
    "encrypt": "your-private-key",
    "domain": "livelinux",
    "addresses": {
      "dns": "127.0.0.1",
      "https": "0.0.0.0",
      "grpc": "127.0.0.1",
      "http": "127.0.0.1"
    },
    "bind_addr": "172.30.0.5", # локальный адрес вм
    "start_join": ["172.30.0.15"], # удаленный адрес консул сервера
    "ports": {
      "dns": 53
     }

Guarde los cambios y continúe con la configuración del archivo de servicio, su contenido:

/etc/systemd/system/consul.service:

[Unit]
Description="HashiCorp Consul - A service mesh solution"
Documentation=https://www.consul.io/
Requires=network-online.target
After=network-online.target

[Service]
User=root
Group=root
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d/client
ExecReload=/usr/local/bin/consul reload
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target

Lanzamos cónsul en el servidor. Ahora, después del lanzamiento, deberíamos ver el servicio configurado en los miembros de nsul. Esto significará que se ha conectado correctamente al clúster como cliente. Repita lo mismo en el segundo servidor y luego podremos comenzar a instalar y configurar Nomad.

La instalación más detallada de Nomad se describe en su documentación oficial. Hay dos métodos de instalación tradicionales: descargar un archivo binario y compilar desde el código fuente. Elegiré el primer método.

Nota: El proyecto se desarrolla muy rápidamente y con frecuencia se publican nuevas actualizaciones. Quizás se publique una nueva versión cuando se complete este artículo. Por eso, antes de leer, recomiendo comprobar la versión actual de Nomad en este momento y descargarla.

root@nomad-livelinux-01:~# wget https://releases.hashicorp.com/nomad/0.9.1/nomad_0.9.1_linux_amd64.zip
root@nomad-livelinux-01:~# unzip nomad_0.9.1_linux_amd64.zip
root@nomad-livelinux-01:~# mv nomad /usr/local/bin/
root@nomad-livelinux-01:~# nomad -autocomplete-install
root@nomad-livelinux-01:~# complete -C /usr/local/bin/nomad nomad
root@nomad-livelinux-01:~# mkdir /etc/nomad.d

Después de descomprimirlo, recibiremos un archivo binario Nomad que pesa 65 MB; debemos moverlo a /usr/local/bin.

Creemos un directorio de datos para Nomad y editemos su archivo de servicio (lo más probable es que no exista al principio):

root@nomad-livelinux-01:~# mkdir --parents /opt/nomad
root@nomad-livelinux-01:~# nano /etc/systemd/system/nomad.service

Pegue las siguientes líneas allí:

[Unit]
Description=Nomad
Documentation=https://nomadproject.io/docs/
Wants=network-online.target
After=network-online.target

[Service]
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/nomad agent -config /etc/nomad.d
KillMode=process
KillSignal=SIGINT
LimitNOFILE=infinity
LimitNPROC=infinity
Restart=on-failure
RestartSec=2
StartLimitBurst=3
StartLimitIntervalSec=10
TasksMax=infinity

[Install]
WantedBy=multi-user.target

Sin embargo, no tenemos prisa por iniciar Nomad; aún no hemos creado su archivo de configuración:

root@nomad-livelinux-01:~# mkdir --parents /etc/nomad.d
root@nomad-livelinux-01:~# chmod 700 /etc/nomad.d
root@nomad-livelinux-01:~# nano /etc/nomad.d/nomad.hcl
root@nomad-livelinux-01:~# nano /etc/nomad.d/server.hcl

La estructura final del directorio será la siguiente:

/etc/nomad.d/
├── nomad.hcl
└── server.hcl

El archivo nomad.hcl debe contener la siguiente configuración:

datacenter = "dc1"
data_dir = "/opt/nomad"

Contenido del archivo server.hcl:

server {
  enabled = true
  bootstrap_expect = 1
}

consul {
  address             = "127.0.0.1:8500"
  server_service_name = "nomad"
  client_service_name = "nomad-client"
  auto_advertise      = true
  server_auto_join    = true
  client_auto_join    = true
}

bind_addr = "127.0.0.1" 

advertise {
  http = "172.30.0.5"
}

client {
  enabled = true
}

No olvide cambiar el archivo de configuración en el segundo servidor; allí deberá cambiar el valor de la directiva http.

Lo último en esta etapa es configurar Nginx para el proxy y configurar la autorización http. Contenido del archivo nomad.conf:

upstream nomad-auth {
        server 172.30.0.5:4646;
}

server {

        server_name nomad.domain.name;
        
        location / {
	        proxy_pass http://nomad-auth;
	        proxy_set_header Host $host;
	        auth_basic_user_file /etc/nginx/.htpasswd;
		   auth_basic "Password-protected Area";
        }
        
}

Ahora podemos acceder al panel web a través de una red externa. Conéctese y vaya a la página de servidores:

Configurar un clúster Nomad usando Consul e integrarlo con Gitlab
1 imagen. Lista de servidores en el clúster Nomad

Ambos servidores se muestran correctamente en el panel, veremos lo mismo en la salida del comando de estado del nodo nómada:

Configurar un clúster Nomad usando Consul e integrarlo con Gitlab
2 imagen. Salida del comando de estado del nodo nómada

¿Qué pasa con el cónsul? Echemos un vistazo. Vaya al panel de control de Consul, a la página de nodos:
Configurar un clúster Nomad usando Consul e integrarlo con Gitlab
3 imagen. Lista de nodos en el clúster Consul

Ahora tenemos un Nómada preparado trabajando en conjunto con el Cónsul. En la etapa final, llegaremos a la parte divertida: configurar la entrega de contenedores Docker desde Gitlab a Nomad, y también hablaremos de algunas de sus otras características distintivas.

Creando el corredor Gitlab

Para implementar imágenes de Docker en Nomad, usaremos un ejecutor separado con el archivo binario de Nomad dentro (aquí, por cierto, podemos observar otra característica de las aplicaciones Hashicorp: individualmente son un único archivo binario). Súbelo al directorio del corredor. Creemos un Dockerfile simple con el siguiente contenido:


FROM alpine:3.9
RUN apk add --update --no-cache libc6-compat gettext
COPY nomad /usr/local/bin/nomad

En el mismo proyecto creamos .gitlab-ci.yml:

variables:
  DOCKER_IMAGE: nomad/nomad-deploy
  DOCKER_REGISTRY: registry.domain.name
 

stages:
  - build

build:
  stage: build
  image: ${DOCKER_REGISTRY}/nomad/alpine:3
  script:
    - tag=${DOCKER_REGISTRY}/${DOCKER_IMAGE}:latest
    - docker build --pull -t ${tag} -f Dockerfile .
    - docker push ${tag}

Como resultado, tendremos una imagen disponible del corredor Nomad en el Registro de Gitlab, ahora podemos ir directamente al repositorio del proyecto, crear un Pipeline y configurar el trabajo nómada de Nomad.

Configuración del proyecto

Comencemos con el archivo de trabajo de Nomad. Mi proyecto en este artículo será bastante primitivo: consistirá en una tarea. El contenido de .gitlab-ci será el siguiente:

variables:
  NOMAD_ADDR: http://nomad.address.service:4646
  DOCKER_REGISTRY: registry.domain.name
  DOCKER_IMAGE: example/project

stages:
  - build
  - deploy

build:
  stage: build
  image: ${DOCKER_REGISTRY}/nomad-runner/alpine:3
  script:
    - tag=${DOCKER_REGISTRY}/${DOCKER_IMAGE}:${CI_COMMIT_SHORT_SHA}
    - docker build --pull -t ${tag} -f Dockerfile .
    - docker push ${tag}


deploy:
  stage: deploy
  image: registry.example.com/nomad/nomad-runner:latest
  script:
    - envsubst '${CI_COMMIT_SHORT_SHA}' < project.nomad > job.nomad
    - cat job.nomad
    - nomad validate job.nomad
    - nomad plan job.nomad || if [ $? -eq 255 ]; then exit 255; else echo "success"; fi
    - nomad run job.nomad
  environment:
    name: production
  allow_failure: false
  when: manual

Aquí la implementación se produce manualmente, pero puede configurarla para cambiar el contenido del directorio del proyecto. Pipeline consta de dos etapas: el ensamblaje de la imagen y su implementación en Nomad. En la primera etapa, ensamblamos una imagen de la ventana acoplable y la insertamos en nuestro Registro, y en la segunda iniciamos nuestro trabajo en Nomad.

job "monitoring-status" {
    datacenters = ["dc1"]
    migrate {
        max_parallel = 3
        health_check = "checks"
        min_healthy_time = "15s"
        healthy_deadline = "5m"
    }

    group "zhadan.ltd" {
        count = 1
        update {
            max_parallel      = 1
            min_healthy_time  = "30s"
            healthy_deadline  = "5m"
            progress_deadline = "10m"
            auto_revert       = true
        }
        task "service-monitoring" {
            driver = "docker"

            config {
                image = "registry.domain.name/example/project:${CI_COMMIT_SHORT_SHA}"
                force_pull = true
                auth {
                    username = "gitlab_user"
                    password = "gitlab_password"
                }
                port_map {
                    http = 8000
                }
            }
            resources {
                network {
                    port "http" {}
                }
            }
        }
    }
}

Tenga en cuenta que tengo un Registro privado y para extraer con éxito una imagen de Docker necesito iniciar sesión en él. La mejor solución en este caso es ingresar un nombre de usuario y contraseña en Vault y luego integrarlo con Nomad. Nomad es compatible de forma nativa con Vault. Pero primero, instalemos las políticas necesarias para Nomad en Vault; se pueden descargar:

# Download the policy and token role
$ curl https://nomadproject.io/data/vault/nomad-server-policy.hcl -O -s -L
$ curl https://nomadproject.io/data/vault/nomad-cluster-role.json -O -s -L

# Write the policy to Vault
$ vault policy write nomad-server nomad-server-policy.hcl

# Create the token role with Vault
$ vault write /auth/token/roles/nomad-cluster @nomad-cluster-role.json

Ahora, habiendo creado las políticas necesarias, agregaremos la integración con Vault en el bloque de tareas del archivo job.nomad:

vault {
  enabled = true
  address = "https://vault.domain.name:8200"
  token = "token"
}

Utilizo autorización por token y la registro directamente aquí, también existe la opción de especificar el token como variable al iniciar el agente nómada:

$ VAULT_TOKEN=<token> nomad agent -config /path/to/config

Ahora podemos usar las claves con Vault. El principio de funcionamiento es simple: creamos un archivo en el trabajo Nomad que almacenará los valores de las variables, por ejemplo:

template {
                data = <<EOH
{{with secret "secrets/pipeline-keys"}}
REGISTRY_LOGIN="{{ .Data.REGISTRY_LOGIN }}"
REGISTRY_PASSWORD="{{ .Data.REGISTRY_LOGIN }}{{ end }}"

EOH
    destination = "secrets/service-name.env"
    env = true
}

Con este sencillo enfoque, puedes configurar la entrega de contenedores al clúster Nomad y trabajar con él en el futuro. Diré que hasta cierto punto simpatizo con Nomad: es más adecuado para proyectos pequeños en los que Kubernetes puede generar una complejidad adicional y no desarrollará todo su potencial. Además, Nomad es perfecto para principiantes: es fácil de instalar y configurar. Sin embargo, al realizar pruebas en algunos proyectos, encuentro un problema con sus primeras versiones: muchas funciones básicas simplemente no están disponibles o no funcionan correctamente. Sin embargo, creo que Nomad seguirá desarrollándose y en el futuro adquirirá las funciones que todos necesitan.

Autor: Ilya Andreev, editado por Alexey Zhadan y el equipo de Live Linux


Fuente: habr.com

Añadir un comentario