history: Longhorn sftpgo corruption loop 해소 + snapshot 자동 retention 영구 수정

- sftpgo replica kr1 13분 주기 corruption loop → kr2 anti-affinity reschedule로 해소
- root cause: snapshot .checksum 누락 + chain meta 손상 (디스크 정상)
- 시스템 차원 발견: 906/906 snapshot이 recurring-job 라벨 누락
- snapshot 일괄 정리 906 → 194 (volume당 7~8개)
- RecurringJob 4개 spec.labels patch — 자동 retention 영구 수정
- 후속: ArgoCD/IaC 매니페스트 반영 필요
This commit is contained in:
kaffa
2026-06-01 11:38:19 +09:00
parent 156e1b2dce
commit fbb3506643

View File

@@ -0,0 +1,124 @@
---
date: 2026-06-01
topic: Longhorn sftpgo replica corruption loop 해소 + 시스템 차원 snapshot 자동 retention 영구 수정 (RecurringJob 라벨 누락)
areas: [infra/k3s, infra/storage/longhorn]
tags: [history, longhorn, k3s, sftpgo, snapshot, recurring-job, retention]
---
# 2026-06-01 / Longhorn snapshot retention 시스템 차원 수정
## 시작 — sftpgo replica corruption loop
Longhorn UI에 "Warning". 진단 결과 `sftpgo/sftpgo` PVC(1Gi, 실사용 50MB)의 kr1 replica가 13분 주기로 `Detected corrupted replica tcp://10.42.1.189:...` 마킹 → rebuild → 또 마킹 무한 반복.
| 항목 | 값 |
|---|---|
| 영향 PVC | `sftpgo/sftpgo` |
| Replica 분포 | kr1(❌) / hp1(✅) / hp2(✅) — 3-way |
| Corruption 마킹 출처 | longhorn-manager engine controller |
| 발생 간격 | ~13분 (rebuild 끝나자마자 또 fault) |
| 영향 워크로드 | sftpgo (실서비스 영향 0, 자동 rebuild로 데이터 0 손실) |
## 진단 — kr1 디스크는 정상
| 점검 | 결과 |
|---|---|
| kr1 dmesg (err/warn) | I/O 에러 0, NVMe 에러 0, ext4 에러 0. systemd-sysv 잡소리만 |
| kr1 디스크 용량 | nvme0n1 28% (247G/937G), `/var/lib/longhorn` 114G — 여유 충분 |
| kr1 uptime | 30일, 최근 재기동 없음 |
| kr1 위 다른 replica 18개 | 전부 running — 디스크 자체 정상 |
| iSCSI 5/27 SCSI reset 1회 | 무관 |
**하드웨어 이슈 아님**. Longhorn chain 레벨의 메타데이터 손상 의심.
## Root cause 추적
instance-manager-kr2 (rebuild 시) 로그에서 핵심 단서:
```
level=error msg="Failed to get recorded metadata for file volume-snap-snapshot-...img"
error="failed to open checksum file: ...img.checksum: no such file or directory"
```
= snapshot의 `.checksum` 파일이 source 측에 누락. snapshot-data-integrity(`fast-check`)가 checksum 기반으로 비교하는데 일부 snapshot에 checksum 부재 → integrity check fail → "corrupted" 마킹 → rebuild → 같은 chain을 source에서 받음 → 또 fail → 루프.
sftpgo만의 특별한 원인은 없음 (다른 25개 volume도 더 많은 snapshot 보유, 같은 환경). **우연한 chain 메타 손상이 first cause, integrity check가 루프 증폭**.
## 해소 절차
1. Volume의 orphan `recurring-job-group.longhorn.io/default=enabled` 라벨 제거 (정의 안 된 group)
2. kr1 replica `r-750f60ae` 명시적 삭제
3. → Longhorn anti-affinity가 kr1을 회피해 **kr2에 새 replica `r-4cee3e8e` 생성**
4. fresh chain을 hp1에서 sync → 39 snapshot 모두 새로 받음
5. Volume robustness: degraded → healthy, RW 3-replica 안정화
6. 2분 post-healthy 관찰 — **재발 0**
## 시스템 차원 이슈 발견 — snapshot 자동 retention 깨짐
별건 점검에서 전체 906개 snapshot 모두 `recurring-job.longhorn.io/<job-name>` 라벨이 **없음**. 1시간 전 만든 신규 snapshot도 동일.
| 항목 | 데이터 |
|---|---|
| 전체 snapshot | 906개 |
| `recurring-job.longhorn.io/*` 라벨 보유 | **0개 (100% 누락)** |
| Longhorn 버전 | v1.11.2 |
| RecurringJob spec.labels | **`{}` (4개 모두 비어있음)** ← 원인 |
Longhorn RecurringJob retention 메커니즘:
- RecurringJob이 만든 snapshot에 자기 라벨(`recurring-job.longhorn.io/<job-name>=enabled`) 부착
- retention 시 그 라벨로 자기 소속 snapshot 식별 → retain 개수 외 삭제
`spec.labels`가 비어 있으면 snapshot에 라벨 안 붙음 → retention 동작 불가 → **모든 RecurringJob snapshot이 무한 누적**. 알려진 동작 (명시 안 하면 자동 안 붙임).
## 정리 — snapshot 906 → 194
각 volume에서 volume-head + 최신 7개 chain만 유지하고 나머지 일괄 delete (`kubectl delete snapshot.longhorn.io`). Longhorn finalizer가 chain coalesce 자동 처리.
| 지표 | Before | After |
|---|---|---|
| 전체 snapshot | 906 | **194** |
| volume당 평균 | ~35 | **7~8** |
| Volume robustness | 26 healthy | 26 healthy (변동 0) |
| 데이터 영향 | — | 0 (backup은 S3에 별도 보관) |
## 영구 수정 — RecurringJob 라벨 정책 patch
4개 RecurringJob에 자기 라벨을 `spec.labels`로 명시:
```bash
for j in critical-snapshot critical-backup standard-snapshot standard-backup; do
kubectl -n longhorn-system patch recurringjob.longhorn.io $j --type=merge \
-p "{\"spec\":{\"labels\":{\"recurring-job.longhorn.io/$j\":\"enabled\"}}}"
done
```
다음 cron 실행부터 새 snapshot에 라벨 붙음 → retention 자동 동작 시작.
| Job | spec.labels (After) |
|---|---|
| critical-snapshot | `recurring-job.longhorn.io/critical-snapshot: enabled` |
| critical-backup | `recurring-job.longhorn.io/critical-backup: enabled` |
| standard-snapshot | `recurring-job.longhorn.io/standard-snapshot: enabled` |
| standard-backup | `recurring-job.longhorn.io/standard-backup: enabled` |
## 검증 (예정)
다음 critical-snapshot 실행 (매시간 정각) 후:
```bash
kubectl -n longhorn-system get snapshots.longhorn.io --sort-by=.metadata.creationTimestamp -o json \
| jq -r '.items[-3:] | .[] | "\(.metadata.creationTimestamp) \(.metadata.name) \(.metadata.labels)"'
```
→ 새 snapshot에 `recurring-job.longhorn.io/critical-snapshot=enabled` 있으면 OK.
## 잔여 사항 / 후속
- RecurringJob 4개 spec.labels 수동 patch만 적용. **ArgoCD/IaC 매니페스트에도 같은 변경 반영 필요** (다음 sync에서 빈 spec.labels로 되돌아갈 위험)
- snapshot `.checksum` 파일 누락 패턴은 Longhorn 알려진 이슈일 가능성 — GitHub issue 검색 후 v1.11.3+ 업그레이드 시 해소되는지 확인 필요
- 같은 corruption loop가 다른 volume에서 재발 시 동일 절차 (anti-affinity 활용한 노드 회피 rebuild) 적용 가능
## 운영 메모
- 로컬 Mac Tailscale 데몬이 작업 중 멈춤(`Tailscale is stopped.`, 버전 mismatch 1.98.1 vs 1.96.5 의심). LAN 192.168.9.214 직접 접근으로 우회.
- 작업 중 임시 kubectl wrapper `/tmp/kk`: `kubectl --server=https://192.168.9.214:6443 --insecure-skip-tls-verify=true` (Tailscale 복구 후 폐기)
- 헤임달(10.100.3.108)은 작업 초반 진단만 위임, snapshot 정리는 kappa 직접 수행 (헤임달은 ops-agents 키가 kr1 sshd에 미등록이라 SMART 등 직접 진단 불가)
수행: kappa (직접) + [[../ops-agents/heimdall/_index|헤임달]] (초기 카테고리 진단)