Slomad
Provides a minimal interface to the Nomad API, facilitating the planning and deployment of Nomad jobs.
Summary
The slomad
Go module is a key component of my lab setup. This package is specifically designed for use in my lab environment, though the general approach is applicable to any Nomad cluster. The focus is on simplicity and ease of use, it generates valid Job specs from a type definition and set of defaults, also responsible for deploying those jobs to the cluster.
It’s been a great project to work on, and I’ve gone through a number of iterations trying out different file organization patterns and tools to manage the deploys. It’s tailor made to address my workflow and needs. The main goal being to have a simple easy to understand job definition, and a straightforward way to deploy those jobs to the cluster.
Details
Job Type Definition
The Job type is leaner than the official Nomad API definition, and is designed to be used as a template for generating job specs. The Job type is defined as follows:
type Job struct {
Name string
Type JobType
Shape TaskResource
Target DeployTarget
Priv bool
Ports []*Port
Volumes []Volume
Args []string
Env map[string]string
User string
Templates map[string]string
GroupServices map[string]string
TaskServiceTags map[string][]string
}
Allowing for the following basic job definition:
var SpeedtestJob = smd.Job{
Name: "speedtest",
Type: smd.SERVICE,
Target: smd.NODE,
Ports: smd.BasicPortConfig(80),
Shape: smd.XTINY_TASK,
}
For examples of how I define jobs with slomad
, check out the registry/ directory and take a look around!
Memorable Challenges
- In the past when I ran a multi-node cluster configuring persistent shared storage was a nightmare, hence some bespoke handling of storage volume creation and mounting. There’s still some work to be done here, but it’s much better than it was.
- I was never quite able to get a Job spec for Traefik to generate correctly, so I did that one manually, though it’s not currently used.
Appendix
Job type definition from official Nomad go docs1:
type Job struct {
Region *string `hcl:"region,optional"`
Namespace *string `hcl:"namespace,optional"`
ID *string `hcl:"id,optional"`
Name *string `hcl:"name,optional"`
Type *string `hcl:"type,optional"`
Priority *int `hcl:"priority,optional"`
AllAtOnce *bool `mapstructure:"all_at_once" hcl:"all_at_once,optional"`
Datacenters []string `hcl:"datacenters,optional"`
NodePool *string `mapstructure:"node_pool" hcl:"node_pool,optional"`
Constraints []*Constraint `hcl:"constraint,block"`
Affinities []*Affinity `hcl:"affinity,block"`
TaskGroups []*TaskGroup `hcl:"group,block"`
Update *UpdateStrategy `hcl:"update,block"`
Multiregion *Multiregion `hcl:"multiregion,block"`
Spreads []*Spread `hcl:"spread,block"`
Periodic *PeriodicConfig `hcl:"periodic,block"`
ParameterizedJob *ParameterizedJobConfig `hcl:"parameterized,block"`
Reschedule *ReschedulePolicy `hcl:"reschedule,block"`
Migrate *MigrateStrategy `hcl:"migrate,block"`
Meta map[string]string `hcl:"meta,block"`
ConsulToken *string `mapstructure:"consul_token" hcl:"consul_token,optional"`
VaultToken *string `mapstructure:"vault_token" hcl:"vault_token,optional"`
Stop *bool
ParentID *string
Dispatched bool
DispatchIdempotencyToken *string
Payload []byte
ConsulNamespace *string `mapstructure:"consul_namespace"`
VaultNamespace *string `mapstructure:"vault_namespace"`
NomadTokenID *string `mapstructure:"nomad_token_id"`
Status *string
StatusDescription *string
Stable *bool
Version *uint64
SubmitTime *int64
CreateIndex *uint64
ModifyIndex *uint64
JobModifyIndex *uint64
}