동적 프로비저닝을 사용하면서 CSI 를 준수하는 벤더의 드라이버가 볼륨 resize 를 지원하는 경우에는 PVC 조정을 통해 볼륨 확장이 가능하다. 아래와 같이 실습을 진행해보자.

 

1. 스토리지 클래스 생성

다음과 같이 allowVolumeExpansion: true 를 지정하여 스토리지 클래스를 생성한다. 스토리지 클래스에 해당 항목을 지정하더라도, 실제 사용하는 볼륨 플러그인 드라이버 구현에서 지원해야 볼륨 확장이 가능한 점에 유의하자.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: sample-block-storageclass-resize
provisioner: local.csi.openebs.io
parameters:
  storage: "lvm"
  volgroup: "lvmvg"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

 

2. PVC 생성

PVC 는 특별한 설정이 필요 없다. Static NFS 는 이미 존재하는 디렉토리를 스토리지로 사용하고, k8s 가 용량을 제어하지 않기 때문에 확장이 불가능하여 Block 스토리지로 사용하였다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-block-pvc-resize
spec:
  storageClassName: sample-block-storageclass-resize
  volumeMode: Block
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

 

3. Pod 생성

위 PVC 를 사용하는 파드를 생성하여 동적 프로비저닝이 일어나도록 한다. 블록 장치 연결 위치는 /dev/sample-block 이다.

apiVersion: v1
kind: Pod
metadata:
  name: sample-block-pod-resize
spec:
  containers:
    - name: nginx-container
      image: nginx:1.27
      volumeDevices:
        - name: nginx-pvc
          devicePath: /dev/sample-block
  volumes:
    - name: nginx-pvc
      persistentVolumeClaim:
        claimName: sample-block-pvc-resize

 

4. 볼륨 크기 확인

동적 프로비저닝이 정상적으로 수행되었는지, 생성된 영구 볼륨의 크기는 몇인지, 실제 파드 연결된 볼륨의 크기는 몇인지 확인해본다.

$ kubectl get pvc sample-block-pvc-resize
NAME                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                       VOLUMEATTRIBUTESCLASS   AGE
sample-block-pvc-resize   Bound    pvc-2d5bf77e-956e-4e38-9517-bb8f4da44ca4   500Mi      RWO            sample-block-storageclass-resize   <unset>                 115s

# PV 용량 확인
$ kubectl get pv pvc-2d5bf77e-956e-4e38-9517-bb8f4da44ca4
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS                       VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-2d5bf77e-956e-4e38-9517-bb8f4da44ca4   500Mi      RWO            Delete           Bound    default/sample-block-pvc-resize   sample-block-storageclass-resize   <unset>                          9s

# 파드에 연결된 볼륨 용량 확인
$ kubectl exec -it sample-block-pod-resize -- blockdev --getsize64 /dev/sample-block
524288000

 

5. 볼륨 크기 확장

이제 아래처럼 PVC 매니페스트의 spec.resources.requests.storage 를 이전보다 더 크게 수정/적용한 후 볼륨 사이즈를 확인해본다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-block-pvc-resize
spec:
  storageClassName: sample-block-storageclass-resize
  volumeMode: Block
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 800Mi # 여기를 수정한 후, 다시 kubectl apply 한다.

apply 후 실제 적용은 최대 1분까지 소요된다.

$ kubectl apply -f sample-block-pvc-resize.yaml
persistentvolumeclaim/sample-block-pvc-resize configured

$ kubectl get pvc sample-block-pvc-resize
NAME                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                       VOLUMEATTRIBUTESCLASS   AGE
sample-block-pvc-resize   Bound    pvc-2d5bf77e-956e-4e38-9517-bb8f4da44ca4   800Mi      RWO            sample-block-storageclass-resize   <unset>                 13m

$ kubectl get pv pvc-2d5bf77e-956e-4e38-9517-bb8f4da44ca4
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS                       VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-2d5bf77e-956e-4e38-9517-bb8f4da44ca4   800Mi      RWO            Delete           Bound    default/sample-block-pvc-resize   sample-block-storageclass-resize   <unset>                          11m

$ kubectl exec -it sample-block-pod-resize -- blockdev --getsize64 /dev/sample-block
838860800

같은 디스크에서 용량만 800Mi 로 증가된 것을 확인할 수 있다.

 

단, 아래처럼 볼륨 사이즈 축소는 불가한 점에 유의하자.

# PVC 의 spec.resources.requests.storage 를 축소한 후 적용시
$ kubectl apply -f sample-block-pvc-resize.yaml
The PersistentVolumeClaim "sample-block-pvc-resize" is invalid: spec.resources.requests.storage: Forbidden: field can not be less than previous value

 

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

영구 볼륨을 일반적인 파일 시스템으로부터 어태치 하지 않고 블록 장치로부터 어태치할 수도 있다. PVC 의 spec.volumeMode: Block 으로 지정하고(기본값이 FileSystem 임), PVC 를 사용하는 Pod 에서는 컨테이너 템플릿의 volumeDevices 를 지정하면 된다.(파일시스템인 경우 volumeMounts 인 것과 대비됨)

 

단, 현재 로컬 머신에는 NFS 스토리지만 준비되어있기 때문에 블록 스토리지를 추가로 구성해줘야 한다. 블록 스토리지를 실습하기 위해서는 Longhorn을 사용하는 방법이 권장되지만, 맥북 리소스의 한계로 이전에 구축에 실패하였다. 따라서 이번에는 OpenEBS LocalPV-LVM/ZFS 방식으로 구축해본다. VM에 추가 가상 디스크를 구성하고, 각 노드에서 해당 디스크를 블록 장치로 사용하는 방식이다. 단, LocalPV 이기 때문에 클러스터 공유 스토리지가 아닌, 특정 노드의 로컬 디스크에 종속된 스토리지라서 노드 간에 데이터 공유가 안된다는 점이 유의하자.

 

1. 가상 머신에 블록 디스크 추가(모든 워커 노드)

각 워커 노드 머신의 전원을 종료(shutdown -h now)한 후, UTM 에서 디스크를 추가한다. 인터페이스는 VirtIO, 크기는 본인의 리소스를 고려하여 적절히 세팅한 후 저장한다.

이후 다시 워커 노드를 부팅 후, lsblk 명령어를 사용하여 추가된 디스크를 확인한다.

$ lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
...
vdb                       253:16   0    2G  0 disk

 

2. LVM(Logical Volume Manager)용 PV(Physical Volume) 생성(모든 워커 노드)

Logical Volume Manager 가 추가한 디스크를 사용할 수 있는 상태로 만드는 작업이다. 모든 워커 노드에서 아래 명령어를 입력한다.

# lvm2 도구 설치
$ sudo apt update && sudo apt install lvm2 -y

# 물리 볼륨 생성
$ sudo pvcreate /dev/vdb
  Physical volume "/dev/vdb" successfully created.

아래 명령어로 PV를 조회한다. 위에에서 생성한 /dev/vdb 가 조회되면 된다.

$ sudo pvs
  PV         VG        Fmt  Attr PSize   PFree
...
  /dev/vdb             lvm2 ---    2.00g  2.00g

 

3. VG(Volume Group) 생성(모든 워커 노드)

물리 볼륨(PV)들을 하나의 그룹으로 묶는다. VG 이름은 나중에 쿠버네티스 스토리지 클래스에서 그대로 사용하게 된다. 여기서는 lvmvg 이라고 지정했다. 모든 워커 노드에서 진행한다.

# /dev/vdb 물리 볼륨을 'lvmvg'라는 이름의 볼륨 그룹으로 생성한다.
$ sudo vgcreate lvmvg /dev/vdb
  Volume group "lvmvg" successfully created
  
# 조회
$ sudo vgs
  VG        #PV #LV #SN Attr   VSize   VFree
  lvmvg       1   0   0 wz--n-  <2.00g <2.00g

 

4. LVM-LocalPV CSI 드라이버 설치(마스터 노드)

OpenEBS 의 LVM 연동 도구를 설치한다. 마스터 노드에서 실행한다. openebs 네임스페이스가 아닌 kube-system 네임스페이스 설치가 기본값인 듯 하다.

# LVM-LocalPV 오퍼레이터(Operator)와 관련 구성 요소를 쿠버네티스 클러스터에 배포한다.
$ kubectl apply -f https://openebs.github.io/charts/lvm-operator.yaml

아래 커맨드를 실행하여 필요한 리소스들이 생성되었는지 확인한다.

$ kubectl -n kube-system get statefulsets -l openebs.io/component-name
NAME                     READY   AGE
openebs-lvm-controller   1/1     70m

$ kubectl -n kube-system get daemonsets -l openebs.io/component-name
NAME               DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
openebs-lvm-node   2         2         2       2            2           <none>          70m

# openebs-lvm-controller 는 statefulset 이 관리하고, openebs-lvm-node 는 daemonset 이 관리한다.
$ kubectl -n kube-system get pods -l openebs.io/component-name
NAME                       READY   STATUS    RESTARTS   AGE
openebs-lvm-controller-0   5/5     Running   0          72m
openebs-lvm-node-8fmwx     2/2     Running   0          72m
openebs-lvm-node-dgjbp     2/2     Running   0          72m

 

5. 스토리지 클래스 생성

아래 매니페스트를 이용하여 SC를 생성한다. 프로비저너로 위에서 설치한 OpenEBS 의 CSI  드라이버를 사용하기 때문에 동적 프로비저닝 기능이 이미 포함되어있다. volumeBindingMode: WaitForFirstConsumer 를 주어서 실제 파드가 노드에 스케쥴링된 후에야 동적으로 볼륨 바인딩이 일어날 수 있도록 한다. 이는 LocalPV 를 사용할 때 중요하다. 스토리지가 노드에 종속되어있기 때문에 실제로 파드가 노드에 배정되었을 때 그 노드의 lvmvg 에서 공간을 쪼개 할당할 수 있기 때문이다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: sample-block-storageclass
provisioner: local.csi.openebs.io # 중요
parameters:
  storage: "lvm"
  volgroup: "lvmvg" # 미리 생성해두 Volume Group 명을 지정한다.
volumeBindingMode: WaitForFirstConsumer # 중요
allowVolumeExpansion: true

 

 

6. PVC 생성

아래 매니페스트를 이용하여 PVC를 생성한다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-block-pvc
spec:
  storageClassName: sample-block-storageclass
  volumeMode: Block # 중요
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

 

7. 파드 생성

실제로 블록 장치를 볼륨으로 사용할 파드를 배포한다.

apiVersion: v1
kind: Pod
metadata:
  name: sample-block-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.27
      volumeDevices:
        - name: nginx-pvc
          devicePath: /dev/sample-block
  volumes:
    - name: nginx-pvc
      persistentVolumeClaim:
        claimName: sample-block-pvc

 

8. 동적 프로비저닝 확인

파드가 PVC 를 사용하는 시점에 동적으로 PV 가 생성되었는지 확인한다.

# PVC 가 BOUND 되었는지 확인
$ kubectl get pvc sample-block-pvc
NAME               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                VOLUMEATTRIBUTESCLASS   AGE
sample-block-pvc   Bound    pvc-560cb363-b43c-498c-b397-309cd893cc6c   500Mi      RWO            sample-block-storageclass   <unset>                 90m

# PV 가 생성되었는지 확인
$ kubectl get pv pvc-560cb363-b43c-498c-b397-309cd893cc6c
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                      STORAGECLASS                VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-560cb363-b43c-498c-b397-309cd893cc6c   500Mi      RWO            Delete           Bound    default/sample-block-pvc   sample-block-storageclass   <unset>                          60m

# Pod 가 Running 중인지 확인
$ kubectl get pods sample-block-pod -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
sample-block-pod   1/1     Running   0          90m   10.244.2.83   worker02   <none>           <none>

# Pod 내에 Block 장치가 연결되었는지 확인
$ kubectl exec -it sample-block-pod -- ls -l /dev/sample-block
brw------- 1 root root 252, 1 Feb 22 10:20 /dev/sample-block

 

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,