153 lines
8.5 KiB
Markdown
153 lines
8.5 KiB
Markdown
---
|
|
title: Longhorn 분산 블록 스토리지
|
|
updated: 2026-05-07
|
|
tags: [infra, platform, longhorn, storage, k3s]
|
|
---
|
|
|
|
## 개요
|
|
|
|
Longhorn은 K3s 클러스터의 **분산 블록 스토리지**. 각 노드 로컬 NVMe에 replica 분산 저장, CSI 드라이버로 PV/PVC 공급. 기본 StorageClass `longhorn` (default), 정적 복구용 `longhorn-static`.
|
|
|
|
| 항목 | 값 |
|
|
|---|---|
|
|
| Helm release | `longhorn` (ns `longhorn-system`) |
|
|
| Chart / App | `longhorn-1.11.2` / `v1.11.2` |
|
|
| 노드 | incus-kr1, incus-kr2, incus-hp1, incus-hp2 (4) |
|
|
| Data engine | v1 (v2 미사용) |
|
|
| Default data path | `/var/lib/longhorn/` |
|
|
| Default replica count | 2 (`{"v1":"2","v2":"2"}`) |
|
|
| Default SC | `longhorn` — WaitForFirstConsumer 아님, Immediate / ReclaimPolicy Delete / ExpansionAllowed true |
|
|
| 정적 복구 SC | `longhorn-static` (Volume CR 경유 복구 시) |
|
|
| Backup target | `s3://longhorn-backup@auto/` (Cloudflare R2) — [[../data/k3s-backup|k3s-backup]] 참조 |
|
|
|
|
## 컴포넌트 (helm rev 6 기준)
|
|
|
|
| 컴포넌트 | 종류 | 이미지 |
|
|
|---|---|---|
|
|
| longhorn-manager | DaemonSet | `longhorn-manager:v1.11.2` + `longhorn-share-manager:v1.11.2` |
|
|
| longhorn-csi-plugin | DaemonSet | `csi-node-driver-registrar:v2.16.0`, `livenessprobe:v2.18.0`, `longhorn-manager:v1.11.2` |
|
|
| longhorn-driver-deployer | Deployment (1) | `longhorn-manager:v1.11.2` |
|
|
| longhorn-ui | Deployment (2) | `longhorn-ui:v1.11.2` |
|
|
| csi-attacher / provisioner / resizer / snapshotter | Deployment (3 replicas each) | `csi-attacher:v4.x`, `csi-provisioner:v5.x`, `csi-resizer:v1.x`, `csi-snapshotter:v8.x` |
|
|
| engine-image | DaemonSet (per-version) | `longhorn-engine:v1.11.2` (ei-c9fa6d45). 신규 EI 적용 후 모든 25 볼륨 live engine upgrade 완료, 구 EI `ei-75a03ec3` (v1.11.1) 는 refcount 0 으로 자동 정리 대기 |
|
|
| instance-manager | per-node per-version | `longhorn-instance-manager:v1.11.2` |
|
|
|
|
## Helm values (커스텀)
|
|
|
|
```yaml
|
|
defaultSettings:
|
|
nodeDownPodDeletionPolicy: delete-both-statefulset-and-deployment-pod
|
|
nodeDrainPolicy: always-allow
|
|
replicaAutoBalance: best-effort
|
|
```
|
|
|
|
- `nodeDownPodDeletionPolicy`: 노드 다운 시 StatefulSet / Deployment 파드 양쪽 모두 강제 삭제하여 PV 재attach 허용
|
|
- `nodeDrainPolicy: always-allow`: `kubectl drain` 시 볼륨 attach 여부 무관하게 허용
|
|
- `replicaAutoBalance: best-effort`: 노드 간 replica 분포 자동 밸런싱 시도
|
|
|
|
## UI
|
|
|
|
- https://longhorn.inouter.com — Traefik IngressRoute 경유
|
|
- 백업 탭에서 R2 저장된 backup volume / snapshot 시각 확인
|
|
|
|
## 볼륨 운영
|
|
|
|
- 기본 PVC 생성: StorageClass `longhorn` (default)
|
|
- 백업/복구·라벨 기반 recurring job: [[../data/k3s-backup|k3s-backup]]
|
|
- 복구 시 주의: `longhorn.io/fromBackup` annotation은 Longhorn v1.8+ CSI에서 무시됨 → Volume CR 직접 생성 후 `longhorn-static` SC PV 만드는 절차. 상세 [[../data/k3s-backup|k3s-backup]]
|
|
- 주기 백업 라벨 키는 **대시 포함**: `recurring-job-group.longhorn.io/<group>=enabled` (과거 오타 이슈 [[../../history/2026-04-15-longhorn-backup-label-typo|history]])
|
|
|
|
## Stuck snapshot 임시 cron (v1.11.1 워크어라운드 — 회수 대상)
|
|
|
|
> **상태 (2026-05-07): v1.11.2 업그레이드로 fix 적용됨** — 업그레이드 직후 stuck CR 12개 자연 cleanup, 23:00 UTC RecurringJob 사이클부터 신규 Warning 0건. 임시 cron 은 **회수 대상**. ArgoCD `longhorn-snapshot-purge` Application 만 삭제, chart 디렉토리는 repo 보존 (재현 시 재활용 가능).
|
|
|
|
v1.11.1 instance-manager 재시작 후 일부 snapshot CR 이 `status.markRemoved=true && status.readyToUse=false && status.ownerID=""` 상태로 멈췄다. ownerId 가 비어 longhorn-manager 가 reconcile 못 했고, 수동 `kubectl delete` / finalizer patch 시 admission webhook 이 finalizer 를 즉시 재추가해 정리 불가했다.
|
|
|
|
근본 fix 는 **v1.11.2 백포트 [#12856](https://github.com/longhorn/longhorn/issues/12856)**. 그 전까지 임시로 snapshotPurge API 를 cron 으로 자동 호출해 engine 단 chain cleanup 을 주기 트리거했다.
|
|
|
|
### 구성
|
|
|
|
| 항목 | 값 |
|
|
|---|---|
|
|
| Helm chart | `gitea.inouter.com/kaffa/helm-charts` · `charts/longhorn-snapshot-purge` |
|
|
| ArgoCD App | `argocd/longhorn-snapshot-purge` (auto-sync, prune, selfHeal) |
|
|
| CronJob | `longhorn-system/longhorn-snapshot-purge` |
|
|
| Schedule | `*/30 * * * *` |
|
|
| ServiceAccount | `longhorn-snapshot-purge` (ns Role: `snapshots.longhorn.io` get/list) |
|
|
| Image | `alpine/k8s:1.32.1` (kubectl + curl + jq 포함) |
|
|
|
|
### 동작
|
|
|
|
1. namespace 내 `snapshots.longhorn.io` 전수 list
|
|
2. `status.markRemoved=true` 이면서 `status.readyToUse=false` 인 CR 추출 → `spec.volume` 중복 제거
|
|
3. 각 volume 에 `POST http://longhorn-frontend.longhorn-system.svc/v1/volumes/{name}?action=snapshotPurge` 호출
|
|
4. HTTP 200 / 비-200 별 카운트, 비-200 있으면 job exit 1
|
|
|
|
### 한계 / 운영 주의
|
|
|
|
- snapshotPurge 는 chain 의 redundant snapshot 만 정리. **stuck snapshot 이 그 볼륨의 유일 snapshot 이고 volume-head 의 직속 parent 라면 .img 파일이 정리되지 않는다** (engine snapshotList 에서 `removed=true` 만 마킹 유지).
|
|
- 따라서 cron 은 디스크 재확보의 best-effort. CR 자체 cleanup 은 보장 안 됨 — 그건 v1.11.2 / v1.12 업그레이드로 해결.
|
|
- 임시 cron 이라 **업그레이드 직후 ArgoCD App 삭제로 회수**할 것 (chart 디렉토리는 repo 에 보존하되 Application 만 prune).
|
|
|
|
### 운영 명령
|
|
|
|
```bash
|
|
# 수동 트리거 (다음 30분 boundary 기다리지 않을 때)
|
|
kubectl -n longhorn-system create job --from=cronjob/longhorn-snapshot-purge longhorn-snapshot-purge-manual-$(date +%s)
|
|
|
|
# 마지막 실행 로그
|
|
kubectl -n longhorn-system logs -l job-name --tail=50 --selector='batch.kubernetes.io/job-name'
|
|
|
|
# stuck snapshot 현재 카운트
|
|
kubectl get snapshots.longhorn.io -A -o json | jq '[.items[] | select(.status.markRemoved == true and .status.readyToUse == false)] | length'
|
|
```
|
|
|
|
상세 도입 기록: [[../../history/2026-05-02-longhorn-snapshot-purge-cron|2026-05-02 도입]] / [[../../history/2026-05-07-longhorn-1-11-2-upgrade|2026-05-07 fix 적용]]
|
|
|
|
## 업그레이드 절차 (표준)
|
|
|
|
minor skip 금지 — 한 단계씩 순차. 각 단계 공통:
|
|
|
|
1. Pre-check: 볼륨 healthy/attached, backup target available, ongoing snapshot 없음, 4노드 Ready
|
|
2. `helm upgrade longhorn longhorn/longhorn -n longhorn-system --version <x.y.z> --reset-then-reuse-values`
|
|
3. `longhorn-manager` DS 롤링 대기
|
|
4. 신규 `engine-image` DS 4/4 state=deployed 확인
|
|
5. 모든 볼륨 `spec.image` 를 신규 engine image 로 일괄 패치 (live engine upgrade, v1 data engine)
|
|
6. `status.currentImage` 전수 확인
|
|
7. 구 engine-image CR refcount=0 확인 — Longhorn 자동 정리 대상
|
|
|
|
구 engine-image CR 과 구 instance-manager pod 는 refcount 0 확인 후 manager가 자동 정리 (기본 timeout ~10분). 수동 삭제 불필요.
|
|
|
|
## 최근 버전 변경
|
|
|
|
### 2026-05-07: 1.11.1 → 1.11.2 (patch, snapshot warning 회귀 fix)
|
|
|
|
| 단계 | Helm rev | Chart | 결과 |
|
|
|---|---|---|---|
|
|
| 1.11.1 → 1.11.2 | 6 | longhorn-1.11.2 | 25/25 볼륨 healthy |
|
|
|
|
- 백포트 [#12856](https://github.com/longhorn/longhorn/issues/12856) 적용 — `snapshot becomes not ready to use` Warning 사이클 해소
|
|
- 업그레이드 직후 stuck CR 12개 자연 cleanup (manager ownership reset 흐름 회복)
|
|
- 35분 관측 동안 신규 Warning 0건, 23:00 UTC `critical-snapshot` RecurringJob 사이클 통과
|
|
- 신규 EI `ei-c9fa6d45` (v1.11.2), 25 볼륨 모두 live engine upgrade 완료
|
|
- 상세: [[../../history/2026-05-07-longhorn-1-11-2-upgrade|history]]
|
|
|
|
### 2026-04-23: 1.8.2 → 1.11.1 (3단계 minor 순차)
|
|
|
|
| 단계 | Helm rev | Chart | 결과 |
|
|
|---|---|---|---|
|
|
| 1.8.2 → 1.9.2 | 3 | longhorn-1.9.2 | 27/27 볼륨 healthy |
|
|
| 1.9.2 → 1.10.2 | 4 | longhorn-1.10.2 | 27/27 볼륨 healthy |
|
|
| 1.10.2 → 1.11.1 | 5 | longhorn-1.11.1 | 27/27 볼륨 healthy |
|
|
|
|
- 전 단계 live engine upgrade (v1 data engine만 사용 중이라 가능)
|
|
- 전 단계 무중단 — attached 25 + detached 2(safeline) 볼륨 전수 신규 엔진 이미지로 이행
|
|
- 각 단계 breaking change 없음 (공식 릴리스 노트 기준)
|
|
- 상세 로그·검증 스냅샷: Outline `heimdall/2026-04-23 Longhorn 업그레이드` (id `750faea0-6720-4e27-b219-0942247d53aa`)
|
|
|
|
## 관련 문서
|
|
|
|
- [[../data/k3s-backup|k3s-backup]] — Longhorn → R2 백업 구성, 라벨 기반 recurring job, 복구 절차
|
|
- [[../data/storage-plan|storage-plan]] — 스토리지 전략 전반
|
|
- [[../compute/infra-hosts|infra-hosts]] — Helm 릴리스 전수 인벤토리
|