Repository navigation
feat(argo): auto-GC orphaned workflow workdir PVCs (B+C) - #384
Conversation
Two layers so failed workflows stop stranding their `workdir` PVCs (and the backing Hetzner volumes): B) workflowDefaults.spec.volumeClaimGC.strategy=OnWorkflowCompletion in the argo-workflows Helm values. Argo's default OnWorkflowSuccess retains the PVC on failure; ttlStrategy then GCs the Workflow, orphaning the PVC forever. C) argo-pvc-janitor CronJob (hourly) as a backstop: deletes a `*-workdir` PVC only when no pod mounts it AND its owning Workflow is gone or terminal (Succeeded/Failed/Error). Running/pending workflows are kept, so it never races a live workflow. Uses alpine/k8s (not the retired bitnami/kubectl). WHY: several failed mctl-agents issue-poll runs left 10Gi workdir PVCs stranded (observed + cleaned manually this week). B fixes the cause; C catches strays and pre-existing orphans.
|
Claude finished @mashkovd's task in 1m 59s —— View job Code Review: Auto-GC Orphaned Workflow Workdir PVCsReview Checklist:
Detailed Analysis1. volumeClaimGC Configuration (argo-workflows.yaml) 2. PVC Janitor Manifest (pvc-janitor.yaml) RBAC & Security: Operational Safety: Janitor Logic: Shell Script Edge Cases: 3. Deployment Mechanism SummaryVerdict: No P1/P2 findings. Good to merge. Both layers of the fix are well-designed and operationally safe:
Post-merge verification (from PR description) is straightforward: confirm configmap setting, run a failed workflow, verify janitor CronJob exists and logs keep/DELETE decisions. |
Problem
Failed Argo workflows strand their per-workflow
workdirPVCs (and the backing 10Gi Hetzner volumes) permanently. Argo's defaultvolumeClaimGC.strategy: OnWorkflowSuccessretains the volumeClaimTemplate PVC when a workflow fails;ttlStrategythen GCs the Workflow object, leaving the PVC with no owner → it lingers forever. Several failedmctl-agentsissue-poll runs left 10Gi orphans (cleaned manually this week).Fix — two layers
B) Cause fix (controller default).
platform-gitops/bootstrap/templates/core-infra/argo-workflows.yaml— add tocontroller.workflowDefaults.spec:Deletes the
workdirPVC on completion regardless of success/failure. Inherited by every workflow that doesn't override it (none do). The valuable output (proposals) is pushed to git before failure and logs go to Loki, so losing the scratch clone on failure is fine.C) Backstop janitor.
platform-gitops/argo-workflows/config/pvc-janitor.yaml— SA + Role + RoleBinding + hourly CronJob. Deletes a*-workdirPVC only when both: no pod mounts it and its owning Workflow is gone or terminal (Succeeded/Failed/Error). Running/pending (incl. just-submitted, empty-phase) workflows are kept, so it never races a live workflow. Catches strays B might miss (force-deleted/TTL-GC'd workflows) and pre-existing orphans.Safety notes
argo-workflowsand only targets*-workdirPVCs — can't touch minio/vault/pg/VM volumes.alpine/k8s:1.33.12, not the retiredbitnami/kubectl(which silently wedges on ImagePullBackOff — same trap that broke vault-auto-unseal).concurrencyPolicy: Forbid+ttlSecondsAfterFinishedso janitor jobs don't pile up.Verify after merge
kubectl get cm -n argo-workflows workflow-controller-configmap -o yaml | grep -A1 volumeClaimGC→ OnWorkflowCompletion*-workdirPVC is deleted on completion (no orphan).kubectl get cronjob -n argo-workflows argo-pvc-janitorexists; first run logskeep/DELETEdecisions and completes.