OpenStack 컨트롤러 노드의 디스크 용량 부족을 Ceph RBD로 해결하기 위해, Ceph 클라이언트 설치·전용 사용자 권한 설정·Data Pool 및 500 GB RBD 이미지 생성·이미지 매핑·XFS 포맷·fstab 등록·rsync를 이용한 기존 OpenSearch 데이터 이전·Kolla Ansible 설정 수정·서비스 재배포 과정을 단계별로 안내하고, exclusive‑lock 사용 시 발생하는 Permission Denied 문제 해결을 위해 mon 권한에 blocklist 명령을 추가하고, 재부팅 시 자동 매핑·마운트를 위한 rbdmap 서비스 설정까지 포함한다.
서론
Kolla Ansible로 배포한 OpenStack Controller 노드에서 용량 부족 문제가 발생했다. 문제의 원인은 단순했다. 디스크 용량이 250GB밖에 되지 않았고, 이 제한된 공간에 각종 로그들이 OpenSearch를 통해 지속적으로 수집되고 있었기 때문이다.
잔여 용량이 30GB 남은 시점에서 대안을 찾아야 했다. 별도의 스토리지로 사용할 수 있는 옵션은 Ceph 뿐이었다. 따라서 이 글에서는 Ceph RBD(RADOS Block Device)를 Controller 노드에 마운트하고, OpenSearch 데이터 볼륨을 해당 위치로 이전하는 전체 과정을 다룬다.
📌
RBD(RADOS Block Device)란?
RBD는 Ceph의 분산 블록 스토리지 기능으로, 가상 블록 디바이스를 제공한다. 씬 프로비저닝(thin-provisioning)을 지원하여 실제 사용량만큼만 물리적 공간을 점유하며, 스냅샷과 클론 기능을 통해 데이터 보호와 복제가 가능하다. OpenStack Cinder, Kubernetes PV 등 다양한 환경에서 백엔드 스토리지로 활용된다.
1. Ceph 클라이언트 설치 (Controller 노드)
Controller 노드에서 Ceph 클러스터에 접근하기 위해서는 먼저 기본 라이브러리 설치가 필요하다. 아래 명령어를 통해 ceph-common 패키지를 설치한다.
역할: Ceph 클러스터의 상태를 추적하고 관리하는 핵심 데몬. 클러스터 맵(cluster map)을 유지하며, 클러스터의 토폴로지와 상태 정보를 포함한다.
권한 옵션:
allow r: 읽기 권한. 클러스터 맵과 상태 정보 조회 가능.
allow rw: 읽기/쓰기 권한. 클러스터 설정 변경 가능.
allow *: 모든 권한. Monitor 데몬 완전 제어.
osd (Object Storage Daemon)
역할: 실제 데이터를 저장하고 복제, 복구, 재조정 등의 작업을 수행하는 데몬. 각 물리적 디스크마다 하나의 OSD가 실행된다.
권한 옵션:
allow r: 데이터 읽기만 가능.
allow w: 데이터 쓰기만 가능.
allow x: 실행 권한. RADOS 클래스 메서드 실행 가능.
allow rwx: 읽기/쓰기/실행 모든 권한.
pool=<name>: 특정 풀에만 권한을 제한.
mgr (Manager)
역할: 클러스터 모니터링, 통계 수집, 대시보드 제공 등의 관리 기능을 담당하는 데몬. 런타임 메트릭과 클러스터 상태를 제공한다.
권한 옵션:
allow r: 클러스터 통계와 상태 정보 읽기 가능.
allow rw: 관리 명령 실행 및 설정 변경 가능.
allow *: 모든 관리 작업 수행 가능.
위 명령어에서 설정한 권한 분석:
mon 'allow r': 클러스터 상태 조회만 가능
osd 'allow rwx pool=opensearch_data': opensearch_data 풀에서 읽기/쓰기/실행 모든 작업 가능
mgr 'allow r': 클러스터 통계 및 메트릭 조회만 가능
이러한 권한 설정은 최소 권한 원칙(Principle of Least Privilege)을 따르며, opensearch2rbd 사용자가 필요한 작업(데이터 저장/조회)만 수행할 수 있도록 제한한다.
생성된 keyring 파일은 /etc/ceph 위치에 저장된다.
해당 키를 각 Controller 노드의 동일 위치에 복사해둔다.
3. Data Pool 생성 (Ceph Cluster)
Controller에서 접근할 Data Pool을 생성해야 한다. Data Pool은 Ceph에서 제공하는 RADOS(Reliable Autonomic Distributed Object Store) 위에 생성되는 논리적 파티션이라고 이해하면 된다.
bash
# Data Pool 생성
ceph osd pool create opensearch_data
# 복제본(Replicas) 개수 지정 (기본값: 3)
ceph osd pool set opensearch_data size 3
# 어떤 애플리케이션이 사용하는 Pool인지 지정 (RBD가 사용)
ceph osd pool application enable opensearch_data rbd
# PG(Placement Group) 개수 지정
ceph osd pool set opensearch_data pg_num 8
📊
PG(Placement Group) 수 계산 공식
적절한 PG 수는 클러스터 성능에 직접적인 영향을 미친다. Ceph 공식 문서에서 권장하는 계산 공식은 다음과 같다:
PGtotal=replica_sizeOSDcount×100
예를 들어, OSD가 10개이고 복제본이 3개인 경우:
PGtotal=310×100≈333
가장 가까운 2의 거듭제곱인 256 또는 512를 선택
소규모 테스트 환경에서는 8~32개의 PG로 시작하고, 운영 환경에서는 위 공식을 참고하여 설정하는 것을 권장한다.
4. RBD 이미지 생성 (Ceph Cluster)
위에서 생성한 Pool에 500GB의 실제 볼륨(이미지)을 생성한다. 이미지 이름은 opensearch1으로 지정했다.
bash
rbd create opensearch_data/opensearch1 --size 512000 --image-feature layering,exclusive-lock,object-map,fast-diff
rbd info opensearch_data/opensearch1
🔧
RBD 이미지 기능(Feature) 설명
layering: 스냅샷 기반 클론 생성 지원. Copy-on-Write 방식으로 효율적인 복제 가능.
exclusive-lock: 동시 쓰기 방지를 위한 배타적 잠금. 단일 클라이언트만 쓰기 가능.
object-map: 할당된 객체 추적. 스냅샷 생성, 내보내기 등의 작업 속도 향상.
fast-diff: 스냅샷 간 차이 계산 고속화. object-map과 함께 사용 시 효과적.
주의: 일부 커널 버전에서는 특정 기능을 지원하지 않을 수 있다. 호환성 문제 발생 시 rbd feature disable 명령어로 비활성화할 수 있다.
5. Ceph 연결 확인 (Controller 노드)
Controller 노드로 돌아와서 연결 작업을 진행한다.
5.1 설정 파일 복사
앞서 생성한 ceph.client.opensearch2rbd.keyring 파일과 Ceph 클러스터의 ceph.conf 파일을 Controller 노드로 복사한다.
opensearch_datadir_volume 변수만 수정하면 원하는 위치를 데이터 볼륨 경로로 마운트할 수 있다.
8. 서비스 재배포
마지막으로 다음 순서로 작업을 완료한다:
Controller 노드의 OpenSearch 컨테이너 종료
rsync 명령어로 최종 백업 진행 (데이터 정합성 보장)
Kolla Ansible로 재배포
bash
kolla-ansible reconfigure -i multinode --limit control
9. 삽질의 역사: 재부팅 후 rbd map Permission Denied 😭
모든 설정을 마치고 안심하며 Controller 노드를 재부팅했다. 그런데 rbd map을 수행하면 Permission Denied 오류가 발생했다.
bash
sudo rbd map --pool opensearch_data opensearch1 --id opensearch2rbd
rbd: sysfs write failed
In some cases useful info is found in syslog - try "dmesg | tail".
rbd: map failed: (13) Permission denied
ceph -s 명령어로 클러스터 연결은 정상적으로 확인되는데, map만 실패하는 상황이었다. dmesg | tail을 확인해보니 원인이 명확했다.
bash
[58508.476702] rbd: rbd0: breaking header lock owned by client92169142
[58508.477394] rbd: rbd0: failed to blocklist client92169142: -13
[58508.477399] rbd: rbd0: failed to acquire lock: -13
9.1 원인 분석
RBD 이미지에 exclusive-lock 기능이 활성화되어 있기 때문에, 한 번에 하나의 클라이언트만 쓰기 lock을 잡을 수 있다. 재부팅 전에 client92169142가 lock을 보유하고 있었는데, 재부팅 과정에서 lock이 정상적으로 해제되지 않은 채 남아있었다.
새로운 클라이언트가 map을 시도하면서 이전 lock holder를 blocklist에 추가하려고 했지만, 이 blocklist 작업은 Monitor에 명령을 보내는 것이다. 문제는 opensearch2rbd 사용자의 mon 권한이 allow r(읽기 전용)이라서 blocklist 명령을 실행할 권한이 없었던 것이다.
🔑
핵심 포인트: exclusive-lock 기능을 사용하는 RBD 이미지를 커널 클라이언트(krbd)로 map하는 경우, lock 경합 시 이전 holder를 blocklist하기 위한 mon 권한이 반드시 필요하다. 처음 map할 때는 lock을 잡고 있는 이전 클라이언트가 없었기 때문에 blocklist 요청 자체가 필요 없어서 문제가 드러나지 않았다.
9.2 해결 방법
Ceph 클러스터(cephadm shell)에서 opensearch2rbd 사용자의 mon 권한에 blocklist 명령 허용을 추가한다.
위 문제를 해결한 뒤, 한 가지 더 고민이 남았다. 매번 재부팅할 때마다 수동으로 rbd map을 실행할 수는 없다. ceph-common 패키지에 포함된 rbdmap 서비스를 활용하면 부팅 시 자동으로 RBD 이미지를 map/mount하고, 종료 시 unmount/unmap을 처리해준다.
10.1 /etc/ceph/rbdmap 파일 설정
rbdmap 서비스는 /etc/ceph/rbdmap 설정 파일을 파싱하여 어떤 이미지를 map할지 결정한다. 형식은 IMAGESPEC RBDOPTS이며, 탭이나 공백으로 구분한다.