13년차의 서버실

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

[태그:] Longhorn

  • [k8s] Kubernetes 스토리지: Longhorn vs Rook-Ceph 성능 벤치마크

    [k8s] Kubernetes 스토리지: Longhorn vs Rook-Ceph 성능 벤치마크

    안녕하세요, 13년차 서버실 지킴이입니다. 🤓

    Kubernetes(쿠버네티스) 환경에서 애플리케이션을 운영하다 보면, 영구 스토리지(Persistent Storage)의 중요성을 정말 뼈저리게 느끼게 됩니다. Pod(파드)가 재시작되거나 다른 노드로 옮겨가도 데이터는 안전하게 보존되어야 하니까요. 특히 저처럼 홈랩(Homelab)에서 이것저것 실험하며 삽질을 즐기는 사람이라면, 안정적이고 성능 좋은 스토리지를 찾는 데 꽤 많은 시간을 투자하게 되죠. 저도 그랬거든요! 🤔

    오늘은 제가 직접 홈랩에서 Longhorn(롱혼)과 Rook-Ceph(룩-세프) 두 가지 Kubernetes 영구 스토리지 솔루션을 설치하고, FIO(Flexible I/O Tester) 벤치마크 툴로 성능을 비교해본 경험을 공유해드리려고 합니다. 과연 어떤 녀석이 제 환경에 더 적합했을까요? 저의 삽질 여정을 따라오시면서 여러분의 Kubernetes 스토리지 선택에 도움이 되시길 바랍니다!

    왜 영구 스토리지가 필요할까요?

    Kubernetes는 기본적으로 컨테이너화된 애플리케이션을 배포하고 관리하는 데 최적화되어 있어요. 그런데 컨테이너는 휘발성(ephemeral)이라는 특징을 가지고 있거든요. 즉, 컨테이너가 죽거나 재시작되면 그 안에 저장된 데이터는 사라져 버린다는 뜻이죠. 데이터베이스나 파일 서버처럼 데이터를 영구적으로 보관해야 하는 애플리케이션에는 치명적일 수 있습니다.

    이런 문제를 해결하기 위해 Kubernetes에서는 영구 볼륨(Persistent Volume, PV)과 영구 볼륨 클레임(Persistent Volume Claim, PVC)이라는 개념을 도입했어요. 쉽게 말해, 스토리지 시스템으로부터 저장 공간을 할당받아 Pod가 데이터를 안정적으로 쓰고 읽을 수 있게 해주는 기능이라고 보시면 됩니다. 그리고 이런 영구 볼륨을 동적으로 프로비저닝(provisioning)해주는 역할을 하는 것이 바로 CSI(Container Storage Interface) 드라이버를 기반으로 하는 분산 스토리지 솔루션들이죠. 오늘 다룰 Longhorn과 Rook-Ceph가 바로 그런 친구들입니다.

    Kubernetes 영구 스토리지 아키텍처 개요

    Kubernetes 클러스터에서 영구 스토리지가 어떻게 작동하는지 대략적인 아키텍처를 그려봤어요. Pod가 PVC를 요청하면, CSI 드라이버가 백엔드 스토리지 시스템에 PV를 생성하고 Pod에 연결해주는 방식이죠. 이 과정에서 Longhorn이나 Rook-Ceph 같은 분산 스토리지 솔루션이 그 백엔드 역할을 하는 겁니다.

    Longhorn과 Rook-Ceph, 넌 누구니?

    본격적인 벤치마크에 앞서, 두 솔루션에 대해 간략하게 알아볼까요? 저도 처음엔 이름만 듣고 뭐가 뭔지 헷갈렸거든요. 😅

    Longhorn (롱혼)

    • 특징: Rancher Labs에서 개발한 오픈소스 분산 블록 스토리지 솔루션이에요. Kubernetes 위에서 컨테이너 형태로 동작하며, 각 노드의 로컬 스토리지를 모아 분산 볼륨을 생성합니다. CSI 드라이버를 기본으로 제공해서 Kubernetes와 통합이 정말 쉬워요. 제가 직접 써보니, 설치도 비교적 간단하고 웹 UI가 직관적이어서 관리하기 편하더라고요. 홈랩이나 소규모 환경에 많이 추천되는 이유를 알겠더군요.
    • 장점: 가벼움, 설치 및 관리 용이, 스냅샷/백업/복원 기능 내장, DR(재해 복구) 지원.

    Rook-Ceph (룩-세프)

    • 특징: Rook는 Kubernetes 네이티브 스토리지 오케스트레이터이고, Ceph(세프)는 강력하고 성숙한 오픈소스 분산 스토리지 시스템이에요. Rook는 Ceph를 Kubernetes 클러스터 위에 배포하고 관리하는 오퍼레이터(Operator) 역할을 합니다. 오브젝트 스토리지(Object Storage), 블록 스토리지(Block Storage), 파일 스토리지(File Storage)를 모두 지원하는 만능 재주꾼이죠. 다만, Ceph 자체가 워낙 복잡한 시스템이라 Rook를 통해 배포해도 초기 설정과 관리에 공수가 좀 들어가는 편이에요. 대규모 프로덕션 환경에서 많이 사용됩니다.
    • 장점: 뛰어난 확장성, 높은 가용성, 다양한 스토리지 타입 지원, 강력한 성능(하드웨어에 따라).

    두 솔루션의 주요 특징을 표로 정리해봤어요.

    구분 Longhorn Rook-Ceph
    개발사/기반 Rancher Labs / 분산 블록 스토리지 Rook (오퍼레이터) + Ceph (분산 스토리지)
    스토리지 타입 블록 스토리지 블록, 오브젝트, 파일 스토리지
    설치 난이도 쉬움 (Helm) 중간 ~ 어려움 (kubectl apply)
    관리 UI 직관적인 웹 UI Ceph Dashboard (별도 설치), Grafana 연동
    확장성 중간 (수십 TB 규모) 매우 높음 (페타바이트 규모)
    주요 사용처 홈랩, 소규모 개발/테스트, 엣지 컴퓨팅 대규모 프로덕션, 클라우드 인프라

    벤치마크 환경 구축하기

    저의 홈랩 환경은 다음과 같았습니다. 실제 벤치마크 결과는 하드웨어 스펙, 네트워크 환경, Kubernetes 설정 등에 따라 크게 달라질 수 있다는 점을 미리 말씀드려요! ⚠️

    • Kubernetes Cluster: 3 Node (1 Master, 2 Worker)
    • OS: Ubuntu Server 22.04 LTS
    • CPU: Intel i5-10400 (각 노드당 6코어 12스레드)
    • RAM: 32GB (각 노드당)
    • Storage: NVMe SSD 500GB (각 노드당, 스토리지용으로 할당)
    • Network: 1Gbps Ethernet

    벤치마크 툴로는 FIO (Flexible I/O Tester)를 사용했어요. FIO는 디스크 I/O 성능을 측정하는 데 널리 사용되는 강력한 도구예요. 순차 읽기/쓰기, 랜덤 읽기/쓰기 등 다양한 패턴으로 I/O를 발생시켜 실제 워크로드와 유사한 환경을 만들 수 있거든요.

    Longhorn 설치 및 설정

    Longhorn은 Helm(헬름) 차트를 이용하면 정말 쉽게 설치할 수 있어요. 저도 처음엔 혹시나 복잡할까 봐 걱정했는데, 생각보다 너무 간단해서 놀랐어요. 🎉

    1. Helm Repository 추가:
      helm repo add longhorn https://charts.longhorn.io
      helm repo update
      
    2. Longhorn 설치: (기본 설정으로 설치했습니다)
      helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace
      
    3. Longhorn UI 접속:

      설치가 완료되면, Longhorn UI에 접속할 수 있도록 Ingress(인그레스, 외부 트래픽 진입점)나 NodePort(노드포트)를 설정해줘요. 저는 간단하게 NodePort로 열어서 접속했어요.

      kubectl -n longhorn-system get svc longhorn-frontend
      # 출력되는 NodePort를 확인하여 접속
      
    4. StorageClass 확인 및 볼륨 생성:

      Longhorn이 설치되면 기본적으로 longhorn이라는 StorageClass(스토리지클래스)가 생성돼요. 이걸 이용해서 PVC를 생성하고 Pod에 마운트하면 끝입니다.

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: longhorn-pvc
      spec:
        accessModes:
          - ReadWriteOnce
        storageClassName: longhorn
        resources:
          requests:
            storage: 10Gi
      

    Longhorn 웹 UI에 접속하면 현재 클러스터의 스토리지 상태, 노드별 디스크 사용량, 볼륨 목록 등을 한눈에 확인할 수 있어요. 시각적으로 깔끔하고 직관적이라서 관리하기 정말 편하더라고요. 💡

    Longhorn 웹 UI 대시보드 화면

    Longhorn 대시보드 화면이에요. 생성된 볼륨, 노드의 스토리지 상태 등을 쉽게 확인할 수 있어요.

    Rook-Ceph 설치 및 설정

    Rook-Ceph는 Longhorn보다 설정할 부분이 많아서, 처음엔 “이게 다 뭔가…” 싶었어요. 하지만 공식 문서(Official Documentation)를 차근차근 따라가면 충분히 설치할 수 있어요. 저는 helm 대신 kubectl apply -f 방식으로 진행했습니다.

    1. Rook Operator 배포:

      먼저 Rook Operator를 배포해요. 이 오퍼레이터가 Ceph 클러스터를 관리하는 역할을 합니다.

      git clone --single-branch --branch v1.11.x https://github.com/rook/rook.git
      cd rook/deploy/examples
      kubectl create -f crds.yaml -f common.yaml -f operator.yaml
      
    2. Ceph Cluster 배포:

      Ceph 클러스터를 배포해요. 이 과정에서 어떤 디스크를 Ceph 스토리지로 사용할지 지정해줘야 해요. 저는 각 워커 노드의 NVMe SSD를 사용하도록 설정했습니다.

      kubectl create -f cluster.yaml
      

      cluster.yaml 파일에서 storage 섹션에 useAllNodes: true와 useAllDevices: true를 설정하여 모든 노드의 모든 디바이스를 사용하도록 했어요. 실제 운영 환경에서는 특정 디스크만 사용하도록 명시하는 것이 좋습니다.

    3. Ceph Block Pool 및 StorageClass 생성:

      Ceph 클러스터가 안정화되면, 블록 스토리지를 위한 CephBlockPool(세프 블록 풀)과 StorageClass를 생성해요.

      kubectl create -f csi/rbd/storageclass.yaml
      

      storageclass.yaml 파일은 다음과 비슷하게 생겼을 겁니다.

      apiVersion: ceph.rook.io/v1
      kind: CephBlockPool
      metadata:
        name: replicapool
        namespace: rook-ceph
      spec:
        failureDomain: host
        replicated:
          size: 3 # 데이터 복제본 수
      ---
      apiVersion: storage.k8s.io/v1
      kind: StorageClass
      metadata:
        name: rook-ceph-block
      provisioner: rook-ceph.rbd.csi.ceph.com
      parameters:
        clusterID: rook-ceph
        pool: replicapool
        imageFormat: "2"
        imageFeatures: "layering"
        csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
        csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
        csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
        csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
      reclaimPolicy: Delete
      allowVolumeExpansion: true
      mountOptions:
        - discard
      
    4. PVC 생성:

      Longhorn과 마찬가지로, 생성된 rook-ceph-block StorageClass를 이용해 PVC를 생성해요.

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: rook-ceph-pvc
      spec:
        accessModes:
          - ReadWriteOnce
        storageClassName: rook-ceph-block
        resources:
          requests:
            storage: 10Gi
      
    Rook-Ceph on Kubernetes 클러스터 구성도

    Rook-Ceph 클러스터의 내부 구성도예요. Ceph의 여러 구성요소(MON, OSD, MGR)가 Pod 형태로 Kubernetes 클러스터 위에서 동작하는 것을 볼 수 있어요.

    FIO 벤치마크 실행 및 결과 분석

    두 스토리지 솔루션의 PVC를 각각 생성한 후, FIO를 실행할 Pod를 띄워 벤치마크를 진행했어요. 저는 주로 랜덤 읽기/쓰기(Random Read/Write)와 순차 읽기/쓰기(Sequential Read/Write) 성능을 중점적으로 살펴봤습니다. 블록 크기(Block Size)는 4KB와 1MB로 다양하게 테스트해봤거든요.

    FIO Pod를 위한 YAML 예시예요. 이 Pod가 PVC를 마운트하여 FIO 테스트를 수행합니다.

    apiVersion: v1
    kind: Pod
    metadata:
      name: fio-test-pod
    spec:
      restartPolicy: Never
      containers:
      - name: fio-container
        image: ghcr.io/fio/fio:latest # FIO 이미지를 사용합니다.
        command: ["/bin/bash", "-c"]
        args:
          - |
            mkdir -p /mnt/data
            fio --name=random-write --ioengine=libaio --iodepth=64 --rw=randwrite --bs=4k --size=1G --numjobs=1 --runtime=60 --group_reporting --filename=/mnt/data/testfile
            fio --name=random-read --ioengine=libaio --iodepth=64 --rw=randread --bs=4k --size=1G --numjobs=1 --runtime=60 --group_reporting --filename=/mnt/data/testfile
            fio --name=sequential-write --ioengine=libaio --iodepth=16 --rw=write --bs=1M --size=2G --numjobs=1 --runtime=60 --group_reporting --filename=/mnt/data/testfile_seq
            fio --name=sequential-read --ioengine=libaio --iodepth=16 --rw=read --bs=1M --size=2G --numjobs=1 --runtime=60 --group_reporting --filename=/mnt/data/testfile_seq
        volumeMounts:
        - name: test-volume
          mountPath: /mnt/data
      volumes:
      - name: test-volume
        persistentVolumeClaim:
          claimName: longhorn-pvc # 또는 rook-ceph-pvc
    

    여러 번의 테스트를 통해 제가 관찰한 결과는 대략 이랬어요. (⚠️ 이 수치는 제 특정 홈랩 환경에서 얻은 결과이며, 환경에 따라 크게 달라질 수 있음을 다시 한번 강조합니다!)

    테스트 항목 (4KB BS) Longhorn (평균) Rook-Ceph (평균) 비고
    랜덤 쓰기 IOPS 약 1,500 ~ 2,500 약 3,000 ~ 5,000 Rook-Ceph가 우위
    랜덤 쓰기 대역폭 (MB/s) 약 6 ~ 10 약 12 ~ 20 Rook-Ceph가 우위
    랜덤 읽기 IOPS 약 2,000 ~ 3,500 약 4,000 ~ 6,500 Rook-Ceph가 우위
    랜덤 읽기 대역폭 (MB/s) 약 8 ~ 14 약 16 ~ 26 Rook-Ceph가 우위
    테스트 항목 (1MB BS) Longhorn (평균) Rook-Ceph (평균) 비고
    순차 쓰기 대역폭 (MB/s) 약 80 ~ 120 약 150 ~ 250 Rook-Ceph가 우위
    순차 읽기 대역폭 (MB/s) 약 100 ~ 150 약 200 ~ 300 Rook-Ceph가 우위

    결과를 보면, 제 홈랩 환경에서는 Rook-Ceph가 전반적으로 Longhorn보다 더 높은 IOPS와 대역폭 성능을 보여줬어요. 특히 작은 블록 크기의 랜덤 I/O에서 Ceph의 강점이 두드러지더라고요. Longhorn은 복제본(replica) 수가 늘어날수록 성능 하락이 좀 더 눈에 띄는 경향이 있었고, Ceph는 안정적으로 성능을 유지했습니다.

    Longhorn과 Rook-Ceph FIO 벤치마크 결과 비교 그래프

    Longhorn과 Rook-Ceph의 FIO 벤치마크 결과를 시각적으로 비교한 그래프예요. Rook-Ceph가 전반적으로 높은 성능을 보였습니다.

    삽질 경험과 트러블슈팅 ⚠️

    솔직히 말씀드리면, 순조롭게만 진행된 건 아니었어요. 삽질 좀 했습니다 ㅎㅎ. 몇 가지 기억에 남는 경험을 공유해볼게요.

    • Longhorn: 네트워크 대역폭과 복제본 수
      처음 Longhorn을 설치하고 테스트했을 때, 생각보다 성능이 안 나와서 당황했어요. 알고 보니, Longhorn은 네트워크를 통해 볼륨 데이터를 복제(replication)하기 때문에, 노드 간 네트워크 대역폭이 정말 중요하더라고요. 제 1Gbps 네트워크 환경에서는 복제본 수를 3개로 설정했을 때 쓰기 성능이 꽤 많이 떨어지는 것을 확인했어요. 복제본 수가 늘어날수록 안정성은 높아지지만, 그만큼 네트워크 오버헤드(overhead)가 커져서 성능에 영향을 미친다는 점! 홈랩에서는 2개로 줄여서 사용하니 훨씬 나아졌습니다.
    • Rook-Ceph: OSD 인식 문제와 초기 설정
      Rook-Ceph는 초기 설정이 Longhorn보다 훨씬 복잡했어요. 특히 OSD(Object Storage Daemon)가 디스크를 제대로 인식하지 못해서 한참을 헤맸거든요. 디스크가 이미 파티셔닝(partitioning)되어 있거나, 이전에 다른 용도로 사용된 흔적이 남아있으면 Rook-Ceph가 제대로 디스크를 잡지 못하는 경우가 있더라고요. ceph-volume lvm zap --destroy /dev/sdX 같은 명령어로 디스크를 완전히 초기화해주거나, lsblk -f 명령어로 디스크의 파일 시스템(filesystem) 정보를 꼼꼼히 확인해서 해결했어요. Ceph의 CRD(Custom Resource Definition)와 설정 파일에 대한 이해가 필요하다는 것을 다시 한번 깨달았습니다.

    결론 및 선택 가이드

    제 홈랩 벤치마크 경험을 바탕으로 Longhorn과 Rook-Ceph에 대한 저의 생각을 정리해봤어요.

    솔루션 장점 단점 추천 시나리오
    Longhorn
    • 설치 및 관리가 매우 쉬움
    • 직관적인 웹 UI 제공
    • 스냅샷, 백업, 재해 복구 기능 내장
    • 가벼운 리소스 사용
    • 네트워크 대역폭에 민감 (복제본 수 증가 시)
    • Rook-Ceph 대비 낮은 최대 성능
    • 블록 스토리지에 한정
    • 홈랩, 개발/테스트 환경
    • 소규모 프로덕션 (수십 TB 이하)
    • 간편한 관리와 사용성을 중시할 때
    Rook-Ceph
    • 최고 수준의 성능 (적절한 하드웨어 시)
    • 뛰어난 확장성 (페타바이트 규모)
    • 블록, 오브젝트, 파일 스토리지 모두 지원
    • 엔터프라이즈급 안정성과 기능
    • 설치 및 설정 난이도가 높음
    • 초기 학습 곡선이 김
    • 상대적으로 많은 리소스 사용
    • 문제 발생 시 트러블슈팅 복잡
    • 대규모 프로덕션 환경
    • 고성능, 고가용성이 필수적인 경우
    • 다양한 스토리지 타입이 필요한 경우

    제 홈랩에서는 아무래도 설치 및 관리의 용이성 때문에 Longhorn에 손이 더 자주 가더라고요. 하지만 성능 자체만 놓고 본다면 Rook-Ceph가 확실히 우위를 점했어요. 결국 어떤 Kubernetes 스토리지 솔루션을 선택할지는 여러분의 환경과 요구사항에 따라 달라진다는 것이 저의 결론입니다.

    여러분도 직접 설치해보시고, 여러분의 워크로드에 맞는 벤치마크를 수행해보시면 좋은 인사이트를 얻으실 수 있을 거예요. 저의 삽질 경험이 여러분의 시행착오를 조금이나마 줄여줄 수 있다면 좋겠습니다! 😊

    다음 글에서는 Kubernetes에서 Grafana(그라파나)와 Prometheus(프로메테우스)를 이용해 스토리지 성능을 모니터링하는 방법에 대해 다뤄볼 예정이에요. 기대해주세요!

    Longhorn과 Rook-Ceph 중 어떤 솔루션이 당신에게 맞을지 요약한 인포그래픽입니다.

  • [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를 조합하면 꽤 탄탄한 백업 체계를 만들 수 있거든요. 기대해 주세요! 🎉

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

  • [k8s] Longhorn 쿠버네티스 영구 스토리지 완벽 가이드: 설치부터 PV/PVC까지

    [k8s] Longhorn 쿠버네티스 영구 스토리지 완벽 가이드: 설치부터 PV/PVC까지

    목차

    파드가 죽으면 데이터도 같이 사라진다고요? 😱

    쿠버네티스 공부하다가 처음으로 맞닥뜨리는 벽 중 하나가 바로 스토리지(Storage) 문제거든요. 저도 처음에 홈랩에 k3s 클러스터 꾸려놓고 MySQL 파드 띄웠다가, 파드 재시작하니까 데이터가 싹 날아간 경험을 했었는데요. 그때 진짜 멘붕이었죠 ㅎㅎ

    쿠버네티스에서 파드(Pod)는 기본적으로 ephemeral(일시적인) 존재입니다. 파드가 죽고 다시 살아나면 컨테이너 내부 파일시스템은 초기화돼요. 그래서 데이터베이스나 파일 서버처럼 상태를 유지해야 하는 워크로드에는 반드시 영구 스토리지(Persistent Storage)가 필요하죠.

    근데 쿠버네티스 스토리지 설정이 처음엔 진짜 복잡하게 느껴지거든요. PV, PVC, StorageClass… 용어만 해도 헷갈리는데, 여기에 분산 스토리지까지 얹으면 더 막막하죠. 오늘은 제가 홈랩에서 직접 운영하면서 가장 만족스럽게 쓰고 있는 Longhorn을 소개해드리려고 합니다. Longhorn 설치부터 PV/PVC 관리까지 한 번에 정리해볼게요.

    Longhorn 분산 스토리지 쿠버네티스 아키텍처 다이어그램

    ▲ Longhorn의 전체 아키텍처: 쿠버네티스 클러스터 내에서 각 노드의 디스크를 묶어 분산 스토리지를 구성하는 방식을 보여줍니다.

    Longhorn이 뭔가요? — 쉽게 말하면 이런 겁니다

    Longhorn 핵심 개념 정리

    Longhorn은 CNCF(Cloud Native Computing Foundation) 프로젝트로 편입된 쿠버네티스 전용 분산 블록 스토리지(Distributed Block Storage) 솔루션이에요. Rancher Labs(현 SUSE)에서 만들었고, 오픈소스로 무료로 사용할 수 있습니다.

    쉽게 말해서, 클러스터에 있는 여러 노드의 디스크를 하나로 묶어서 마치 네트워크 스토리지처럼 쓸 수 있게 해주는 거예요. 그리고 데이터를 여러 노드에 복제(Replication)해서 노드 하나가 죽어도 데이터가 안전하게 보존되죠.

    제가 Longhorn을 선택한 이유는 딱 세 가지였어요:

    • 💡 웹 UI가 있다 — 대시보드에서 볼륨 상태를 한눈에 볼 수 있어요. 이게 진짜 편하더라고요.
    • 💡 설치가 간단하다 — Helm 차트나 kubectl 한 방으로 설치 가능
    • 💡 스냅샷/백업 기능 — Longhorn 볼륨 스냅샷이나 S3 백업 연동이 기본 탑재

    PV, PVC, StorageClass — 헷갈리는 개념 한번에 정리

    저도 처음엔 이 세 개 개념이 너무 헷갈렸는데요. 비유로 설명하면 이해가 쉬워요.

    개념 풀네임 비유 설명
    PV PersistentVolume 실제 창고 공간 관리자가 미리 만들어둔 실제 스토리지 리소스
    PVC PersistentVolumeClaim 창고 사용 신청서 사용자(파드)가 필요한 스토리지를 요청하는 오브젝트
    StorageClass StorageClass 창고 종류/등급 PV를 동적으로 생성하는 방법을 정의한 템플릿

    Longhorn을 설치하면 longhorn이라는 StorageClass가 자동으로 생성되고, PVC를 만들면 그에 맞는 PV가 자동으로 프로비저닝(Dynamic Provisioning)돼요. 직접 PV를 만들 필요가 없어서 진짜 편합니다.

    사전 준비 — 설치 전에 꼭 확인하세요 ⚠️

    노드 요구사항 체크리스트

    Longhorn 설치 전에 반드시 확인해야 할 것들이 있어요. 저도 처음에 이걸 빠뜨려서 삽질을 좀 했거든요 ㅎㅎ

    1. open-iscsi 패키지 설치 — 각 노드에 반드시 필요합니다
    2. NFSv4 클라이언트 — 백업 기능 사용 시 필요
    3. curl, findmnt, grep, awk, blkid, lsblk — 기본 유틸리티 확인
    4. 마운트 전파(Mount Propagation) — 컨테이너 런타임 설정 확인

    Longhorn 공식에서는 사전 체크 스크립트를 제공해줘요. 이걸 먼저 돌려보는 게 좋습니다:

    # Longhorn 환경 체크 스크립트 실행
    curl -sSfL https://raw.githubusercontent.com/longhorn/longhorn/master/scripts/environment_check.sh | bash

    Ubuntu/Debian 계열 노드라면 open-iscsi를 이렇게 설치해요:

    # 각 노드에서 실행 (모든 워커 노드에 적용)
    sudo apt-get update
    sudo apt-get install -y open-iscsi
    sudo systemctl enable iscsid
    sudo systemctl start iscsid
    
    # 상태 확인
    sudo systemctl status iscsid

    RHEL/CentOS 계열이라면:

    sudo yum install -y iscsi-initiator-utils
    sudo systemctl enable iscsid
    sudo systemctl start iscsid

    Longhorn 설치하기 — 3가지 방법

    방법 1: kubectl로 한 방에 설치 (가장 간단)

    가장 빠른 방법이에요. 테스트 환경이나 홈랩이라면 이걸로 충분합니다:

    # Longhorn 설치 (공식 manifest 사용)
    kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.6.0/deploy/longhorn.yaml
    
    # 설치 진행 상황 확인
    kubectl get pods --namespace longhorn-system --watch
    
    # 모든 파드가 Running 상태가 될 때까지 기다립니다
    # 보통 2~3분 정도 걸려요

    방법 2: Helm으로 설치 (권장 — 프로덕션 환경)

    커스터마이징이 필요하거나 GitOps로 관리하고 싶다면 Helm이 훨씬 나아요. 저도 실제 환경에서는 Helm을 써요:

    # Helm 레포지토리 추가
    helm repo add longhorn https://charts.longhorn.io
    helm repo update
    
    # longhorn-system 네임스페이스 생성
    kubectl create namespace longhorn-system
    
    # 기본 설치
    helm install longhorn longhorn/longhorn \
      --namespace longhorn-system \
      --set defaultSettings.defaultReplicaCount=2
    
    # 설치 확인
    kubectl -n longhorn-system get pods

    💡 팁: defaultReplicaCount는 볼륨 복제본 개수예요. 노드가 3개 이상이면 3으로 설정하는 게 좋고, 홈랩처럼 노드가 적으면 2로 줄이세요.

    방법 3: values.yaml로 세부 설정

    프로덕션 환경에서는 values 파일로 관리하는 게 좋아요:

    # longhorn-values.yaml
    defaultSettings:
      # 기본 복제본 수
      defaultReplicaCount: 3
      # 스토리지 예약 비율 (각 노드 디스크의 25% 예약)
      storageReservedPercentageForDefaultDisk: 25
      # 백업 타겟 (S3나 NFS 경로)
      # backupTarget: s3://my-bucket@us-east-1/
      
    ingress:
      enabled: true
      host: longhorn.yourdomain.com
      # 인증 설정 (Basic Auth 권장)
      annotations:
        nginx.ingress.kubernetes.io/auth-type: basic
        nginx.ingress.kubernetes.io/auth-secret: basic-auth
    
    persistence:
      # 기본 StorageClass로 설정
      defaultClass: true
      defaultClassReplicaCount: 3
      reclaimPolicy: Retain
    # values 파일로 설치
    helm install longhorn longhorn/longhorn \
      --namespace longhorn-system \
      --values longhorn-values.yaml
    Longhorn 웹 UI 대시보드 볼륨 관리 화면

    ▲ Longhorn 웹 UI 대시보드: 볼륨 상태, 노드별 디스크 사용량, 복제본 상태를 한눈에 확인할 수 있습니다.

    실전: PVC 만들고 파드에 마운트하기

    StorageClass 확인

    설치가 완료됐으면 StorageClass가 잘 생성됐는지 먼저 확인해요:

    kubectl get storageclass
    
    # 출력 예시
    # NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION
    # longhorn (default)   driver.longhorn.io   Delete          Immediate           true

    (default) 표시가 붙어있으면 PVC 만들 때 StorageClass를 따로 지정 안 해도 Longhorn이 자동으로 사용돼요.

    PVC 생성하기

    이제 실제로 PVC를 만들어볼게요. 예시로 MySQL용 스토리지를 만들어보겠습니다:

    # mysql-pvc.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: mysql-data-pvc
      namespace: default
    spec:
      accessModes:
        - ReadWriteOnce   # RWO: 하나의 노드에서만 읽기/쓰기
      storageClassName: longhorn
      resources:
        requests:
          storage: 10Gi   # 10GB 요청
    # PVC 생성
    kubectl apply -f mysql-pvc.yaml
    
    # PVC 상태 확인
    kubectl get pvc
    
    # 출력 예시
    # NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES
    # mysql-data-pvc   Bound    pvc-a1b2c3d4-...                          10Gi       RWO

    STATUS가 Bound로 바뀌면 PV가 자동 생성되고 연결된 거예요. 드디어 됐다! 🎉

    파드에 볼륨 마운트하기

    이제 이 PVC를 실제 파드에 붙여볼게요:

    # mysql-deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: mysql
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          containers:
            - name: mysql
              image: mysql:8.0
              env:
                - name: MYSQL_ROOT_PASSWORD
                  value: "your-password"
              ports:
                - containerPort: 3306
              volumeMounts:
                - name: mysql-storage
                  mountPath: /var/lib/mysql   # 컨테이너 내부 마운트 경로
          volumes:
            - name: mysql-storage
              persistentVolumeClaim:
                claimName: mysql-data-pvc    # 위에서 만든 PVC 이름
    # 배포
    kubectl apply -f mysql-deployment.yaml
    
    # 파드 상태 확인
    kubectl get pods -l app=mysql
    
    # 볼륨 마운트 확인
    kubectl describe pod <파드이름> | grep -A 5 Volumes

    볼륨 확장(Expand)하기

    나중에 스토리지가 부족해지면 PVC를 확장할 수 있어요. 이거 진짜 편한 기능이거든요:

    # PVC 수정으로 볼륨 확장
    kubectl patch pvc mysql-data-pvc -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
    
    # 확장 상태 확인
    kubectl get pvc mysql-data-pvc
    
    # Conditions 항목에서 확장 진행 상황 확인
    kubectl describe pvc mysql-data-pvc

    ⚠️ 주의: Longhorn 볼륨 확장은 가능하지만 축소는 지원하지 않습니다. 처음부터 넉넉하게 잡기보다는 필요할 때 늘리는 방식이 좋아요.

    Longhorn 고급 기능 — 스냅샷과 백업

    볼륨 스냅샷 설정

    Longhorn의 숨겨진 킬러 기능 중 하나가 바로 스냅샷이에요. 쿠버네티스 VolumeSnapshot API와 연동해서 사용할 수 있습니다:

    # VolumeSnapshotClass 생성
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshotClass
    metadata:
      name: longhorn-snapshot-class
    driver: driver.longhorn.io
    deletionPolicy: Delete
    # 스냅샷 생성
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: mysql-snapshot-20240101
    spec:
      volumeSnapshotClassName: longhorn-snapshot-class
      source:
        persistentVolumeClaimName: mysql-data-pvc
    # 스냅샷 확인
    kubectl get volumesnapshot
    
    # 스냅샷에서 PVC 복원
    # source 항목에 dataSource를 지정하면 됩니다

    RecurringJob으로 자동 스냅샷

    Longhorn에는 RecurringJob이라는 기능이 있어서 스냅샷을 자동으로 주기적으로 찍을 수 있어요. 이거 설정해두면 정말 마음이 편해지더라고요:

    # 매일 새벽 2시에 스냅샷, 최대 7개 보관
    apiVersion: longhorn.io/v1beta2
    kind: RecurringJob
    metadata:
      name: daily-snapshot
      namespace: longhorn-system
    spec:
      cron: "0 2 * * *"       # 크론 표현식
      task: snapshot
      groups:
        - default
      retain: 7               # 최대 7개 보관
      concurrency: 2
      labels:
        interval: daily

    ⚠️ 삽질 모음 — 트러블슈팅 가이드

    문제 1: PVC가 Pending 상태에서 안 넘어가요

    이거 정말 자주 겪는 문제예요. 저도 처음에 한참 헤맸거든요.

    # PVC 이벤트 확인
    kubectl describe pvc <pvc-name>
    
    # Longhorn 관련 파드 상태 확인
    kubectl -n longhorn-system get pods
    
    # 특정 파드 로그 확인
    kubectl -n longhorn-system logs -l app=longhorn-manager --tail=50

    대부분의 원인은:

    • 노드에 open-iscsi가 설치 안 됨 → 각 노드에 설치 후 iscsid 서비스 재시작
    • 디스크 여유 공간 부족 → kubectl -n longhorn-system get nodes.longhorn.io로 확인
    • Longhorn 파드 중 하나가 비정상 → 해당 파드 재시작

    문제 2: 볼륨이 Degraded(저하됨) 상태예요

    복제본 중 하나가 정상적으로 동기화 안 됐을 때 나타나요. Longhorn UI에서 확인하면 어느 노드의 복제본이 문제인지 바로 보여서 편합니다.

    # 볼륨 상태 확인
    kubectl -n longhorn-system get volumes.longhorn.io
    
    # 특정 볼륨 상세 확인
    kubectl -n longhorn-system describe volume.longhorn.io <volume-name>

    보통은 자동으로 복구되는데, 안 된다면 UI에서 해당 복제본을 삭제하고 재생성하면 해결돼요.

    문제 3: 노드 추가 후 스토리지가 인식이 안 돼요

    새 노드 추가 후 Longhorn이 디스크를 자동으로 추가하지 않을 때가 있어요. UI의 Node 탭에서 해당 노드 클릭 → Add Disk로 수동 추가하거나, 노드에 node.longhorn.io/create-default-disk: config 어노테이션을 추가하면 돼요.

    Longhorn 볼륨 복제본 분산 및 Degraded 상태 시각화

    ▲ Longhorn 볼륨 복제본 분산 현황: 각 노드에 복제본이 어떻게 분산되어 있는지, Degraded 상태 발생 시 어떤 노드에 문제가 있는지 확인할 수 있습니다.

    ✅ 설치 완료 후 검증하기

    전체 상태 한번에 확인하는 명령어

    # Longhorn 시스템 파드 전체 상태
    kubectl -n longhorn-system get pods
    
    # StorageClass 확인
    kubectl get storageclass
    
    # 현재 PV/PVC 목록
    kubectl get pv,pvc --all-namespaces
    
    # Longhorn 볼륨 목록
    kubectl -n longhorn-system get volumes.longhorn.io
    
    # 노드별 디스크 상태
    kubectl -n longhorn-system get nodes.longhorn.io

    실제 데이터 보존 테스트

    진짜 제대로 되는지 확인하려면 직접 테스트해보는 게 최고예요:

    # 파드에 접속해서 테스트 파일 생성
    kubectl exec -it <mysql-pod-name> -- bash
    # 컨테이너 내부에서
    echo "Longhorn 스토리지 테스트!" > /var/lib/mysql/test.txt
    exit
    
    # 파드 강제 삭제
    kubectl delete pod <mysql-pod-name>
    
    # 새 파드가 자동으로 올라옴
    kubectl get pods -w
    
    # 새 파드에서 파일 확인
    kubectl exec -it <새-mysql-pod-name> -- cat /var/lib/mysql/test.txt
    # "Longhorn 스토리지 테스트!" 가 출력되면 성공! 🎉

    이게 출력되면 진짜 영구 스토리지가 제대로 동작하는 거예요. 처음 이 테스트 통과했을 때 얼마나 뿌듯했던지 ㅎㅎ

    Longhorn vs 다른 쿠버네티스 스토리지 솔루션 비교

    솔루션 특징 장점 단점 추천 환경
    Longhorn 쿠버네티스 전용 분산 블록 스토리지 웹 UI, 쉬운 설치, 스냅샷/백업 성능이 Ceph보단 낮음 홈랩, 중소규모 클러스터
    Rook-Ceph Ceph 기반 엔터프라이즈급 스토리지 높은 성능, 다양한 스토리지 타입 복잡한 설치/운영, 리소스 많이 사용 대규모 프로덕션
    NFS Provisioner NFS 서버 기반 동적 프로비저닝 간단, 기존 NFS 서버 활용 가능 HA 미지원, 성능 한계 소규모, 테스트 환경
    OpenEBS 경량 분산 스토리지 다양한 엔진 선택 가능 엔진별 기능 차이 있음 엣지, 경량 환경

    홈랩이나 중소규모 환경이라면 Longhorn이 가성비 최고라고 생각해요. 운영 복잡도 대비 기능이 충실하거든요.

    쿠버네티스 스토리지 솔루션 Longhorn Rook-Ceph NFS 비교 인포그래픽

    ▲ 쿠버네티스 스토리지 솔루션 비교: Longhorn, Rook-Ceph, NFS Provisioner의 사용 환경과 특성을 한눈에 비교한 인포그래픽입니다.

    자주 묻는 질문 (FAQ)

    Q. 노드가 2개밖에 없는데 Longhorn 써도 되나요?

    A. 네, 됩니다. 다만 defaultReplicaCount를 2로 설정하세요. 노드 수보다 복제본 수가 많으면 Longhorn 볼륨이 Degraded 상태가 됩니다.

    Q. ReadWriteMany(RWX) 지원하나요?

    A. Longhorn v1.1부터 NFS 기반으로 RWX(여러 노드에서 동시 읽기/쓰기)를 지원합니다. 단, 블록 스토리지 기반 RWX보다 성능이 낮을 수 있어요.

    Q. 기존 로컬 PV 데이터를 Longhorn으로 마이그레이션할 수 있나요?

    A. 직접 마이그레이션 기능은 없어요. 보통 애플리케이션 레벨에서 데이터를 백업 후 새 Longhorn PVC에 복원하는 방식을 사용합니다.

    Q. Longhorn UI에 외부에서 접근하려면 어떻게 하나요?

    A. Ingress를 설정하면 돼요. 단, 반드시 인증(Basic Auth 등)을 걸어두세요. 외부에 무방비로 열면 안 됩니다.

    마무리 — 이제 데이터 걱정 없이 쿠버네티스 쓰세요 🎉

    오늘 Longhorn 설치부터 PV/PVC 관리, 스냅샷, 트러블슈팅까지 쭉 훑어봤는데요. 처음 보면 복잡해 보이지만 한번 설치해놓으면 이후 운영은 생각보다 편합니다.

    제가 정리한 핵심 포인트:

    • ✅ 설치 전 open-iscsi 반드시 설치 — 이거 빠뜨리면 PVC가 Pending에서 안 풀림
    • ✅ 복제본 수는 노드 수에 맞게 — 노드 2개면 replica 2, 3개면 3
    • ✅ RecurringJob으로 자동 스냅샷 — 데이터 보험 필수
    • ✅ UI 접근에 인증 설정 — 보안 필수
    • ✅ 볼륨 확장은 가능, 축소는 불가 — 처음부터 너무 크게 잡지 말 것

    다음 글에서는 Longhorn 백업을 S3 호환 오브젝트 스토리지(MinIO)와 연동하는 방법을 다뤄볼 예정이에요. 백업까지 자동화하면 진짜 마음 편하거든요. 이전 글에서 다룬 MetalLB + Ingress 설정과 함께 구성하면 완성도 높은 홈랩 환경이 만들어집니다.

    혹시 설치하다가 막히는 부분 있으면 댓글로 남겨주세요. 제가 겪은 삽질 경험을 바탕으로 같이 해결해봐요! 😄