Automatische Bereinigung von Docker-Cache-Volumes für GitLab Runner
Wie Sie das Problem ständig wachsender Docker-Volumes für den GitLab-Runner-Cache lösen und deren automatische Bereinigung einrichten.
In diesem Artikel
Das Problem
GitLab Runner legt bei Verwendung des Docker-Executors Volumes an, in denen der Cache zwischen den Builds gespeichert wird. Diese Volumes haben jedoch keinen eingebauten Mechanismus zur automatischen Bereinigung und können mit der Zeit gewaltige Ausmaße annehmen – Hunderte Gigabyte oder sogar Terabyte belegten Speicherplatzes sind keine Seltenheit.
Die Volumes können Sie mit folgendem Befehl anzeigen:
docker volume ls | grep runner
Ihre Größe ermitteln Sie mit:
for vol in $(docker volume ls -q | grep -E '^runner-.*-cache'); do
SIZE=$(docker run --rm -v "$vol":/data alpine du -sh /data 2>/dev/null | cut -f1)
echo "$SIZE $vol"
done
Eine typische Ausgabe kann so aussehen:
132G runner-yd6eca4h-project-100-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
124G runner-88bmy4dg2-project-100-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
29G runner-0558e6a41bfb19b22a086fc2330d186c-cache-3c3f060a0374fc8bc39395164f415a70
Beachten Sie die zwei unterschiedlichen Namensformate – ältere Versionen von GitLab Runner (vor 15.x) verwendeten einen 32-stelligen Hash, neuere Versionen verwenden das Format runner-{system_id}-project-{id}-concurrent-{n}.
Die Ursache
GitLab Runner legt neue Cache-Volumes an, wenn:
- sich der
cache:keyin der.gitlab-ci.ymländert - der Runner neu registriert wird (neue
system_id) - sich das Projekt oder der Branch ändert (abhängig von der Konfiguration des Cache-Keys)
Die alten Volumes bleiben jedoch auf der Festplatte und werden nicht automatisch gelöscht. Hinzu kommt, dass bei einer Neuregistrierung des Runners eine neue system_id entsteht und alle bisherigen Volumes "verwaist" zurückbleiben.
Die aktuelle system_id Ihres Runners ermitteln Sie mit:
cat /etc/gitlab-runner/.runner_system_id
Die Lösung
Einmalige Bereinigung
GitLab Runner enthält ein offizielles Skript zum Leeren des Caches. Unter Debian/Ubuntu ist es Teil des Pakets gitlab-runner und liegt unter /usr/share/gitlab-runner/clear-docker-cache.
/usr/share/gitlab-runner/clear-docker-cache
Das Skript bietet mehrere Optionen:
# Hilfe anzeigen
/usr/share/gitlab-runner/clear-docker-cache help
# Entfernt nur verwaiste Volumes (Standard)
/usr/share/gitlab-runner/clear-docker-cache prune-volumes
# Entfernt alle Runner-Cache-Volumes
/usr/share/gitlab-runner/clear-docker-cache space
Das offizielle Skript enthält einen Workaround für eine Verhaltensänderung in Docker 23.0, der die API-Version künstlich auf 1.41 herabsetzt. Bei neueren Docker-Versionen (API 1.44+) führt das zu einem Fehler, z. B.:
Error response from daemon: client version 1.41 is too old. Minimum supported API version is 1.44
Verwenden Sie in diesem Fall direkt die Docker-Befehle:
# Entfernt Volumes mit dem GitLab-Runner-Label
docker volume prune -f --filter "label=com.gitlab.gitlab-runner.managed=true"
Zum manuellen Löschen aller Cache-Volumes:
docker volume ls -q | grep -E '^runner-.*-cache' | xargs -r docker volume rm
Automatische Bereinigung per Cron
Für eine regelmäßige Bereinigung legen Sie die Datei /etc/cron.d/gitlab-runner-cache-cleanup an:
# Entfernt jeden Sonntag um 3:00 Uhr ungenutzte Runner-Cache-Volumes
0 3 * * 0 root docker volume prune -f --filter "label=com.gitlab.gitlab-runner.managed=true" >> /var/log/gitlab-runner-cache-cleanup.log 2>&1
Vorbeugung
Um das Wachstum des Caches direkt in den Projekten zu begrenzen, können Sie in der .gitlab-ci.yml ein Ablaufdatum festlegen:
cache:
key:
files:
- package-lock.json # neuer Cache nur bei Änderung der Dependencies
paths:
- node_modules/
expire_in: 1 week
Die Einstellung expire_in wirkt allerdings nur auf Ebene des GitLab-Servers, nicht auf Ebene der Docker-Volumes. Um die Größe auf Runner-Ebene tatsächlich zu begrenzen, ist die oben beschriebene Bereinigung erforderlich.