Install Nomad, Podman, and Traefik for Home Selfhosting
Background #
Nomad is a scheduler developed by Hashicorp, which can be used to schedule containers, raw execution, and other applications. This unique feature makes Nomad capable of running various types of applications, not just containers through the Task Driver concept.
Prerequisites #
Knowledge Requirements #
- Basic understanding of containerization (Docker, Podman, etc.)
- Basic knowledge about Load balancer (Traefik)
Required Environment #
What needs to be prepared:
- Host server with Ubuntu 21.04 OS
- hashi-up - CLI tool to simplify the installation process
Important Notes #
- Installation will be done in single-node mode
- The Nomad server will serve dual purposes:
- As a server
- As a client to run workloads
- This mode is chosen to reduce resource requirements
Installation #
Make sure the target server can be accessed via SSH key. Then run the following command:
hashi-up nomad install \
--ssh-target-addr 192.168.1.10 \
--ssh-target-user ubuntu \
--ssh-target-key ~/.ssh/id_ed25519 \
--serverPlease make sure to replace the IP, user, and SSH key address according to your environment.
Podman Task Driver #
Podman is one of the task drivers supported by Nomad. Why choose Podman? Because recently I’ve been using Podman as my daily driver. The installation process can follow the guide from Nomad’s official documentation on this page.
Additionally, make sure Podman is already installed.
sudo apt install podmanNext, we need to ensure that Nomad recognizes this plugin.
sudo vim /etc/nomad.d/nomad.hclAdd the following lines.
# generated with hashi-up
datacenter = "dc1"
data_dir = "/opt/nomad"
plugin_dir = "/opt/nomad/data/plugins"
server {
enabled = true
bootstrap_expect = 1
}
plugin "nomad-driver-podman" {
enabled = true
} Restart the Nomad server.
sudo systemctl restart nomadMake sure the plugin appears in the task driver section.
nomad node status -self -short | grep Drivers
CSI Drivers = <none>
Drivers = exec,podmanNomad Single Node #
To run Nomad as a single-node, we need to enable client mode
on this Nomad server. Edit the file /etc/nomad.d/nomad.hcl again and add
the following lines:
# generated with hashi-up
datacenter = "dc1"
data_dir = "/opt/nomad"
plugin_dir = "/opt/nomad/data/plugins"
server {
enabled = true
bootstrap_expect = 1
}
client {
enabled = true
} Don’t forget to restart the nomad service
Traefik and Nomad service discovery #
Open nomad webui through your browser, usually at http://192.168.1.10:4646/ui. Then
click the “Run job” button and add the following job specification:
job "traefik" {
datacenters = ["dc1"]
type = "service"
group "traefik" {
count = 1
network {
port "http" {
static = 8080
}
port "admin" {
static = 8081
}
}
service {
name = "traefik-http"
provider = "nomad"
port = "http"
}
task "server" {
driver = "podman"
config {
image = "docker.io/traefik:v2.11.20"
ports = ["admin", "http"]
args = [
"--api.dashboard=true",
"--api.insecure=true", # Traefik will be installed in insecure mode, preferably not exposed to the internet
"--entrypoints.web.address=:${NOMAD_PORT_http}",
"--entrypoints.traefik.address=:${NOMAD_PORT_admin}",
"--providers.nomad=true",
"--providers.nomad.endpoint.address=http://${NOMAD_IP_http}:4646",
"--providers.nomad.exposedByDefault=false"
]
}
}
}
}Deploy demo application #
Next, we’ll deploy an application that demonstrates simple load balancing through Traefik that is already connected to Nomad service discovery.
job "demo-webapp" {
datacenters = ["dc1"]
group "demo" {
count = 3
network {
port "http"{
to = -1
}
}
service {
name = "demo-webapp"
port = "http"
provider = "nomad"
tags = [
"traefik.enable=true",
"traefik.http.routers.demo-webapp-http.rule=Host(`demo-webapp-192-168-1-10.nip.io`)",
"traefik.http.routers.demo-webapp-http.tls=false",
]
check {
type = "http"
path = "/"
interval = "2s"
timeout = "2s"
}
}
task "server" {
env {
PORT = "${NOMAD_PORT_http}"
NODE_IP = "${NOMAD_IP_http}"
}
driver = "podman"
config {
image = "docker.io/hashicorp/demo-webapp-lb-guide"
ports = ["http"]
}
}
}
}After the above job is run, the demo-webapp application will go through the
Load balancing process by Traefik first, then be directed to each container.
ubuntu@nomad01:~$ curl http://demo-webapp-192-168-1-10.nip.io:8080
Welcome! You are on node 192.168.1.10:20190
ubuntu@nomad01:~$ curl http://demo-webapp-192-168-1-10.nip.io:8080
Welcome! You are on node 192.168.1.10:25458
ubuntu@nomad01:~$ curl http://demo-webapp-192-168-1-10.nip.io:8080
Welcome! You are on node 192.168.1.10:25482
ubuntu@nomad01:~$ curl http://demo-webapp-192-168-1-10.nip.io:8080
Welcome! You are on node 192.168.1.10:20190As you can see, responding to our requests are several containers each with different ports, those ports are allocated by Nomad dynamically.
That’s the short tutorial, in the next article I will discuss how to run stateful applications like databases with host volumes in Nomad.