fix(ansible): the swarm prune never runs a docker prune that touches images; it lives in its own folder (#6399)
The first applied run lost VDNT-Docker03 29 images (10.4 GB) before its script ran. Its `docker system prune` removes dangling images, and Docker counts an image with no tag as dangling: every image a swarm task pulled by digest. Docker03 was left holding only its own tasks' images, as under the old prune. Nothing went down, since a running container's image can't be removed. - Step 1 now prunes containers, networks, build cache and (prune_volumes) volumes one by one. Every image decision is left to the script, which keeps the images services are pinned to. - A test guards against any image-pruning command in the playbook. - The playbook moves to maintenance/swarm_prune/, with its script in that folder's files/, so a helper's name can't collide with another playbook's (the operator's direction for playbooks with helpers). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Steward's swarm prune (maintenance/swarm_prune.yml), run on each node.
|
||||
"""Steward's swarm prune (maintenance/swarm_prune/swarm_prune.yml), run on each node.
|
||||
|
||||
Removes the images on this node that no swarm service is pinned to and no
|
||||
container uses (by id, or by the reference it was made from), and keeps every image a service is pinned to even when its
|
||||
+19
-11
@@ -4,10 +4,11 @@
|
||||
# steward:confirm: true
|
||||
# Run on the swarm's nodes; each must be a manager (only a manager can list
|
||||
# services). On each node:
|
||||
# 1. docker system prune: stopped containers, unused networks, dangling
|
||||
# images, build cache (+ prune_volumes=true: unused anonymous volumes).
|
||||
# 2. files/swarm_prune.py: removes every other image no container uses and
|
||||
# no swarm service is pinned to, wherever that service's task runs. A
|
||||
# 1. Stopped containers, unused networks and build cache are pruned
|
||||
# (+ prune_volumes=true: unused anonymous volumes). No image is: Docker
|
||||
# calls an untagged image dangling, and swarm pulls by digest, untagged.
|
||||
# 2. files/swarm_prune.py: removes every image no container uses and no
|
||||
# swarm service is pinned to, wherever that service's task runs. A
|
||||
# node keeps the images for the services running elsewhere, so it can
|
||||
# start them at once when the other node fails or is drained.
|
||||
# A node that can't list the swarm's services removes no images and the run
|
||||
@@ -19,13 +20,19 @@
|
||||
vars:
|
||||
prune_volumes: false
|
||||
tasks:
|
||||
- name: Prune stopped containers, unused networks, dangling images and build cache
|
||||
# Never `docker system prune` or `docker image prune`: Docker counts an
|
||||
# image with no tag as dangling, and every image a swarm task pulled by
|
||||
# digest has none. Images are left to the script below.
|
||||
- name: Prune stopped containers, unused networks and build cache
|
||||
ansible.builtin.command:
|
||||
argv: >-
|
||||
{{ ['docker', 'system', 'prune', '-f']
|
||||
+ (['--volumes'] if prune_volumes | bool else []) }}
|
||||
register: system_prune
|
||||
changed_when: "'Total reclaimed space: 0B' not in system_prune.stdout"
|
||||
argv: "{{ item }}"
|
||||
loop: >-
|
||||
{{ [['docker', 'container', 'prune', '-f'],
|
||||
['docker', 'network', 'prune', '-f'],
|
||||
['docker', 'builder', 'prune', '-f']]
|
||||
+ ([['docker', 'volume', 'prune', '-f']] if prune_volumes | bool else []) }}
|
||||
register: cleanup
|
||||
changed_when: "'Total reclaimed space: 0B' not in cleanup.stdout and cleanup.stdout | trim | length > 0"
|
||||
|
||||
- name: Remove images no container uses and no swarm service is pinned to
|
||||
ansible.builtin.script:
|
||||
@@ -39,5 +46,6 @@
|
||||
- name: Report what went
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{ (system_prune.stdout_lines | default([]) | select | list)[-1:]
|
||||
{{ (cleanup.results | default([]) | map(attribute='stdout', default='')
|
||||
| select('search', 'reclaimed') | list)
|
||||
+ [image_prune.stdout | from_json] }}
|
||||
Reference in New Issue
Block a user