Configurazione del cluster Nomad con Consul e integrazione con Gitlab

Introduzione

Negli ultimi tempi, la popolarità di Kubernetes è in rapida crescita; sempre più progetti lo stanno adottando. Tuttavia, vorrei parlare di un orchestratore come Nomad: è perfetto per i progetti che utilizzano già altre soluzioni di HashiCorp, come Vault e Consul, e non presentano una infrastruttura complessa. In questo materiale troverete 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 con Consul e integrazione con Gitlab

Banchi di prova

Un po' sul nostro ambiente di test: utilizziamo tre server virtuali con le seguenti caratteristiche: 2 CPU, 4 RAM, 50 Gb SSD, tutti connessi a 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 del cluster Nomad

Iniziamo con l'installazione di base. Nonostante la semplicità del processo, la descriverò per completezza dell'articolo: in sostanza, è stata redatta da bozze e appunti per un rapido riferimento in caso di necessità.

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

Abbiamo due nodi Nomad e vogliamo unirli in un cluster; inoltre, in futuro avremo bisogno di un scaling automatico del cluster: per questo abbiamo bisogno di Consul. Con questo strumento, la clusterizzazione e l'aggiunta di nuovi nodi diventano compiti molto semplici: il nodo Nomad creato si collega all'agente Consul e poi si connette al cluster Nomad esistente. Perciò, all'inizio installeremo il server Consul, configureremo l'autenticazione http di base per il pannello web (che di default è accessibile senza autenticazione e può essere raggiunto tramite indirizzo esterno), e installeremo anche gli agenti Consul sui server Nomad, per poi passare a Nomad.

L'installazione degli strumenti di HashiCorp è molto semplice: in sostanza, spostiamo semplicemente il file binario nella directory bin, configuriamo il file di configurazione dello strumento e creiamo il suo file di servizio.

Scarichiamo il file binario di Consul e lo decomprimiamo nella directory home 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 di consul pronto per ulteriori configurazioni.

Per lavorare con Consul, dobbiamo creare una chiave unica utilizzando 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 ci sarà il file di configurazione config.json — qui 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 valori:

  • bootstrap: true. Abilita l'aggiunta automatica di nuovi nodi al momento della loro connessione. Va notato che non specifichiamo qui il numero esatto di nodi attesi.
  • server: true. Attiviamo la modalità server. Consul su questa macchina virtuale fungerà al momento da unico server e master, mentre le VM di Nomad saranno clienti.
  • datacenter: dc1. Indichiamo il nome del data center per la creazione del cluster. Deve essere identico sia sui clienti che sui server.
  • encrypt: your-key. La chiave che deve essere unica e corrispondere su tutti i clienti e server. Viene generata usando il comando consul keygen.
  • start_join. In questo elenco indichiamo gli indirizzi IP a cui sarà effettuata la connessione. Per il 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 fare debug in questo momento, tuttavia, non sarà possibile utilizzare questo metodo in modo permanente per ovvi motivi. Creiamo un file di servizio per gestire Consul tramite systemd:

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

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

Verifichiamo: il nostro servizio dovrebbe essere in esecuzione, 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

Fase successiva: installazione di Nginx e configurazione del proxy, autorizzazione http. Installiamo nginx tramite il gestore di pacchetti e nella directory /etc/nginx/sites-enabled creiamo il 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 "Password-protected Area";
    }
}

Non dimenticate di creare il file .htpasswd e generare un nome utente e una password. Questo passaggio è necessario affinché il pannello web non sia accessibile a chiunque conosca il nostro dominio. Tuttavia, durante la configurazione di Gitlab, dovremo rinunciarci: in caso contrario, non saremo in grado di implementare la nostra applicazione in Nomad. Nel mio progetto, sia Gitlab che Nomad si trovano solo nella rete interna, quindi non ci sono problemi in questo caso.

Sugli altri due server, installiamo gli agenti Consul seguendo le istruzioni seguenti. 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/

Allo stesso modo del server precedente, creiamo la directory per i file di configurazione /etc/consul.d con la seguente struttura:

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

Il 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 del server consul
    "ports": {
      "dns": 53
     }

Salviamo le modifiche e procediamo con la configurazione del file di servizio, il suo contenuto:

/etc/systemd/system/consul.service:

[Unit]
Description="HashiCorp Consul - Una soluzione di 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, dovremmo vedere il servizio configurato in nsul members. Questo significherà che si è connesso con successo al cluster come cliente. Ripetere lo stesso sul secondo server e dopo possiamo procedere con l'installazione e la configurazione di Nomad.

Per ulteriori dettagli sull'installazione di Nomad, fare riferimento alla sua documentazione ufficiale. Ci sono due modi tradizionali per installarlo: scaricare il file binario e compilare dai sorgenti. Scelgo il primo modo.

Nota: il progetto si sviluppa molto rapidamente, con nuovi aggiornamenti che escono frequentemente. È possibile che, al momento della conclusione dell'articolo, venga rilasciata una nuova versione. Pertanto, consiglio di controllare l'ultima versione di Nomad disponibile prima di leggere e scaricare 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 la decompressione, otterremo il file binario di Nomad del peso di 65 MB — deve essere spostato in /usr/local/bin.

Creeremo una directory data per Nomad e modificheremo il suo file di servizio (probabilmente non esisterà inizialmente):

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

Incolliamo 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 eseguire 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"

Il 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 — sarà necessario cambiare il valore della direttiva http.

L'ultimo passaggio consiste nella configurazione di Nginx per il proxy e l'installazione dell'autenticazione http. Il 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 dalla rete esterna. Ci connettiamo e andiamo alla pagina servers:

Configurazione del cluster Nomad con 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 con Consul e integrazione con Gitlab
Immagine 2. Output del comando nomad node status

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

Ora abbiamo un Nomad configurato, funzionante in combinazione con Consul. Nella fase finale, ci concentreremo sulla parte più interessante: configureremo la consegna dei contenitori Docker da Gitlab a Nomad e discuteremo alcune delle sue altre caratteristiche distintive.

Creazione di Gitlab Runner

Per il deployment delle immagini Docker in Nomad utilizzeremo un runner separato con il file binario di Nomad all'interno (a proposito, vale la pena notare un'altra caratteristica delle applicazioni Hashicorp: separatamente rappresentano un singolo file binario). Caricatelo nella directory del runner. 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 stesso progetto creiamo .gitlab-ci.yml:

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

fasi:
  - build

build:
  fase: build
  immagine: ${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 in Gitlab Registry, ora possiamo passare direttamente al repository del progetto, creare una Pipeline e configurare il job Nomad.

Configurazione del progetto

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

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

fasi:
  - build
  - deploy

build:
  fase: build
  immagine: ${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:
  fase: deploy
  immagine: 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
  ambiente:
    nome: produzione
  allow_failure: false
  when: manual

Qui il deploy avviene in modalità manuale, ma puoi configurarlo per modificare il contenuto della directory del progetto. Il pipeline consiste in due fasi: costruzione dell'immagine e il suo deploy su Nomad. Nella prima fase creiamo l'immagine Docker e la carichiamo nel 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 privato e per effettuare correttamente il pull dell'immagine Docker è necessario autenticarsi. La soluzione migliore in questo caso è inserire il login e la password in Vault, integrandolo poi con Nomad. Nomad supporta nativamente Vault. Ma per iniziare, su Vault installiamo 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, una volta create 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 inserisco direttamente qui; c'è anche la possibilità di specificare il token come variabile durante l'avvio dell'agente nomad:

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

Ora possiamo utilizzare le chiavi di Vault. Il funzionamento è semplice: creiamo un file nel job di 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, puoi configurare la consegna dei container nel cluster Nomad e lavorarci successivamente. Devo dire che, in un certo senso, mi piace Nomad: è più adatto per piccoli progetti, dove Kubernetes può creare ulteriore complessità e non realizzerebbe completamente il suo potenziale. Inoltre, Nomad è ideale per i principianti: è facile da installare e configurare. Tuttavia, durante i test su alcuni progetti ho riscontrato problemi con le sue versioni precedenti: molte funzioni di base semplicemente non ci sono o non funzionano correttamente. Nonostante ciò, credo che Nomad continuerà a svilupparsi e in futuro avrà tutte le funzionalità necessarie.

Autore: Ilya Andreyev, a cura di Alexey 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