스토리지 토폴로지
GenD는 블록 스토리지(PVC) 와 객체 스토리지(S3 API) 를 이원화하여 운영합니다. dev(Kind)와 prod(AKS)는 백엔드만 다르고 동일한 S3 API 추상화 레이어(datax-s3-config ConfigMap + Secret) 를 공유하므로 애플리케이션 코드 변경 없이 환경 전환이 가능합니다.
토폴로지
환경별 매핑
| 용도 | dev (Kind) | prod (AKS) |
|---|---|---|
| 블록 PVC | local-path-provisioner | managed-csi-tagged (Ceph RBD + LUKS + Vault Transit) |
| 객체 (S3) | SeaweedFS 3.80 | Ceph RGW + SSE-KMS |
| DB (PostgreSQL) | StatefulSet PVC | StatefulSet PVC (Managed DB 미사용 — 자체 운영 확정) |
| 인증서 키 | self-signed | cert-manager + Let's Encrypt |
PVC 카탈로그
| 워크로드 | 크기 | 모드 | 비고 |
|---|---|---|---|
vault | 1Gi | RWO | Raft state |
kafka-N × 3 | 10Gi | RWO | per-broker |
opensearch | (동적) | RWO | 감사 로그 |
prometheus | (동적) | RWO | 메트릭 TSDB |
seaweedfs-data | 100Gi (prod) | RWO | 논리 상한은 아래 §SeaweedFS 용량 참조 |
SeaweedFS 용량 — 디스크가 아니라 볼륨 슬롯이 상한이다
:::danger 실제 저장 가능량 = volume.max × master.volumeSizeLimitMB
PVC 크기가 아니라 이 곱이 상한이다. 초과하면 마스터가
No writable volumes and no free volumes left 로 PUT 을 거부한다 —
디스크에 여유가 아무리 많아도 그렇다.
:::
2026-07-31 장애 (#2784): volume.max=20 × 1024 MB = 20 GiB 하드 상한에 도달해
Iceberg 쓰기가 약 30시간 100% 실패했다. 그때 디스크 사용률은 20% 였다
(98 GiB 중 20 GiB). #630 이 PVC 를 20Gi→100Gi 로 늘렸지만 volume.max 를 20 그대로
두어, 늘린 용량의 80% 를 구조적으로 쓸 수 없는 상태였다.
공식 이미지의 entrypoint 가 server 모드에 아래를 강제 주입한다 — 매니페스트에
없다고 기본값이 아니다:
weed -logtostderr=true server -dir=/data \
-master.volumePreallocate -master.volumeSizeLimitMB=1024 ...
확인: kubectl exec deploy/seaweedfs -c seaweedfs -- cat /proc/1/cmdline | tr '\0' ' '
매니페스트 args 는 그 뒤에 붙으므로, 같은 플래그를 다시 지정하면 Go flag 의
"나중 값 우선" 규칙으로 덮어쓸 수 있다. 현재 prod 설정은 volume.max=40 ×
volumeSizeLimitMB=2048 = 80 GiB (98 GiB 파일시스템의 81%).
점검 방법
# Free=0 이면 슬롯 고갈. 컬렉션별 writables 가 [] 이면 그 컬렉션은 쓰기 불가.
kubectl exec deploy/seaweedfs -c seaweedfs -- \
wget -qO- "http://$(kubectl get pod -l app=seaweedfs -o jsonpath='{.items[0].status.podIP}'):9333/dir/status"
Topology.Free == 0 은 임박, 어떤 컬렉션의 writables == [] 은 이미 장애다.
:::warning preallocate 가 켜져 있다
볼륨 1개 생성 = 즉시 volumeSizeLimitMB 만큼 디스크 점유(fallocate). 두 값을 올릴
때는 반드시 곱이 파일시스템 크기 이하인지 재계산할 것 — 넘으면 ENOSPC 다.
:::
운영 주의
-
SeaweedFS 용량 알람 (#2793): PVC 사용률 알람으로는 이 장애를 원리적으로 잡을 수 없다 (장애 당시 20%).
Topology.Free와 컬렉션별writables를 봐야 한다 (#2784).infra/monitoring/prometheus-rules/seaweedfs.yaml이 위 exporter 메트릭을 근거로 4종을 감시한다.SeaweedFSCollectionNotWritable—seaweedfs_collection_writable_volumes == 0(critical, 5m). 해당 컬렉션은 이미 PUT 전량 거부 중이다.SeaweedFSVolumeSlotsExhausted—seaweedfs_volume_slots_free == 0(critical, 5m). 신규 볼륨 생성 불가 — 남은 볼륨이 차는 순간 전체 컬렉션이 쓰기 불가로 전이된다.SeaweedFSVolumeSlotsLow— 슬롯 사용률 80% 초과 (warning, 30m). 컬렉션 첫 grow 가 슬롯 7개를 한 번에 잡으므로 여유 7개 미만은 실질적으로 고갈이다.SeaweedFSExporterDown—absent_over_time(seaweedfs_volume_slots_free[10m])(critical, 10m). dead-man's switch: 위 3종은 전부 exporter 가 스크레이프되고 있을 때만 발화하므로, exporter 가 죽으면 셋 다 조용히 사라진다. 이 알람이 떠 있는 동안 SeaweedFS 용량 감시는 전면 실명 상태로 취급할 것.up == 0대신absent_over_time을 쓰는 이유는 파드가 Endpoints 에서 빠지면up시계열 자체가 사라져up == 0이 원리적으로 발화하지 못하기 때문이다.
대응 절차: 위 "점검 방법" 명령으로
Topology.Free와 컬렉션별writables를 확인한다. 두 critical 알람은 심각도는 같아도 뜻이 다르다 —SeaweedFSCollectionNotWritable은 해당 컬렉션이 이미 쓰기 불가이므로 즉시 대응한다.SeaweedFSVolumeSlotsExhausted는 신규 볼륨을 못 만든다는 뜻일 뿐, writable 볼륨이 남은 다른 컬렉션은 아직 정상 이다 — 다만 그 볼륨이 마저 차는 순간 끊기므로 임박으로 보고 신속히 처리한다.SeaweedFSVolumeSlotsLow는 그보다 앞선 선행 경고다. 조치는 세 경우 공통이다:volume.max또는master.volumeSizeLimitMB를 상향하되(곱이 PVC 용량 이하인지 재계산 — 위 preallocate 경고 참고)kubectl rollout restart deploy/seaweedfs로 반영한다. exporter 파드가 다운되면 세 알람 모두 못 뜨는 사각지대이므로 파드가Running인지도 함께 확인한다. -
Ceph RGW: SSE-KMS는
datax-ceph-kmsVault Transit 키와 연동 — 키 회전 시 객체 재암호화 정책 확인 -
백업: Managed DB 미사용 결정에 따라 PostgreSQL은 CronJob 기반 자체 백업 (
backup-restore.md참고)