Skip to document
pieroot log
Markdown Preview

OpenStack의 저장소 부족 문제를 Ceph RBD로 해결하는 완벽 가이드

Frontmatter

OpenStack 컨트롤러 노드의 디스크 용량 부족을 Ceph RBD로 해결하기 위해, Ceph 클라이언트 설치·전용 사용자 권한 설정·Data Pool 및 500 GB RBD 이미지 생성·이미지 매핑·XFS 포맷·fstab 등록·rsync를 이용한 기존 OpenSearch 데이터 이전·Kolla Ansible 설정 수정·서비스 재배포 과정을 단계별로 안내하고, exclusive‑lock 사용 시 발생하는 Permission Denied 문제 해결을 위해 mon 권한에 blocklist 명령을 추가하고, 재부팅 시 자동 매핑·마운트를 위한 rbdmap 서비스 설정까지 포함한다.

OpenStack의 저장소 부족 문제를 Ceph RBD로 해결하는 완벽 가이드

서론

Kolla Ansible로 배포한 OpenStack Controller 노드에서 용량 부족 문제가 발생했다. 문제의 원인은 단순했다. 디스크 용량이 250GB밖에 되지 않았고, 이 제한된 공간에 각종 로그들이 OpenSearch를 통해 지속적으로 수집되고 있었기 때문이다.
notion image
잔여 용량이 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 패키지를 설치한다.
bash
# Ubuntu/Debian
sudo apt-get update && sudo apt-get install -y ceph-common

# RHEL/CentOS/Rocky/Alma
sudo dnf install -y ceph-common
설치가 완료되면 /etc/ceph 디렉토리가 자동으로 생성된다. 이 디렉토리는 Ceph 연결에 필요한 설정 파일과 인증 키를 저장하는 위치이다.
bash
cd /etc/ceph
모두 작업하고 캡쳐하여 필요한 내용이 모두 담겨있다
모두 작업하고 캡쳐하여 필요한 내용이 모두 담겨있다

2. Ceph 연결용 User 생성 (Ceph Cluster)

각 Controller에서 Ceph 클러스터에 접근하기 위한 전용 사용자를 생성해야 한다.
notion image
Ceph 대시보드를 통해 사용자를 생성할 수도 있지만, 향후 대시보드 인터페이스가 변경될 경우를 대비하여 CLI 명령어를 통해 진행하는 것을 권장한다.

2.1 Ceph 관리자 터미널 접속

아래 명령어를 통해 Ceph 관리자 터미널에 접근한다.
bash
sudo cephadm shell
notion image

2.2 사용자 및 권한 설정

Controller에서 RBD에 접근하기 위한 사용자와 최소 권한을 설정한다.
bash
sudo ceph auth get-or-create client.opensearch2rbd \
  mon 'allow r' \
  osd 'allow rwx pool=opensearch_data' \
  mgr 'allow r' \
  -o /etc/ceph/ceph.client.opensearch2rbd.keyring
📚

Ceph 권한 구성 요소 상세 설명

mon (Monitor)
  • 역할: 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 위치에 저장된다.
notion image
해당 키를 각 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=OSDcount×100replica_sizePG_{total} = \frac{OSD_{count} \times 100}{replica\_size}
예를 들어, OSD가 10개이고 복제본이 3개인 경우:
  • PGtotal=10×1003≈333PG_{total} = \frac{10 \times 100}{3} \approx 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
notion image
🔧
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 노드로 복사한다.
notion image

5.2 연결 테스트

복사한 keyring과 conf 파일로 실제 연결과 인증이 가능한지 테스트한다.
bash
ceph -c /etc/ceph/ceph.conf -n client.opensearch2rbd -k /etc/ceph/ceph.client.opensearch2rbd.keyring -s
notion image
위 명령어 실행 결과, 클러스터 상태가 정상적으로 출력되면 연결이 성공한 것이다. 만약 통신이 실패한다면 다음 사항들을 확인한다:
  • 네트워크 연결 상태 (방화벽, 포트 개방 여부)
  • 계정 정보와 Pool 설정
  • keyring 파일 권한 (600 권장)

5.3 RBD 이미지 매핑

Ceph RBD 이미지를 현재 호스트에 매핑한다. 매핑된 디바이스는 /dev/rbd/<pool>/<image> 경로에 생성된다.
bash
sudo rbd map --pool opensearch_data opensearch1 --id opensearch2rbd
notion image

5.4 파일시스템 포맷

매핑된 이미지를 사용하기 위해 파일시스템으로 포맷한다. 대용량 데이터 저장에 적합한 XFS를 사용한다.
bash
sudo mkfs.xfs -f /dev/rbd/opensearch_data/opensearch1
notion image
💾
XFS vs EXT4 선택 기준
항목
XFS
EXT4
최대 파일 크기
8 EiB
16 TiB
최대 볼륨 크기
8 EiB
1 EiB
대용량 파일 성능
우수
보통
병렬 I/O
우수
보통
온라인 축소
불가
가능
OpenSearch와 같이 대용량 로그 데이터를 다루는 경우 XFS가 더 적합하다.

5.5 마운트 및 fstab 등록

실제 사용할 위치에 마운트를 진행한다. 재부팅 시에도 자동으로 마운트되도록 fstab에 등록한다.
bash
sudo mkdir -p /srv/rbd/opensearch
echo "/dev/rbd/opensearch_data/opensearch1 /srv/rbd/opensearch xfs noatime,_netdev,nofail,x-systemd.requires=network-online.target,x-systemd.automount,x-systemd.idle-timeout=10min 0 2" | sudo tee -a /etc/fstab

sudo systemctl daemon-reload
sudo mount /srv/rbd/opensearch

df -h
notion image
⚙️
fstab 옵션 설명
  • noatime: 파일 접근 시간 기록 비활성화. I/O 성능 향상.
  • _netdev: 네트워크 장치임을 표시. 네트워크 연결 후 마운트 시도.
  • nofail: 마운트 실패 시에도 부팅 계속 진행.
  • x-systemd.automount: 자동 마운트 활성화.
  • x-systemd.idle-timeout=10min: 유휴 시 자동 언마운트 시간.

6. 기존 OpenSearch 데이터 이전 (Controller 노드)

기존 Docker 볼륨에 존재하던 데이터를 새로 마운트한 위치로 이전한다. 단순 cp 명령어 대신 rsync를 사용하여 권한, 메타데이터를 보존하면서 안전하게 이전한다.
bash
rsync -aHAX --numeric-ids --info=progress2 \
  /var/lib/docker/volumes/opensearch/_data/  \
  /srv/rbd/opensearch/

rsync 옵션 상세 설명

-aHAX 옵션 조합:
  • -a (archive): 권한, 소유자, 타임스탬프, 심볼릭 링크 등 대부분의 메타데이터를 유지하면서 복사
  • -H: 하드 링크 보존. 같은 inode를 공유하던 파일 구조 유지
  • -A: ACL(접근 제어 목록) 보존
  • -X: 확장 속성(xattr) 보존. SELinux 컨텍스트 등도 유지
이 조합은 원본을 최대한 그대로 옮기기 위한 옵션이다. Docker 볼륨의 권한, 소유자, 라벨이 변경되면 컨테이너가 오동작할 수 있기 때문에 반드시 사용해야 한다.
--numeric-ids:
  • 사용자/그룹을 이름이 아니라 UID/GID 숫자 그대로 복사
  • 마이그레이션 대상 서버에서 /etc/passwd 계정명이 다르더라도 UID/GID가 같으면 권한이 유지됨
  • 컨테이너 UID 매핑을 고려할 때 안전한 선택
--info=progress2:
  • 전송 진행률을 요약 형식으로 표시
  • 전체 전송 속도, 남은 파일 수, 예상 완료 시간 등을 실시간으로 표시
  • 대용량 데이터 이동 시 진행 상황 모니터링에 유용
이전이 완료되면 rbd0 볼륨에 기존 데이터가 정상적으로 올라간 것을 확인할 수 있다. 250GB 중 142GB가 OpenSearch 데이터였으니 용량 부족이 발생할 수밖에 없었다.
notion image

7. Kolla Ansible globals.yml 수정

Kolla Ansible로 OpenSearch를 배포했기 때문에, 컨테이너의 볼륨 위치를 변경하려면 globals.yml 파일을 수정해야 한다.
변경 사항은 간단하다. 다음 한 줄을 추가하면 된다:
yaml
opensearch_datadir_volume: "/srv/rbd/opensearch"
OpenSearch의 기본 볼륨 설정은 다음과 같이 구성되어 있다:
bash
opensearch_default_volumes:
  - " node_config_directory /opensearch/: container_config_directory /"
  - "/etc/localtime:/etc/localtime:ro"
  - " '/etc/timezone:/etc/timezone:ro' if ansible_facts.os_family == 'Debian' else '' "
  - " opensearch_datadir_volume :/var/lib/opensearch/data"
  - "kolla_logs:/var/log/kolla/"
opensearch_datadir_volume 변수만 수정하면 원하는 위치를 데이터 볼륨 경로로 마운트할 수 있다.

8. 서비스 재배포

마지막으로 다음 순서로 작업을 완료한다:
  1. Controller 노드의 OpenSearch 컨테이너 종료
  1. rsync 명령어로 최종 백업 진행 (데이터 정합성 보장)
  1. 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 명령 허용을 추가한다.
bash
sudo cephadm shell
bash
ceph auth caps client.opensearch2rbd \
  mon 'allow r, allow command "osd blocklist"' \
  osd 'allow rwx pool=opensearch_data' \
  mgr 'allow r'
⚠️
주의: ceph auth caps는 기존 권한을 전체 덮어쓰기한다. 따라서 기존 osd, mgr 권한도 반드시 함께 명시해야 한다. 누락하면 해당 권한이 사라진다.
권한 변경 후 Controller 노드에서 다시 map을 시도하면 정상적으로 동작한다.
bash
sudo rbd map --pool opensearch_data opensearch1 --id opensearch2rbd

10. 재부팅 시 자동 RBD 매핑: rbdmap 서비스

위 문제를 해결한 뒤, 한 가지 더 고민이 남았다. 매번 재부팅할 때마다 수동으로 rbd map을 실행할 수는 없다. ceph-common 패키지에 포함된 rbdmap 서비스를 활용하면 부팅 시 자동으로 RBD 이미지를 map/mount하고, 종료 시 unmount/unmap을 처리해준다.

10.1 /etc/ceph/rbdmap 파일 설정

rbdmap 서비스는 /etc/ceph/rbdmap 설정 파일을 파싱하여 어떤 이미지를 map할지 결정한다. 형식은 IMAGESPEC RBDOPTS이며, 탭이나 공백으로 구분한다.
bash
sudo vi /etc/ceph/rbdmap
다음 내용을 추가한다:
javascript
opensearch_data/opensearch1    id=opensearch2rbd,keyring=/etc/ceph/ceph.client.opensearch2rbd.keyring
📚
rbdmap 설정 파일 형식
javascript
IMAGESPEC    RBDOPTS
  • IMAGESPEC: <pool>/<image> 형식으로 RBD 이미지를 지정
  • RBDOPTS: rbd map 명령에 전달할 옵션들을 쉼표로 구분하여 지정
    • id: Ceph 사용자 이름 (client. 접두사 제외)
    • keyring: 인증 키링 파일 경로
    • lock_on_read, queue_depth 등 추가 옵션도 지정 가능

10.2 fstab 수정

rbdmap 서비스는 map 후 fstab에서 noauto 옵션이 설정된 항목을 찾아 자동으로 mount해준다. 따라서 기존 fstab 항목을 수정해야 한다.
bash
sudo vi /etc/fstab
기존 항목을 다음과 같이 변경한다:
bash
# 기존 항목 (삭제 또는 주석처리)
# /dev/rbd/opensearch_data/opensearch1 /srv/rbd/opensearch xfs noatime,_netdev,nofail,x-systemd.requires=network-online.target,x-systemd.automount,x-systemd.idle-timeout=10min 0 2

# rbdmap 서비스와 연동하는 새 항목
/dev/rbd/opensearch_data/opensearch1 /srv/rbd/opensearch xfs noauto,noatime 0 0
💡
왜 noauto로 변경하는가?
rbdmap 서비스가 RBD map → fstab의 noauto 항목 mount → 종료 시 unmount → unmap 순서를 자동으로 처리해준다. 기존의 _netdev, x-systemd.* 옵션들은 rbdmap 서비스가 대신 관리하므로 더 이상 필요하지 않다.

10.3 rbdmap 서비스 활성화

bash
sudo systemctl enable rbdmap.service

10.4 동작 확인

현재 매핑을 해제한 뒤 rbdmap 서비스로 다시 map/mount가 되는지 테스트한다.
bash
# 현재 매핑 해제
sudo umount /srv/rbd/opensearch
sudo rbd unmap /dev/rbd/opensearch_data/opensearch1

# rbdmap 서비스로 map + mount
sudo systemctl start rbdmap.service

# 확인
rbd showmapped
df -h | grep rbd
⚙️
rbdmap 서비스 동작 흐름
javascript
부팅 → 네트워크 활성화 → rbdmap.service 시작
  → /etc/ceph/rbdmap 파싱
  → rbd map 수행
  → /etc/fstab에서 noauto 항목 찾아서 mount
  → 종료 시 자동 unmount + unmap
shutdown 시 자동으로 unmap이 수행되므로, 다음 재부팅 때 이전 lock holder가 남아있는 문제(9장의 blocklist 이슈)가 발생할 확률이 크게 줄어든다.

마무리

이 가이드에서는 Ceph RBD를 활용하여 OpenStack Controller 노드의 용량 부족 문제를 해결하는 방법을 다루었다. 핵심 단계를 요약하면 다음과 같다:
  1. Ceph 클라이언트 설치: Controller 노드에 ceph-common 패키지 설치
  1. 사용자 권한 설정: 최소 권한 원칙에 따른 전용 사용자 생성
  1. Pool 및 RBD 이미지 생성: 논리적 저장 공간 구성
  1. 마운트 및 데이터 이전: rsync를 통한 안전한 데이터 마이그레이션
  1. Kolla Ansible 설정 변경: 새로운 볼륨 경로 반영
  1. Ceph 사용자 권한 보완: exclusive-lock 사용 시 blocklist 권한 추가
  1. rbdmap 서비스 설정: 재부팅 시 자동 RBD 매핑/마운트 구성
이 방법은 OpenSearch뿐만 아니라 다른 서비스의 데이터 볼륨 확장에도 동일하게 적용할 수 있다.

참고 자료