Study/K8s

[Kubernetes] Volume (emptyDir, hostPath, PV/PVC)

Omoknooni 2023. 12. 25. 17:34

이번에는 쿠버네티스에서 데이터를 저장하는 Volume을 정리해보도록 한다.

 

Volume

컨테이너가 데이터를 저장하고 공유하는 방식을 제공하는 객체, 기존 컨테이너에서의 Volume과 유사하나 더 유연하게 사용할 수 있다.

이전의 Service를 정리했을때에 알아보았듯이 컨테이너는 일시적인 특성을 가져 일반적으로 컨테이너가 삭제되면 컨테이너에 저장된 내용들이 휘발되는 점이 존재한다.

특히나 데이터베이스와 같은 리소스는 파드나 컨테이너가 삭제되더라도 내부의 데이터를 보존을 해주어야하는데, 여기서 Volume을 사용하게 된다.

 

 쿠버네티스에서 제공하는 Volume의 종류는 아래와 같다.

  • emptyDir
  • hostPath
  • PV/PVC

 

emptyDir

파드 내에서만 지속되는 컨테이너의 임시적인 데이터를 저장하기 위한 Volume

파드가 생성될 때에 아무 데이터도 없는 빈 Volume을 생성해 emptyDir이라고 칭한다.

볼륨의 생명주기가 파드의 생명주기가 동일하고, 같은 파드 내의 컨테이너끼리 Volume을 공유할 수 있다.

파드가 삭제되면 emptyDir Volume의 데이터도 삭제되기에, emptyDir에는 반드시 일시적인 데이터만 보관하도록 한다.

 

아래는 emptyDir Volume을 생성하는 Manifest이다.

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mycontainer
      image: myimage
      volumeMounts:
        - name: myvolume
          mountPath: /path/in/container
  volumes:
    - name: myvolume
      emptyDir: {}

 

파드 내의 mycontainer 컨테이너의 /path/in/container 경로에 emptyDir Volume을 마운트하는 것을 볼 수 있다. 이렇게 Volume을 구성하고 파드 내의 다른 컨테이너에서도 동일한 Volume을 마운트시켜 컨테이너간의 공유된 Volume을 사용할 수 있는 것이다.

 

hostPath

호스트(노드) 머신의 파일 시스템 경로를 사용하는 Volume, 파드가 올라간 노드의 파일 시스템을 사용한다.

데이터의 저장이 파드가 아닌 노드 쪽이므로, emptyDir과 다르게 파드가 사라져도 Volume의 데이터가 사라지지 않는다.

단, 파드가 매번 동일한 노드에 생성된다는 보장이 없기 때문에, 파드가 다른 노드에 생성되면 해당 hostPath Volume을 마운트 할 수 없다.

hostPath는 파드에 데이터를 저장하기 위한 것이 아닌, 노드에 있는 데이터를 파드에서 사용하기 위한 것이라고 볼 수 있다.

 

아래는 hostPath Volume을 생성하는 Manifest이다.

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mycontainer
      image: nginx
      volumeMounts:
        - name: myvolume
          mountPath: /usr/share/nginx/html
  volumes:
    - name: myvolume
      hostPath:
        path: /usr/share/web
        type: Directory

 

파드에 nginx 컨테이너를 생성하는데, /usr/share/nginx/html 경로를 Volume에 마운트시켰다.

이 Volume은 hostPath를 사용하고, 노드의 /usr/share/web 경로를 사용한다. 즉, 파드의 컨테이너가 노드의 /usr/share/web이라는 디렉토리에 접근할 수 있게 되는 것이다.

 

PV / PVC

PV와 PVC는 클러스터의 파드나 노드와 별개의 리소스로, 위에서 알아본 emptyDir, hostPath와는 다르게 파드/노드의 생명주기와 별개로 동작한다.

 

먼저 PersistentVolume은 볼륨 그 자체를 뜻한다. PV는 클러스터 외부의 스토리지와 연결해 생성하는 Volume으로 파드와 별개로 관리한다.

 

PV를 생성하는 Manifest는 아래와 같다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /data/pv-data

 

이 PV의 설정 내용은 아래와 같다.

  • capacity : PV의 용량
  • volumeMode: Volume을 파일시스템 / 블록으로 사용할 것인지 
  • accessModes : PV의 액세스모드, 아래 3가지를 지원한다.
    • ReadWriteOnce : 단일 노드에서 읽기/쓰기 가능하도록 마운트
    • ReadWriteMany : 여러 노드에서 읽기/쓰기 가능하도록 마운트
    • ReadOnlyMany : 여러 노드에서 읽기 전용으로 마운트
  • hostPath : PV의 볼륨 플러그인, 여기서는 hostPath로 마운트시킬 로컬 서버의 경로를 지정해준다.

쿠버네티스에서 지원하는 PV의 볼륨 플러그인은 NFS, iSCSI, 클라우드 스토리지 서비스 등이 있다.

 

다음으로 PersistentVolumeClaim은 볼륨을 사용하기 위해 PV에 하는 요청으로 PV와 파드를 연결시켜주는 리소스이다.

PV를 얼마나 사용할 것인지부터 시작해서, Read/Write는 어떤 방식으로 할 것인지 등을 설정한다.

 

쿠버네티스에서 PV와 PVC는 역할을 바탕으로 Admin과 User의 레벨로 분리시켜 놓았다.

Admin은 스토리지에 PV리소스를 생성해서 스토리지를 사용할수 있도록 하며, User는 Admin이 생성한 PV리소스를 사용하는 PVC를 생성해서 파드에서 Volume을 사용하는 구조인 것이다.

 

다음으로 이 PV를 사용하는 PVC Manifest이다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

 

PVC의 설정도 PV와 유사한 구조를 가지는 것을 볼 수 있다.

resources.requests.storage 구문에서 PV에 자원을 얼마나 사용할 것인지 용량을 명시해주는데, 이 용량은 PV의 용량을 초과할 수 없다.

(당연한 말이다. 16GB usb에 50GB 파일을 넣을 수 없듯이...)

 

그리고 마지막으로 파드를 생성해 PVC를 사용해서 PV Volume을 사용하도록 연결해본다

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mycontainer
      image: nginx
      volumeMounts:
        - name: myvolume
          mountPath: /usr/share/nginx/html
  volumes:
    - name: myvolume
      persistentVolumeClaim:
        claimName: mypvc

 

Pod spec에 volumes 항목으로 myvolume을 PVC를 파드에 연결 후, 컨테이너의 volumeMounts로 /usr/share/ngin/html 경로를 myvolume로 마운트해준다. 

 

PV/PVC 생명주기

PV와 PVC의 생명주기는 프로비저닝 → 바인딩 → 사용 → 반환의 4단계로 나누어져 있다.

프로비저닝

PV가 생성되는 단계로, 프로비저닝에는 정적과 동적이 존재한다.

정적 프로비저닝은 PV를 미리 만들어두고 사용하는 방법으로, PVC 요청이 들어오면 만들어둔 PV를 할당하는 방식이다.

동적 프로비저닝은 PVC가 생성될 때 클러스터에서자동으로 스터리지를 프로비저닝해 PV를 생성하는 방식이다. 

 

바인딩

프로비저닝으로 만든 PV를 PVC와 연결하는 단계, PVC에서 스토리지 용량과 접근방법을 명시해 요청해 PV를 할당받는다.

여기서 PVC에 맞는 PV가 없으면, PVC가 PV가 생성될 때까지 대기하게 된다.

그리고 PV와 PVC는 반드시 일대일 대응되어야한다.

 

사용

PVC가 파드에 설정되고 파드가 PV를 마운트해 사용하는 단계, 이때 파드가 사용중인 PV와 PVC는 임의로 삭제할 수 없다.

 

반환

파드가 PVC 사용을 끝내고 PV를 회수하는 단계로, PV를 회수하는 방법에는 3가지가 존재한다.

 

Retain

PV 리소스를 그대로 유지하는 것, 연결해제 정도로 바라볼 수 있다. 이 PV 리소스를 다른 PVC가 사용할 수 없다.

PV를 재사용하기 위해서는 PV와 외부 스토리지의 정리를 직접 해주어야 한다.

 

Delete

PVC가 삭제될 때 PV도 같이 삭제하는 것, 외부 스토리지의 데이터도 삭제된다.

동적 프로비저닝의 기본 반환 정책이다.

 

Recycle

외부 스토리지의 데이터를 삭제하고 다른 PVC가 이 PV를 사용할 수 있도록 하는 것

 

이렇게 쿠버네티스의 Volume의 종류와 PV/PVC를 집중적으로 알아보았다.

다음으로 Configmap과 Secret을 알아보도록한다.