Skip to main content

Configurazione Cluster Nomad

Guida per installare e configurare un cluster Nomad in produzione.

Prerequisiti

  • 3+ VM per Control Plane (Nomad + Consul servers)
  • 2+ VM per Workers
  • Rete privata (VPC)
  • Docker installato sui workers

1. Installazione Nomad

Su tutti i nodi

# Aggiungi repository HashiCorp
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

# Installa Nomad e Consul
sudo apt-get update && sudo apt-get install -y nomad consul

# Verifica installazione
nomad version
consul version

2. Configurazione Consul (Service Discovery)

Server Configuration (/etc/consul.d/consul.hcl)

datacenter = "visla-dc1"
data_dir = "/opt/consul"
log_level = "INFO"

server = true
bootstrap_expect = 3

bind_addr = "{{ GetPrivateIP }}"
client_addr = "0.0.0.0"

ui_config {
enabled = true
}

# Encryption (genera con: consul keygen)
encrypt = "GENERA_CHIAVE_CON_CONSUL_KEYGEN"

# TLS (opzionale ma consigliato)
# verify_incoming = true
# verify_outgoing = true
# verify_server_hostname = true
# ca_file = "/etc/consul.d/certs/ca.pem"
# cert_file = "/etc/consul.d/certs/consul.pem"
# key_file = "/etc/consul.d/certs/consul-key.pem"

# Auto-join altri server
retry_join = [
"consul-server-1.internal",
"consul-server-2.internal",
"consul-server-3.internal"
]

# ACL (consigliato per produzione)
acl {
enabled = true
default_policy = "deny"
enable_token_persistence = true
}

Client Configuration (sui Workers)

datacenter = "visla-dc1"
data_dir = "/opt/consul"
log_level = "INFO"

server = false
bind_addr = "{{ GetPrivateIP }}"

retry_join = [
"consul-server-1.internal",
"consul-server-2.internal",
"consul-server-3.internal"
]

encrypt = "STESSA_CHIAVE_DEI_SERVER"

Avvio Consul

sudo systemctl enable consul
sudo systemctl start consul

# Verifica cluster
consul members

3. Configurazione Nomad

Server Configuration (/etc/nomad.d/nomad.hcl)

datacenter = "visla-dc1"
data_dir = "/opt/nomad"
log_level = "INFO"

server {
enabled = true
bootstrap_expect = 3

# Encryption (genera con: nomad operator keygen)
encrypt = "GENERA_CHIAVE_CON_NOMAD_OPERATOR_KEYGEN"
}

# Consul integration
consul {
address = "127.0.0.1:8500"
}

# Telemetry per monitoring
telemetry {
collection_interval = "1s"
disable_hostname = true
prometheus_metrics = true
publish_allocation_metrics = true
publish_node_metrics = true
}

# ACL (consigliato per produzione)
acl {
enabled = true
}

Client Configuration (sui Workers)

datacenter = "visla-dc1"
data_dir = "/opt/nomad"
log_level = "INFO"

client {
enabled = true

# Opzioni Docker
options = {
"docker.privileged.enabled" = "false"
"docker.volumes.enabled" = "true"
}

# Meta per scheduling (opzionale)
meta {
node_type = "general"
zone = "europe-west1-b"
}
}

# Consul integration
consul {
address = "127.0.0.1:8500"
}

# Plugin Docker
plugin "docker" {
config {
allow_privileged = false
volumes {
enabled = true
}
gc {
image = true
image_delay = "3m"
container = true
}
}
}

# Telemetry
telemetry {
collection_interval = "1s"
prometheus_metrics = true
publish_allocation_metrics = true
}

Avvio Nomad

sudo systemctl enable nomad
sudo systemctl start nomad

# Verifica cluster
nomad server members
nomad node status

4. Configurazione Traefik (Ingress)

Traefik come ingress controller, integrato con Consul per service discovery automatico.

Job File (traefik.nomad)

job "traefik" {
datacenters = ["visla-dc1"]
type = "system" # Esegue su tutti i nodi

group "traefik" {
network {
port "http" {
static = 80
}
port "https" {
static = 443
}
port "api" {
static = 8080
}
}

service {
name = "traefik"

check {
name = "alive"
type = "tcp"
port = "http"
interval = "10s"
timeout = "2s"
}
}

task "traefik" {
driver = "docker"

config {
image = "traefik:v3.0"
network_mode = "host"

volumes = [
"local/traefik.yml:/etc/traefik/traefik.yml"
]
}

template {
data = <<EOF
api:
dashboard: true
insecure: true

entryPoints:
web:
address: ":80"
websecure:
address: ":443"

providers:
consulCatalog:
prefix: traefik
exposedByDefault: false
endpoint:
address: 127.0.0.1:8500
scheme: http

certificatesResolvers:
letsencrypt:
acme:
email: admin@vislagps.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
EOF
destination = "local/traefik.yml"
}

resources {
cpu = 200
memory = 256
}
}
}
}

5. Verifica Cluster

Comandi Utili

# Status cluster Nomad
nomad status

# Nodi disponibili
nomad node status

# Jobs in esecuzione
nomad job status

# Membri Consul
consul members

# Servizi registrati in Consul
consul catalog services

# UI Web
# Nomad: http://<server-ip>:4646
# Consul: http://<server-ip>:8500
# Traefik: http://<worker-ip>:8080

Health Check Script

#!/bin/bash
# health-check.sh

echo "=== Nomad Cluster Status ==="
nomad server members
echo ""
nomad node status
echo ""

echo "=== Consul Cluster Status ==="
consul members
echo ""

echo "=== Running Jobs ==="
nomad job status
echo ""

echo "=== Registered Services ==="
consul catalog services

6. Sicurezza

Firewall Rules

PortaProtocolloUsoAccesso
4646TCPNomad HTTP APIInternal + Admin
4647TCPNomad RPCInternal only
4648TCP/UDPNomad SerfInternal only
8500TCPConsul HTTPInternal + Admin
8301TCP/UDPConsul Serf LANInternal only
8302TCP/UDPConsul Serf WANInternal only
80TCPTraefik HTTPPublic
443TCPTraefik HTTPSPublic

Genera Encryption Keys

# Per Consul
consul keygen
# Output: pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s=

# Per Nomad
nomad operator keygen
# Output: cg8StVXbQJ0gPvMd9o7yrg==

[!WARNING] Salva queste chiavi in un posto sicuro (Vault, Secret Manager). Sono necessarie per aggiungere nuovi nodi al cluster.