Kubernetes 영구 볼륨, StorageClass 설정 완벽 가이드 (Kubespray 환경)

1 min read

Kubespray를 사용하여 온프레미스(On-premise) 환경에 쿠버네티스 클러스터를 성공적으로 구축했다면, 이제 막 클러스터의 ‘뇌’와 ‘뼈대’를 완성한 셈입니다. 하지만 애플리케이션이 데이터를 저장하고 상태를 유지하기 위해서는 ‘심장’과 같은 영구 스토리지(Persistent Storage)가 반드시 필요합니다. 이 역할을 수행하는 핵심 요소가 바로 스토리지 클래스(StorageClass)입니다.

ArgoCD, Prometheus, 데이터베이스 등 상태 유지가 필수적인(Stateful) 애플리케이션을 배포하기 전에, 동작하는 StorageClass를 설정하는 것은 선택이 아닌 필수 과정입니다. 이 가이드에서는 Kubespray로 구축된 클러스터에 가장 많이 사용되는 스토리지 클래스 설정 방법을 단계별로 안내하고, 각 방식의 장단점을 명확히 분석합니다.

왜 StorageClass가 필수적인가? 동적 프로비저닝의 이해

쿠버네티스에서 컨테이너는 데이터를 영구적으로 저장하기 위해 PersistentVolumeClaim(PVC)이라는 저장 공간을 요청합니다. 이때 관리자가 미리 만들어 둔 PersistentVolume(PV)과 수동으로 연결할 수도 있지만, 이는 매우 비효율적입니다.

StorageClass는 이 과정을 자동화하는 ‘동적 프로비저닝(Dynamic Provisioning)’을 담당합니다. 개발자가 PVC를 통해 “10GB의 빠른 스토리지가 필요해”라고 요청하면, StorageClass는 정의된 방식(e.g., NFS, 로컬 디스크)에 따라 즉시 해당하는 PV를 자동으로 생성하고 PVC와 연결해 줍니다. 이 자동화 메커니즘이 없으면 최신 DevOps 도구들을 원활하게 사용할 수 없습니다.

어떤 스토리지 전략을 선택할 것인가?

사용자의 환경과 요구사항에 따라 선택할 수 있는 스토리지 전략은 다양합니다.

방법설명추천 상황
Local Path Provisioner각 노드의 로컬 디스크 경로를 스토리지로 사용소규모 클러스터, 단일 노드 환경, 개발/테스트/학습 용도
NFS 서버 연결외부 NFS 서버의 공유 디렉토리를 스토리지로 사용온프레미스 환경, 데이터 공유가 필요한 다중 노드 환경
Rook-Ceph클러스터 자체에 분산 스토리지 시스템을 구축고가용성, 대규모 프로덕션 환경, 고성능이 요구될 때
클라우드 제공사 스토리지AWS EBS, GCP Persistent Disk 등 클라우드 스토리지를 사용퍼블릭 클라우드 환경 (EKS, GKE, AKS 등)

실전 가이드 1: Local Path Provisioner (가장 빠른 시작)

가장 빠르고 간단하게 동적 프로비저닝을 활성화할 수 있는 방법입니다. 각 노드의 로컬 디스크를 사용하므로 별도의 외부 스토리지가 필요 없습니다. 단, 데이터가 특정 노드에 종속되므로 해당 노드에 장애가 발생하면 데이터에 접근할 수 없다는 한계가 있습니다.

1. 설치

아래 kubectl 명령어 한 줄이면 Local Path Provisioner의 설치와 함께 local-path라는 이름의 StorageClass가 생성됩니다.

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml

2. 기본 StorageClass로 지정 (권장)

클러스터에 여러 StorageClass가 있을 때, PVC 생성 시 storageClassName을 명시하지 않으면 기본(Default) StorageClass가 사용됩니다. local-path를 기본값으로 설정하려면 아래 명령어를 실행합니다.

kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

이 어노테이션(storageclass.kubernetes.io/is-default-class)이 true로 설정된 StorageClass가 기본값으로 동작합니다.

실전 가이드 2: 외부 NFS 서버 연결 (보다 안정적인 구성)

온프레미스 환경에서 여러 노드가 데이터를 공유해야 할 때 가장 현실적인 선택지입니다. 이 방법을 사용하려면 클러스터 외부에서 접근 가능한 NFS 서버가 미리 준비되어 있어야 합니다.

1. NFS Subdir External Provisioner 설치

이 프로비저너는 NFS 서버의 공유 디렉토리 내에 PVC 요청마다 새로운 하위 디렉토리를 생성하여 PV로 제공하는 역할을 합니다.

참고: 프로덕션 환경에서는 아래 YAML을 그대로 적용하기보다, Helm 차트를 사용하여 nfs.servernfs.path 같은 중요 값을 명시적으로 설정하여 배포하는 것이 좋습니다.

# Helm을 사용하지 않는 빠른 설치 예시
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/nfs-subdir-external-provisioner/master/deploy/deployment.yaml
# 실제로는 deployment.yaml의 NFS 서버 IP와 경로를 수정해야 합니다.

2. StorageClass 생성

NFS 프로비저너를 사용하는 nfs-client StorageClass를 생성합니다.

# nfs-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 프로비저너 이름
parameters:
  archiveOnDelete: "true" # PV 삭제 시 데이터를 보관할지 여부
mountOptions:
  - vers=4.1
kubectl apply -f nfs-storageclass.yaml

3. 기본 StorageClass로 지정

필요하다면 NFS StorageClass를 기본값으로 설정합니다.

kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

설치 후 상태 확인 및 테스트

StorageClass가 올바르게 설치되고 설정되었는지 반드시 확인해야 합니다.

kubectl get storageclass

예상 출력:

NAME                   PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path (default)   rancher.io/local-path           Delete          WaitForFirstConsumer   false                  5m
nfs-client             k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate              true                   2m

(default) 표시가 현재 기본으로 설정된 StorageClass를 의미합니다.

이제 동적 프로비저닝이 실제로 동작하는지 테스트합니다. 간단한 PVC를 생성하여 PV와 자동으로 연결되는지 확인합니다.

# test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  # storageClassName: nfs-client # 기본값이 아닌 것을 테스트하려면 명시
kubectl apply -f test-pvc.yaml

# 잠시 후 상태 확인
kubectl get pvc test-claim

STATUSBound로 표시되면 성공적으로 PV가 동적 생성되어 연결된 것입니다. kubectl get pv 명령으로 새로 생성된 PV도 확인할 수 있습니다.

고급 팁: Kubespray 설치 시 StorageClass 자동 설정

Kubespray 설치 단계에서 미리 StorageClass를 설정하여 클러스터 생성과 동시에 영구 스토리지를 준비할 수 있습니다. inventory/mycluster/group_vars/k8s_cluster/addons.yml 파일을 아래와 같이 수정하면 됩니다.

# addons.yml
...
nfs_provisioner_enabled: true
nfs_provisioner_nfs_server: <YOUR_NFS_SERVER_IP>
nfs_provisioner_nfs_path: /path/to/your/nfs_share
...

이 설정을 적용하고 Kubespray를 실행하면 클러스터 설치 과정에 NFS 프로비저너가 자동으로 포함됩니다.


견고한 StorageClass의 설정은 쿠버네티스 클러스터를 단순한 컨테이너 실행 환경에서 실제 서비스를 운영할 수 있는 플랫폼으로 발전시키는 핵심 단계입니다. 자신의 환경에 맞는 스토리지 전략을 선택하고, 동적 프로비저닝을 통해 애플리케이션에 안정적인 데이터 저장소를 제공하는 기반을 마련하시기 바랍니다.

쿠버네티스 시크릿 관리, 어떤 방법이 최선일까? 4가지 방식 장단점…

쿠버네티스에서 애플리케이션을 운영할 때, DB 접속 정보나 API 키 같은 민감한 정보, 즉 ‘시크릿(Secret)’을 어떻게 관리해야 할지는 모두의 공통된 고민입니다. 관리 방식은 보안, 운영...
eve
13 sec read

[MSA] Spring Cloud Gateway VS Apache APISIX : 단계별…

마이크로서비스 아키텍처(MSA)에서 API 게이트웨이는 시스템의 관문 역할을 하는 핵심 컴포넌트입니다. 수많은 Java 개발팀이 Spring 생태계와의 완벽한 통합성을 자랑하는 Spring Cloud Gateway를 선택해왔습니다. 그러나 시스템이...
eve
1 min read

[Kafka] 카프카의 심장: 토픽, 파티션, 프로듀서, 컨슈머 완벽 해부

Apache Kafka가 어떻게 대용량 데이터를 실시간으로, 그리고 안정적으로 처리할 수 있는지 궁금하신가요? 그 비밀은 Kafka를 구성하는 핵심 요소들의 유기적인 협력에 있습니다. Kafka는 마치 잘...
eve
1 min read