실전 과제 — 스토리지
결론부터
- 기본 StorageClass는 애너테이션 하나로 정한다. 새 클래스에 붙이고 기존 기본 클래스에서는 뗀다.
- StorageClass의 프로비저너와 바인딩 모드는 만든 뒤 못 고친다. 틀렸으면 지우고 다시 만든다.
- 남아 있는 PV를 다시 쓰려면 PVC의 클래스·접근 모드를 PV와 맞추고
volumeName으로 대상을 고정한다. - PVC가
Bound여도VOLUME열이 기존 PV인지 확인한다. 새 빈 볼륨에 묶였을 수 있다.
과제는 연습용으로 만든 시나리오이고 이름과 값은 예시다. 과제마다 조건 → 풀이 → 확인 → 함정 순서로 읽고, 원리는 링크한 개념 페이지에서 확인한다. 호스트 접속과 네임스페이스 확인은 문제마다 반복하는 3단계를 따른다.
새 StorageClass를 기본 클래스로 지정하기
섹션 제목: “새 StorageClass를 기본 클래스로 지정하기”과제
- 클러스터에 설치된 프로비저너
rancher.io/local-path를 쓰는 StorageClasslocal-delayed를 만든다. - 볼륨 바인딩 모드는
WaitForFirstConsumer로 한다. - 이 클래스를 클러스터의 기본 StorageClass로 지정한다.
- 기존 PVC와 Deployment는 고치지 않는다.
kind로 만든 클러스터에는 이 프로비저너와 기본 클래스 standard가 이미 있어 준비 없이 따라 할 수 있다.
풀이
-
지금의 기본 클래스를 확인한다. 이름 옆에
(default)가 붙어 있다.터미널 창 kubectl get storageclass# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE# standard (default) rancher.io/local-path Delete WaitForFirstConsumer -
새 클래스를 기본 애너테이션과 함께 만든다.
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:name: local-delayedannotations:storageclass.kubernetes.io/is-default-class: "true"provisioner: rancher.io/local-pathvolumeBindingMode: WaitForFirstConsumer터미널 창 kubectl apply -f local-delayed.yaml -
기존 기본 클래스에서 기본 표시를 뗀다.
터미널 창 kubectl patch storageclass standard \-p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}' -
(default)가 새 클래스에만 붙었는지 본다.터미널 창 kubectl get storageclass# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE# local-delayed (default) rancher.io/local-path Delete WaitForFirstConsumer# standard rancher.io/local-path Delete WaitForFirstConsumer
기본 클래스가 둘일 때의 동작과 바인딩 모드의 차이는 StorageClass에서 본다.
남아 있는 PV에 새 PVC를 연결해 워크로드 복구하기
섹션 제목: “남아 있는 PV에 새 PVC를 연결해 워크로드 복구하기”과제
- 네임스페이스
orders의 데이터베이스 Deployment가 실수로 삭제됐다. 데이터가 든 PV 하나가Retain정책으로 남아 있다. - 그 PV를 쓰는 PVC
orders-data를orders네임스페이스에 만든다. 요청 용량은 500Mi다. ~/orders-db.yaml의 Deployment가 이 PVC를 쓰도록 고쳐 적용한다.
준비 — PV를 만들고, PVC를 만들었다 지워 Released 상태로 만든다. 단일 노드 연습 클러스터를 전제로 한다.
kubectl create namespace orderscat <<'EOF' | kubectl apply -f -apiVersion: v1kind: PersistentVolumemetadata: name: orders-pvspec: capacity: { storage: 1Gi } accessModes: ["ReadWriteOnce"] persistentVolumeReclaimPolicy: Retain storageClassName: manual hostPath: { path: /mnt/orders-data }---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: old-claim namespace: ordersspec: accessModes: ["ReadWriteOnce"] storageClassName: manual resources: { requests: { storage: 500Mi } }EOFkubectl delete pvc old-claim -n orders
cat <<'EOF' > ~/orders-db.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: orders-db namespace: ordersspec: replicas: 1 selector: { matchLabels: { app: orders-db } } template: metadata: { labels: { app: orders-db } } spec: containers: - name: db image: busybox:stable command: ["sleep", "3600"] volumeMounts: - name: data mountPath: /var/lib/data volumes: - name: data emptyDir: {}EOF풀이
-
PV의 조건을 읽는다. 용량, 접근 모드, 클래스, 상태가 PVC를 쓰는 데 필요하다.
터미널 창 kubectl get pv# NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS# orders-pv 1Gi RWO Retain Released orders/old-claim manual -
상태가
Released면 옛 연결 정보를 지운다. 데이터는 건드리지 않는다.터미널 창 kubectl patch pv orders-pv -p '{"spec":{"claimRef":null}}'kubectl get pv orders-pv # STATUS Available -
PV 조건에 맞춘 PVC를 만든다.
apiVersion: v1kind: PersistentVolumeClaimmetadata:name: orders-datanamespace: ordersspec:accessModes: ["ReadWriteOnce"] # PV와 같게storageClassName: manual # PV와 같게. PV에 클래스가 없으면 ""volumeName: orders-pv # 이 PV로 고정resources:requests:storage: 500Mi터미널 창 kubectl apply -f orders-data.yamlkubectl get pvc orders-data -n orders # STATUS Bound, VOLUME orders-pv -
Deployment 파일의 볼륨을 PVC로 바꿔 적용한다.
volumes:- name: datapersistentVolumeClaim:claimName: orders-data터미널 창 kubectl apply -f ~/orders-db.yaml -
Pod이 뜨고 PV가 새 PVC에 묶였는지 본다.
터미널 창 kubectl rollout status deployment orders-db -n orderskubectl get pv orders-pv # STATUS Bound, CLAIM orders/orders-data
PV 상태가 바뀌는 이유는 같은 데이터로 PV를 다시 연결하기, 묶이는 조건은 바인딩 규칙에서 본다.
연습이 끝나면 kubectl delete namespace orders와 kubectl delete pv orders-pv로 정리한다.