쿠버네티스(kubernetes) (5) - 영구 볼륨 - Persistent Volume

Share

Last Updated on 9월 7, 2022 by Jade(정현호)

안녕하세요 

이번 포스팅은 쿠버네티스에서 영구 볼륨을 설정하여 사용하는 내용에 대해서 확인 해 보도록 하겠습니다. 

해당 포스팅은 아래 포스팅에서 이어지는 글 입니다. 

             

쿠버네티스 volume

쿠버네티스는 다양한 유형의 볼륨을 지원합니다. 쿠버네티스는 스토리지를 추상적인 방법으로 접근하여 사용하게 됩니다.

실제 스토리지가 파일 스토리지를 사용하거나 또는 블록 스토리지를 사용 하는 것과 상관이 없이 추상화하여 사용하기 때문에 접근 과 사용하는 방식은 다르지 않고 차이가 없게 됩니다.
그래서 스토리지 타입이 달라도 쿠버네티스는 일관성 있게 접근하여 사용 할 수 있습니다.

또한 쿠버네티스에서는 여러 유형의 스토리지를 사용할 수 있으며, NFS 를 사용하면서 iSCSI 를 사용하는 등으로 동시에 여러 볼륨 유형을 사용할 수도 있습니다.

NFS 를 사용하거나 iSCSI 를 사용하거나 동일하게 기본적으로 볼륨은 디렉토리로 접근되게 됩니다 왜냐면 파드에 볼륨을 마운트 해서 사용하는 형태이기 때문 입니다.
볼륨을 사용하려면 yaml 파일에서 spec.volumes 에서 볼륨을 지정을 하게 됩니다.

임시 볼륨 유형은 파드의 수명과 동일하지만, 퍼시스턴트 볼륨은 파드의 수명을 넘어서 존재하게 됩니다.
즉 파드가 삭제되면 쿠버네티스는 임시(ephemeral) 볼륨을 삭제하지만, 퍼시스턴트(persistent) 볼륨은 삭제 하지 않습니다.


다양한 볼륨 유형을 지원

awsElasticBlockStore , azureDisk ,azureFile, cephfs,cinder, fc (파이버 채널) ,gcePersistentDisk, hostPath 등 다양한 볼륨 유형을 지원을 하고 있습니다

              

hostPath

hostPath 는 볼륨을 호스트 노드의 파일시스템에 있는 파일이나 디렉토리를 파드에 마운트 해서 사용 합니다.
즉, 로컬 디스크의 공간을 사용하는 볼륨 유형 입니다.

yaml 파일을 작성하여 hostPath 볼륨을 생성하도록 하겠습니다.

~$ vi nginx-volume-test-pod.yaml


apiVersion: v1
kind: Pod
metadata:
    name: nginx-volume-test-pod
    labels:
      app: myweb-nginx-vol-test
spec:
    containers:
    - name: nginx-volume-test-pod
      image: nginx:latest
      ports:
      - containerPort: 80
      volumeMounts:
      - name: hostpath-nginx-volume
        mountPath: /usr/share/nginx/html
    volumes:
    - name: hostpath-nginx-volume
      hostPath:
        path: /var/tmp/nginx_volume


nginx 컨테이너 이미지를 통해 파드를 생성하면서 볼륨(hostPath 타입)을 설정 하였습니다.
작성한 yaml 파일의 내용은 아래의 의미를 가지고 있습니다.

volumeMounts.mountPath : 파드안에서 외부 볼륨이 마운트 될 위치
volumes.name : 볼륨의 이름
hostPath.path : 파드 외부에서 마운 경로로 파일이 저장 되는 경로

작성한 yaml 파일을 통해서 파드를 생성 하도록 하겠습니다.

kubectl create -f nginx-volume-test-pod.yaml 
pod/nginx-volume-test-pod created

/home/devops/work:$ kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP          NODE      NOMINATED NODE   READINESS GATES
nginx-volume-test-pod   1/1     Running   0          9s    10.32.0.2   worker2   <none>           <none>


hostPath 로 설정된 노드의 로컬 경로는 자동으로 생성되기 때문에 별도로 생성 할 필요는 없습니다.

[devops@worker2]$ ls -al /var/tmp/
total 8
drwxrwxrwt.  7 root root 4096 Oct 24 16:48 .
drwxr-xr-x. 21 root root 4096 Jun 19 13:17 ..
drwxr-xr-x   2 root root    6 Oct 24 16:47 nginx_volume


hostPath 경로에 index.html 파일을 생성해보도록 하겠습니다.

[devops@worker2]$ cd /var/tmp/nginx_volume

[devops@worker2]$ sudo vi index.html


# 아래 내용으로 파일 작성

<html>
<head>
<title>Welcome to nginx - kubernetes pods !</title>
<style>
html { color-scheme: light dark; }
body { width: 40em; margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!  - kubernetes pods !</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

  <p><em>Thank you for using nginx.</em></p>
</body>
</html>


마스터(노드)에서 curl 로 조회를 해보겠습니다.

/home/devops/work:$ curl 10.32.0.2
<html>
<head>
<title>Welcome to nginx - kubernetes pods !</title>
<style>
html { color-scheme: light dark; }
body { width: 40em; margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!  - kubernetes pods !</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

  <p><em>Thank you for using nginx.</em></p>
</body>
</html>


curl 로 조회한 결과는 kubernetes pods ! 문구가 들어간 별도로 작성한 index.html 파일 인 것을 확인 할 수 있으며, hostPath 에 지정된 경로에 파일을 생성하니 파드 에서 사용 할 수 있는 것을 확인 하였습니다.

그럼 파드를 삭제 후 다시 재생성 해보도록 하겠습니다. 다시 생성 후에 다시 curl 로 조회를 해보도록 하겠습니다.

## 파드 삭제
~$ kubectl delete pods nginx-volume-test-pod
pod "nginx-volume-test-pod" deleted


## 파드 생성
~$ kubectl create -f nginx-volume-test-pod.yaml


## curl 로 다시 조회
/home/devops/work:$ curl 10.32.0.2
<html>
<head>
<title>Welcome to nginx - kubernetes pods !</title>
<style>
html { color-scheme: light dark; }
body { width: 40em; margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
< ... 중략 ... >


이전 단계에서 별도로 생성한 index.html 파일을 읽어들이는 것을 확인 할 수 있습니다.

테스트 환경에서 Node Select 을 사용하지 않았지만 이전 파드와 삭제 후 다시 생성된 파드가 worker2 노드에 배치 되었기 때문에 별도의 작업 없이 바로 curl 로 읽을수는 있었습니다.

테스트를 위해서 hostPath 사용하여 생성 하였으나 실제로는 동작하는 노드의 디스크가 문제가 생기거나 또는 Deployment 나 Replica 설정으로 늘어나고 줄어들고 하는 파드가 다수의 노드를 사용할 경우 워커노드의 로컬 디스크에 저장하는 형태는 파드를 다수의 노드에 배치해서 사용하는 대부분의 환경에서는 사실 사용하기 어려운 부분이 있습니다.

또한 데이터가 중복되어 저장되어 용량 낭비를 초래할 수도 있게 됩니다.

그렇지 않은 더 중요한 파드이면서 1개 노드에서만 사용 되는 형태라면 hostPath 를 사용해도 될 것 입니다.
      

Persistent Volume

이번 단계에서는 Persistent Volume 에 대해서 확인 해보도록 하겠습니다.
        

퍼시스턴트 볼륨 개요

퍼시스턴트 볼륨 시스템은 사용자 및 관리자에게 스토리지 사용 방법 에서부터 스토리지가 제공되는 방법에 대한 세부 사항을 추상화하는 API를 제공 합니다.
이를 위해 퍼시스턴트 볼륨 및 퍼시스턴트 볼륨 클레임 이라는 두 가지 새로운 API 리소스에 대해서 내용을 확인 해보겠습니다.

PV(Persistent Volume)PVC(Persistent Volume Claim) 는 스토리지를 추상화하여 접근 하는 방식 입니다. 그래서 PV 와 PVC 를 사용하면 스토리지 타입이 다르더라도 Access 방식은 거의 동일하게 사용할 수 있습니다.

yaml 파일에서 스토리지 타입에 따라서 다른 설정을 하는 것은 일부 복잡하거나 스토리지 타입에 따라서 작성 내용이 다를 수 있지만 PV 와 PVC 를 이용하게 되면 일관성 있게 접근 할 수 있습니다.

PV 와 PVC 를 사용하지 않고 파드 생성시 직접 스토리지 타입에 따라서 구성하여 사용할 수 있지만 PV 와 PVC 를 사용하면 스토리지가 달라도 접근은 동일하게 할 수 있기 때문에 볼륨을 사용할 경우에 가급적 PV 와 PVC 를 활용하는 것이 좋을 것 같습니다.


PV 와 PVC

PV(Persistent Volume) - 영구 스토리지 볼륨으로 설정하기 위한 객체
PVC(Persistent Volume Claim) - 영구 스토리지 볼륨 사용을 요청하기 위한 객체


PVC 의 AccessModes

PVC 는 볼륨 사용을 요청하는 객체로 아래의 종류로 AccessMode 를 설정 할 수 있습니다.

ReadWriteOnce - 하나의 노드에서 볼륨을 읽기-쓰기로 마운트

ReadOnlyMany - 여러 노드에서 볼륨을 읽기 전용으로 마운트
ReadWriteMany - 여러 노드에서 볼륨을 읽기-쓰기로 마운트
ReadWriteOncePod - 하나의 파드에서 볼륨을 읽기-쓰기로 마운트, 쿠버네티스 버전 1.22 이상인 경우에 CSI 볼륨에 대해서만 지원됨

위의 접근 모드는 다음과 같이 약어로 표시됩니다.
 • RWO - ReadWriteOnce
 • ROX - ReadOnlyMany
 • RWX - ReadWriteMany
 • RWOP - ReadWriteOncePod


Reclaim Policy

PVC 를 삭제 하였을 때 스토리지 볼륨을 처리하는 방법에 대한 정책으로 retain, delete, recycle 이 있습니다.

디폴트는 retain 입니다.
 • retain : pvc 사용이 끝난후에도 스토리지 볼륨의 데이터를 보존
 • delete : pvc 사용이 끝난 후에는 스토리지 볼륨 삭제 및 pv 도 삭제
 • recycle : pvc 사용이 끝난후에 데이터 삭제후 다른 파드에서 사용할 수 있도록 스토리지 볼륨을 사용 가능한 상태로 설정
         

패키지 설치

포스팅에서는 Persistent Volume 에서 NFS 를 통해서 사용을 하려고 합니다. NFS 를 노드 별로 미리 마운트를 하고 hostPath 를 사용해도 되지만 이번 단계에서는 PV 와 PVC 객체를 통해서 영구 스토리지 볼륨을 관리하는 것이 일반적입니다.
이번에는 NFS 통해 공유 스토리지를 사용하는 방법에 대해서 확인해 보려고 합니다.

NFS 를 PV 와 PVC 에서 사용하기 위해서는 공유를 하는 서버 와 워커노드에 NFS 패키지 설치, 그리고 공유 설정이 되어 있어야 합니다.

NFS 패키지 설치를 설치 하도록 하겠습니다.

-- 패키지 설치(서버 와 클라이언트 모두 설치)
sudo yum -y install nfs-utils


설치가 완료 되었다면 그 다음은 공유 설정을 하도록 하겠습니다.

-- 공유할 디렉토리 생성
sudo mkdir -p /var/nfs_storage
sudo chmod 777 /var/nfs_storage


-- 설정 파일 생성
sudo touch /etc/exports


-- 파일 내용 입력
sudo vi /etc/exports
/var/nfs_storage 192.168.56.0/24(rw)


NFS 서버 서비스 시작 합니다.(NFS 서버에서 실행)

~$ sudo systemctl start nfs-server


~$sudo exportfs
/var/nfs_storage
                192.168.56.0/24


/etc/exports 에서 192.168.56.0/24(rw) 는 NFS 로 공유할 IP 대역대를 의미 하며, RW 권한을 부여 함을 의미 합니다.
          

PV 와 PVC 생성

아래 이미지 처럼 쿠버네티스에서는 다양한 스토리지 유형을 사용할 수 있습니다. 스토리지에 대해서 먼저 PV(Persistent Volume) 객체로 생성을 하게 되고 그 다음 PVC(Persistent Volume Claim) 객체를 통해서 사용을 요청 하게 되고 PVC 를통해서 파드를 볼륨을 사용하는 순서로 진행된다고 생각하시면 됩니다.

[https://blog.naver.com/alice_k106/221348788068]

NFS 에 대해서 파드가 직접 마운트를 해서 사용하는 것이 아닌 워커 노드에서 마운트를 하게 되고 마운트 한 경로를 파드에서는 볼륨으로 설정하여 사용을 하게 됩니다.

그래서 다음 단계에서 설치를 하게 되는 nfs-utils 패키지에서 대해서 파드 에서는 설치할 필요는 없고 파드가 실행되는 워커노드에는 설치가 필요 하게 됩니다.


PV yaml 파일 작성

~$ vi nfs-pv.yaml


apiVersion: v1
kind: PersistentVolume
metadata:
# 아래 name 은 어떤 이름이라도 상관 없음 
  name: nfs-pv
  labels:
    volume: nfs-pv-volume 
spec:
  capacity:
# 스토리지 크기 결정 
    storage: 5Gi
  accessModes:
    # ReadWriteMany - multi node 에서 읽고 쓰기가 가능
    - ReadWriteMany 
  persistentVolumeReclaimPolicy:
  # retain even if pods terminate 
    Retain
  nfs:
    # NFS server's definition
    # nfs 공유 디렉토리 
    path: /var/nfs_storage 
    # nfs 서버의 주소  
    server: 192.168.56.55
    # 공유디렉토리에 대해서 읽고 쓰기 권한 부여 
    readOnly: false


yaml 파일 주요 내용
capacity.storage : 포스팅 예제에서는 5GB 로 설정
accessModes : ReadWriteMany 로 설정
persistentVolumeReclaimPolicy : Retain 으로 설정
nfs.path: NFS 서버의 원격 볼륨의 경로를 입력(/var/nfs_storage)


PVC yaml 파일 작성

~$ vi nfs-pvc.yaml


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  selector:
    matchLabels:
      volume: nfs-pv-volume
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      # storage size to use
      storage: 1Gi


yaml 파일 주요 내용
spec.accessModes : ReadWriteMany 로 설정
resources.requests.storage : 포스팅 예제에서는 실제 사용가능한 공간을 1GB 를 요청 하는 내용 입니다.


PV, PVC 생성

~$ kubectl create -f nfs-pv.yaml

~$ kubectl create -f nfs-pvc.yaml


볼륨 정보 확인
생성한 PV 와 PVC 를 확인 해보겠습니다.

~$ kubectl get persistentvolume -o wide
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                      STORAGECLASS   REASON   AGE     VOLUMEMODE
nfs-pv   5Gi        RWX            Retain           Bound      workns/nfs-pvc                                     2m46s   Filesystem


~$ kubectl get persistentvolumeclaims -o wide
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
nfs-pvc   Bound    nfs-pv   5Gi        RWX                           2m58s   Filesystem


~$ kubectl describe persistentvolume nfs-pv
Name:            nfs-pv
Labels:          volume=nfs-pv-volume
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    
Status:          Bound
Claim:           workns/nfs-pvc
Reclaim Policy:  Retain
Access Modes:    RWX
VolumeMode:      Filesystem
Capacity:        5Gi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.56.55
    Path:      /var/nfs_storage
    ReadOnly:  false
Events:        <none>


~$ kubectl describe persistentvolumeclaims nfs-pvc 
Name:          nfs-pvc
Namespace:     workns
StorageClass:  
Status:        Bound
Volume:        nfs-pv
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      5Gi
Access Modes:  RWX
VolumeMode:    Filesystem
Used By:       <none>
Events:        <none>


파드 생성

## yaml 파일 작성
~$ vi test-centos-nfs-volume.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-centos-nfs-volume
spec:
  containers:
    - name: test-centos-nfs-volume
      image: centos:7
      # 즉시 종료 되게 하지 않기 위해서 cmd 
      command: ['sh','-c','/usr/bin/sleep 3600s']
      volumeMounts:
      - name: nfs-volume
        # 컨테이너 내의 nfs 공유디렉토리의 마운트 포인트  
        mountPath: /mnt/nfs
  volumes:
    - name: nfs-volume
      persistentVolumeClaim:
        claimName: nfs-pvc



## 파드 생성
~$ kubectl create -f test-centos-nfs-volume.yaml


이전에 NFS 에 대해서 파드가 직접 마운트를 해서 사용하는 것이 아닌 워커 노드에서 마운트를 하게 되고 마운트 한 경로를 파드에서는 볼륨으로 설정하여 사용을 한다고 설명 하였습니다.
파드를 생성하게 되면 파드가 실행된 노드에서 nfs 가 마운트 될 것을 확인 할 수 있습니다.

NFS 마운트 현황 및 파드에서 사용 내역

## 워커노드에서 조회
[devops@worker2 ~]$ sudo df -h | grep nfs
192.168.56.55:/var/nfs_storage    46G  7.5G   38G  17% /var/lib/kubelet/pods/e62a1b08-62af-455b-8621-817036ec5382/volumes/kubernetes.io~nfs/nfs-pv


## 마스터 노드에서 실행
~$ kubectl exec -it test-centos-nfs-volume /bin/bash

[root@test-centos-nfs-volume ~]# df -h
Filesystem                       Size  Used Avail Use% Mounted on
overlay                           46G  6.4G   39G  15% /
tmpfs                             64M     0   64M   0% /dev
tmpfs                            1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/mapper/centos_docker1-root   46G  6.4G   39G  15% /etc/hosts
192.168.56.55:/var/nfs_storage    46G  7.5G   38G  17% /mnt/nfs <-- 외부 볼륨 마운트 정보
< ... 중략 ...>


위의 내용 처럼 워커노드에서 nfs 가 마운트 되어 있으며 그 다음 파드에서는 해당 볼륨을 사용을 하고 있게 됩니다.

파드에서 생성한 파일이 NFS 에 잘 저장 되는지 확인 해보기 위해서 파드안에서 파일을 생성 후 확인 해보도록 하겠습니다.

## 파드 안에서 파일 생성(file_created_by_the_pod.txt)
[root@test-centos-nfs-volume ~]# cd /mnt/nfs
[root@test-centos-nfs-volume nfs]# touch file_created_by_the_pod.txt <-- 파일을 생성함


## NFS 서버 : 공유 패스에서 확인
NFS_Server ~$ cd /var/nfs_storage/
NFS_Server ~$ ls -al
total 4
drwxrwxrwx   2 root      root        41 Oct 25  .
drwxr-xr-x. 23 root      root      4096 Oct 25  ..
-rw-r--r--   1 nfsnobody nfsnobody    0 Oct 25 file_created_by_the_pod.txt <-- 파일이 존재함


파드안에서 file_created_by_the_pod.txt 파일을 만들었고 공유를 설정한 NFS 서버에서 확인해보면 파드에서 생성한 파일이 있는 것을 확인 할 수 있습니다.
           

PV 와 PVC 의 수정(재생성)

PV 와 PVC 를 수정 하려면 생성시 작성한 yaml 파일을 수정 후에 PV 삭제 그리고 PV, PVC 생성 순으로 진행 합니다.

# PV 삭제
~$ kubectl delete pv nfs-pv

# PV,PVC 생성
~$ kubectl create -f nfs-pv.yaml
~$ kubectl create -f nfs-pvc.yaml


~$  kubectl get pv -o wide
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE   VOLUMEMODE
nfs-pv   5Gi        RWX            Retain           Bound    testns/nfs-pvc                           83s   Filesystem


~$  kubectl get pvc -o wide
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
nfs-pvc   Bound    nfs-pv   5Gi        RWX                           51s   Filesystem


상위 객체인 PV 를 삭제하면 PVC 도 같이 삭제가 됩니다.
         

Reference

Reference Site
 • kubernetes.io/volumes

 • kubernetes.io/persistent-volumes
 • kubernetes.io/volume-types


여기 까지 해서 쿠버네티스의 볼륨 과 Persistent Volume 에 대해서 확인해보았습니다.

추가적으로 더 많은 내용은 계속적으로 업데이트 하도록 하겠습니다.


관련된 다른 글

 

          

0
글에 대한 당신의 생각을 기다립니다. 댓글 의견 주세요!x