Files
obsidian/history/2026-05-02-longhorn-snapshot-purge-cron.md

131 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
date: 2026-05-02
topic: Longhorn stuck snapshot cleanup workaround
areas: [infra/platform/longhorn]
---
# 2026-05-02 / Longhorn snapshot-purge cron 도입
## 배경
Longhorn v1.11.1 에서 instance-manager 재시작(2026-05-02 09:00 UTC 즈음) 후 12개 snapshot CR 이 다음 패턴으로 stuck:
- `status.markRemoved = true`
- `status.readyToUse = false`
- `status.ownerID = ""`
- `metadata.finalizers = ["longhorn.io"]`
ownerID 가 비어 longhorn-manager controller 가 이 CR 들을 reconcile 하지 않음. 수동 `kubectl delete` / finalizer patch 는 admission webhook(`admission.go:115`) 이 즉시 finalizer 를 다시 추가해 무력화.
근본 원인은 v1.11.1 의 ownerId-loss 회귀로 추정. 1.11.2 / 1.12 에서 fix 예상. 임시로 snapshotPurge API 를 cron 으로 주기 호출.
## stuck 12개 식별
```
pvc-0440758f-f056-46d0-9733-dbb77f2e9101 (snapshot 1e632239-...)
pvc-15af4f6d-6129-4858-ae51-a3aa3546c4c2 (snapshot d95f165a-...)
pvc-384dd143-05b6-4cd6-a0dd-3edf5dca3acc (snapshot a8f0cbfd-...)
pvc-3c39ef90-d8ea-402d-8363-772ddbaf56a2 (snapshot 8f80ed9d-...)
pvc-411b3be5-ce8f-4039-a73e-d9b1e61a07de (snapshot 545f2ca5-...)
pvc-4d4cb56b-7be8-43ac-80be-5367cacd625a (snapshot 26dbf46f-...)
pvc-573db32c-f3fa-494e-8e1f-9f899938ec40 (snapshot 300158d8-...)
pvc-8534d9f3-91b9-49c3-9acd-804581c51893 (snapshot ef714f28-...)
pvc-8f9bfed6-236d-49d3-94d9-41880c351059 (snapshot b700b4d7-...)
pvc-bc38d860-0bc5-4b49-ab19-2586e0f78515 (snapshot 2581dac8-...)
pvc-c702c67d-7c5d-47d5-8814-b13fff45cbe7 (snapshot d43c685b-...)
pvc-f4b8b3b4-1a51-45a7-a460-422f9fca023f (snapshot cd9c36a3-...)
```
12 snapshot ↔ 12 volume (1:1).
## 도입 단계
### Chart 작성 + push
`gitea.inouter.com/kaffa/helm-charts` · `charts/longhorn-snapshot-purge/` 생성.
- `Chart.yaml`: name longhorn-snapshot-purge, version 0.1.0
- `values.yaml`: schedule `*/30 * * * *`, image `alpine/k8s:1.32.1`, longhornFrontendUrl http://longhorn-frontend.longhorn-system.svc.cluster.local
- `templates/serviceaccount.yaml`: SA `longhorn-snapshot-purge`
- `templates/role.yaml`: Role + RoleBinding (snapshots.longhorn.io get/list, ns-scoped)
- `templates/cronjob.yaml`: CronJob with kubectl + curl shell script
commit: `0edf886 Add longhorn-snapshot-purge chart for stuck snapshot cleanup`
fix commit: `d75c9a6 longhorn-snapshot-purge: query in-namespace to match Role scope` (`-A``-n longhorn-system` — RBAC scope mismatch 수정)
### ArgoCD Application 생성
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: longhorn-snapshot-purge
namespace: argocd
spec:
destination: { namespace: longhorn-system, server: https://kubernetes.default.svc }
project: default
source:
path: charts/longhorn-snapshot-purge
repoURL: https://gitea.inouter.com/kaffa/helm-charts.git
targetRevision: HEAD
syncPolicy:
automated: { prune: true, selfHeal: true }
```
`Synced/Healthy` 도달.
### 수동 트리거 검증
```
kubectl -n longhorn-system create job --from=cronjob/longhorn-snapshot-purge \
longhorn-snapshot-purge-manual-2
[2026-05-02T06:14:55Z] longhorn-snapshot-purge starting
stuck snapshot owner volumes (deduped): 12
ok pvc-0440758f-... (HTTP 200)
ok pvc-15af4f6d-... (HTTP 200)
ok pvc-384dd143-... (HTTP 200)
ok pvc-3c39ef90-... (HTTP 200)
ok pvc-411b3be5-... (HTTP 200)
ok pvc-4d4cb56b-... (HTTP 200)
ok pvc-573db32c-... (HTTP 200)
ok pvc-8534d9f3-... (HTTP 200)
ok pvc-8f9bfed6-... (HTTP 200)
ok pvc-bc38d860-... (HTTP 200)
ok pvc-c702c67d-... (HTTP 200)
ok pvc-f4b8b3b4-... (HTTP 200)
[2026-05-02T06:15:03Z] longhorn-snapshot-purge done (rc=0)
```
snapshotPurge 12/12 HTTP 200. job 8 초 내 완료 (rc=0).
### snapshotPurge 한계 확인
`POST snapshotList` 로 첫 stuck volume 의 engine snapshot 상태 검사:
```json
{"data":[
{"id":"volume-head", "parent":"1e632239-...", "removed":false},
{"id":"1e632239-...", "parent":"", "removed":true, "size":"51265536"}
]}
```
- `1e632239-...` 가 chain 의 유일 snapshot, volume-head 의 직속 parent
- `removed=true` 마킹은 됐으나 **.img 파일은 미정리** (chain merge 대상 없음)
- snapshotPurge 는 chain 중간의 redundant snapshot 만 합치므로 leaf snapshot 은 정리 불가
- 따라서 stuck snapshot CR 12 → 12 그대로 (5분 대기 후 재확인)
### 결론
- cron 은 사용자 요건 (3) "snapshotPurge API 매 30분 자동 호출" 을 정확히 수행
- engine 의 chain redundancy 가 발생하면 정리 — 향후 같은 볼륨에 추가 snapshot 이 쌓일 때 효과
- 단일 leaf stuck snapshot 들은 v1.11.2 / v1.12 업그레이드로 manager 가 reconcile 회복할 때까지 그대로 잔존
- 디스크 사용량은 12 × ~50MiB ≈ 600MiB 수준 — 운영 임팩트 무시 가능
- 향후 새 stuck 이 생기더라도 cron 이 자동 처리
## 후속
- v1.11.2 또는 v1.12 출시 → 표준 minor 순차 업그레이드 절차로 진행
- 업그레이드 완료 후 `kubectl -n argocd delete application longhorn-snapshot-purge` 로 cron 회수 (chart 디렉토리는 repo 에 보존)
- 만약 disk 회수가 시급한 stuck 이 발생하면 ownerID 강제 부여 patch + delete 흐름 도입 검토 — admission webhook 우회 필요해 별도 작업