본문 바로가기

[k8s] K8s Storage with OpenEBS 본문

Infra

[k8s] K8s Storage with OpenEBS

겨울바람_ 2024. 8. 2. 19:45

k8s Storage

컨테이너 환경에서는 별도 설정을 하지 않으면 데이터는 호스트 노드의 임시 디스크에 보관된다. 컨테이너를 삭제하면 임시 디스크에 있는 데이터는 저장되지 않고 컨테이너와 함께 삭제된다.

 

이러한 문제를 쿠버네티스에서는 Pod와 데이터를 분리해서 영구 볼륨이라는 별도의 추상화된 리소스로 해결한다.

쿠버네티스 볼륨을 구성하는 주요 리소스로 Persistent Volume (영구볼륨), PVC (Persistent VolumeClaim, 영구볼륨 요청자), Storage Class가 있다.

 

클러스터 관리자와 사용자(개발자)의 역할에 따라 쿠버네티스 볼륨에 관련된 작업이 서로 다르다.

 

클러스터 관리자는 클라우드 서비스 제공업자, 상용 혹은 오픈소스 솔루션 중에서 원하는 성능과 기
능을 제공하는 스토리지를 선택하여 개발자에게 적절한 솔루션을 제공하는 역할을 한다.

 

게빌지는 애플리케이션에서 필요한 스토리지 용량과 특성(ReadWriteOnce/ReadWriteMany)을 고려해 애플리케이션에 연결하는 작업을 진행한다.

 

이번 예제에서는 오픈소스 OpenEBS 로컬 호스트패스를 이용해 스토리지 클래스를 만들고 스토리지 관련 설정을 YAML 파일로 작성하는 방법에 대해 알아보려고 한다.

PersistentVolume

PV (Persistent Volume) 영구볼륨은 실제 데이터가 영속적으로 저장되는 스토리지의 일부다. 실제 데이터가 저장되는 리소스이며, 관리자는 정적으로 직접 영구볼륨을 생성할 수 있으나 운영 환경에서는 대부분 스토리지 클래스를 이용해 동적으로 영구볼륨을 할당한다.

 

PVC (Persistent Volume Claim) 영구볼륨 요청자는 실제 데이터가 저장돠는 영구볼륨과 분리해서 영구볼륨의 스토리지 용량과 액세스 모드 등 영구볼륨과 관련된 설정만 별도로 분리한 쿠버네티스 리소스다.

 

관리자는 PV, 스토리지 클래스를 만들고 개발자는 영구볼륨의 상세한 설정 내역을 몰라도 PVC를 이용해 볼륨을 사용할 수 있다.

 

스토리지 클래스는 스토리지 솔루션 또는 클라우드 서비스 제공업체에서 제공하는 여러 가지 스토리지 중 동일한 속성 (IOPS, 레이턴시, 백업정책 등)을 가지는 스토리지의 집합 리소스다.


사용자는 원하는 스토리지 클래스를 지정해 PVC에서 요청하면 스토리지 클래스에서 해당 볼륨을 동적으로 할당한다.

이러한 쿠버네티스 볼륨을 할당하는 프로세스를 간략히 정리하면 관리자는 사전에 클러스터에 필요한 스토리지 유형을 정하고 이를 스토리지 클래스로 생성한다.


사용자는 PVC로 볼륨 할당을 요청하면 해당 스토리지 클래스에서 동적으로 PV가 할당된다.

OpenEBS 로컬 호스트패스 설치

쿠버네티스 자체에서는 스토리지 클래스를 제공하지 않고 별도의 솔루션을 설치해야 사용할 수 있다. 일반적으로 퍼블릭 클라우드 서비스 업체는 스토리지 클래스를 기본으로 제공하고 온프레미스 환경은 별도 스토리지 솔루션으로 구현한다.

 

현업에서 많이 사용하는 오픈소스 스토리지 솔루션으로 CephGlusterFS, OpenEBS 등이 있다. 이번 포스팅의 예제에서는 속도가 빠르고 설치 및 사용이 쉬운 OpenEBS 호스트패스를 사용한다.

 

OpenEBS는 Pod가 실행되는 호스트 노드의 특정 디렉터리(호스트패스)를 Pod의 볼륨으로 할당한다. OpenEBS 솔루션 없이 호스트 노드의 원하는 경로를 직접 Pod의 볼륨으로 할당할 수 있지만 스토리지 클래스를 이용하지 않으므로 필요할 때마다 영구볼륨을 생성하고 다시 수동으로 삭제해야 하는 정적인 구성으로 굉장히 번거롭다.

 

OpenEBS를 사용하면 스토리지 클래스를 이용해 동적으로 볼륨을 생성하고 삭제할 수 있다. 또한 볼륨 관련 구성은 공통 속성을 사용하므로 기존에 사용하는 애플리케이션 YAML 파일을 수정하지 않고도 OpenEBS 환경에 그대로 사용할 수 있다는 장점이 있다.

 

외부 네트워크 지연과 분산 파일 시스템을 사용하지 않고 노드의 로컬 디스크에 직접 데이터를 읽고 쓰므로 다른 스토리지 솔루션에 비해 성능이 뛰어나다.

k create ns openbs
k ns openbs

k apply -f https://openebs.github.io/charts/openebs-operator-lite.yaml
k apply -f https://openebs.github.io/charts/openebs-lite-sc.yaml

k get sc

 

위의 명령어를 입력하면, openebs-deviceopenebs-hostpath라는 2가지 스토리지 클래스가 생성된다.

 

openebs-device는 노드에서 마운트하지 않은 별도의 디스크 디바이스에 Pod의 데이터를 저장하고 openebs-hostpath는 호스트 노드의 특정 디렉터리에 데이터를 할당하는 방식이다.

 

호스트패스에서 사용하는 디렉터리 위치는 관리자가 변경할 수 있는데, 기본 설정은 /var/openebs/local이다.

 

OpenEBS에서 사용하는 볼륨이 호스트 노드의 파일시스템 용량에 영향을 끼치지 않도록 기본 디렉터리 경로가 아니라 별도의 마운트 포인트를 사용하는 것을 권장한다.

 

이제 새롭게 생성한 openebs-hostpath 스토리지 클래스를 이용해 PVC를 생성하고 Pod에 볼륨을 할당한다.

스토리지 클래스를 이용한 PVC 및 영구볼륨 사용

YAML 파일을 이용해 PVC를 생성하고 애플리케이션 내 영구 볼륨을 마운트하는 실습을 진행하려 한다. 개발자는 해당 작업만 가능하면 쿠버네티스 스토리지를 사용하는 데 별다른 문제가 없다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: default-pvc
  namespace: default
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: FileSystem
  resources:
    requests: 
      storage: 1Gi
storageClassName: "openebs-hostpath"
  • kind: PersistentVolumeClaim
    • 쿠버네티스는 영구볼륨을 요청하는 PersistentVolumeClaim을 별도의 리소스로 지정한다
  • namespace: default
    • PVC는 네임스페이스 단위로 생성하고 구분된다
    • 영구볼륨은 특정 네임스페이스가 아닌 전체 클러스터 단위로 할당된다
  • spec.accessModes: ReadWriteOnce
    • 스토리지 클래스에서 지원하는 액세스 모드 중 한 가지를 지정한다
  • spec.volumeMode: Filesystem
    • Filesystem과 Block의 두 가지 모드를 선택할 수 있다
  • spec.resources.requests.storage: 1Gi
    • 영구볼륨이 사용하는 용량을 지정한다. Pod가 마운트한 볼륨은 해당 용량을 초과해서 사용할 수 없다
  • spec.storageClassName: "openebs-hostpath"
    • 클러스터가 지원한느 스토리지 클래스 이름을 지정한다. 클러스터에서 사용 가능한 복수의 스토리지 클래스가 있으면 원하는 스토리지 클래스를 선택할 수 있다

개발자는 위와 같은 기본 템플릿 PVC 파일에서 용량과 스토리지 클래스 이름 등 몇 가지 변수만 변경해서 새로운 PVC를 반복 생성할 수 있다.

k ns default
k apply -f date-pvc.yaml
k get pvc

 

PVC를 생성하면 정상적으로 default-pvc가 생성된다. PVC 또한 리소스이므로 k get 명령어로 PVC 목록을 확인할 수 있다. 하지만, 상태가 정상이지 않고 Pending으로 표기되는 것을 확인할 수 있다.

 

k describe pvc default-pvc 명령어를 통해 확인해보면, 첫 번째 사용자(Pod)가 볼륨을 연결하기를 기다린다. 라는 의미의 메시지를 확인할 수 있다.

 

OpenEBS 스토리지 클래스의 특징으로 PVC는 해당 PVC를 사용하는 Pod가 먼저 생성되고 다음으로 볼륨이 연결된다. Pod가 생성되고 해당 PVC를 마운트하면 상태가 Pending에서 Bound로 변경된다.

 

이처럼 사용자는 먼저 Pod가 사용할 볼륨을 PVC로 생성한다. 이후 헤당 PVC를 Pod YAML 파일의 volumeMountsvolumes에 추가해서 사용한다.

 

아래는 실제 애플리케이션에서 PVC를 사용하는 Deployment YAML 파일의 예제다

apiVersion: apps/v1
kind: Deployment
metadata:
  name: data-pod
  namespace: default
  labels:
    app: date
spec:
  replicas: 1
  selector:
    matchLabels:
      app: date
  template:
    metadata:
      labels:
        app: date
    spec:
      containers:
      - name: date-pod
        image: busybox
        command:
        - "/bin/sh"
        - "-c"
        - "while true; do date >> /data/pod-out.txt; cd /data; sync; sync; sleep 30; done"
        volumeMounts:
        - name: date-vol
          mountPath: /data
    volumes:
    - name: date-vol
      persistentVolumeClaim:
        claimName: default-pvc
  • spec.template.spec.containers.volumeMounts
    • 컨테이너에서 사용할 볼륨의 정보를 지정한다. Pod는 볼륨을 사용하기 위해 volumeMounts와 volumes의 2가지를 사용한다
  • spec.template.spec.containers.volumeMounts.name
    • 컨테이너 마운트 포인트에 사용할 볼륨의 이름을 지정한다
  • spec.template.spec.containers.volumeMounts.mountPath
    • 컨테이너 내부의 마운트 포인트를 지정한다. 지정된 마운트 포인트로 볼륨이 할당된다
  • spec.template.spec.volumes.name
    • 컨테이너 마운트 포인트 이름과 동일하게 매핑한다. YAML 파일 내에 볼륨 마운트가 여러 개 있으면 해당하는 볼륨 마운트 이름과 일치시킨다
  • spec.template.spec.volumes.persistentVolumeClaim.claimName
    • 볼륨에 사용할 PVC 이름을 지정한다. PVC는 Pod와 동일한 네임스페이스에 있어야 한다

이전 Pod 예제와 동일하게 date 명령의 출력 결과를 파일에 저장하는 Deployment YAML파일이다. 이전과 다르게 PVC를 사용해 데이터가 사라지지 않고 영구볼륨에 저장된다.

 

PVC 볼륨을 사용하는 Deployment YAML 파일은 기존의 Deployment YAML과 동일하지만 volumeMountsvolumes 부분만 기존 Deployment YAML에 추가됐다.

 

위의 YAML 파일을 통해 Deployment를 생성한다.

k apply -f date-pvc-deploy.yaml
k get pod -o wide
k get pvc

PV/PVC 삭제

영구볼륨은 Pod에서 볼륨으로 사용하고 있으므로 영구볼륨을 삭제하려면 먼저 볼륨을 사용하고 있는 Pod를 삭제해야 한다. Pod를 삭제하지 않으면, 영구볼륨이 삭제되지 않는다.

 

PVC를 삭제할 때는 영구볼륨의 삭제와 관련된 정책은 해당 스토리지 클래스의 정책을 따르며 k get pv 출력 결과에서 확인할 수 있다.

 

영구볼륨 삭제와 관련된 ReclaimPolicy(재요구정책)에는 DeleteRetain옵션이 있다. Delete는 PVC를 삭제하면 영구볼륨도 함께 삭제되고, Retain은 PVC는 삭제돼도 영구볼륨은 삭제되지 않고 유지하는 정책이다.

 

Retain 옵션을 사용하면 PVC를 삭제해도 PV는 삭제되지 않으므로 안전하지만, 삭제 작업은 수동으로 진행해야 한다. 만약 지워지지 않은 영구볼륨이 있다면 향후 해당 영구볼륨을 이용해 수동으로 새로운 PVC를 생성할 수 있다.

 

OpenEBS 스토리지 클래스의 기본 정책은 Delete다.

사용자 스토리지 클래스를 지정해 헬름 차트 MySQL 설치하기

쿠버네티스 환경에서 애플리케이션을 설치하는 데는 주로 헬름을 이용한다. 헬름 차트는 템플릿 파일로 개별 상황에 맞게 설치 옵션을 지정할 수 있다. 스토리지 클래스도 템플릿 파일을 이용해 지정할 수 있다.

 

대부분의 헬름 파일에 스토리지 클래스만 지정하면 PVC가 자동으로 생성된다. 이번 예제에서는 OpenEBS 호스트패스를 스토리지 클래스로 지정해 헬름 차트로 MySQL 애플리케이션을 설치한다.

helm search repo mysql
helm pull bitnami/mysql
tar xvfz mysql-9.1.0.tgz
mv mysql mysql-9.1.0
cd mysql-9.1.0/
cp values.yaml my-values.yaml

이후 YAML 파일의 내용 중 아래 부분을 변경한다.

  • architecture: replication
    • MySQL 애플리케이션 구조를 복제 구성으로 변경한다
  • persistence.storageClass
    • primary.persistence.storageClasssecondary.persistence.storageClass의 스토리지 클래스를 openebs-hostpath로 변경한다
      k create ns mysql
      k ns mysql
      helm install mysql -f my-values.yaml .

헬름 차트를 이용해 애플리케이션을 설치할 때 헬름의 스토리지 클래스를 새롭게 생성한 openebs-hostpath로 지정하면 해당 스토리지 클래스를 이용해 자동으로 영구볼륨을 생성한다.

 

헬름 차트 삭제시, 데이터 보호를 위해 기본적으로 PVC는 삭제하지 않는다. 따라서 헬름 차트가 업그레이드되거나 변경돼도 데이터는 그대로 유지해서 기존 데이터의 변경 없이 그대로 사용할 수 있다.

 

PVC를 삭제하려면 다음과 같이 수동으로 삭제해야 한다.

k delete pvc --all

로컬 호스트패스 스토리지 클래스의 장점 및 제약 사항

OpenEBS 호스트패스는 이름에서 알 수 있듯이 로컬 호스트의 특정 디렉터리를 스토리지 클래스로 이용한다. 네트워크에 연결된 별도의 스토리지를 이용하지 않으므로 네트워크 전송에 따른 추가 지연 시간이 없다.

 

또한, 분산 파일 시스템을 사용하지 않고 로컬 노드의 디스크를 바로 사용하므로 다른 스토리지 솔루션에 비해 성능이 월등하다. 하지만 해당 노드에서만 Pod가 실행되므로 노드가 다운되면 Pod 역시 함께 사용하지 못한다는 제약 사항이 있다.

 

고가용성 측면에서의 제약 사항은 애플리케이션 단에서 다른 노드의 Pod와 데이터를 동기화하여 해결할 수 있다. 데이터베이스 자체에서 제공하는 동기화 기능을 사용하면 이러한 제약 사항이 없기 때문에 로컬 호스트패스를 실제 운영 환경의 데이터베이스 스토리지 클래스로 사용하는 경우도 있다.

스토리지 고가용성 구성 제약

로컬 호스트패스 스토리지 클래스는 Pod가 실행 중인 노드의 특정 디렉터리를 Pod의 볼륨으로 할당한다. 따라서 Pod의 데이터는 해당 노드에만 존재해서 다른 노드로 Pod를 이동하는 것이 불가능하다.

 

볼륨을 가지지 않는 일반 파드(Stateless POD)는 특정 노드에 장애가 발생해도 다른 노드로 이전이 가능하지만, 로컬 호스트패스를 스토리지 클래스로 가진 Pod는 다른 노드로 이동이 불가능하다.

 

PVC가 특정 노드만 실행 중인 Pod는 해당 노드에서만 실행 가능하다. 해당 노드의 문제가 발생하면 Pod가 실행되지 않아 서비스 장애가 발생한다.

 

호스트패스를 사용하는 Pod는 애플리케이션 단에서 서로 다른 노드의 Pod와 서로 데이터를 복제하도록 설정할 필요가 있다. 볼륨 복제를 지원하면 기존 PVC를 삭제했을 때 새로운 노드에서 기존 데이터를 처음부터 복제해서 Pod 실행이 가능하다.

 

다음 포스팅에서는 EKS 환경에서의 Storage 설정에 대해 작성해보고자 한다.

Comments