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
| Porta | Protocollo | Uso | Accesso |
|---|---|---|---|
| 4646 | TCP | Nomad HTTP API | Internal + Admin |
| 4647 | TCP | Nomad RPC | Internal only |
| 4648 | TCP/UDP | Nomad Serf | Internal only |
| 8500 | TCP | Consul HTTP | Internal + Admin |
| 8301 | TCP/UDP | Consul Serf LAN | Internal only |
| 8302 | TCP/UDP | Consul Serf WAN | Internal only |
| 80 | TCP | Traefik HTTP | Public |
| 443 | TCP | Traefik HTTPS | Public |
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.