According to the update stanza, the parameter max_parallel applies for tasks within a group.
The doc also states that The task groups themselves are updated in parallel
I was wondering if there is a way to update groups within a single job separately, using stagger.
Meaning, a job with 3 groups will wait X between updating groups 1-3.
The update stanza can be used to control how the deployment progresses in exactly the manner you describe. The rolling update Learn guide has more information on this along with examples that could be useful.
This is obviously a very old thread, but the lack of this feature seems to still exist today.
One use case for sequential group deployments is when running workloads that are clustered applications with quorum implementations. In my case I came across this now when trying to deploy RustFS, it needs 4 unique nodes and listens to port 9000 and 9001 with each container. This means that you can’t put all the allocations into one group because the same port can’t be in the network namespace four times, and you have to instead spread them out by using a dynamic group block to create 4 unique groups with unique network namespaces.
This all however fails completely when deploying any change to the environment variables or other config for the allocations, as they will indeed get replaced all at the same time instead of a controlled rolling update due to the lack of options for group rollouts.
I don’t necessarily think you need four groups for this. Allocations in one group can all use the same static port. The only conflict is two of them landing on the same node, and distinct_hosts handles that:
hcl
group "rustfs" {
count = 4
constraint {
operator = "distinct_hosts"
value = "true"
}
update {
max_parallel = 1
health_check = "checks"
min_healthy_time = "30s"
healthy_deadline = "5m"
}
network {
port "api" { static = 9000 }
port "console" { static = 9001 }
}
service {
name = "rustfs"
port = "api"
# Use whatever endpoint only passes once the node is back in the cluster
check {
type = "http"
path = "/health"
interval = "10s"
timeout = "2s"
}
}
task "rustfs" {
driver = "docker"
config {
image = "rustfs/rustfs:<version>"
volumes = ["/opt/rustfs/data-${NOMAD_ALLOC_INDEX}:/data"]
}
}
}
With one group, update { max_parallel = 1 } gets you the rolling update back. It’s the four separate groups that make everything get replaced at once. If each member needs its own identity or data dir, use ${NOMAD_ALLOC_INDEX} (0-3).
One caveat: by default the rollout moves on once a task has been running for min_healthy_time, not once that member has rejoined the cluster. Use health_check = “checks” with a check that only passes when the node is back in quorum.
I run postgres with patroni more or less the same way if you want to see something similar that is working for me right now:
the redis-sentinel job in that repo has some similar concepts but I think the patroni one is probably closer to what you are describing