귀염둥이의 메모

[K8s] 쿠버네티스 볼륨 (emptyDir, hostPath, NFS, Persistent Volume, Persistent Volume Claim) 본문

Infra & Devops/Kubernetes

[K8s] 쿠버네티스 볼륨 (emptyDir, hostPath, NFS, Persistent Volume, Persistent Volume Claim)

겸둥이xz 2021. 10. 12. 21:16
반응형

Why Volume?

컨테이너는 기본적으로 stateless 앱 컨테이너를 사용한다. 상태가 없기 때문에 노드에 장애가 발생했을 때 다른 노드로 자유롭게 옮길 수 있는 장점을 가진다. 하지만 어떠한 이유로든 컨테이너가 실행되지 않거나 삭제되었을 때, 현재까지 저장된 데이터는 사라진다는 단점이 있다. 특성에 따라서 컨테이너에 문제가 발생하더라도 데이터 보존이 필요한 경우가 있다. 이런 상황에서 볼륨(Volume)을 사용한다.

 

예를 들어 MySQL 같은 DB는 컨테이너는 종료하거나 재시작했을 때 저장된 데이터가 사라지면 치명적이다. PV(Persistent Volume)를 사용하면 기존에 데이터를 저장했던 노드가 아닌 다른 노드에서 컨테이너를 재시작하더라도 데이터를 저장한 볼륨을 그대로 사용할 수 있다. 볼륨이나 PV를 사용하면 단순히 서버 하나에서 데이터를 저장해 사용하는 것보다 안정적으로 서비스 운영이 가능하다.

 

emptyDir, hostPath, local처럼 컨테이너가 실행된 노드의 디스크를 볼륨으로 사용하는 옵션도 있다. NFS 볼륨 플러그인을 이용하면 하나의 컨테이너에 볼륨을 붙여서 NFS 서버로 설정하고, 다른 컨테이너에서 NFS 서버 컨테이너를 가져다가 사용할 수 있다.

 

emptyDir

  • 파드가 실행되는 호스트의 디스크를 임시로 컨테이너에 볼륨으로 할당해서 사용하는 방법
  • 파드가 사라지면 emptyDir에 할당해서 사용했던 볼륨의 데이터도 함께 사라진다
  • 주로 메로리와 디스크를 함께 이용하는 대용량 데이터 계산에 사용
  • 문제가 발생해서 컨테이너가 재시작되더라도 파드는 살아 있으므로 emptyDir에 저장해둔 데이터를 계속 이용 가능
  • 볼륨 선언과 컨테이너에서 마운트하는 부분을 분리해서 설정
# emptyDir 설정 예시

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-emptydir-pod
spec:
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    volumeMounts: # 마운트
    - mountPath: /emptydir
      name: emptydir-vol
  volumes: # 볼륨 선언
  - name: emptydir-vol
    emptyDir: {}

 

hostPath

  • 파드가 실행된 호스트의 파일이나 디렉터리를 파드에 마운트
  • emptyDir과 다르게 호스트에 있는 실제 파일이나 디렉터리를 마운트 한다
  • 파드를 재시작했을 때도 호스트에 데이터가 남아있음
  • 파드가 재시작되어서 새로운 노드에서 시작할 경우, 새로운 노드의 hostPath를 사용함 (이전 노드에서 사용한 hostPath 접근 불가)

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-hostpath-pod
spec:
  containers:
  - name: kubernetes-hostpath-pod
    image: arisu1000/simple-container-app:latest
    volumeMounts:
    - mountPath: /test-volume
      name: hostpath-vol
    ports:
    - containerPort: 8080
  volumes:
  - name: hostpath-vol
    hostPath:
      path: /tmp
      type: Directory
  • 호스트의 /tmp 디렉터리를 컨테이너의 /test-volume 디렉터리에 마운트

 

NFS

  • NFS 서버를 이용해서 파드에 마운트
  • 파드 하나에 안정성이 높은 외부 스토리지를 볼륨으로 설정한 후 해당 파드에 NFS 서버 설정
  • 다른 파드는 NFS 볼륨으로 마운트
# NFS 서버 설정

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-server
  labels:
    app: nfs-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-server
  template:
    metadata:
      labels:
        app: nfs-server
    spec:
      containers:
      - name: nfs-server
        image: arisu1000/nfs-server:latest
        ports:
        - name: nfs
          containerPort: 2049
        - name: mountd
          containerPort: 20048
        - name: rpcbind
          containerPort: 111
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /exports
          name: hostpath-vol
      volumes:
      - name: hostpath-vol
        hostPath:
          path: /tmp
          type: Directory
# NFS 서버에 접속할 클라이언트 컨테이너 설정

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubernetes-nfsapp-pod
  labels:
    app: nfs-client
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nfs-client
  template:
    metadata:
      labels:
        app: nfs-client
    spec:
      containers:
      - name: kubernetes-nfsapp-pod
        image: arisu1000/simple-container-app:latest
        volumeMounts:
        - mountPath: /test-nfs
          name: nfs-vol
        ports:
        - containerPort: 8080
      volumes:
      - name: nfs-vol
        nfs:
          server: 10.233.92.29 # nfs-server 파드의 IP
          path: "/exports"

PV(Persistent Volume)와 PVC(Persistent Volume Claim)

쿠버네티스에서 볼륨의 구조는 PV와 PVC 2개로 분리되어 있다. PV는 볼륨 자체를 뜻하며 클러스터 안에서 자원으로 다룬다. 파드와는 별개로 관리되고 별도의 생명 주기(LifeCycle)가 있다.

PVC는 사용자가 PV에 하는 요청이다. 사용하고 싶은 용량, Read/Write 모드 등을 설정해서 요청한다. 쿠버네티스는 볼륨을 파드에 직접 할당하지 않고 중간에 PVC를 두어 파드와 파드가 사용할 스토리지를 분리한다. 그래서 파드 각각의 상황에 맞게 다양한 스토리지를 사용할 수 있게 한다.

 

큰 조직의 경우 PV는 쿠버네티스에서 관리하지 않는 외부 자원으로 두고 스토리지에 전문성이 있는 다른 부서에서 관리할 수 있도록 할 수 있다. 또한, AWS, GCP, Azure 등의 CSP 서비스에 있는 볼륨 관련 서비스를 이용할 수도 있다.
PV와 PVC를 분리하면 PV를 하나의 파드에서만 사용하는 것이 아닌 여러 개의 파드에서 하나의 PV를 사용할 수 있게 하고, PVC와 PV의 생명 주기를 분리함으로 데이터의 안정성을 조금 더 확보할 수 있다.

 

PV와 PVC의 생명 주기

프로비저닝(Provisioning)

  • PV를 만드는 단계, 2가지 방법 존재
  • PV를 미리 만들어 두고 사용하는 정적 방법
  • 요청이 있을 때마다 PV를 만드는 동적 방법

바인딩(Binding)

  • 프로비저닝으로 만들어진 PV를 PVC와 바인딩하는 단계
  • PVC에서 원하는 용량, 접근 방법을 명시해서 요청하면 거기에 맞는 PV 할당
  • 요청에 실패하면 원하는 PV가 있을 때까지 대기함
  • PV와 PVC의 매핑은 1:1 관계

사용(Using)

  • PVC가 파드에 설정되고 파드는 PVC를 볼륨으로 인식해서 사용
  • 할당된 PVC는 파드를 유지하는 동안 계속 사용하며 시스템에서 임의로 삭제 불가

반환(Reclaiming)

  • 사용이 끝난 PVC는 삭제되고 PVC를 사용하던 PV를 초기화하는 과정
  • Retain, Delete, Recycle 정책이 있다
    • Retain : PV를 그대로 보존
    • Delete : PV를 삭제하고 연결된 외부 스토리지 쪽의 볼륨도 삭제 (동적 할당의 기본 반환 정책)
    • Recycle : PV의 데이터들을 삭제하고 새로운 PVC에서 PV를 사용할 수 있도록 한다

PV 설정 템플릿

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-hostpath
spec:
  capacity:
    storage: 2Gi # 용량 2Gi
  volumeMode: Filesystem # 볼륨을 파일 시스템 형식으로 설정해서 사용
  accessModes: # 읽기 쓰기 옵션
  - ReadWriteOnce # 노드 하나에만 볼륨을 read/write 하도록 마운트
  storageClassName: manual # 해당 스토리지 클래스에 맞는 PVC와 연결
  persistentVolumeReclaimPolicy: Delete # PV 해제시 초기화 정책
  hostPath: # 볼륨 플러그인
    path: /tmp/k8s-pv

  • 정상적으로 설정되었고, 아직 Claim 없음

PVC 설정 템플릿

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-hostpath
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests: # 자원을 어마나 사용할 것인지 요청, 앞에서 만든 PV 용량을 초과하면 안됨
      storage: 1Gi
  storageClassName: manual

  • PV가 PVC에 정상적으로 연결됨

파드에서 PVC를 볼륨으로 사용하기

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubernetes-simple-app
  labels:
    app: kubernetes-simple-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kubernetes-simple-app
  template:
    metadata:
      labels:
        app: kubernetes-simple-app
    spec:
      containers:
      - name: kubernetes-simple-app
        image: arisu1000/simple-container-app:latest
        ports:
        - containerPort: 8080
        imagePullPolicy: Always
        volumeMounts: # 볼륨을 실제 컨테이너에 연결
        - mountPath: "/tmp"
          name: myvolume
      volumes: # 사용할 볼륨 설정
      - name: myvolume
        persistentVolumeClaim: # 사용할 PVC 설정
          claimName: pvc-hostpath

References

https://arisu1000.tistory.com/27849?category=787056 

쿠버네티스 입문 : 90가지 예제로 배우는 컨테이너 관리 자동화 표준

반응형
Comments