Macie już kilkanaście usług i trzy–pięć serwerów. Kontenery startują przez docker compose, na każdej maszynie osobno. Deploy to ssh i skrypt, który rozumie jedna osoba. Gdy serwer pada, usługi na nim leżą, dopóki ktoś ręcznie nie przeniesie ich gdzie indziej.
Naturalny następny krok to orkiestrator. I wszyscy od razu mówią: Kubernetes. Tylko że dla zespołu dwóch–trzech programistów bez dedykowanego inżyniera platformy to często nowe źródło problemów: kilkanaście komponentów, własne abstrakcje na wszystko, aktualizacja klastra jako osobny projekt. Część zasobów skromnych serwerów zjada sam control plane, a nie wasze aplikacje.
Przy takiej skali stawiamy Nomada. Rozwiązuje ten sam problem — „uruchom te usługi, pilnuj ich, restartuj i aktualizuj bez przestojów” — a da się go ogarnąć w kilka dni.
Co robimy
Typowy układ na 3–10 serwerach (dedyki w OVH lub Hetznerze albo maszyny wirtualne na Proxmoksie):
- Serwery Nomada — trzy węzły z konsensusem Raft. Decydują, co gdzie ma działać. Jeden serwer też zadziała, ale wtedy jest pojedynczym punktem awarii.
- Klienci Nomada — pozostałe maszyny, na których działają wasze zadania. W małych klastrach obie role często dzielą te same węzły.
- Consul — katalog usług i health checki. Każda usługa sama się rejestruje, a inne znajdują ją po nazwie, nie po IP.
- Traefik — reverse proxy na wejściu. Czyta katalog Consula i sam buduje routing: pojawia się nowa usługa, Traefik już wie, dokąd kierować ruch. Certyfikaty Let’s Encrypt też załatwia sam.
- Sekrety — Nomad Variables w prostych przypadkach albo Vault, jeśli potrzebne są dynamiczne hasła do bazy, rotacja i audyt.
- Prometheus i Grafana — metryki Nomada, Consula, Traefika i samych aplikacji, alerty.
Maszyny tworzymy Terraformem, konfigurujemy Ansiblem, a job-pliki Nomada trzymamy w tym samym repozytorium infrastruktury. Cały klaster jest opisany kodem i da się go odtworzyć od zera.
Dlaczego Nomad i jak to działa
Nomad to jedna binarka. Serwer i klient to ten sam plik, różni je tylko konfiguracja. Aktualizacja polega na podmianie pliku i restarcie usługi po kolei na każdym węźle.
Zadania opisuje się w HCL, co czyta się prościej niż stos manifestów YAML. Fragment job-pliku z wdrożeniem canary:
group "api" {
count = 3
update {
max_parallel = 1
canary = 1
auto_promote = true
auto_revert = true
}
service {
name = "shop-api"
port = "http"
tags = ["traefik.enable=true"]
check {
type = "http"
path = "/health"
interval = "10s"
timeout = "2s"
}
}
}
Przy aktualizacji Nomad najpierw stawia jedną nową kopię obok starych. Jeśli /health odpowiada poprawnie, wymienia kopie po jednej. Jeśli nowa wersja nie wstaje, Nomad sam wraca do poprzedniej. Nikt nie musi robić rollbacku w nocy.
Poza Dockerem Nomad uruchamia też zwykłe binarki przez sterowniki exec (z izolacją) i raw_exec (bez niej). Przydaje się, gdy część systemu to stara usługa w Javie albo binarka w Go, której nie ma sensu pakować w kontener.
Traefika zwykle instalujemy jako osobną usługę systemd na węzłach brzegowych, a nie jako zadanie w Nomadzie. Wejście do systemu nie zależy wtedy od schedulera: nawet gdy klaster ma gorszy dzień, proxy działa.
Deploy z GitLab CI to build obrazu i nomad job run z nowym tagiem. Wcześniej nomad job plan pokazuje, co dokładnie się zmieni. Token CI ma uprawnienia tylko do swojego namespace’u, nie do całego klastra.
Kompromisy, o których trzeba wiedzieć
Mniejszy ekosystem. Dla Kubernetesa jest chart Helma prawie na wszystko. Dla Nomada wiele rzeczy piszemy sami. Job-plik na 40 linii to nie dramat, ale to jednak praca.
Licencja. W 2023 roku HashiCorp przeniósł Nomada, Consula, Vaulta i Terraforma z MPL na BSL. Przy użyciu we własnej infrastrukturze zwykle nic to nie zmienia — ograniczenia dotyczą tych, którzy chcą sprzedawać konkurencyjny produkt. Warto jednak o tym wiedzieć. W nowych projektach rozważamy OpenTofu zamiast Terraforma i OpenBao zamiast Vaulta.
Kiedy jednak Kubernetes. Jeśli zespół zna już k8s, planujecie dziesiątki serwerów i setki usług albo potrzebujecie operatorów do baz danych czy gotowych chartów od dostawcy — bierzcie Kubernetesa. Dla małego klastra jest k3s: pełny Kubernetes, tylko lżejszy w instalacji. Powiemy wprost, jeśli Nomad to zły wybór.
Bazy danych zwykle trzymamy poza orkiestratorem — na osobnych maszynach lub kontenerach LXC, z replikacją i backupami. Nomad świetnie radzi sobie z usługami bezstanowymi. Z danymi lepiej nie eksperymentować.
Co dostajecie
- Klaster Nomad + Consul z trzema serwerami, który przeżyje utratę węzła.
- Traefika na wejściu z automatycznymi certyfikatami i routingiem z katalogu Consula.
- Job-pliki waszych usług w Gicie, z wdrożeniami rolling lub canary i automatycznym rollbackiem.
- Pipeline w GitLab CI: build, sprawdzenie planu, deploy.
- Sekrety w Nomad Variables lub Vaulcie, a nie w plikach
.envna serwerach. - Prometheusa i Grafanę z dashboardami klastra i alertami.
- Kod Terraform i Ansible do odtworzenia klastra od zera.
- Dokumentację: jak wdrożyć nową usługę, jak zaktualizować klaster, co robić, gdy padnie węzeł.
- Dostępy administracyjne — klaster jest wasz, nie nasz.
Jeśli wasze usługi wyrosły z docker compose, a Kubernetes wydaje się przesadą, napiszcie do nas. Przejrzymy, co u was działa, i powiemy, czy Nomad pasuje — albo co lepiej wybrać.