Aller au contenu
Conteneurs & Orchestration medium

Nomad : orchestrer conteneurs et workloads simplement

28 min de lecture

logo nomad

Vous cherchez à orchestrer vos workloads sans la complexité de Kubernetes ? HashiCorp Nomad est un orchestrateur léger, distribué sous forme d’un seul binaire, capable de gérer aussi bien des conteneurs Docker que des binaires natifs, des machines virtuelles ou des jobs batch. Là où Kubernetes exige plusieurs composants (etcd, API server, scheduler, kubelet…), Nomad s’installe en une commande et devient opérationnel en quelques minutes. Ce guide s’adresse aux développeurs et ops qui veulent déployer rapidement des workloads variés sur un ou plusieurs datacenters.

  • Installer Nomad et lancer un cluster de développement en une commande
  • Écrire des fichiers de jobs en HCL pour déployer des conteneurs Docker
  • Différencier les types de jobs : service (continu), batch (ponctuel), system (chaque nœud) et periodic (cron)
  • Configurer des rolling updates avec rollback automatique
  • Utiliser les templates pour générer dynamiquement des fichiers de configuration
  • Diagnostiquer les problèmes courants avec les commandes CLI essentielles

Nomad est un orchestrateur de workloads développé par HashiCorp (les créateurs de Terraform). Là où Kubernetes se concentre sur les conteneurs, Nomad peut orchestrer tout type de charge de travail : conteneurs Docker, applications Java, binaires natifs, machines virtuelles QEMU, et même des GPU Nvidia.

Pensez à Nomad comme un chef d’orchestre polyvalent : au lieu de ne diriger que les violons (les conteneurs), il dirige l’orchestre entier — cuivres, bois, percussions et tout le reste.

CritèreNomadKubernetes
Complexité d’installationUn seul binaire, opérationnel en minutesPlusieurs composants (etcd, API server, scheduler…)
Types de workloadsConteneurs, binaires, VMs, batchs, GPUPrincipalement conteneurs
Courbe d’apprentissageDouce, HCL lisiblePlus raide, YAML verbeux
ÉcosystèmePlus restreint, intégration HashiCorpTrès vaste (Helm, operators, CRDs…)
Cas d’usage idéalInfra mixte, équipes réduites, multi-datacenterMicroservices à grande échelle, cloud-native
Découverte de servicesVia Consul ou intégrée (Nomad natif)DNS interne + Services natifs

Avant de passer à la pratique, voici les concepts fondamentaux de Nomad. Chacun a un rôle précis dans le cycle de vie de vos déploiements.

Nomad est distribué sous la forme d’un seul binaire qui peut jouer deux rôles :

  • Server (master) : prend les décisions de planification, maintient l’état du cluster. On en déploie 3 ou 5 pour la haute disponibilité en production.
  • Client (worker) : exécute les tâches planifiées par les servers. Chaque client remonte ses ressources disponibles (CPU, mémoire, disque) au server.

Un même nœud peut être server et client à la fois, ce qui est pratique pour le développement ou les petits clusters.

Les workloads dans Nomad suivent une hiérarchie simple :

Job (le déploiement complet)
└── Group (ensemble de tâches co-localisées)
├── Task (une unité de travail)
└── Task (une autre unité de travail)
  • Job : l’objet de plus haut niveau. Il définit ce que vous voulez déployer et où (datacenter, région). Un fichier de job est écrit en HCL (HashiCorp Configuration Language), le même langage que Terraform.
  • Task Group : un ensemble de tâches qui doivent tourner sur le même nœud. Les tâches d’un même groupe partagent le réseau et le stockage. C’est l’équivalent d’un Pod dans Kubernetes.
  • Task : la plus petite unité de travail. C’est ce qui s’exécute réellement : un conteneur Docker, un binaire, une commande.
TypeDescriptionExemple d’usage
serviceTourne en continu, redémarré automatiquementApplication web, API REST
batchS’exécute une fois puis se termineMigration de données, génération de rapport
systemDéployé sur chaque nœud du clusterCollecteur de logs, agent de monitoring
sysbatchBatch exécuté une fois sur chaque nœudMise à jour de configuration système

Un task driver (pilote de tâche) indique à Nomad comment exécuter une task. Nomad en intègre plusieurs nativement :

DriverCe qu’il exécute
dockerConteneurs Docker
execBinaires isolés (avec cgroups)
raw_execBinaires sans isolation
javaApplications Java (JARs)
qemuMachines virtuelles QEMU
podmanConteneurs via Podman (plugin)

Quand vous soumettez un job, Nomad suit ce processus :

  1. Évaluation : Nomad compare l’état souhaité (votre fichier de job) avec l’état actuel du cluster et décide ce qui doit changer.

  2. Planification : le scheduler détermine sur quel nœud placer chaque groupe de tâches, en fonction des ressources disponibles et des contraintes.

  3. Allocation : une allocation est la correspondance entre un groupe de tâches et un nœud client. C’est l’unité d’exécution concrète.

Pour suivre ce guide, vous avez besoin de :

  • Linux (Ubuntu 22.04+ ou équivalent)
  • Docker installé et fonctionnel (docker run hello-world doit fonctionner)
  • wget et unzip pour l’installation
  • Droits sudo pour lancer Nomad en mode dev

Nomad est distribué sous forme d’un binaire unique. Pas de dépendances, pas de base de données externe, pas de composants multiples à configurer.

Fenêtre de terminal
cd /tmp
wget https://releases.hashicorp.com/nomad/1.11.2/nomad_1.11.2_linux_amd64.zip
unzip nomad_1.11.2_linux_amd64.zip
sudo mv nomad /usr/local/bin/
rm nomad_1.11.2_linux_amd64.zip

Vérification : la commande suivante doit afficher la version installée :

Fenêtre de terminal
nomad --version
Nomad v1.11.2
BuildDate 2026-02-11T19:01:47Z

Le mode dev lance un agent Nomad qui fait office de server et de client sur la même machine. C’est parfait pour apprendre et tester.

Fenêtre de terminal
sudo nomad agent -dev -bind 0.0.0.0

Ouvrez un second terminal pour interagir avec le cluster. Vérifiez que tout fonctionne :

Fenêtre de terminal
nomad server members
Name Address Port Status Leader Raft Version Build Datacenter Region
master1.global 192.168.20.103 4648 alive true 3 1.11.2 dc1 global
Fenêtre de terminal
nomad node status
ID Node Pool DC Name Class Drain Eligibility Status
851cb730 default dc1 master1 <none> false eligible ready

L’interface web est accessible sur http://localhost:4646. Elle offre une vue complète des jobs, des nœuds, de la topologie et des allocations.

Un job de type service tourne en continu. Si le conteneur s’arrête, Nomad le redémarre automatiquement. C’est le type le plus courant, équivalent à un Deployment dans Kubernetes.

Créez le fichier webapp.nomad.hcl :

job "webapp" {
datacenters = ["dc1"]
type = "service"
group "web" {
count = 2
network {
port "http" {
to = 80
}
}
service {
name = "webapp"
port = "http"
provider = "nomad"
check {
type = "http"
path = "/"
interval = "10s"
timeout = "2s"
}
}
task "nginx" {
driver = "docker"
config {
image = "nginx:alpine"
ports = ["http"]
}
resources {
cpu = 100
memory = 128
}
}
}
}

Ce fichier déclare :

  • Un job nommé webapp sur le datacenter dc1
  • Un group web avec 2 instances (count = 2)
  • Un port dynamique mappé vers le port 80 du conteneur
  • Un service avec un health check HTTP toutes les 10 secondes
  • Une task qui utilise le driver Docker avec l’image nginx:alpine
  • Des limites de ressources : 100 MHz de CPU et 128 MB de RAM

Déployez le job :

Fenêtre de terminal
nomad job run webapp.nomad.hcl
==> Monitoring evaluation "eac314ee"
Evaluation triggered by job "webapp"
Allocation "5847c171" created: node "851cb730", group "web"
Allocation "35d6fd42" created: node "851cb730", group "web"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "eac314ee" finished with status "complete"
==> Monitoring deployment "11f3d442"
✓ Deployment "11f3d442" successful
Deployed
Task Group Desired Placed Healthy Unhealthy Progress Deadline
web 2 2 2 0 2026-03-04T07:59:08+01:00

Vérification : consultez le statut du job et de ses allocations :

Fenêtre de terminal
nomad job status webapp
ID = webapp
Name = webapp
Type = service
Status = running
Summary
Task Group Queued Starting Running Failed Complete Lost Unknown
web 0 0 2 0 0 0 0
Allocations
ID Node ID Task Group Version Desired Status Created Modified
35d6fd42 851cb730 web 0 run running 1m41s ago 1m25s ago
5847c171 851cb730 web 0 run running 1m41s ago 1m25s ago

Pour voir les logs d’une allocation, utilisez les 8 premiers caractères de l’ID d’allocation :

Fenêtre de terminal
nomad alloc logs 35d6fd42

Pour accéder à l’application, consultez le port dynamique attribué :

Fenêtre de terminal
nomad service info webapp
Job ID Address Tags Node ID Alloc ID
webapp 127.0.0.1:31918 [] 851cb730 35d6fd42
webapp 127.0.0.1:29580 [] 851cb730 493bee81

Testez avec curl en utilisant l’un des ports affichés :

Fenêtre de terminal
curl http://127.0.0.1:31918

Un job batch s’exécute une seule fois puis se termine. C’est l’équivalent d’un Job Kubernetes. Idéal pour les migrations, les exports ou les traitements ponctuels.

Créez le fichier batch-job.nomad.hcl :

job "batch-exemple" {
datacenters = ["dc1"]
type = "batch"
group "traitement" {
count = 1
task "generer-rapport" {
driver = "docker"
config {
image = "alpine:3.19"
command = "/bin/sh"
args = [
"-c",
"echo 'Début du traitement...' && sleep 3 && echo 'Rapport généré avec succès' && echo 'Lignes traitées : 1542'"
]
}
resources {
cpu = 100
memory = 64
}
}
}
}
Fenêtre de terminal
nomad job run batch-job.nomad.hcl

Récupérez les logs une fois le job terminé en utilisant l’ID d’allocation affiché lors du déploiement :

Fenêtre de terminal
nomad alloc logs <ALLOC_ID>
Début du traitement...
Rapport généré avec succès
Lignes traitées : 1542

Le statut du job passe à dead une fois terminé, ce qui est le comportement attendu pour un batch :

Fenêtre de terminal
nomad job status batch-exemple
Status = dead
Summary
Task Group Queued Starting Running Failed Complete Lost Unknown
traitement 0 0 0 0 1 0 0
Allocations
ID Node ID Task Group Version Desired Status Created Modified
286eeb2e 851cb730 traitement 0 run complete 17s ago 13s ago

Nomad intègre nativement un scheduler cron via le bloc periodic. Plus besoin de crontab système ou de CronJob Kubernetes.

job "sauvegarde" {
datacenters = ["dc1"]
type = "batch"
periodic {
crons = ["*/5 * * * *"]
prohibit_overlap = true
}
group "backup" {
count = 1
task "dump-db" {
driver = "docker"
config {
image = "alpine:3.19"
command = "/bin/sh"
args = [
"-c",
"echo '[INFO] Sauvegarde démarrée' && sleep 2 && echo '[OK] Sauvegarde terminée - taille: 42MB'"
]
}
resources {
cpu = 100
memory = 64
}
}
}
}
  • crons : syntaxe cron standard, ici toutes les 5 minutes
  • prohibit_overlap : empêche le lancement d’une nouvelle exécution si la précédente n’est pas terminée
Fenêtre de terminal
nomad job run sauvegarde.nomad.hcl
Job registration successful
Approximate next launch time: 2026-03-04T06:55:00Z (2m49s from now)

Un job system s’exécute sur chaque nœud client du cluster. C’est l’équivalent d’un DaemonSet dans Kubernetes. Cas d’usage typique : collecteur de logs, agent de monitoring, antivirus.

job "collecteur-logs" {
datacenters = ["dc1"]
type = "system"
group "logging" {
task "fluentbit" {
driver = "docker"
config {
image = "alpine:3.19"
command = "/bin/sh"
args = [
"-c",
"echo 'Collecteur de logs démarré' && while true; do echo '[LOG] Collecte en cours...'; sleep 60; done"
]
}
resources {
cpu = 50
memory = 32
}
}
}
}

Quand vous ajoutez un nouveau nœud au cluster, Nomad y déploie automatiquement le job system sans intervention manuelle.

Nomad permet d’injecter des variables d’environnement dans vos tâches via le bloc env. Chaque variable est accessible par le processus lancé dans le conteneur.

job "app-config" {
datacenters = ["dc1"]
type = "service"
group "api" {
count = 1
network {
port "http" {
to = 8080
}
}
task "api-server" {
driver = "docker"
config {
image = "hashicorp/http-echo"
ports = ["http"]
args = [
"-listen", ":8080",
"-text", "API v1.2.0 - production"
]
}
env {
APP_ENV = "production"
APP_VERSION = "1.2.0"
LOG_LEVEL = "info"
}
resources {
cpu = 100
memory = 64
}
}
}
}

Utiliser les templates pour générer des fichiers

Section intitulée « Utiliser les templates pour générer des fichiers »

Le système de templates de Nomad permet de générer des fichiers de configuration à la volée, en injectant des variables d’environnement Nomad. Les templates utilisent la syntaxe Go template (identique à Consul Template).

job "app-template" {
datacenters = ["dc1"]
type = "service"
group "web" {
count = 1
network {
port "http" {
to = 80
}
}
task "nginx" {
driver = "docker"
config {
image = "nginx:alpine"
ports = ["http"]
volumes = [
"local/default.conf:/etc/nginx/conf.d/default.conf"
]
}
template {
data = <<-TPL
server {
listen 80;
server_name _;
location / {
return 200 'App: {{ env "NOMAD_JOB_NAME" }}\nAllocation: {{ env "NOMAD_ALLOC_ID" }}\n';
add_header Content-Type text/plain;
}
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
}
TPL
destination = "local/default.conf"
change_mode = "restart"
}
resources {
cpu = 100
memory = 64
}
}
}
}

Le template génère une configuration Nginx personnalisée. La directive change_mode = "restart" redémarre la task si le template change (par exemple lors d’une mise à jour de variable).

Vérification : inspectez le fichier généré dans le conteneur :

Fenêtre de terminal
nomad alloc exec <ALLOC_ID> cat /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name _;
location / {
return 200 'App: app-template
Allocation: 4a0699d1-3cba-7b6c-42a9-7d2c342cdb94
';
add_header Content-Type text/plain;
}
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
}

Les variables NOMAD_JOB_NAME et NOMAD_ALLOC_ID ont été remplacées par leurs valeurs réelles.

Nomad gère nativement les mises à jour progressives (rolling updates) via le bloc update. Cette stratégie permet de déployer une nouvelle version sans interruption de service.

job "webapp" {
datacenters = ["dc1"]
type = "service"
update {
max_parallel = 1
min_healthy_time = "10s"
healthy_deadline = "3m"
auto_revert = true
}
group "web" {
count = 3
network {
port "http" {
to = 80
}
}
service {
name = "webapp"
port = "http"
provider = "nomad"
check {
type = "http"
path = "/"
interval = "10s"
timeout = "2s"
}
}
task "nginx" {
driver = "docker"
config {
image = "nginx:alpine"
ports = ["http"]
}
resources {
cpu = 100
memory = 128
}
}
}
}

Les paramètres du bloc update :

ParamètreRôle
max_parallelNombre d’instances mises à jour simultanément
min_healthy_timeDurée minimale pendant laquelle la nouvelle instance doit être saine
healthy_deadlineDélai maximum pour qu’une instance devienne saine
auto_revertRevient automatiquement à la version précédente en cas d’échec

Avant d’appliquer une mise à jour, utilisez nomad job plan pour visualiser les changements sans les appliquer (comme un terraform plan) :

Fenêtre de terminal
nomad job plan webapp-v2.nomad.hcl
+/- Job: "webapp"
+/- Task Group: "web" (2 create, 3 ignore)
+/- Count: "3" => "5" (forces create)
+/- Task: "nginx" (forces create/destroy update)
+/- Resources {
+/- CPU: "100" => "200"
+/- MemoryMB: "128" => "256"
}
Scheduler dry-run:
- All tasks successfully allocated.

Nomad montre clairement les changements : nombre d’instances, ressources CPU, mémoire. Si le résultat est conforme, appliquez avec nomad job run.

Voici les commandes que vous utiliserez au quotidien pour opérer un cluster Nomad :

Fenêtre de terminal
# Vérifier les serveurs du cluster
nomad server members
# Voir les nœuds clients et leur état
nomad node status
# Informations détaillées sur le cluster
nomad agent-info
# Installer l'autocomplétion (bash/zsh)
nomad -autocomplete-install
Fenêtre de terminal
# Valider la syntaxe d'un fichier de job
nomad job validate webapp.nomad.hcl
# Prévisualiser les changements (dry-run)
nomad job plan webapp.nomad.hcl
# Déployer ou mettre à jour un job
nomad job run webapp.nomad.hcl
# Voir le statut d'un job
nomad job status webapp
# Lister tous les jobs
nomad job status
# Voir l'historique des versions d'un job
nomad job history webapp
# Inspecter un job au format JSON
nomad job inspect webapp
# Arrêter un job (conserve l'historique)
nomad job stop webapp
# Arrêter et purger un job (supprime tout)
nomad job stop -purge webapp
Fenêtre de terminal
# Voir les allocations d'un job
nomad job allocs webapp
# Consulter les logs d'une allocation
nomad alloc logs <ALLOC_ID>
# Exécuter une commande dans un conteneur
nomad alloc exec <ALLOC_ID> /bin/sh
# Récupérer des fichiers d'une allocation
nomad alloc fs <ALLOC_ID> /alloc/logs/
Fenêtre de terminal
# Lister les services enregistrés
nomad service list
# Voir les instances d'un service
nomad service info webapp
Fenêtre de terminal
# Nettoyer les ressources orphelines
nomad system gc

En mode dev, tout tourne sur un seul nœud. En production, vous séparez les rôles server et client.

data_dir = "/opt/nomad/data"
datacenter = "dc1"
server {
enabled = true
bootstrap_expect = 3
}

Le paramètre bootstrap_expect indique le nombre de servers attendus avant de démarrer l’élection du leader. Utilisez 3 ou 5 pour la haute disponibilité.

data_dir = "/opt/nomad/data"
datacenter = "dc1"
client {
enabled = true
servers = ["10.240.0.10", "10.240.0.11", "10.240.0.12"]
}

Le client doit connaître les adresses des servers pour s’y connecter.

SymptômeCause probableSolution
No cluster leaderUn seul server en mode non-devLancez le nombre de servers indiqué dans bootstrap_expect
Allocation pendingRessources insuffisantes sur les clientsVérifiez nomad node status -verbose et réduisez les resources
Driver docker not foundDocker non installé ou non démarréInstallez Docker et vérifiez avec docker info
Eval blockedAucun nœud ne satisfait les contraintesVérifiez le datacenter, le node pool et les ressources demandées
Unhealthy allocationLe health check échoueVérifiez que l’application est bien sur le bon port et que le path du check est correct
Job submission errorSyntaxe HCL invalideValidez avec nomad job validate fichier.nomad.hcl
Permission deniedDroits insuffisantsExécutez Nomad avec sudo ou configurez les permissions Docker
  • Nomad est un seul binaire qui orchestre conteneurs, binaires, VMs et batchs sans la complexité de Kubernetes.
  • La hiérarchie Job > Group > Task organise vos workloads. Un Group est l’équivalent d’un Pod Kubernetes.
  • Les quatre types de jobs couvrent tous les cas : service (continu), batch (ponctuel), system (chaque nœud), periodic (cron).
  • Le bloc update avec auto_revert assure des mises à jour progressives sans interruption.
  • nomad job plan vous montre les changements avant de les appliquer, exactement comme terraform plan.
  • Les templates génèrent des fichiers de configuration dynamiques en injectant les variables d’environnement Nomad.
  • Nomad s’intègre naturellement avec Consul (découverte de services) et Vault (secrets), mais fonctionne parfaitement seul pour démarrer.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn