13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] CephFS

  • [OpenStack] OpenStack Manila 도입 1년 회고

    [OpenStack] OpenStack Manila 도입 1년 회고

    [OpenStack] OpenStack Manila 도입 1년 회고

    프라이빗 클라우드 파일 스토리지 이야기를 하면, 많은 분들이 처음엔 Cinder(신더, 블록 스토리지)나 Swift(스위프트, 오브젝트 스토리지)부터 떠올리시더라고요. 저도 그랬습니다. 그런데 VM(가상머신) 여러 대와 컨테이너 워크로드가 같이 굴러가기 시작하면, 결국 팀에서 꼭 묻는 질문이 하나 나옵니다. “공유 폴더처럼 쓸 수 있는 스토리지는 없나요?” 바로 그 지점에서 OpenStack Manila가 등장합니다.

    저는 지난 1년 동안 홈랩과 사내와 유사한 형태의 프라이빗 환경에서 Manila 운영 방식을 꽤 집요하게 다듬어봤습니다. 처음엔 “이게 Nova(노바, 컴퓨트)나 Neutron(뉴트론, 네트워크)처럼 그냥 붙이면 되겠지” 했었는데요. 막상 들어가 보니 기능은 명확한데, 프라이빗 클라우드 파일 스토리지 운영할 때 고려할 포인트가 생각보다 많더라고요. 특히 Manila로 파일 스토리지를 운영하면 자동화가 편해지는 대신, 네트워크와 백엔드 설계를 대충 하면 나중에 꼭 되돌아오니까요. 오늘은 OpenStack Manila 도입 1년 회고라는 관점에서, 좋았던 점과 아쉬웠던 점을 솔직하게 정리해보겠습니다.

    OpenStack Manila, 컴퓨트 노드, 스토리지 백엔드, 사용자 네트워크가 어떻게 연결되는지 한눈에 보여주는 아키텍처 이미지가 들어갈 자리입니다.

    1. 왜 OpenStack Manila를 보게 되었는가

    처음 문제는 단순했습니다. 프로젝트마다 VM 안에 데이터를 따로 넣어두다 보니, 배치 작업 서버와 애플리케이션 서버가 같은 데이터를 봐야 하는 상황에서 계속 복사본이 생겼거든요. 이러면 데이터 일관성도 깨지고, 백업 정책도 꼬이고, 장애가 나면 복구 지점도 애매해집니다.

    프라이빗 클라우드 파일 스토리지 요구가 계속 나오면서 선택지를 세 가지로 놓고 봤습니다.

    • VM 내부 디스크를 각자 관리한다
    • Cinder 볼륨을 붙여서 우회한다
    • 공유 파일 스토리지 자체를 서비스로 제공한다

    세 번째가 바로 OpenStack Manila, 즉 프라이빗 클라우드 파일 스토리지 서비스의 자리였습니다. 실제로 써보니까, 파일 공유를 사람 손으로 매번 만들어주는 방식보다 API(에이피아이, 프로그램 호출 인터페이스) 기반으로 표준화하는 게 훨씬 관리가 잘 되더라고요.

    2. OpenStack Manila란 무엇인가

    쉽게 말해 OpenStack Manila는 공유 파일 시스템을 서비스 형태로 제공하는 컴포넌트입니다. Cinder가 블록 디바이스를 내주는 역할이라면, Manila는 NFS(엔에프에스, 네트워크 파일 시스템)나 SMB(에스엠비, 파일 공유 프로토콜) 같은 형태의 공유 스토리지를 만들어주는 쪽에 가깝습니다.

    처음엔 이름이 좀 낯설죠. 저도 처음엔 “왜 이름이 Manila지?” 싶었는데, 기능 자체는 꽤 직관적입니다. 핵심 개념만 잡아두면 어렵지 않거든요.

    핵심 개념 한 번에 정리

    • Share: 실제로 사용자에게 제공되는 파일 공유 자원
    • Share Type: 성능, 백엔드, 기능 정책을 구분하는 템플릿
    • Share Network: 공유 스토리지가 붙을 네트워크 정보
    • Backend Driver: CephFS(세프에프에스), NetApp, Generic driver 같은 실제 구현체와 연결되는 계층
    • Access Rule: 어떤 IP나 사용자에게 접근을 허용할지 정하는 규칙

    여기서 중요한 포인트! Manila 자체가 스토리지를 저장하는 제품은 아닙니다. 정확히는 백엔드 파일 스토리지를 OpenStack 방식으로 관리해주는 제어 계층이라고 생각하시면 돼요. 이 차이를 이해 못 하면 설계가 꼬입니다.

    다른 스토리지와 무엇이 다른가

    구분 주 용도 접근 방식 운영 시 느낌
    Ephemeral Disk 인스턴스 로컬 작업 VM 내부 로컬 디스크 빠르지만 수명과 이동성 제약이 크다
    Cinder 데이터베이스, 단일 서버 디스크 블록 디바이스 마운트 명확하지만 다중 공유에는 부적합
    Swift 백업, 아카이브, 객체 저장 HTTP API 확장성은 좋지만 파일시스템처럼 쓰긴 어렵다
    Manila (프라이빗 클라우드 파일 스토리지) 공유 파일 스토리지 NFS/SMB 등 협업과 공용 데이터셋에 강하다

    3. 도입 전에 꼭 봐야 했던 설계 포인트

    제가 1년 운영하면서 느낀 건, Manila는 설치보다 설계가 더 중요하다는 점입니다. 특히 아래 세 가지를 먼저 정리해야 나중에 덜 고생합니다.

    1. 백엔드 선택: CephFS처럼 분산 파일 시스템을 붙일지, 전통적인 NAS(나스, 네트워크 스토리지)를 붙일지 결정해야 한다
    2. 네트워크 분리: 스토리지 트래픽과 테넌트 트래픽을 어느 정도 분리할지 판단해야 한다
    3. 운영 권한 모델: 누가 share를 만들고, 누가 접근 규칙을 열 수 있는지 기준을 세워야 한다

    사실 여기서 많이들 놓치는 게 두 번째입니다. 프라이빗 클라우드 파일 스토리지는 결국 네트워크 영향을 강하게 받습니다. 스토리지 백엔드는 멀쩡한데도 MTU(엠티유, 최대 전송 단위)나 라우팅, 보안그룹 정책 때문에 체감 성능이 무너지는 경우를 꽤 봤거든요.

    4. OpenStack Manila 실전 구현: 제가 실제로 잡았던 기본 흐름

    이제 구현 얘기를 해보겠습니다. 환경마다 패키지 설치 방식은 다를 수 있으니, 여기서는 운영 개념과 명령 흐름 위주로 정리하겠습니다. 저는 처음에 모든 설정을 한 번에 넣으려다가 꼬여서, 결국 가장 단순한 형태부터 올리는 방식으로 갔습니다. 이게 훨씬 낫더라고요.

    1) 서비스 상태 확인

    openstack share service list
    openstack endpoint list --service manila
    openstack network list
    

    맨 처음엔 화려한 기능보다 서비스가 보이느냐부터 확인했습니다. 생각보다 기본 서비스 등록이나 엔드포인트 누락이 자주 나옵니다.

    2) share type 생성

    openstack share type create default_share false
    openstack share type set --extra-specs snapshot_support=true default_share
    

    Share Type은 나중에 Manila 운영 정책의 중심이 됩니다. 성능 클래스, 스냅샷 허용 여부, 백엔드 매핑 기준을 여기에 녹여두면 사용자 설명이 쉬워지거든요.

    3) share network 생성

    openstack share network create \
      --name manila-share-net \
      --neutron-net-id <tenant-network-id> \
      --neutron-subnet-id <tenant-subnet-id>
    

    여기서 저도 한 번 크게 삽질했습니다. 인스턴스가 붙은 네트워크와 share network 관계를 대충 맞추면 될 줄 알았는데, 실제로는 접근 경로와 라우팅이 명확해야 마운트 단계에서 덜 막힌다더라고요.

    4) 공유 스토리지 생성

    openstack share create \
      --name project-data \
      --share-type default_share \
      --share-network manila-share-net \
      --size 100 \
      NFS
    

    생성 직후 바로 쓰려고 하면 안 됩니다. 상태가 available이 될 때까지 기다려야 합니다.

    openstack share list
    openstack share show project-data
    
    OpenStack Manila share type과 share network 구성 흐름 이미지

    Share type, share network, backend driver, tenant network가 어떤 순서로 연결되는지 보여주는 구성 다이어그램이 들어갈 자리입니다.

    5) 접근 제어 추가

    openstack share access create project-data ip 10.10.20.15
    openstack share access list project-data
    

    Manila 운영하면서 가장 체감이 좋았던 부분 중 하나가 이겁니다. 예전엔 파일 공유를 열 때 네트워크팀, 스토리지팀, 운영팀이 각각 손대야 했었는데요. Manila를 붙이니 최소한 권한과 절차가 API로 정리되니까 일이 많이 단순해졌습니다.

    6) 인스턴스에서 마운트

    sudo mkdir -p /mnt/project-data
    sudo mount -t nfs <share-export-location> /mnt/project-data
    df -h
    mount | grep project-data
    

    여기서 export location이 올바르게 나오는지 확인해야 합니다. 실제 사용자는 이 지점만 보기 때문에, 앞단 자동화가 아무리 좋아도 마운트 실패하면 평가가 박해집니다. 냉정하죠 ㅎㅎ

    7) 설정 예시

    [DEFAULT]
    default_share_type = default_share
    enabled_share_backends = cephfsnfs
    
    [cephfsnfs]
    share_backend_name = CEPHFSNFS
    driver_handles_share_servers = false
    

    설정은 백엔드마다 달라지니 그대로 복붙하시면 안 되고, 운영 중인 백엔드 문서와 정확히 맞춰야 합니다. 다만 관점 자체는 비슷합니다. 어떤 백엔드를 활성화할지, 드라이버가 share server를 직접 다룰지 여부를 정하는 구조니까요.

    5. 1년 운영하며 좋았던 점: 명(明)

    OpenStack Manila 운영을 1년쯤 해보니까, 분명 장점이 있습니다. 이건 꽤 명확했습니다.

    • 셀프서비스화: 사용 부서가 요청만 하면 표준 절차로 공유 스토리지를 만들 수 있다
    • 정책 통일: share type 중심으로 Manila 운영 기준을 맞추기 쉽다
    • 접근 제어 가시성: 누가 어떤 share에 접근 가능한지 추적이 쉬워진다
    • 자동화 친화적: Terraform(테라폼, 인프라 선언형 자동화)이나 내부 포털과 엮기 좋다

    특히 프로젝트 단위로 수명주기를 관리할 때 편했습니다. 인스턴스는 바뀌어도 데이터 공유 계층은 유지할 수 있으니, 작업 서버를 새로 올려도 공유 데이터를 다시 설계할 필요가 없거든요. 이거 진짜 편하더라고요.

    또 하나는 운영 책임 구간이 분리된다는 점입니다. 예전엔 “공유 폴더 느려요”라는 말이 나오면 원인 범위가 너무 넓었는데, Manila 도입 후에는 적어도 API 계층, 네트워크 계층, 백엔드 계층으로 잘게 나눠서 볼 수 있었습니다.

    6. 1년 운영하며 아쉬웠던 점: 암(暗)

    근데 여기서 중요한 게 있습니다. Manila는 만능이 아닙니다. 오히려 기대치를 너무 높게 잡으면 실망하기 쉽습니다.

    첫째, 문제의 절반은 결국 백엔드와 네트워크입니다

    사용자 입장에서는 OpenStack Manila가 파일 스토리지를 제공하는 것처럼 보이지만, 실제 체감 품질은 백엔드 스토리지와 네트워크 설계에 크게 좌우됩니다. 즉, Manila가 느린 게 아니라 뒤쪽이 느린 경우가 많습니다. 이걸 분리해서 설명하는 데 시간이 꽤 들었습니다.

    둘째, 권한 설계가 느슨하면 금방 복잡해집니다

    처음엔 “필요한 사람에게 IP만 열어주면 되지” 했었는데요. 몇 달 지나면 예외 규칙이 누적됩니다. 접근 규칙을 누가 승인하는지, 만료 기준은 뭔지, 프로젝트 종료 시 어떻게 닫을지 초반에 정해야 합니다.

    셋째, 장애 분석이 생각보다 단순하지 않습니다

    마운트 실패 하나만 놓고 봐도 원인이 다양합니다. DNS(디엔에스, 이름 해석), 라우팅, 보안그룹, export location, 백엔드 상태, 커널 NFS 클라이언트 옵션까지 봐야 하거든요. 처음엔 “왜 이렇게 복잡하지?” 싶었는데, 결국 파일 공유라는 게 여러 계층이 맞물리는 서비스라 그렇더라고요.

    7. ⚠️ 실제로 겪었던 트러블슈팅

    이 섹션은 좀 현실적으로 적어볼게요. 저도 처음엔 문서만 보면 금방 될 줄 알았는데, 실제 Manila 운영에선 아래 이슈를 자주 만났습니다.

    문제 1. share는 생성됐는데 마운트가 안 되는 경우

    • 증상: `mount.nfs: access denied by server`
    • 원인 후보: 접근 규칙 누락, 클라이언트 IP 변경, 잘못된 네트워크 경로
    • 해결: `openstack share access list`로 허용 규칙 확인 후, 실제 클라이언트 IP와 비교
    openstack share access list project-data
    ip addr
    ip route
    

    생각보다 NAT(엔에이티, 주소 변환)나 점프 구간 때문에 사용자가 보는 IP와 실제 서버가 보이는 IP가 다른 경우가 있었습니다.

    문제 2. 생성 속도는 괜찮은데 체감 성능이 들쭉날쭉한 경우

    • 증상: 어떤 VM은 빠르고 어떤 VM은 유독 느림
    • 원인 후보: 네트워크 경로 차이, MTU 불일치, 혼잡 구간 존재
    • 해결: 경로별 성능 차이를 먼저 분리 측정하고, Manila 문제로 단정하지 않기

    여기서 제가 배운 건 하나입니다. 스토리지 문제를 API 문제로 착각하지 말 것. 관리 평면(control plane)과 데이터 평면(data plane)을 분리해서 봐야 합니다.

    문제 3. 공유는 살아 있는데 운영 기록이 남지 않는 경우

    • 증상: 누가 왜 접근 규칙을 열었는지 추적이 어려움
    • 원인 후보: 수동 작업, 표준 요청 절차 부재
    • 해결: 변경 요청 번호나 티켓 번호를 share 이름 또는 메타데이터 규칙에 반영

    이건 기술 이슈 같지 않지만 실제 Manila 운영에선 꽤 큽니다. 나중에 감사나 보안 점검 때 힘들어지거든요.

    문제 4. 기대보다 운영 난도가 높게 느껴지는 경우

    사실 OpenStack 스토리지는 모두 그렇지만, Manila도 “기능 추가”보다 “운영 모델 정리”가 더 어렵습니다. 백엔드 드라이버 특성, 네트워크 토폴로지, 접근 정책이 모두 연결되니까요. 그래서 제가 추천하는 방식은 이겁니다.

    1. 처음엔 딱 한 가지 share type만 운영한다
    2. 접근 제어는 가장 보수적으로 시작한다
    3. 사용자 수요가 확인된 뒤에 스냅샷, 멀티 백엔드, 성능 클래스 분리를 확장한다

    한 번에 다 하려 하지 않는 것, 이게 제일 중요했습니다.

    8. 검증과 운영 결과: 무엇이 달라졌나

    그럼 1년 운영해서 뭐가 남았냐, 이 질문이 제일 중요하겠죠. 제가 직접 해보니 결과는 꽤 분명했습니다.

    • 프라이빗 클라우드 파일 스토리지 개설 절차가 표준화됐다
    • 프로젝트별 데이터 공유 방식이 단순해졌다
    • 수동 NAS 작업이 줄어들었다
    • 장애 시 원인 구간을 더 빨리 좁힐 수 있게 됐다

    반대로, 운영 문서와 접근 정책이 없으면 Manila 운영은 금방 복잡해진다는 것도 확인했습니다. 즉, OpenStack Manila의 성공 조건은 설치가 아니라 운영 규칙이에요.

    openstack share list
    openstack share service list
    openstack share type list
    openstack share network list
    

    검증할 때는 단순히 리소스가 보이는지보다, 아래 항목을 같이 확인했습니다.

    1. Share 상태가 `available`인지
    2. 접근 규칙이 기대한 대상에만 열려 있는지
    3. 실제 인스턴스에서 마운트와 읽기/쓰기가 되는지
    4. 장애 시 로그와 변경 이력이 추적 가능한지
    OpenStack Manila 운영 결과와 검증 체크리스트 대시보드 이미지

    Share 상태, 접근 규칙, 마운트 성공 여부, Manila 운영 지표를 한 화면에서 점검하는 대시보드 이미지가 들어갈 자리입니다.

    9. FAQ와 마무리: 다음 단계는 어떻게 가면 좋을까

    자주 묻는 질문

    • Q. Manila는 모든 환경에서 꼭 필요한가요?
      아닙니다. 프라이빗 클라우드 파일 스토리지 요구가 적고 운영 단순성이 더 중요하면 굳이 넣지 않는 게 나을 수도 있습니다.
    • Q. 프라이빗 클라우드 파일 스토리지로 바로 도입해도 될까요?
      가능은 하지만, 먼저 한두 팀 대상 파일 공유 서비스로 시작해 Manila 운영 모델을 검증하는 걸 추천합니다.
    • Q. OpenStack 스토리지 중 우선순위는 어떻게 잡아야 하나요?
      블록, 오브젝트, 파일의 요구가 다르니 워크로드 기준으로 판단해야 합니다. “공유 파일”이 핵심이면 Manila가 후보가 됩니다.

    정리해보면 이렇습니다. OpenStack Manila는 프라이빗 클라우드 파일 스토리지 운영을 표준화하는 데 꽤 좋은 도구입니다. 다만 제품만 올린다고 끝나는 게 아니고, 백엔드 선택과 네트워크 설계, 접근 정책, 운영 문서화까지 같이 가야 진짜 효과가 납니다.

    저도 처음엔 이게 뭔가 싶었는데, 1년쯤 지나고 나니 보이더라고요. Manila 운영의 핵심은 “기능 활성화”가 아니라 “운영 경계 정의”였습니다. 이걸 빨리 이해할수록 삽질이 줄어들더라고요.

    다음 글에서는 OpenStack Manila 운영 시 백엔드 선택 기준, 예를 들면 CephFS 계열과 전통적인 NAS 연동 관점에서 무엇을 봐야 하는지 더 구체적으로 다뤄볼 예정입니다. 이전 글에서 다뤘던 OpenStack 네트워크 설계 내용과도 연결해서 보시면 훨씬 이해가 쉬우실 겁니다.

    OpenStack Manila 도입 전후 장단점 비교 인포그래픽

    도입 전 수동 운영 방식과 도입 후 표준화된 프라이빗 클라우드 파일 스토리지 운영 방식을 비교하는 요약 인포그래픽이 들어갈 자리입니다.

    혹시 지금 OpenStack Manila 도입을 고민 중이시라면, 제 경험상 가장 먼저 할 일은 하나입니다. “누가 어떤 데이터를 어떤 방식으로 공유해야 하는가”를 먼저 적어보세요. 그 다음에 Manila를 붙이면 훨씬 덜 헤맵니다. 이 순서, 생각보다 정말 중요합니다. 🎉

  • [k8s] 쿠버네티스 영구 스토리지: Longhorn vs Rook Ceph 비교 및 선택 가이드

    쿠버네티스 영구 스토리지, 왜 이렇게 어렵냐고요

    쿠버네티스(Kubernetes)로 처음 스테이트풀(Stateful) 애플리케이션을 올려본 분들이라면 공감하실 텐데요. 컨테이너는 죽었다 살아나는 게 당연한 세계인데, 데이터는 절대 사라지면 안 되잖아요. 데이터베이스, 메시지 큐, 로그 수집기… 이런 것들을 올리려면 결국 쿠버네티스 영구 스토리지(Persistent Storage) 문제를 해결해야 합니다.

    저도 처음 홈랩에서 쿠버네티스 클러스터를 구성할 때 이 부분에서 꽤 오래 고민했거든요. NFS 마운트로 버티다가 결국 제대로 된 분산 스토리지를 써야겠다 싶어서 Longhorn이랑 Rook Ceph를 둘 다 실제로 구성해봤습니다. 오늘은 그 경험을 바탕으로 두 솔루션을 비교하고, 어떤 상황에서 뭘 선택해야 하는지 정리해 드릴게요.

    ▲ 쿠버네티스 영구 스토리지의 전체 구조 — PVC(Persistent Volume Claim)가 어떻게 실제 스토리지 백엔드와 연결되는지 보여주는 아키텍처 다이어그램

    먼저 개념부터: PV, PVC, CSI가 뭔가요?

    비교 얘기 전에 기본 개념을 짚고 넘어가겠습니다. 저도 처음엔 이 용어들이 다 비슷비슷해 보여서 헷갈렸거든요 ㅎㅎ

    • PV (Persistent Volume, 영구 볼륨): 클러스터 관리자가 프로비저닝한 실제 스토리지 리소스입니다. 쉽게 말해 “실제 저장 공간”이에요.
    • PVC (Persistent Volume Claim, 영구 볼륨 클레임): 개발자(또는 파드)가 스토리지를 요청하는 오브젝트입니다. “나 10GB짜리 저장 공간 필요해요”라고 요청하는 거죠.
    • StorageClass (스토리지 클래스): 스토리지의 종류와 프로비저닝 방식을 정의합니다. PVC가 요청하면 자동으로 PV를 만들어주는 동적 프로비저닝(Dynamic Provisioning)을 가능하게 해줘요.
    • CSI (Container Storage Interface, 컨테이너 스토리지 인터페이스): 쿠버네티스가 다양한 스토리지 벤더와 통신하기 위한 표준 인터페이스입니다. Longhorn도, Rook Ceph도 이 CSI 드라이버를 통해 쿠버네티스와 연동돼요.

    💡 핵심 포인트: 개발자는 PVC만 선언하면 되고, 실제 스토리지가 어디에 있는지는 신경 안 써도 됩니다. 그 복잡한 연결을 StorageClass와 CSI 드라이버가 처리해주거든요.

    Longhorn 소개: CNCF가 인정한 경량 분산 스토리지

    Longhorn은 Rancher(현재 SUSE 산하)에서 개발한 쿠버네티스 전용 분산 블록 스토리지입니다. CNCF(Cloud Native Computing Foundation) 졸업 프로젝트로 등록되어 있고, 오픈소스이면서 완전히 쿠버네티스 네이티브하게 설계됐어요.

    Longhorn의 주요 특징

    • 쿠버네티스 위에서 동작하는 컨트롤러 기반 아키텍처
    • 볼륨 복제본(Replica)을 여러 노드에 자동 분산
    • 내장 UI 대시보드 — 볼륨 상태를 시각적으로 확인 가능
    • 스냅샷(Snapshot) 및 백업 기능 내장 (S3, NFS 등으로 백업 가능)
    • 볼륨 확장(Volume Expansion) 지원
    • RWO(ReadWriteOnce) 지원, RWX(ReadWriteMany)는 NFS 게이트웨이를 통해 제한적으로 지원

    Longhorn 설치 — Helm으로 빠르게

    실제로 설치해보겠습니다. 저는 k3s 기반 3노드 클러스터에서 테스트했어요.

    # 사전 요구사항 확인 (iscsi 패키지 필요)
    sudo apt-get install -y open-iscsi
    sudo systemctl enable --now iscsid
    
    # Helm 저장소 추가
    helm repo add longhorn https://charts.longhorn.io
    helm repo update
    
    # longhorn 네임스페이스 생성 및 설치
    helm install longhorn longhorn/longhorn \
      --namespace longhorn-system \
      --create-namespace \
      --set defaultSettings.defaultReplicaCount=3

    설치가 완료되면 longhorn-system 네임스페이스에 여러 파드가 뜨는 걸 확인할 수 있어요.

    kubectl get pods -n longhorn-system
    # NAME                                        READY   STATUS    RESTARTS
    # longhorn-manager-xxxxx                      1/1     Running   0
    # longhorn-driver-deployer-xxxxx              1/1     Running   0
    # longhorn-ui-xxxxx                           1/1     Running   0
    # engine-image-ei-xxxxx-xxxxx                 1/1     Running   0

    Longhorn UI에 접근하려면 포트 포워딩이나 인그레스(Ingress, 외부 트래픽 진입점)를 설정해야 합니다.

    kubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80

    브라우저에서 http://localhost:8080으로 접속하면 볼륨 상태, 노드 디스크 현황을 한눈에 볼 수 있는 대시보드가 나옵니다. 이거 처음 봤을 때 진짜 편하다 싶었어요.

    Longhorn StorageClass 및 PVC 생성 예시

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: longhorn
    provisioner: driver.longhorn.io
    allowVolumeExpansion: true
    parameters:
      numberOfReplicas: "3"
      staleReplicaTimeout: "2880"
      fromBackup: ""
      fsType: "ext4"
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-longhorn-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      storageClassName: longhorn
      resources:
        requests:
          storage: 10Gi

    Rook Ceph 소개: 엔터프라이즈급 분산 스토리지

    Rook은 Ceph를 쿠버네티스에서 오퍼레이터(Operator) 패턴으로 운영할 수 있게 해주는 프레임워크입니다. Ceph 자체는 수십 년의 역사를 가진 검증된 분산 스토리지 시스템이고, Rook은 그 복잡한 Ceph를 쿠버네티스 위에서 쉽게(?) 운영하게 해주죠.

    솔직히 말하면 “쉽게”라는 말에 따옴표를 붙인 이유가 있어요. 처음 Rook Ceph 설치할 때 삽질을 꽤 했거든요 ㅎㅎ

    Rook Ceph의 주요 특징

    • 블록 스토리지(RBD), 파일시스템(CephFS), 오브젝트 스토리지(S3 호환 RGW) 모두 지원
    • CephFS를 통한 RWX(ReadWriteMany) 네이티브 지원 — 여러 파드가 동시에 같은 볼륨 마운트 가능
    • PG(Placement Group), CRUSH Map 등 고급 튜닝 옵션
    • 대규모 클러스터에서 검증된 안정성
    • Ceph Dashboard 내장
    • 최소 3개 OSD(Object Storage Daemon) 노드 권장

    Rook Ceph 설치 — 조금 더 복잡합니다

    # Rook 오퍼레이터 설치
    git clone --single-branch --branch v1.13.0 https://github.com/rook/rook.git
    cd rook/deploy/examples
    
    # CRD 및 공통 리소스 먼저 설치
    kubectl create -f crds.yaml
    kubectl create -f common.yaml
    
    # 오퍼레이터 배포
    kubectl create -f operator.yaml
    
    # 오퍼레이터 파드 확인
    kubectl get pods -n rook-ceph
    # NAME                                  READY   STATUS    RESTARTS
    # rook-ceph-operator-xxxxx              1/1     Running   0

    오퍼레이터가 Running 상태가 되면 Ceph 클러스터를 생성합니다. 아래는 기본 클러스터 설정이에요.

    apiVersion: ceph.rook.io/v1
    kind: CephCluster
    metadata:
      name: rook-ceph
      namespace: rook-ceph
    spec:
      cephVersion:
        image: quay.io/ceph/ceph:v18.2.0
      dataDirHostPath: /var/lib/rook
      mon:
        count: 3
        allowMultiplePerNode: false
      mgr:
        count: 2
      dashboard:
        enabled: true
        ssl: true
      storage:
        useAllNodes: true
        useAllDevices: false
        deviceFilter: "^sd[b-z]"
      resources:
        mgr:
          requests:
            cpu: "500m"
            memory: "512Mi"

    ⚠️ 주의사항: deviceFilter 설정이 중요합니다. 잘못 설정하면 OS 디스크까지 Ceph OSD로 사용하려고 할 수 있어요. 저도 이 부분에서 한 번 아찔한 경험을 했습니다. 반드시 데이터 디스크만 지정하세요.

    # Ceph 블록 스토리지 풀 및 StorageClass 생성
    kubectl create -f csi/rbd/storageclass.yaml
    
    # CephFS (RWX 지원) StorageClass 생성
    kubectl create -f filesystem.yaml
    kubectl create -f csi/cephfs/storageclass.yaml

    ▲ Rook Ceph 아키텍처 — MON(모니터), MGR(매니저), OSD(오브젝트 스토리지 데몬)의 구성과 CSI 드라이버를 통한 쿠버네티스 연동 구조

    Longhorn vs Rook Ceph: 직접 써본 비교

    두 솔루션을 실제로 운영해보면서 느낀 점들을 솔직하게 비교해 드릴게요.

    항목 Longhorn Rook Ceph
    설치 난이도 ⭐⭐ (쉬움) ⭐⭐⭐⭐ (복잡함)
    최소 노드 수 1개 (복제본 설정에 따라) 3개 (OSD 최소 3개 권장)
    리소스 사용량 가벼움 무거움 (MON, MGR, OSD 등 다수)
    RWX 지원 제한적 (NFS 게이트웨이 필요) 네이티브 지원 (CephFS)
    오브젝트 스토리지 미지원 지원 (S3 호환 RGW)
    UI/관리 편의성 직관적인 내장 UI Ceph Dashboard (기능 풍부)
    백업 기능 내장 (S3, NFS 백업) 별도 구성 필요
    성숙도/안정성 CNCF 졸업 프로젝트 CNCF 졸업 프로젝트 (Ceph는 업계 표준)
    운영 복잡도 낮음 높음 (PG 튜닝, CRUSH Map 등)
    적합한 규모 소~중형 클러스터 중~대형 클러스터

    실제로 겪은 트러블슈팅 사례들

    Longhorn에서 겪은 문제: 노드 한 대를 재부팅했더니 해당 노드의 복제본이 degraded 상태가 됐어요. 근데 이건 Longhorn이 자동으로 다른 노드에 복제본을 재빌드해주더라고요. 시간이 좀 걸리긴 했지만 데이터 손실은 없었습니다. ✅

    Rook Ceph에서 겪은 문제: OSD 디스크 하나에 파티션이 남아있었는데, Rook이 해당 디스크를 인식 못 하는 문제가 있었어요. 이게 처음엔 왜 안 되는지 몰라서 꽤 삽질했습니다.

    # OSD 디스크 초기화 — 기존 파티션 제거
    sgdisk --zap-all /dev/sdb
    dd if=/dev/zero of=/dev/sdb bs=1M count=100 oflag=direct
    blkdiscard /dev/sdb
    
    # 파티션 확인
    lsblk /dev/sdb

    ⚠️ 경고: 위 명령어는 해당 디스크의 모든 데이터를 완전히 삭제합니다. 반드시 올바른 디스크를 지정했는지 확인하고 실행하세요.

    또 Ceph 클러스터 상태가 HEALTH_WARN으로 뜰 때 원인 파악하는 방법도 알아두면 좋아요.

    # Ceph 상태 확인
    kubectl exec -n rook-ceph -it deploy/rook-ceph-tools -- ceph status
    kubectl exec -n rook-ceph -it deploy/rook-ceph-tools -- ceph health detail
    
    # OSD 상태 확인
    kubectl exec -n rook-ceph -it deploy/rook-ceph-tools -- ceph osd status

    ▲ Longhorn 대시보드 — 볼륨 상태, 노드별 복제본 분산 현황, 백업 상태를 한눈에 모니터링하는 화면

    어떤 상황에서 뭘 선택해야 할까요?

    이게 결국 핵심 질문이잖아요. 저는 이렇게 기준을 잡아드리고 싶어요.

    Longhorn을 선택하세요, 만약…

    • ✅ 홈랩이나 소규모 클러스터(노드 3~5개 이하)를 운영한다면
    • ✅ 쿠버네티스 스토리지를 처음 도입하는 팀이라면
    • ✅ 운영 인력이 부족하고 관리 부담을 최소화하고 싶다면
    • ✅ 블록 스토리지(RWO) 위주로만 사용한다면
    • ✅ 백업/복구 기능을 간편하게 쓰고 싶다면
    • ✅ 빠르게 구성해서 바로 써야 하는 상황이라면

    Rook Ceph를 선택하세요, 만약…

    • ✅ 중대형 클러스터(노드 5개 이상)를 운영한다면
    • ✅ RWX(ReadWriteMany) 볼륨이 반드시 필요하다면
    • ✅ S3 호환 오브젝트 스토리지도 함께 필요하다면
    • ✅ 전담 인프라 운영 인력이 있다면
    • ✅ 엔터프라이즈 환경에서 검증된 기술 스택이 필요하다면
    • ✅ 고가용성과 세밀한 스토리지 정책 제어가 필요하다면

    둘 다 쓰는 경우도 있어요

    실제로 일부 팀에서는 일반적인 파드 스토리지는 Longhorn으로, RWX가 필요한 공유 파일시스템이나 오브젝트 스토리지는 Rook Ceph로 나눠서 운영하기도 합니다. 복잡해지긴 하지만 각각의 장점을 활용할 수 있는 방법이기도 해요.

    결과 검증: 실제로 제대로 동작하는지 확인하기

    설치만 하면 끝이 아니죠. 실제로 데이터가 잘 보존되는지 확인해봐야 합니다. 아래는 간단한 테스트 시나리오예요.

    # 테스트용 파드 생성
    apiVersion: v1
    kind: Pod
    metadata:
      name: storage-test
    spec:
      containers:
      - name: test
        image: busybox
        command: ["/bin/sh", "-c", "while true; do date >> /data/test.log; sleep 5; done"]
        volumeMounts:
        - mountPath: /data
          name: test-volume
      volumes:
      - name: test-volume
        persistentVolumeClaim:
          claimName: my-longhorn-pvc
    # 파드 실행 후 데이터 확인
    kubectl exec storage-test -- cat /data/test.log
    
    # 파드를 강제 삭제
    kubectl delete pod storage-test
    
    # 새 파드로 다시 마운트해서 데이터가 남아있는지 확인
    kubectl apply -f storage-test.yaml
    kubectl exec storage-test -- cat /data/test.log
    # 이전 로그가 그대로 남아있으면 성공! 🎉

    🎉 데이터가 살아있는 걸 확인했을 때의 그 안도감… 처음엔 진짜 설레더라고요. 쿠버네티스에서 영구 스토리지가 제대로 동작한다는 걸 눈으로 확인한 순간이었습니다.

    추가로 볼륨 상태도 확인해두면 좋아요.

    # PVC 상태 확인
    kubectl get pvc
    # NAME               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    # my-longhorn-pvc    Bound    pvc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   10Gi       RWO            longhorn       5m
    
    # PV 상세 정보
    kubectl describe pv pvc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

    ▲ Longhorn vs Rook Ceph 선택 가이드 요약 — 클러스터 규모, 기능 요구사항, 운영 복잡도를 기준으로 한 비교 인포그래픽

    자주 묻는 질문 (FAQ)

    Q. Longhorn은 프로덕션 환경에서 써도 되나요?

    네, CNCF 졸업 프로젝트이고 실제로 많은 기업에서 프로덕션에 사용하고 있습니다. 다만 대규모 클러스터나 높은 I/O가 필요한 환경에서는 Ceph 대비 한계가 있을 수 있어요.

    Q. Rook Ceph 최소 사양이 어떻게 되나요?

    OSD 노드 최소 3개를 권장합니다. 각 OSD 노드에는 전용 디스크가 필요하고, MON(모니터) 데몬 운영을 위한 CPU와 메모리도 여유 있게 확보해야 해요. 리소스가 빠듯한 환경에서는 Longhorn이 훨씬 현실적입니다.

    Q. 기존 NFS 스토리지에서 마이그레이션이 가능한가요?

    직접적인 마이그레이션 도구는 없고, 보통 데이터를 백업 후 새 PVC에 복원하는 방식을 사용합니다. Velero(벨레로) 같은 쿠버네티스 백업 도구를 활용하면 좀 더 체계적으로 진행할 수 있어요. 이 내용은 다음 글에서 다룰 예정입니다.

    Q. 홈랩에서는 뭘 추천하세요?

    저는 홈랩에서 Longhorn을 쓰고 있어요. 설치가 간단하고 UI가 직관적이어서 관리하기 편합니다. 노드 3대 이하 환경이라면 Longhorn이 압도적으로 편해요.

    마무리: 결국 “상황에 맞는” 선택이 정답입니다

    13년 동안 인프라 일을 하면서 느낀 건데요. 기술 선택에 “절대적인 정답”은 없더라고요. Longhorn이 좋냐, Rook Ceph가 좋냐가 아니라 내 환경에 뭐가 맞냐가 핵심이에요.

    소규모 클러스터에서 빠르게 쿠버네티스 영구 스토리지를 도입하고 싶다면 Longhorn으로 시작하세요. 운영하다가 규모가 커지고 RWX나 오브젝트 스토리지가 필요해지면 그때 Rook Ceph로 전환하거나 병행하는 것도 방법이에요.

    중요한 건 일단 시작하는 거라고 생각해요. NFS로 버티다가 나중에 대규모 마이그레이션 하는 것보다, 처음부터 제대로 된 CSI 드라이버 기반 스토리지를 도입하는 게 훨씬 낫거든요.

    다음 글에서는 Velero를 활용한 쿠버네티스 백업 전략에 대해 다룰 예정입니다. Longhorn 내장 백업과 Velero를 조합하면 꽤 탄탄한 백업 체계를 만들 수 있거든요. 기대해 주세요! 🎉

    혹시 설치하다가 막히는 부분이 있으시면 댓글로 남겨주세요. 제가 겪었던 삽질 경험이 도움이 될 수도 있으니까요 ㅎㅎ