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

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

Helm 으로 Rook-Ceph 세우기 — 빈 디스크 셋에서 PVC 까지

TT Lab 에서 이어서 보기

목표

VM 네 대(컨트롤 플레인 하나, 스토리지 노드 셋)로 된 쿠버네티스에 Helm 으로 Rook 오퍼레이터와 Ceph 클러스터를 설치합니다. 스토리지 노드마다 붙은 빈 디스크 17GiB 셋, 합계 51GiB 가 Ceph 의 원시 용량이 되고, 3벌 복제를 거쳐 쓸 수 있는 블록 볼륨이 되기까지를 따라갑니다.

왜 중요한가

지금까지 PVC 는 누군가 이미 만들어 둔 저장소(클라우드 디스크, NFS)에 이어 붙이는 것이었습니다. Rook-Ceph 는 그 저장소 자체를 클러스터 안에 세웁니다. 그래서 세 가지를 직접 결정하게 됩니다. 어느 디스크를 넘길지, 데몬이 메모리를 얼마나 쓸지, 몇 벌을 복제할지입니다. 기본값은 서버급 노드를 전제로 합니다 — OSD 하나가 메모리 4GiB 를 요청합니다. 작은 노드에서 기본값으로 설치하면 파드가 뜨지 못하거나, 뜬 뒤 메모리 한도에 걸려 죽습니다. 이 실습의 스토리지 노드는 4GiB 라서 그 문제를 처음부터 풀어야 합니다.

단계

  1. controlplane 에서 ssh node01 처럼 세 스토리지 노드(node01·node02·node03)에 들어가, 파일시스템도 파티션도 없는 17GiB 디스크를 찾으세요. 세 노드를 /root/rook/disks.txt 에 노드 장치 크기 한 줄씩 적습니다(예: node01 /dev/vdX 17G).
  2. Helm 저장소 rook-release(https://charts.rook.io/release)를 더하고, 차트 rook-release/rook-ceph v1.21.1 을 릴리스 이름 rook-ceph, 네임스페이스 rook-ceph 에 설치하세요. 오퍼레이터 Deployment rook-ceph-operator 가 Available 이어야 합니다.
  3. Helm 저장소 ceph-csi-operator(https://ceph.github.io/ceph-csi-operator)를 더하고, 차트 ceph-csi-operator/ceph-csi-drivers 1.1.0 을 릴리스 이름 ceph-csi-drivers, 네임스페이스 rook-ceph 에 Rook 이 권하는 values(https://raw.githubusercontent.com/rook/rook/v1.21.1/deploy/charts/ceph-csi-drivers/values.yaml)로 설치하세요. 받은 values 는 /root/rook/csi-drivers-values.yaml 에 두고 -f 로 넘깁니다. CSIDriver rook-ceph.rbd.csi.ceph.com·rook-ceph.cephfs.csi.ceph.com 이 생기고, RBD 노드 플러그인이 네 노드 모두에서 떠야 합니다.
  4. 클러스터 차트(rook-ceph-cluster)에 넘길 /root/rook/cluster-values.yaml 을 만드세요. 지켜야 할 것: mon 3개·mgr 1개, OSD 컨테이너 메모리 한도 2Gi 이하와 그보다 작은 osd_memory_target(cephConfig 의 osd 절), mon 메모리 한도 1Gi 이하, storage.useAllDevices: false 와 빈 디스크의 by-id 이름만 고르는 devicePathFilter, 모든 Ceph 데몬을 라벨 role=storage 노드에만 두는 placement.all, toolbox 켜기, 그리고 cephFileSystems: []·cephObjectStores: [].
  5. 차트 rook-release/rook-ceph-cluster v1.21.1 을 릴리스 이름 rook-ceph-cluster, 네임스페이스 rook-ceph 에 /root/rook/cluster-values.yaml 로 설치하세요. 릴리스가 deployed 이고, CephCluster rook-ceph 가 만들어져야 합니다.
  6. CephCluster 가 Ready 가 되면 toolbox 에서 ceph health detail 을 읽으세요. 이 VM 의 커널(6.8)은 cephx 의 aes 키만 읽을 수 있어서 Ceph 20 이 AUTH_INSECURE_ 로 시작하는 경고 셋을 냅니다. 이유를 확인했으면 그 셋만 ceph health mute <코드> --sticky 로 묵음 처리해 HEALTH_OK 로 만들고, ceph status 출력을 /root/rook/status.txt 에 저장하세요. mon 3개가 정족수를 이루고 OSD 3개가 모두 up·in 이어야 합니다.
  7. ceph osd tree 와 ceph osd metadata 로 OSD 마다 어느 노드의 어느 장치를 쓰는지 확인해 /root/rook/osd-map.txt 에 osd.번호 노드 장치 한 줄씩 적으세요. OSD 셋이 서로 다른 노드에 있어야 하고, 각 장치가 1단계에서 찾은 빈 디스크여야 합니다.
  8. toolbox 의 ceph df 로 원시 용량과 풀 ceph-blockpool 이 실제로 쓸 수 있는 용량(MAX AVAIL)을 GiB 로 읽고, ceph config get osd osd_memory_target 로 OSD 메모리 목표를 읽어 /root/rook/capacity.txt 에 raw_gib=·usable_gib=·osd_memory_target= 세 줄로 적으세요(GiB 는 소수 첫째 자리까지, 목표는 바이트).
  9. 네임스페이스 demo 에 StorageClass ceph-block 의 1Gi PVC data 를 만들고, node01 에 뜬 파드 writer 가 무작위 토큰을 /data/token 에 쓰게 하세요. writer 의 출력(토큰)을 /root/rook/written.txt 에 저장하고 writer 를 지운 뒤, controlplane 에 뜬 파드 reader 가 같은 PVC 를 붙여 읽은 값을 /root/rook/readback.txt 에 저장합니다. 두 파일이 같아야 하고, PVC 의 볼륨이 ceph-blockpool 의 RBD 이미지로 있어야 합니다.

참고

세 스토리지 노드에서 빈 디스크를 찾는다

controlplane 에서 ssh node01 처럼 세 스토리지 노드(node01·node02·node03)에 들어가, 파일시스템도 파티션도 없는 17GiB 디스크를 찾으세요. 세 노드를 /root/rook/disks.txt 에 노드 장치 크기 한 줄씩 적습니다(예: node01 /dev/vdX 17G).

lsblk -f 를 보면 디스크마다 FSTYPE 칸이 있습니다. 루트(vda)·cloud-init(vdb)·스크래치(vdc)에는 무언가 적혀 있고, 한 디스크만 비어 있습니다. 장치 이름은 붙는 순서로 정해지므로, 바뀌지 않는 이름도 함께 보세요 — ls -l /dev/disk/by-id/. 크기는 lsblk -dno SIZE <장치> 의 글자 그대로 적습니다.

Rook 오퍼레이터 차트를 설치한다

Helm 저장소 rook-release(https://charts.rook.io/release)를 더하고, 차트 rook-release/rook-ceph v1.21.1 을 릴리스 이름 rook-ceph, 네임스페이스 rook-ceph 에 설치하세요. 오퍼레이터 Deployment rook-ceph-operator 가 Available 이어야 합니다.

판을 --version 으로 못박지 않으면 오늘 설치한 것과 내일 설치한 것이 달라집니다. 네임스페이스가 없으면 --create-namespace 가 만듭니다. 오퍼레이터 이미지를 받는 동안은 kubectl -n rook-ceph get pods -w 로 지켜보세요.

CSI 드라이버 차트를 설치한다

Helm 저장소 ceph-csi-operator(https://ceph.github.io/ceph-csi-operator)를 더하고, 차트 ceph-csi-operator/ceph-csi-drivers 1.1.0 을 릴리스 이름 ceph-csi-drivers, 네임스페이스 rook-ceph 에 Rook 이 권하는 values(https://raw.githubusercontent.com/rook/rook/v1.21.1/deploy/charts/ceph-csi-drivers/values.yaml)로 설치하세요. 받은 values 는 /root/rook/csi-drivers-values.yaml 에 두고 -f 로 넘깁니다. CSIDriver rook-ceph.rbd.csi.ceph.com·rook-ceph.cephfs.csi.ceph.com 이 생기고, RBD 노드 플러그인이 네 노드 모두에서 떠야 합니다.

Rook v1.20 부터 CSI 는 세 조각입니다. 오퍼레이터 차트가 ceph-csi-operator 를 함께 깔고, 실제 드라이버(컨트롤러·노드 플러그인)는 이 차트가 Driver 객체로 선언합니다. 이 차트를 빼면 PVC 가 Pending 에 머뭅니다 — 받아 줄 드라이버가 없기 때문입니다. Rook 의 values 는 드라이버 이름 앞에 rook-ceph. 을 붙여 StorageClass 의 provisioner 와 맞춥니다. 노드 플러그인은 DaemonSet 이라 볼륨을 쓰는 controlplane 에도 떠야 합니다 — kubectl -n rook-ceph get ds.

실습 VM 에 맞게 클러스터 values 를 쓴다

클러스터 차트(rook-ceph-cluster)에 넘길 /root/rook/cluster-values.yaml 을 만드세요. 지켜야 할 것: mon 3개·mgr 1개, OSD 컨테이너 메모리 한도 2Gi 이하와 그보다 작은 osd_memory_target(cephConfig 의 osd 절), mon 메모리 한도 1Gi 이하, storage.useAllDevices: false 와 빈 디스크의 by-id 이름만 고르는 devicePathFilter, 모든 Ceph 데몬을 라벨 role=storage 노드에만 두는 placement.all, toolbox 켜기, 그리고 cephFileSystems: []·cephObjectStores: [].

차트 기본값은 helm show values rook-release/rook-ceph-cluster --version v1.21.1 로 봅니다. OSD 하나가 요청 4Gi 라서 기본값 그대로면 4GiB VM 에 OSD 가 뜨지 못합니다. 목록(cephFileSystems 등)은 values 에서 합쳐지지 않고 통째로 바뀝니다 — 비워 두지 않으면 차트 기본값이 파일시스템과 오브젝트 저장소까지 만듭니다. 필터는 정규식이고 ^…$ 로 양끝을 묶어야 비슷한 이름까지 잡지 않습니다.

values 로 클러스터 차트를 설치한다

차트 rook-release/rook-ceph-cluster v1.21.1 을 릴리스 이름 rook-ceph-cluster, 네임스페이스 rook-ceph 에 /root/rook/cluster-values.yaml 로 설치하세요. 릴리스가 deployed 이고, CephCluster rook-ceph 가 만들어져야 합니다.

values 파일은 -f 로 넘깁니다. 설치 명령은 금방 끝나지만 클러스터가 서는 것은 그다음부터입니다 — 오퍼레이터가 CephCluster 를 읽고 mon → mgr → OSD 순으로 세웁니다. kubectl -n rook-ceph get pods -w 로 그 순서를 지켜보세요. 실제로 들어간 값은 helm get values 로 확인합니다.

HEALTH_OK 가 될 때까지 지켜보고, 경고의 이유를 읽는다

CephCluster 가 Ready 가 되면 toolbox 에서 ceph health detail 을 읽으세요. 이 VM 의 커널(6.8)은 cephx 의 aes 키만 읽을 수 있어서 Ceph 20 이 AUTH_INSECURE_ 로 시작하는 경고 셋을 냅니다. 이유를 확인했으면 그 셋만 ceph health mute <코드> --sticky 로 묵음 처리해 HEALTH_OK 로 만들고, ceph status 출력을 /root/rook/status.txt 에 저장하세요. mon 3개가 정족수를 이루고 OSD 3개가 모두 up·in 이어야 합니다.

toolbox 는 Deployment rook-ceph-tools 입니다 — kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph health detail. values 의 security.cephx.csi.keyType: aes(차트 기본값)가 이유를 적어 둡니다 — 커널 7.0 보다 낮은 노드는 새 키 형식을 못 읽습니다. 경고를 끄는 것은 원인을 알고 받아들일 때만입니다. --sticky 가 없으면 경고 대상의 수가 바뀌는 순간(예: 3실습에서 CephFS 를 켤 때) 묵음이 풀립니다. 처음 몇 분의 PG 생성 중 경고는 기다리면 사라집니다.

OSD 셋이 각 노드의 빈 디스크를 잡았는지 본다

ceph osd tree 와 ceph osd metadata 로 OSD 마다 어느 노드의 어느 장치를 쓰는지 확인해 /root/rook/osd-map.txt 에 osd.번호 노드 장치 한 줄씩 적으세요. OSD 셋이 서로 다른 노드에 있어야 하고, 각 장치가 1단계에서 찾은 빈 디스크여야 합니다.

ceph osd metadata 0 의 hostname 과 devices(또는 bluestore_bdev_dev_node)를 보세요. toolbox 안에서 -f json 을 붙이면 jq 로 고르기 쉽습니다(jq 는 controlplane 에 있습니다). 노드에서 lsblk -f 를 다시 보면 그 디스크의 FSTYPE 이 무엇으로 바뀌었는지도 보입니다.

원시 용량과 쓸 수 있는 용량을 잰다

toolbox 의 ceph df 로 원시 용량과 풀 ceph-blockpool 이 실제로 쓸 수 있는 용량(MAX AVAIL)을 GiB 로 읽고, ceph config get osd osd_memory_target 로 OSD 메모리 목표를 읽어 /root/rook/capacity.txt 에 raw_gib=·usable_gib=·osd_memory_target= 세 줄로 적으세요(GiB 는 소수 첫째 자리까지, 목표는 바이트).

ceph df -f json 의 stats.total_bytes 가 원시 용량이고, 풀 항목의 stats.max_avail 이 그 풀에 더 쓸 수 있는 양입니다. 디스크 셋이 17GiB 씩이니 원시는 약 51GiB 입니다. 3벌 복제라 쓸 수 있는 것은 원시의 3분의 1보다 더 작습니다 — 왜 더 작은지 숫자로 설명할 수 있어야 합니다(가득 참 비율, 이미 쓴 공간). GiB 는 바이트를 2의 30제곱으로 나눈 값입니다.

RBD 볼륨에 쓰고 다른 노드에서 읽는다

네임스페이스 demo 에 StorageClass ceph-block 의 1Gi PVC data 를 만들고, node01 에 뜬 파드 writer 가 무작위 토큰을 /data/token 에 쓰게 하세요. writer 의 출력(토큰)을 /root/rook/written.txt 에 저장하고 writer 를 지운 뒤, controlplane 에 뜬 파드 reader 가 같은 PVC 를 붙여 읽은 값을 /root/rook/readback.txt 에 저장합니다. 두 파일이 같아야 하고, PVC 의 볼륨이 ceph-blockpool 의 RBD 이미지로 있어야 합니다.

이미지는 registry.k8s.io/e2e-test-images/busybox:1.36.1-1 를 쓰세요(노드에 미리 받아 두지 않았으니 처음엔 받는 시간이 듭니다). 노드를 고르는 것은 nodeSelector: {kubernetes.io/hostname: node01} 입니다. RBD 는 한 번에 한 노드만 붙일 수 있는 블록 장치(ReadWriteOnce)라 writer 가 남아 있으면 reader 가 붙지 못합니다. PV 의 spec.csi.volumeAttributes.imageName 이 Ceph 쪽 이미지 이름이고, toolbox 에서 rbd ls ceph-blockpool 로 확인합니다.