Configurazione del cluster Nomad tramite Consul e integrazione con Gitlab

Introduzione

Negli ultimi tempi sta rapidamente crescendo la popolarità di Kubernetes: sempre più progetti lo stanno implementando. Io voglio invece parlare di un orchestratore come Nomad: è perfetto per progetti in cui vengono già utilizzate altre soluzioni di HashiCorp, come Vault e Consul, e che non presentano complessità in termini di infrastruttura. In questo documento troverai una guida all'installazione di Nomad, alla creazione di un cluster con due nodi e all'integrazione di Nomad con Gitlab.

Configurazione del cluster Nomad tramite Consul e integrazione con Gitlab

Banchina di test

Un po' sul testbed: vengono utilizzati tre server virtuali con le seguenti caratteristiche: 2 CPU, 4 RAM, 50 Gb SSD, collegati in una rete locale comune. I loro nomi e indirizzi IP sono:

  1. nomad-livelinux-01: 172.30.0.5
  2. nomad-livelinux-02: 172.30.0.10
  3. consul-livelinux-01: 172.30.0.15

Installazione di Nomad e Consul. Creazione di un cluster Nomad

Iniziamo con l'installazione di base. Nonostante la semplicità dell'installazione, la descriverò per completezza dell'articolo: fondamentalmente è stata creata a partire da bozze e note per un accesso rapido in caso di necessità.

Prima di passare alla pratica, discutiamo la parte teorica, poiché a questo punto è importante comprendere la futura struttura.

Abbiamo due nodi Nomad e vogliamo unirli in un cluster. Inoltre, in futuro necessiteremo di scalabilità automatizzata per il cluster: per questo abbiamo bisogno di Consul. Con questo strumento, la creazione di un cluster e l'aggiunta di nuovi nodi diventa un compito molto semplice: il nodo Nomad creato si connette all'agente Consul, dopodiché si collega al cluster Nomad esistente. Pertanto, inizieremo installando il server Consul, configurando l'autenticazione http di base per il pannello web (che è senza autenticazione per impostazione predefinita e può essere accessibile tramite un indirizzo esterno), così come gli agenti Consul sui server Nomad, per poi passare a Nomad.

L'installazione degli strumenti di HashiCorp è molto semplice: in sostanza, dobbiamo solo spostare il file binario nella directory bin, configurare il file di configurazione dello strumento e creare il suo file di servizio.

Scarichiamo il file binario di Consul e lo estraiamo nella home directory dell'utente:

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/

Ora abbiamo il file binario consul pronto per ulteriori configurazioni.

Per lavorare con Consul, dobbiamo creare una chiave unica usando il comando keygen:

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

Passiamo alla configurazione di Consul, creando la directory /etc/consul.d/ con la seguente struttura:

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

Nella directory bootstrap si troverà il file di configurazione config.json, in cui imposteremo le configurazioni di Consul. Il suo contenuto:

{
"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"]
}

Analizziamo separatamente le principali direttive e i loro significati:

  • bootstrap: true. Attiviamo l'aggiunta automatica di nuovi nodi in caso di connessione. Vorrei sottolineare che non specifichiamo qui il numero esatto di nodi attesi.
  • server: true. Attiviamo la modalità server. Consul su questa macchina virtuale sarà attualmente l'unico server e master, mentre le VM di Nomad saranno client.
  • datacenter: dc1. Specifichiamo il nome del datacenter per creare il cluster. Deve essere identico sia sui client che sui server.
  • encrypt: your-key. La chiave deve anch'essa essere unica e coincidere tra tutti i client e i server. Generata con il comando consul keygen.
  • start_join. In questo elenco indichiamo gli indirizzi IP ai quali verrà effettuata la connessione. Al momento, lasciamo solo il nostro indirizzo.

A questo punto possiamo avviare consul tramite la riga di comando:

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

Questo è un buon modo di debug al momento, tuttavia, non possiamo utilizzare questo metodo su base permanente per motivi ovvi. Creiamo un file di servizio per gestire Consul tramite systemd:

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

Il contenuto del file consul.service:

[Unit]
Description=Processo di avvio di Consul
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

Avviamo Consul tramite systemctl:

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

Controlliamo: il nostro servizio dovrebbe essere attivo e, eseguendo il comando consul members, dovremmo vedere il nostro server:

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

Il passo successivo: installazione di Nginx e configurazione del proxy e dell'autenticazione http. Installa nginx tramite il gestore di pacchetti e nella directory /etc/nginx/sites-enabled crea un file di configurazione consul.conf con il seguente contenuto:

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 "Area protetta da password";
    }
}

Ricordati di creare il file .htpasswd e di generare un nome utente e una password per esso. Questo passaggio è necessario affinché il pannello web non sia accessibile a chiunque conosca il nostro dominio. Tuttavia, durante la configurazione di Gitlab, ci sarà necessario rinunciarvi: altrimenti non potremo distribuire la nostra applicazione in Nomad. Nel mio progetto, sia Gitlab che Nomad si trovano solo nella rete interna, quindi questo problema non sussiste.

Sugli altri due server, installiamo gli agenti Consul seguendo le istruzioni qui di seguito. Ripetiamo le operazioni con il file 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/

Analogamente al server precedente, creiamo la directory per i file di configurazione /etc/consul.d con la seguente struttura:

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

Contenuto del file 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", # indirizzo locale vm
    "start_join": ["172.30.0.15"], # indirizzo remoto server consul
    "ports": {
      "dns": 53
     }

Salviamo le modifiche e procediamo alla configurazione del file di servizio, il cui contenuto è:

/etc/systemd/system/consul.service:

[Unit]
Description="HashiCorp Consul - Una soluzione per il service mesh"
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

Avviamo consul sul server. Ora, dopo l'avvio, dobbiamo vedere il servizio configurato in nsul members. Questo significa che è riuscito a connettersi al cluster come client. Ripeti la stessa operazione sul secondo server e dopo potremo procedere all'installazione e configurazione di Nomad.

Un'installazione più dettagliata di Nomad è descritta nella sua documentazione ufficiale. Ci sono due modi tradizionali per installarlo: scaricando il file binario o compilando dai sorgenti. Io sceglierò il primo modo.

Nota: il progetto sta evolvendo molto rapidamente e spesso vengono rilasciati nuovi aggiornamenti. È possibile che, al momento della conclusione dell'articolo, venga rilasciata una nuova versione. Pertanto, ti consiglio di controllare prima l'ultima versione di Nomad disponibile e di scaricare proprio quella.

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

Dopo l'estrazione avremo un file binario di Nomad del peso di 65 MB: è necessario spostarlo in /usr/local/bin.

Creiamo una directory data per Nomad e modifichiamo il suo file di servizio (probabilmente non esisterà all'inizio):

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

Inseriamo le seguenti righe:

[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

Tuttavia, non ci affrettiamo a lanciare nomad — non abbiamo ancora creato il suo file di configurazione:

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 struttura finale della directory sarà la seguente:

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

Il file nomad.hcl deve contenere la seguente configurazione:

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

Contenuto del file 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
}

Non dimenticate di modificare il file di configurazione sul secondo server: dovrà essere cambiato il valore della direttiva http.

L'ultimo passo in questa fase è la configurazione di Nginx per il proxy e l'installazione dell'autenticazione http. Contenuto del file 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 "Area protetta da password";
        }
        
}

Ora possiamo accedere al pannello web attraverso la rete esterna. Connettiamoci e andiamo alla pagina servers:

Configurazione del cluster Nomad tramite Consul e integrazione con Gitlab
Immagine 1. Elenco dei server nel cluster Nomad

Entrambi i server vengono visualizzati correttamente nel pannello, lo stesso lo vedremo nell'output del comando nomad node status:

Configurazione del cluster Nomad tramite Consul e integrazione con Gitlab
Immagine 2. Output del comando nomad node status

E per quanto riguarda Consul? Vediamo. Andiamo al pannello di controllo di Consul, alla pagina nodes:
Configurazione del cluster Nomad tramite Consul e integrazione con Gitlab
Immagine 3. Elenco delle nodi nel cluster Consul

Ora abbiamo un Nomad configurato, funzionante in sinergia con Consul. Nell'ultima fase ci concentreremo sulla parte più interessante: configurare la consegna dei container Docker da Gitlab a Nomad, e discuteremo anche di alcune delle sue altre peculiarità distintive.

Creazione di un Gitlab Runner

Per distribuire le immagini Docker in Nomad utilizzeremo un runner separato con il file binario di Nomad al suo interno (qui, tra l'altro, si può notare un'altra caratteristica delle applicazioni Hashicorp: separatamente sono rappresentate da un singolo file binario). Caricalo nella directory del runner. Per questo creeremo un semplice Dockerfile con il seguente contenuto:


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

In questo progetto creiamo .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}

Alla fine avremo un'immagine del runner di Nomad disponibile nel Gitlab Registry, ora possiamo andare direttamente nel repository del progetto, creare un Pipeline e configurare il job di Nomad.

Configurazione del progetto

Iniziamo con il file job per Nomad. Il mio progetto in questo articolo sarà piuttosto semplice: consisterà in un solo task. Il contenuto di .gitlab-ci sarà il seguente:

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}'  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

Qui la distribuzione avviene in modalità manuale, ma puoi configurarla in modo da modificare il contenuto della directory del progetto. Il Pipeline è composto da due fasi: la costruzione dell'immagine e la sua distribuzione in Nomad. Nella prima fase costruiamo l'immagine Docker e la inviamo al nostro Registry, mentre nella seconda eseguiamo il nostro job in 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" {}
                }
            }
        }
    }
}

Si prega di notare che ho un Registry chiuso e per scaricare con successo l'immagine Docker devo autenticarmi. La soluzione migliore in questo caso è inserire il nome utente e la password in Vault e successivamente integrare il tutto con Nomad. Nomad supporta nativamente Vault. Ma per iniziare, in Vault stesso configuriamo le policy necessarie per Nomad, che possono essere caricate:

# 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

Ora, dopo aver creato le policy necessarie, aggiungeremo l'integrazione con Vault nel blocco task del file job.nomad:

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

Utilizzo l'autenticazione tramite token e lo specifico qui; c'è anche la possibilità di fornire il token come variabile durante l'avvio dell'agente Nomad:

$ VAULT_TOKEN= nomad agent -config /path/to/config

Ora possiamo utilizzare le chiavi da Vault. Il principio di funzionamento è semplice: creiamo un file nel job Nomad, che conterrà i valori delle variabili, ad esempio:

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 questo approccio semplice è possibile configurare la distribuzione dei container nel cluster Nomad e lavorarci successivamente. Posso dire che, in una certa misura, mi piace Nomad: è più adatto per progetti piccoli, dove Kubernetes può creare complicazioni aggiuntive e non sfrutterebbe appieno il suo potenziale. Inoltre, Nomad è perfetto per i principianti: è facile da installare e configurare. Tuttavia, durante i test su alcuni progetti ho riscontrato problemi con le sue versioni precedenti: molte funzionalità di base sono assenti o non funzionano correttamente. Tuttavia, credo che Nomad continuerà a svilupparsi e in futuro avrà tutte le funzionalità necessarie.

Autore: Il'ya Andreev, a cura di Aleksey Zhadan e del team di «Live Linux»


Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster