mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
update_config never set failure_action, so swarmkit's default applied: pause, at a max_failure_ratio of zero. One failed task stops the rollout for good, and nothing in the deploy resumes it. That contradicts the restart_policy three lines below. The policy replaces the task and the service ends up healthy, while the update status stays latched and service_converged.sh reads that status before it looks at any task, so the deploy reports a failure over a service that is running. The rescue artifact shows the sequence: the old task shut down, its replacement tripped over a containerd object runsc could not reap, and the third task was Running while the job died on "update latched". Four swarm jobs failed that way, all in the update pass, never in the first. The convergence check is untouched and stays as strict as it was: a genuinely broken spec fails every task and still trips "tasks not running yet". What this does give up: the latch was also the only thing catching a service that keeps crash-looping. At ratio zero any failure latched, so a task dying and restarting forever was guaranteed to be reported. Now the rollout completes, and the check samples task state at one moment - a task on its fiftieth restart still reads as Running, and wait_converged's `until` needs a single lucky sample. Restoring that detection needs the check to look at task churn, which the service ps history already carries and the script prints only on failure today. Not in this commit. max_failure_ratio cannot substitute here: at replicas 1, the common case in this repository, one failure is always the whole service. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
51 lines
2.3 KiB
Django/Jinja
51 lines
2.3 KiB
Django/Jinja
{% if compose_mode == 'swarm' %}
|
|
{{ "\n" }}
|
|
{% if service_replicas_forced is defined %}
|
|
{% set _replicas = service_replicas_forced %}
|
|
{% else %}
|
|
{% set _replicas = lookup('applications') | resource_filter(application_id, 'replicas', service_name | default(''), '') %}
|
|
{% endif %}
|
|
deploy:
|
|
{{ lookup('compose_replicas', _replicas) if _replicas != '' else lookup('compose_replicas') }}
|
|
{% set _constraints = [] %}
|
|
{% if application_id in lookup('roles_with_placement', 'manager') %}
|
|
{% set _ = _constraints.append('node.role == manager') %}
|
|
{% endif %}
|
|
{% set _arch = lookup('applications') | resource_filter(application_id, 'platform_arch', service_name | default(''), '') %}
|
|
{% if _arch != '' %}
|
|
{% set _ = _constraints.append('node.platform.arch == ' ~ _arch) %}
|
|
{% endif %}
|
|
{% if groups['svc-virt-kata'] is defined %}
|
|
{% if lookup('config', application_id, 'services.kata.enabled', false) | bool %}
|
|
{% set _ = _constraints.append('node.labels.' ~ SANDBOX_NODE_LABEL ~ ' == true') %}
|
|
{% else %}
|
|
{% set _ = _constraints.append('node.labels.' ~ SANDBOX_NODE_LABEL ~ ' != true') %}
|
|
{% endif %}
|
|
{% endif %}
|
|
{% if _constraints | length > 0 %}
|
|
placement:
|
|
constraints:
|
|
{% for _constraint in _constraints %}
|
|
- {{ _constraint }}
|
|
{% endfor %}
|
|
{% endif %}
|
|
update_config:
|
|
parallelism: {{ service_update_parallelism | default(1) }}
|
|
delay: {{ service_update_delay | default('10s') }}
|
|
failure_action: continue
|
|
{% if service_update_order is defined %}
|
|
order: {{ service_update_order }}
|
|
{% endif %}
|
|
restart_policy:
|
|
condition: {{ docker_restart_policy | default(DOCKER_RESTART_POLICY) | swarm_restart_condition }}
|
|
resources:
|
|
limits:
|
|
cpus: "{{ lookup('applications') | resource_filter(application_id, 'cpus', service_name | default(''), RESOURCE_CPUS) | string }}"
|
|
memory: {{ lookup('applications') | resource_filter(application_id, 'mem_limit', service_name | default(''), RESOURCE_MEM_LIMIT) }}
|
|
pids: {{ lookup('applications') | resource_filter(application_id, 'pids_limit', service_name | default(''), RESOURCE_PIDS_LIMIT) }}
|
|
{% if RUNTIME != 'github' %}
|
|
reservations:
|
|
memory: {{ lookup('applications') | resource_filter(application_id, 'mem_reservation', service_name | default(''), RESOURCE_MEM_RESERVATION) }}
|
|
{% endif %}
|
|
{% endif %}
|