Nomad — планировщик от HashiCorp для контейнеров и обычных процессов на пуле машин. В отличие от Kubernetes, здесь нет etcd, CNI и десятка контроллеров: один бинарник работает и сервером, и клиентом, а состояние хранится через Raft. Для небольшой лаборатории этого достаточно для обновлений без простоя и самовосстановления.

Как устроен кластер

Серверы хранят состояние, клиенты запускают задачи и сообщают о ресурсах. На маленьком стенде три сервера совмещают обе роли, а остальные машины остаются клиентами. Порты: 4646 — HTTP API и веб-интерфейс, 4647 — RPC между узлами, 4648 — Serf для служебных сообщений.

Отличия от Kubernetes:

  • нет отдельного хранилища состояния и CNI-плагина;
  • jobspec описывает задачу, группу и сеть в одном файле HCL;
  • поддерживаются контейнеры, обычные процессы и Java;
  • namespaces, canary и multi-region доступны только в Enterprise.

Лицензия — BUSL 1.1: исходники открыты, но коммерческое использование ограничено.

Установка

Официальный репозиторий HashiCorp содержит пакеты для Debian и Ubuntu. Ключ и список источников добавляются один раз, после чего обновление идёт через apt.

wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update
sudo apt install nomad
nomad version

Режим nomad agent -dev поднимает сервер и клиент в одном процессе и не сохраняет состояние; он подходит только для ноутбука.

Конфигурация сервера и клиента

Файлы лежат в /etc/nomad.d/. Ниже минимальный стенд из трёх узлов, каждый из которых совмещает сервер и клиент. В боевой схеме клиенты выносят отдельно.

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

server {
  enabled          = true
  bootstrap_expect = 3
}

client {
  enabled = true
  servers = ["10.0.0.11:4647", "10.0.0.12:4647", "10.0.0.13:4647"]
}

telemetry {
  prometheus_metrics = true
  disable_hostname   = true
}

acl {
  enabled = true
}

bootstrap_expect должен совпадать с числом серверов, иначе выборы лидера не завершатся. После запуска получите management-токен командой nomad acl bootstrap и сохраните его в менеджере секретов. Не открывайте 4646 в интернет: панель без ACL доступна всем.

Первый job: веб-сервис

Jobspec — файл HCL. В нём задаются группа, количество экземпляров, сеть, задача и проверка здоровья. Ниже nginx с динамическим портом и регистрацией в службе обнаружения Nomad.

job "web" {
  datacenters = ["dc1"]
  type        = "service"

  group "app" {
    count = 2

    network {
      mode = "bridge"
      port "http" {
        to = 80
      }
    }

    task "server" {
      driver = "docker"

      config {
        image = "nginx:stable-alpine"
        ports = ["http"]
      }

      resources {
        cpu    = 300
        memory = 256
      }

      service {
        name     = "web"
        port     = "http"
        provider = "nomad"

        check {
          type     = "http"
          path     = "/"
          interval = "10s"
          timeout  = "2s"
        }
      }
    }
  }
}
nomad job plan web.nomad.hcl
nomad job run web.nomad.hcl
nomad job status web
nomad alloc logs -f 1a2b3c4d server

plan показывает, что изменится, и не трогает кластер. Просматривайте diff: он ловит опечатки в образе и неверный порт. alloc logs принимает идентификатор аллокации, а не имя задачи.

Обновления и откаты

Стратегия обновления задаётся в группе. Nomad поднимает новые аллокации постепенно, ждёт проверок и при неудаче возвращает предыдущую версию.

update {
  max_parallel      = 1
  min_healthy_time  = "10s"
  healthy_deadline  = "3m"
  progress_deadline = "10m"
  auto_revert       = true
}

История хранится на сервере: nomad job history web показывает версии, а nomad job revert web 2 откатывает на вторую. Перед обслуживанием узла включите drain, чтобы задачи переехали:

nomad node status
nomad node drain -enable -deadline 10m 2f4a1b7c
nomad node drain -disable 2f4a1b7c

Если задача не переезжает, проверьте constraint и свободные ресурсы: планировщик не разместит аллокацию там, где не хватает CPU или памяти.

Постоянные данные

Для домашних сервисов проще всего host volume: каталог на клиенте монтируется в контейнер. Том объявляется в конфигурации клиента, а точка монтирования — в jobspec.

# в блоке client на узле
host_volume "appdata" {
  path      = "/srv/appdata"
  read_only = false
}

# фрагмент jobspec
group "app" {
  volume "appdata" {
    type   = "host"
    source = "appdata"
  }

  task "server" {
    volume_mount {
      volume      = "appdata"
      destination = "/data"
    }
  }
}

Host volume привязывает задачу к конкретному узлу, поэтому для отказоустойчивости нужны репликация средствами приложения или CSI-плагин сетевого хранилища. Состояние кластера сохраняется снимком Raft:

nomad operator snapshot save /var/backups/nomad.snap
nomad operator snapshot inspect /var/backups/nomad.snap
nomad operator snapshot restore /var/backups/nomad.snap

Снимок содержит задания и метаданные, но не данные приложений. Храните его вне того же диска и проверяйте восстановление на тестовом стенде.

Безопасность

После nomad acl bootstrap все запросы требуют токен. Передавайте его через NOMAD_TOKEN, а не аргументом командной строки: аргументы видны в ps. Для автоматизации создайте политику с минимальными правами и отдельный токен.

export NOMAD_TOKEN="management-token"
nomad acl policy apply deploy deploy.hcl
nomad acl token create -name=deploy -policy=deploy -ttl=720h
nomad acl token self

Включайте TLS для HTTP и RPC, если узлы общаются через недоверенную сеть. Веб-интерфейс держите за обратным прокси с TLS и дополнительной аутентификацией.

Диагностика: чек-лист

Порядок проверки — от кластера к задаче. Сначала убедитесь, что серверы видят друг друга и есть лидер, затем проверьте узел и только потом аллокацию.

nomad server members
nomad operator raft list-peers
nomad node status -verbose
nomad alloc status 1a2b3c4d
journalctl -u nomad -n 100 --no-pager
ss -lntp | grep -E '4646|4647|4648'
  • нет лидера — проверьте bootstrap_expect, время и связность по 4647;
  • узел в статусе down — смотрите journalctl и версию Nomad;
  • аллокация в pending — не хватает ресурсов или не выполняются constraints;
  • контейнер падает — читайте логи задачи и проверяйте переменные окружения;
  • обновление зависло — смотрите nomad deployment status.

Итог

Nomad закрывает средний класс задач: несколько машин, десятки контейнеров, предсказуемые обновления и минимум инфраструктуры. Он не заменяет Kubernetes в крупной компании с платформенной командой, но в домашней лаборатории или небольшом отделе экономит время и ресурсы.

Начните с трёх серверов, ACL и резервных снимков, затем перенесите один реальный сервис. Если через неделю вы не заглядываете в панель без необходимости, а обновления проходят сами, выбор сделан правильно.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте