Skip to content

Nomad

  • It has a client-server architecture. There is a main server and worker nodes (clients).
  • Integrates with Consul for service discoverability
  • Can integrate with other CNIs

Commands

https://developer.hashicorp.com/nomad/commands

  • nomad node
  • nomad node status Display basic information about all the nodes.
  • nomad node status 42635b82 Display detailed information and resource usage about a node.
  • nomad job status
  • nomad job status -verbose job-name
  • nomad job scale
  • nomad job scale job-name 2 Set the number of instances (Horizontal scaling).
  • nomad job stop
  • nomad job allocs job-name Show the allocation ID for a job
  • nomad alloc status <alloc-id> Show detailed info about the allocation (resources, ports, status, etc)
  • nomad alloc exec -i -t <alloc-id> /bin/sh Run command inside a container

Start agent

In dev mode

nomad agent -dev

With a config file

nomad agent -config server.hcl

Access the webui on port 4646.

Config file

Server and worker

data_dir = "/opt/nomad/data"
bind_addr = "0.0.0.0"

server {
  enabled = true
  bootstrap_expect = 1
}

client {
  enabled = true
  servers = ["127.0.0.1"]
}

Worker

data_dir = "/opt/nomad/data"
bind_addr = "0.0.0.0"

client {
  enabled = true
  servers = ["<Server_Node_IP>:4647"]
}

Jobs

Type of jobs

  • Service jobs (default) are long-running tasks that should never go down.
  • Batch jobs are short-lived and run to completion.
  • System jobs are tasks that should be run on all clients matching certain criteria.
  • Parameterized jobs are templates that can be triggered with specific parameters.

Job lifecycles

  • Submission: initial step where you submit your job spec to Nomad using nomad job run example.nomad
  • Planning: Nomad creates a plan for how and where to run the job.
  • Allocation: Once the plan is approved, Nomad allocates resources and schedules the job.
  • Execution: Finally, the job is executed. Nomad monitors its execution, ensuring it's restarted in case of failure according to the job's restart policy.

Scheduling Algorithms

Nomad uses sophisticated scheduling algorithms to optimize resource utilization and fault tolerance. It considers resource availability, job priority, and data locality, among other factors, to make scheduling decisions.

Bin Packing Nomad's bin packing algorithm aims to minimize resource fragmentation and maximize resource utilization by fitting jobs into the smallest number of clients.

Spread For fault tolerance, Nomad can also spread jobs across different clients to reduce the impact of a single client's failure.

Create a job

Create a job definition.

job "hello-world" {
  type = "batch"
  datacenters = ["dc1"]
  group "hello-world-group" {
    task "hello" {
      driver = "exec"
      config {
        command = "/bin/echo"
        args    = ["Hello, Nomad!"]
      }
      resources {
        cpu    = 500 # MHz
        memory = 256 # MB
      }
    }
  }
}

job "fast-api" {
  datacenters = ["dc1"]
  group "api" {
    network {
      mode = "bridge"
      port "http" {}
    }
    task "fastapi" {
      driver = "docker"
      config {
        image = "tiangolo/uvicorn-gunicorn-fastapi"
        ports = ["http"]
      }
    }
  }
}

Execute it with nomad run example.nomad

Services

Connect the job with Consul. I have not tested this.

job "webapp" {
  datacenters = ["dc1"]

  group "backend" {
    count = 1

    task "redis" {
      driver = "docker"
      config {
        image = "redis:latest"
      }
      service {
        name = "redis"
        port = "6379"
        provider = "consul"
        tags = ["redis", "db", "backend"]
        check {
          type     = "tcp"
          interval = "10s"
          timeout  = "2s"
        }
      }
    }
  }

  group "frontend" {
    network {
      mode = "bridge" 
      port "http" {
        static = 8080
        to = 80
      }
    }
    count = 2

    task "frontend" {
      driver = "docker"
      config {
        image = "nginx"
        ports = ["http"]
      }
      env {
        REDIS_ADDR = "redis.service.consul:80"
      }
    }
  }
}

Secrets

Using Vault to store and retrieve secrets.

job "example-vault" {
  datacenters = ["dc1"]

  group "group1" {
    task "task1" {
      driver = "docker"

      vault {
        policies = ["my-policy"]
      }

      template {
        data = <<EOH
        MY_SECRET="{{ with secret "secret/myapp/config" }}{{ .Data.password }}{{ end }}"
        EOH

        destination = "secrets/file.env"
        env         = true
      }

      config {
        image = "busybox"
      }
    }
  }
}