TT Lab
블로그 시작하기
배우기 러닝패스 코스

Helm 으로 Rook-Ceph 세우기 — 블록·파일·오브젝트와 장애

RBD 블록 볼륨 — 온라인 확장·스냅숏·복원·복제

TT Lab 에서 이어서 보기

목표

Rook-Ceph 의 블록 저장소(RBD) 위에서 운영에서 자주 쓰는 네 가지 — 쓰는 중에 볼륨 늘리기, 스냅숏 찍기, 스냅숏에서 복원하기, 볼륨 통째로 복제하기 — 를 직접 해 봅니다. 스냅숏과 복제가 쿠버네티스 객체 층과 Ceph 이미지 층에서 각각 어떻게 보이는지도 확인합니다.

왜 중요한가

데이터베이스를 업그레이드하기 전에 되돌릴 지점을 남기는 것, 운영 데이터로 시험 환경을 빨리 만드는 것, 디스크가 모자랄 때 서비스를 멈추지 않고 늘리는 것은 매주 하는 일입니다. 쿠버네티스는 이것을 PVC·VolumeSnapshot 이라는 같은 모양으로 감싸지만, 실제로 일하는 것은 스토리지입니다. RBD 는 스냅숏과 복제를 '복사' 가 아니라 '부모를 가리키는 새 이미지(copy-on-write)' 로 만들어서 수백 MiB 든 수백 GiB 든 몇 초 만에 끝납니다. 그리고 스냅숏 기능은 쿠버네티스에 기본으로 들어 있지 않습니다. CRD 와 컨트롤러를 설치하지 않으면 VolumeSnapshot 이라는 종류 자체가 없습니다 — 이것을 모르고 백업 계획을 세웠다가 막히는 일이 흔합니다.

단계

  1. /root/rook/cluster-values.yaml(1실습에서 만든 values)로 Rook 을 다시 세우세요. 1실습과 같은 차트 셋을 같은 판으로 네임스페이스 rook-ceph 에 설치합니다 — rook-ceph(rook-release/rook-ceph v1.21.1), ceph-csi-drivers(ceph-csi-operator/ceph-csi-drivers 1.1.0, Rook 이 권하는 values 를 /root/rook/csi-drivers-values.yaml 로 받아서), rook-ceph-cluster(rook-release/rook-ceph-cluster v1.21.1, -f /root/rook/cluster-values.yaml). 세 릴리스가 deployed 이고 CephCluster 가 만들어져야 합니다.
  2. CephCluster 가 Ready 가 될 때까지 기다린 뒤, 1실습처럼 커널(6.8) 때문에 생기는 AUTH_INSECURE_ 경고 셋만 ceph health mute <코드> --sticky 로 묵음 처리하세요. Ceph 가 HEALTH_OK 이고, mon 셋이 정족수를 이루고, OSD 셋이 up·in 이어야 합니다.
  3. 쿠버네티스는 VolumeSnapshot 을 기본으로 갖고 있지 않습니다. kubernetes-csi/external-snapshotter v8.6.0 의 CRD 셋(volumesnapshotclasses·volumesnapshotcontents·volumesnapshots)과 snapshot-controller(kube-system)를 설치하세요. CRD 셋이 Established 이고 snapshot-controller Deployment 가 Available 이어야 합니다.
  4. 스냅숏은 두 차트가 함께 켜야 합니다. ① CSI 드라이버 차트(ceph-csi-drivers)의 값 drivers.rbd.snapshotPolicy 를 volumeSnapshot 으로 helm upgrade 해 RBD 컨트롤러에 csi-snapshotter 사이드카가 붙게 하고, ② 클러스터 차트(rook-ceph-cluster)의 값 cephBlockPoolsVolumeSnapshotClass.enabled 를 true 로 helm upgrade 해 VolumeSnapshotClass ceph-block(드라이버 rook-ceph.rbd.csi.ceph.com)을 만드세요. 나머지 값은 그대로 둡니다.
  5. 네임스페이스 rbd-demo 에 StorageClass ceph-block 의 1Gi PVC vol 을 만들고, controlplane 에 뜬 파드 app(계속 떠 있게)이 /data 에 붙여 무작위 200MiB 파일 /data/blob 을 쓰게 하세요. 그 sha256 을 /root/rook/sum-blob.txt 에 64자 16진수 한 줄로 저장합니다.
  6. 파드 app 을 멈추지 않고 PVC vol 을 2Gi 로 늘리세요. PVC 의 용량이 2Gi 가 되고, app 안에서 df 로 본 /data 의 크기도 늘어나 있어야 합니다(파드 재시작 없이).
  7. PVC vol 의 VolumeSnapshot snap1(클래스 ceph-block)을 만들고 readyToUse 가 될 때까지 기다리세요. 그다음 app 에서 /data/after.txt 를 쓰세요(내용 자유). 스냅숏은 찍은 순간의 상태라서, 다음 단계에서 이 파일이 복원본에 없어야 합니다.
  8. snap1 에서 PVC restored(2Gi, ceph-block)를 만들고 controlplane 에 뜬 파드 restored 에 붙이세요. 복원본의 /data/blob 체크섬이 /root/rook/sum-blob.txt 와 같고, /data/after.txt 는 없어야 합니다.
  9. PVC vol 을 원본으로 하는 복제 PVC cloned(2Gi, ceph-block)를 만들고 controlplane 의 파드 cloned 에 붙이세요. 복제본에는 /data/blob(체크섬 같음)과 /data/after.txt 가 모두 있어야 합니다. 마지막으로 toolbox 에서 rbd ls -l ceph-blockpool 출력을 /root/rook/rbd-ls.txt 에 저장하세요.

참고

1실습의 values 로 Ceph 를 다시 설치한다

/root/rook/cluster-values.yaml(1실습에서 만든 values)로 Rook 을 다시 세우세요. 1실습과 같은 차트 셋을 같은 판으로 네임스페이스 rook-ceph 에 설치합니다 — rook-ceph(rook-release/rook-ceph v1.21.1), ceph-csi-drivers(ceph-csi-operator/ceph-csi-drivers 1.1.0, Rook 이 권하는 values 를 /root/rook/csi-drivers-values.yaml 로 받아서), rook-ceph-cluster(rook-release/rook-ceph-cluster v1.21.1, -f /root/rook/cluster-values.yaml). 세 릴리스가 deployed 이고 CephCluster 가 만들어져야 합니다.

1실습의 2·3·5단계와 같습니다. 오퍼레이터 차트가 CRD 를 함께 깔기 때문에 그것을 먼저 설치하고, CRD 가 등록될 때까지 기다린 뒤(kubectl wait --for=condition=Established crd/drivers.csi.ceph.io) 드라이버 차트를 설치합니다. Rook 의 CSI values 주소는 {CSI_VALUES_URL} 입니다. 설치 명령은 금방 끝나고, 클러스터가 서는 것은 다음 단계에서 기다립니다.

HEALTH_OK 까지 기다린다

CephCluster 가 Ready 가 될 때까지 기다린 뒤, 1실습처럼 커널(6.8) 때문에 생기는 AUTH_INSECURE_ 경고 셋만 ceph health mute <코드> --sticky 로 묵음 처리하세요. Ceph 가 HEALTH_OK 이고, mon 셋이 정족수를 이루고, OSD 셋이 up·in 이어야 합니다.

처음 설치는 이미지와 OSD 준비 때문에 수 분이 걸립니다 — kubectl -n rook-ceph get pods -w. toolbox 의 ceph health detail 이 남은 경고를 말합니다. AUTH_INSECURE_ 가 아닌 경고는 묵음 처리하지 말고 기다리거나 원인을 고치세요.

스냅숏 CRD 와 컨트롤러를 설치한다

쿠버네티스는 VolumeSnapshot 을 기본으로 갖고 있지 않습니다. kubernetes-csi/external-snapshotter v8.6.0 의 CRD 셋(volumesnapshotclasses·volumesnapshotcontents·volumesnapshots)과 snapshot-controller(kube-system)를 설치하세요. CRD 셋이 Established 이고 snapshot-controller Deployment 가 Available 이어야 합니다.

CRD 는 저장소의 client/config/crd/, 컨트롤러는 deploy/kubernetes/snapshot-controller/ 에 있습니다. 판을 못박은 raw 주소로 받으세요: https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v8.6.0/…. 스냅숏은 두 층입니다 — 이 컨트롤러는 쿠버네티스 객체를 다루고, 실제로 Ceph 에 스냅숏을 만드는 것은 CSI 드라이버 옆의 snapshotter 사이드카입니다.

드라이버에 스냅숏을 켜고 VolumeSnapshotClass 를 만든다

스냅숏은 두 차트가 함께 켜야 합니다. ① CSI 드라이버 차트(ceph-csi-drivers)의 값 drivers.rbd.snapshotPolicy 를 volumeSnapshot 으로 helm upgrade 해 RBD 컨트롤러에 csi-snapshotter 사이드카가 붙게 하고, ② 클러스터 차트(rook-ceph-cluster)의 값 cephBlockPoolsVolumeSnapshotClass.enabled 를 true 로 helm upgrade 해 VolumeSnapshotClass ceph-block(드라이버 rook-ceph.rbd.csi.ceph.com)을 만드세요. 나머지 값은 그대로 둡니다.

드라이버 차트의 RBD 기본값은 snapshotPolicy: none 입니다(CephFS 는 volumeSnapshot). 그대로 두면 VolumeSnapshot 을 만들어도 받아 줄 사이드카가 없어 readyToUse 가 영영 오지 않습니다 — kubectl -n rook-ceph get deploy rook-ceph.rbd.csi.ceph.com-ctrlplugin -o jsonpath='{.spec.template.spec.containers[*].name}' 로 확인해 보세요. 바꾸는 값만 작은 파일에 적어 -f 를 하나 더 주면(뒤의 파일이 앞을 덮습니다) 다음 upgrade 때 빠뜨리지 않습니다. --reuse-values --set … 은 지난 값에 하나만 바꿉니다. kubectl 로 VolumeSnapshotClass 를 직접 만들면 다음 helm upgrade 가 그것을 모릅니다.

볼륨을 만들고 데이터를 쓴다

네임스페이스 rbd-demo 에 StorageClass ceph-block 의 1Gi PVC vol 을 만들고, controlplane 에 뜬 파드 app(계속 떠 있게)이 /data 에 붙여 무작위 200MiB 파일 /data/blob 을 쓰게 하세요. 그 sha256 을 /root/rook/sum-blob.txt 에 64자 16진수 한 줄로 저장합니다.

이미지는 registry.k8s.io/e2e-test-images/busybox:1.36.1-1 입니다. dd if=/dev/urandom of=/data/blob bs=1M count=200 뒤 sync 를 하세요. 체크섬은 kubectl exec app -- sha256sum /data/blob 의 첫 칸입니다. 다음 단계에서 이 파드를 멈추지 않고 볼륨을 늘리므로 파드는 sleep 으로 계속 떠 있게 둡니다.

쓰는 중인 볼륨을 2Gi 로 늘린다

파드 app 을 멈추지 않고 PVC vol 을 2Gi 로 늘리세요. PVC 의 용량이 2Gi 가 되고, app 안에서 df 로 본 /data 의 크기도 늘어나 있어야 합니다(파드 재시작 없이).

StorageClass 의 allowVolumeExpansion: true 가 이것을 허락합니다(values 에 적었습니다). PVC 의 spec.resources.requests.storage 만 고치면 CSI 가 RBD 이미지를 늘리고, 노드 쪽 CSI 가 ext4 를 온라인으로 늘립니다. kubectl get pvc vol -w 로 용량 칸이 바뀌는 것을 보세요.

스냅숏을 찍고, 그 뒤에 파일을 하나 더 쓴다

PVC vol 의 VolumeSnapshot snap1(클래스 ceph-block)을 만들고 readyToUse 가 될 때까지 기다리세요. 그다음 app 에서 /data/after.txt 를 쓰세요(내용 자유). 스냅숏은 찍은 순간의 상태라서, 다음 단계에서 이 파일이 복원본에 없어야 합니다.

VolumeSnapshot 의 spec.source.persistentVolumeClaimName 이 원본입니다. readyToUse 는 kubectl get volumesnapshot snap1 의 READYTOUSE 칸입니다. Ceph 쪽에서는 RBD 이미지의 스냅숏(실제로는 그 스냅숏에서 복제한 이미지)으로 보입니다 — toolbox 에서 rbd ls -l ceph-blockpool 로 확인해 보세요.

스냅숏에서 새 볼륨으로 복원한다

snap1 에서 PVC restored(2Gi, ceph-block)를 만들고 controlplane 에 뜬 파드 restored 에 붙이세요. 복원본의 /data/blob 체크섬이 /root/rook/sum-blob.txt 와 같고, /data/after.txt 는 없어야 합니다.

PVC 의 spec.dataSource 에 {kind: VolumeSnapshot, name: snap1, apiGroup: snapshot.storage.k8s.io} 를 적습니다. 크기는 스냅숏을 찍을 때의 원본(2Gi)보다 작을 수 없습니다. RWO 라도 새 PVC 는 새 RBD 이미지라서 app 이 붙어 있어도 따로 붙습니다.

지금의 볼륨을 통째로 복제한다

PVC vol 을 원본으로 하는 복제 PVC cloned(2Gi, ceph-block)를 만들고 controlplane 의 파드 cloned 에 붙이세요. 복제본에는 /data/blob(체크섬 같음)과 /data/after.txt 가 모두 있어야 합니다. 마지막으로 toolbox 에서 rbd ls -l ceph-blockpool 출력을 /root/rook/rbd-ls.txt 에 저장하세요.

복제는 dataSource: {kind: PersistentVolumeClaim, name: vol} 입니다. 스냅숏 복원과 달리 '지금' 의 상태를 뜹니다. rbd ls -l 에서 이미지 셋(원본·복원·복제)과 스냅숏이 어떻게 이어져 있는지(PARENT 칸) 읽어 보세요.