init: 폴더구조 설계 및 인프라 설계
This commit is contained in:
@@ -0,0 +1,641 @@
|
||||
# storage / PVC 예시
|
||||
|
||||
모든 예시는 `kubectl apply -f` 로 바로 적용 가능한 완성 매니페스트다.
|
||||
생략(`...`)이 있는 곳은 의도적으로 다른 문서로 위임한 부분이다.
|
||||
|
||||
---
|
||||
|
||||
## 좋은 예시 1: 운영 StorageClass 표준 세트 (WaitForFirstConsumer + Retain)
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: fast-ssd-retain
|
||||
labels:
|
||||
app.kubernetes.io/part-of: platform-storage
|
||||
storage.platform.io/tier: gold
|
||||
annotations:
|
||||
storage.platform.io/description: "prod stateful (DB, vault, object store). retain on PVC delete."
|
||||
provisioner: driver.longhorn.io
|
||||
parameters:
|
||||
numberOfReplicas: "3"
|
||||
staleReplicaTimeout: "30"
|
||||
fsType: ext4
|
||||
reclaimPolicy: Retain
|
||||
volumeBindingMode: WaitForFirstConsumer
|
||||
allowVolumeExpansion: true
|
||||
---
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: standard-delete
|
||||
labels:
|
||||
app.kubernetes.io/part-of: platform-storage
|
||||
storage.platform.io/tier: silver
|
||||
annotations:
|
||||
storage.platform.io/description: "dev/test, ephemeral, rebuild-safe data. deletes on PVC removal."
|
||||
provisioner: driver.longhorn.io
|
||||
parameters:
|
||||
numberOfReplicas: "2"
|
||||
fsType: ext4
|
||||
reclaimPolicy: Delete
|
||||
volumeBindingMode: WaitForFirstConsumer
|
||||
allowVolumeExpansion: true
|
||||
---
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: rwx-shared
|
||||
labels:
|
||||
app.kubernetes.io/part-of: platform-storage
|
||||
storage.platform.io/tier: shared
|
||||
provisioner: nfs.csi.k8s.io
|
||||
parameters:
|
||||
server: nfs.storage.svc.cluster.local
|
||||
share: /exports/shared
|
||||
reclaimPolicy: Retain
|
||||
volumeBindingMode: Immediate # 네트워크 스토리지이고 topology 제약 없음 → 예외적으로 Immediate 허용
|
||||
allowVolumeExpansion: true
|
||||
mountOptions:
|
||||
- nfsvers=4.1
|
||||
- hard
|
||||
- noatime
|
||||
```
|
||||
|
||||
왜 좋은가:
|
||||
- `volumeBindingMode: WaitForFirstConsumer` 기본, `Immediate`는 이유를 주석으로 명시
|
||||
- `reclaimPolicy`가 데이터 등급에 따라 다르게 선언됨 (Retain / Delete)
|
||||
- `allowVolumeExpansion: true` 기본
|
||||
- 라벨/annotation으로 용도 구분
|
||||
|
||||
❌ 나쁜 예시 1: 기본값 의존 + Immediate 바인딩
|
||||
|
||||
```yaml
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: default
|
||||
provisioner: driver.longhorn.io
|
||||
# reclaimPolicy 미지정 → 기본 Delete (운영 데이터도 삭제됨)
|
||||
# volumeBindingMode 미지정 → 기본 Immediate (topology 충돌 유발)
|
||||
# allowVolumeExpansion 미지정 → 확장 불가
|
||||
```
|
||||
|
||||
문제:
|
||||
- `reclaimPolicy` 기본 `Delete`: 실수로 PVC를 지우면 PV와 데이터까지 사라진다
|
||||
- `volumeBindingMode` 기본 `Immediate`: Pod가 스케줄되지 못하는 zone/node에 PV가 붙을 수 있다
|
||||
- 확장 불가
|
||||
|
||||
---
|
||||
|
||||
## 좋은 예시 2: VolumeSnapshotClass를 StorageClass와 매칭
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: snapshot.storage.k8s.io/v1
|
||||
kind: VolumeSnapshotClass
|
||||
metadata:
|
||||
name: fast-ssd-snap-retain
|
||||
labels:
|
||||
app.kubernetes.io/part-of: platform-storage
|
||||
velero.io/csi-volumesnapshot-class: "true"
|
||||
driver: driver.longhorn.io
|
||||
deletionPolicy: Retain
|
||||
parameters:
|
||||
type: bak
|
||||
csi.storage.k8s.io/snapshotter-secret-name: longhorn-backup-secret
|
||||
csi.storage.k8s.io/snapshotter-secret-namespace: longhorn-system
|
||||
---
|
||||
apiVersion: snapshot.storage.k8s.io/v1
|
||||
kind: VolumeSnapshotClass
|
||||
metadata:
|
||||
name: standard-snap-delete
|
||||
labels:
|
||||
app.kubernetes.io/part-of: platform-storage
|
||||
driver: driver.longhorn.io
|
||||
deletionPolicy: Delete
|
||||
```
|
||||
|
||||
왜 좋은가:
|
||||
- snapshot class가 StorageClass 등급과 1:1 매칭
|
||||
- 운영 데이터용은 `deletionPolicy: Retain`
|
||||
- Velero가 인식하도록 `velero.io/csi-volumesnapshot-class: "true"` 라벨 부여
|
||||
|
||||
---
|
||||
|
||||
## 좋은 예시 3: PostgreSQL StatefulSet + PVC retention Retain
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: data-prod
|
||||
labels:
|
||||
pod-security.kubernetes.io/enforce: restricted
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: data-prod
|
||||
labels:
|
||||
app.kubernetes.io/name: postgres
|
||||
app.kubernetes.io/instance: postgres-prod
|
||||
app.kubernetes.io/component: database
|
||||
app.kubernetes.io/part-of: auth-platform
|
||||
app.kubernetes.io/managed-by: argocd
|
||||
app.kubernetes.io/version: "16.4"
|
||||
spec:
|
||||
serviceName: postgres
|
||||
replicas: 1
|
||||
persistentVolumeClaimRetentionPolicy:
|
||||
whenDeleted: Retain
|
||||
whenScaled: Retain
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: postgres
|
||||
app.kubernetes.io/instance: postgres-prod
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: postgres
|
||||
app.kubernetes.io/instance: postgres-prod
|
||||
app.kubernetes.io/component: database
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
fsGroup: 999
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres@sha256:8a6b7c6f0e0b5e2b0e2b0e2b0e2b0e2b0e2b0e2b0e2b0e2b0e2b0e2b0e2b0e2b
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: pg
|
||||
containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_DB
|
||||
value: auth
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: postgres-credentials
|
||||
resources:
|
||||
requests:
|
||||
cpu: "500m"
|
||||
memory: "1Gi"
|
||||
limits:
|
||||
cpu: "2"
|
||||
memory: "4Gi"
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", "postgres"]
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", "postgres"]
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: run
|
||||
mountPath: /var/run/postgresql
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: run
|
||||
emptyDir: {}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
labels:
|
||||
app.kubernetes.io/name: postgres
|
||||
app.kubernetes.io/instance: postgres-prod
|
||||
backup.platform.io/tier: gold
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: fast-ssd-retain
|
||||
resources:
|
||||
requests:
|
||||
storage: 50Gi
|
||||
```
|
||||
|
||||
왜 좋은가:
|
||||
- `persistentVolumeClaimRetentionPolicy`가 명시적으로 `Retain`
|
||||
- StorageClass `fast-ssd-retain`에 맞물리는 `RWO`
|
||||
- `fsGroup` + `fsGroupChangePolicy` 설정
|
||||
- restricted PSA 준수 (runAsNonRoot, readOnlyRootFilesystem, capabilities drop all)
|
||||
- `emptyDir`로 tmp/run 분리 (PVC 남발 방지)
|
||||
- 라벨 full set + backup tier 라벨
|
||||
|
||||
---
|
||||
|
||||
## 좋은 예시 4: 단일 PVC Deployment (RWO, replicas 1)
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: minio-data
|
||||
namespace: object-prod
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/component: object-store
|
||||
backup.platform.io/tier: gold
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: fast-ssd-retain
|
||||
resources:
|
||||
requests:
|
||||
storage: 500Gi
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: minio
|
||||
namespace: object-prod
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio-prod
|
||||
app.kubernetes.io/component: object-store
|
||||
app.kubernetes.io/part-of: platform-storage
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate # RWO 단일 PVC이므로 RollingUpdate 금지
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio-prod
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: minio
|
||||
app.kubernetes.io/instance: minio-prod
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: minio
|
||||
image: quay.io/minio/minio@sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789
|
||||
args: ["server", "/data", "--console-address", ":9001"]
|
||||
ports:
|
||||
- {name: s3, containerPort: 9000}
|
||||
- {name: console, containerPort: 9001}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: minio-root-credentials
|
||||
resources:
|
||||
requests: {cpu: "250m", memory: "512Mi"}
|
||||
limits: {cpu: "2", memory: "4Gi"}
|
||||
readinessProbe:
|
||||
httpGet: {path: /minio/health/ready, port: s3}
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
httpGet: {path: /minio/health/live, port: s3}
|
||||
periodSeconds: 20
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
volumeMounts:
|
||||
- {name: data, mountPath: /data}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: minio-data
|
||||
```
|
||||
|
||||
왜 좋은가:
|
||||
- StatefulSet 없이도 stable한 단일 writer 구성
|
||||
- `strategy: Recreate`로 RWO 충돌 방지
|
||||
- PVC와 StorageClass가 명시적으로 매칭
|
||||
- backup tier 라벨 → Velero selector와 연동
|
||||
|
||||
❌ 나쁜 예시 2: RWO에 RollingUpdate + replicas 2
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
replicas: 2
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- volumeMounts:
|
||||
- {name: data, mountPath: /data}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: minio-data # RWO인데 두 Pod가 동시에 마운트 시도
|
||||
```
|
||||
|
||||
문제:
|
||||
- RWO PVC를 두 Pod가 동시에 잡을 수 없어 신규 Pod가 영원히 Pending
|
||||
- RollingUpdate가 old→new 전환 시 마운트 충돌
|
||||
- 해결: replicas=1 + Recreate, 또는 RWX, 또는 StatefulSet
|
||||
|
||||
---
|
||||
|
||||
## 좋은 예시 5: separate PVC (정당한 수명/복구 단위 차이)
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: archive-ledger
|
||||
namespace: finance-prod
|
||||
labels:
|
||||
app.kubernetes.io/name: archive-ledger
|
||||
app.kubernetes.io/instance: archive-ledger-prod
|
||||
spec:
|
||||
serviceName: archive-ledger
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: archive-ledger
|
||||
app.kubernetes.io/instance: archive-ledger-prod
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: archive-ledger
|
||||
app.kubernetes.io/instance: archive-ledger-prod
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10001
|
||||
runAsGroup: 10001
|
||||
fsGroup: 10001
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: archive-ledger
|
||||
image: registry.example.com/finance/archive-ledger@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79
|
||||
ports:
|
||||
- { name: http, containerPort: 8080 }
|
||||
resources:
|
||||
requests: { cpu: 500m, memory: 1Gi }
|
||||
limits: { memory: 2Gi }
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
volumeMounts:
|
||||
- { name: data, mountPath: /var/lib/ledger }
|
||||
- { name: audit-archive, mountPath: /var/lib/ledger/audit }
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
labels:
|
||||
backup.platform.io/tier: gold # 5분 RPO, 매일 snapshot
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: fast-ssd-retain
|
||||
resources:
|
||||
requests: {storage: 500Gi}
|
||||
- metadata:
|
||||
name: audit-archive
|
||||
labels:
|
||||
backup.platform.io/tier: bronze # 24h RPO, 주 1회 snapshot, 7년 보존
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: archive-retain
|
||||
resources:
|
||||
requests: {storage: 2Ti}
|
||||
```
|
||||
|
||||
왜 좋은가:
|
||||
- data와 audit-archive의 RPO/retention이 다름
|
||||
- StorageClass도 다름 (SSD vs 아카이브)
|
||||
- backup tier 라벨이 Velero schedule selector에 의해 다르게 잡힘
|
||||
|
||||
❌ 나쁜 예시 3: separate PVC 남발
|
||||
|
||||
```yaml
|
||||
volumeClaimTemplates:
|
||||
- {metadata: {name: logs}}
|
||||
- {metadata: {name: tmp}}
|
||||
- {metadata: {name: config-copy}}
|
||||
- {metadata: {name: cache}}
|
||||
```
|
||||
|
||||
문제:
|
||||
- 로그/tmp/cache는 `emptyDir` 또는 stdout 대상
|
||||
- PVC 4개는 수명 구분 없이 쪼갠 것 — 운영 복잡도만 증가
|
||||
- snapshot/backup 단위가 파편화됨
|
||||
|
||||
---
|
||||
|
||||
## 좋은 예시 6: 파이프라인 전체 — PVC → Snapshot → Restore → Verify
|
||||
|
||||
아래 6개 블록은 순서대로 `kubectl apply` 한다.
|
||||
|
||||
### (1) PVC
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: app-data
|
||||
namespace: app-prod
|
||||
labels:
|
||||
app.kubernetes.io/name: app
|
||||
backup.platform.io/tier: gold
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: fast-ssd-retain
|
||||
resources:
|
||||
requests: {storage: 20Gi}
|
||||
```
|
||||
|
||||
### (2) VolumeSnapshotClass (전역 1회)
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: snapshot.storage.k8s.io/v1
|
||||
kind: VolumeSnapshotClass
|
||||
metadata:
|
||||
name: fast-ssd-snap-retain
|
||||
labels:
|
||||
velero.io/csi-volumesnapshot-class: "true"
|
||||
driver: driver.longhorn.io
|
||||
deletionPolicy: Retain
|
||||
```
|
||||
|
||||
### (3) On-demand VolumeSnapshot
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: snapshot.storage.k8s.io/v1
|
||||
kind: VolumeSnapshot
|
||||
metadata:
|
||||
name: app-data-2026-04-16-pre-migration
|
||||
namespace: app-prod
|
||||
labels:
|
||||
app.kubernetes.io/name: app
|
||||
snapshot.platform.io/reason: pre-migration
|
||||
spec:
|
||||
volumeSnapshotClassName: fast-ssd-snap-retain
|
||||
source:
|
||||
persistentVolumeClaimName: app-data
|
||||
```
|
||||
|
||||
### (4) Restore: snapshot을 소스로 하는 새 PVC
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: app-data-restored
|
||||
namespace: app-prod
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: fast-ssd-retain
|
||||
resources:
|
||||
requests: {storage: 20Gi}
|
||||
dataSource:
|
||||
name: app-data-2026-04-16-pre-migration
|
||||
kind: VolumeSnapshot
|
||||
apiGroup: snapshot.storage.k8s.io
|
||||
```
|
||||
|
||||
### (5) Verify Job
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: app-data-restore-verify
|
||||
namespace: app-prod
|
||||
spec:
|
||||
backoffLimit: 0
|
||||
ttlSecondsAfterFinished: 3600
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: verify
|
||||
image: busybox@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
set -eu
|
||||
test -d /data
|
||||
COUNT=$(find /data -type f | wc -l)
|
||||
echo "file_count=${COUNT}"
|
||||
test "${COUNT}" -gt 0
|
||||
resources:
|
||||
requests: { cpu: 50m, memory: 64Mi }
|
||||
limits: { memory: 128Mi }
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities: {drop: ["ALL"]}
|
||||
volumeMounts:
|
||||
- {name: data, mountPath: /data, readOnly: true}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: app-data-restored
|
||||
```
|
||||
|
||||
### (6) 최종 확인
|
||||
|
||||
```bash
|
||||
kubectl -n app-prod get volumesnapshot,pvc,job
|
||||
kubectl -n app-prod logs job/app-data-restore-verify
|
||||
```
|
||||
|
||||
왜 좋은가:
|
||||
- PVC → SnapshotClass → Snapshot → dataSource 기반 PVC restore → Job 검증의 end-to-end 흐름
|
||||
- `deletionPolicy: Retain`으로 snapshot을 실수로 삭제해도 PV는 남음
|
||||
- Job이 restricted PSA 준수, 이미지 digest 고정, `backoffLimit: 0`
|
||||
|
||||
---
|
||||
|
||||
## 나쁜 예시 4: hostPath를 운영 PV로 사용
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: pg-host
|
||||
spec:
|
||||
capacity: {storage: 50Gi}
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
hostPath:
|
||||
path: /data/postgres
|
||||
```
|
||||
|
||||
문제:
|
||||
- 노드 장애 = 데이터 손실
|
||||
- snapshot / expansion / 다중 노드 스케줄링 전부 불가
|
||||
- 운영 표준 아님
|
||||
|
||||
---
|
||||
|
||||
## 나쁜 예시 5: K3s local-path로 production Postgres
|
||||
|
||||
```yaml
|
||||
volumeClaimTemplates:
|
||||
- metadata: {name: data}
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: local-path # K3s default
|
||||
resources: {requests: {storage: 100Gi}}
|
||||
```
|
||||
|
||||
문제:
|
||||
- local-path는 snapshot 미지원 → Velero CSI snapshot 불가
|
||||
- expansion 미지원 → 용량 부족 시 마이그레이션 필요
|
||||
- 노드 pin → 노드 장애 시 Postgres 복구 불가
|
||||
- 해결: Longhorn / OpenEBS / cloud CSI driver로 교체
|
||||
|
||||
---
|
||||
|
||||
## 나쁜 예시 6: StorageClass 생략
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: {requests: {storage: 20Gi}}
|
||||
# storageClassName 미지정 → 클러스터 default annotation 사용
|
||||
```
|
||||
|
||||
문제:
|
||||
- 어떤 tier를 기대했는지 선언에서 드러나지 않음
|
||||
- 클러스터 default가 바뀌면 침묵적으로 다른 StorageClass로 바인딩
|
||||
- 환경 간 재현 불가
|
||||
Reference in New Issue
Block a user