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.

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:
- nomad-livelinux-01: 172.30.0.5
- nomad-livelinux-02: 172.30.0.10
- 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.jsonNella 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 -uiQuesto è 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.targetAvviamo 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 dc1Fase 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.jsonIl 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.targetAvviamo 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.dDopo 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.serviceIncolliamo 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.targetTuttavia, 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.hclIl 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:

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:

Immagine 2. Output del comando nomad node status
E per quanto riguarda Consul? Vediamo. Andiamo nel pannello di controllo di Consul, alla pagina nodi:

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: manualQui 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.jsonOra, 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
