Post

Section 8-1. Volumes

udemy의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의 및 쿠버네티스 인 액션 (마르코 룩샤)를 참고하여 정리한 글입니다.

Section08. Storage

Volumes

  • 컨테이너 내의 디스크에 있는 파일은 임시적이며, 컨테이너가 크래시될 때 파일이 손실된다. 즉 로그 파일을 보관해야 한다거나, 데이터 베이스를 사용할 경우 실시간으로 생성되던 데이터가 사라질 위험이 있다.
  • 쿠버네티스는 이러한 이유로 실제 데이터가 있는 디렉터리를 보존하기 위해 저장소 볼륨을 정의한다.
  • 볼륨은 컨테이너 단위가 아닌 파드 단위이기 때문에 그 파드 안에 속해 있는 여러 개의 컨테이너가 공유해서 사용될 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: random-bynber-genarator
    spec:
      containers:
      - name: alpine
        image: alpine
        command: ["/bin/sh", "-c"]
        args: ["shuf -i 0-100 -n 1 >> /opt/number.out;"]
        volumeMounts:
        - mountPath: /opt
          name: data-volume
        volumes:
        - name: data-volume
          hostpath:
            path: /data
            type: Directory
    
    • 이 예제의 경우 노드의 로컬 디스크 경로를 볼륨으로 사용하는 hostPath 볼륨이다. 파드가 생성된 노드의 /data 디렉터리에 저장된다.
    • 볼륨이 생성되면 컨테이너에서 그에 액세스하기 위해 컨테이너 내부의 디렉터리에 그 볼륨을 마운트한다.
    • 파드가 삭제 되더라도 hostPath에 있는 파일들은 삭제되지 않으므로 다른 파드가 같은 hostPath에 마운트하게 되면 남아 있는 파일에 액세스할 수 있다.
    • 그러나 노드의 해당 경로에 볼륨을 마운트한 파드가 다른 노드에서 재생성될 경우 그 노드의 볼륨에 마운트할 수 없다.

Volume의 종류

  • emptyDir: 일시적인 데이터를 저장하는 빈 디렉토리

Persistent Volumes

  • 퍼시스턴트볼륨 (PV)은 관리자가 프로비저닝하거나 스토리지 클래스를 사용하여 동적으로 프로비저닝한 클러스터의 스토리지이다.
  • 노드가 클러스터 리소스인 것처럼 PV는 클러스터 리소스이다.
  • Volume은 Pod과 동일한 라이프사이클을 가지지만 PV는 리소스를 사용하는 Pod과 별개의 라이프사이클을 가진다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-voll
    spec:
      accessModes:
      - ReadWriteOnce
      capacity:
        storage: 1Gi
      hostPath:
        path: /tmp/data
    
    $ kubectl create -f pv-definition.yaml
     persistentvolume/pv-vol1 created
      
    $ kubectl get pv
     NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
     pv-vol1   1Gi        RWO            Retain           Available                                   3min
    
    • accessModes: 호스트에 볼륨이 어떻게 마운트되어야 하는지 정의한다. (ReadOnly, ReadWriteOnce, ReadWriteMany)
    • capacity: PV를 위해 예약될 저장소 크기를 정의한다.
    • hostPath: hostPath는 노드의 로컬 디렉토리에 저장소를 둔다.

Persistent Volume Claims

  • PVC는 사용자의 스토리지에 대한 요청이다.
  • 특정 크기 및 접근 모드를 요청할 수 있다(예: ReadWriteOnce, ReadOnlyMany 또는 ReadWriteMany로 마운트 할 수 있다)
  • 모든 PVC는 단일 PV에 묶인다.
    • 쿠버네티스는 PVC에서 요구하는 storage 용량을 확보할 수 있는 쪽으로 access mode, volume mode, storage class, sufficient capacity를 고려하여 PV를 바인딩한다. ```

      pvc-definition.yaml

    apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim spec: accessModes:

    • ReadWriteOnce resources: requests: storage: 500Mi

    $ kubectl create -f pvc-definition.yaml persistentvolumeclaim/myclaim created

    $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE myclaim Pending

    $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE myclaim Bound pv-vol1 1Gi RWO 43m ```

    • 위와 같이 PVC를 생성하면 PV 중 accessModes가 일치하고 storage 용량을 확보할 수 있는 pv에 바운딩된다

PV와 PVC의 생명주기

  • PV와 PVC는 프로비저닝 -> 바인딩 -> 사용 -> 반환의 생명주기를 따른다.

프로비저닝

  • PV를 프로비저닝 할 수 있는 방법은 정적(static) 프로비저닝과 동적(dynamic) 프로비저닝 두 가지 방법이 있다:

정적 프로비저닝

  • 클러스터 관리자는 여러 PV를 만든다. 클러스터 사용자가 사용할 수 있는 실제 스토리지의 세부 사항을 제공한다. 이 PV들은 쿠버네티스 API에 존재하며 사용할 수 있다

동적 프로비저닝

  • 관리자가 생성한 정적 PV가 사용자의 퍼시스턴트볼륨클레임과 일치하지 않으면 클러스터는 PVC를 위해 특별히 볼륨을 동적으로 프로비저닝 하려고 시도할 수 있다.
  • 클러스터 관리자는 PV를 생성하는 대신에, 퍼시스턴트 볼륨 프로비저너를 배포해 사용자가 선택 가능한 볼륨 타입을 하나 이상의 스토리지클래스 오브젝트로 정의하면 사용자가 퍼시스턴트볼륨클레임에서 스토리지클래스를 참조하여 프로비저너가 이를 프로비저닝할 시에 처리한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    # storage-definition.yaml
      
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: silver
    provisioner: kubernetes.io/gce-pd
    parameters:
      type: pd-standard
      replication-type: none
      
    # storageClass-pvc-definition.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: mongodb-pvc
    spec:
      resources:
        requests:
          storage: 100Mi
      accessModes:
        - ReadWriteOnce
      storageClassName: silver
    
    • storageClassName 항목에 생성한 storage class의 이름을 명시한다.
    • storage class에 참조한 프로비저너가 알아서 PV를 생성해주고, PVC와 연결도 해준다.

바인딩

  • 마스터의 컨트롤 루프는 새로운 PVC를 감시하고 일치하는 PV(가능한 경우)를 찾아 서로 바인딩한다.
  • PV가 새 PVC에 대해 동적으로 프로비저닝된 경우 루프는 항상 해당 PV를 PVC에 바인딩한다.
  • 일치하는 볼륨이 없는 경우 클레임은 무한정 바인딩되지 않은 상태로 남아 있다. 일치하는 볼륨이 제공되면 클레임이 바인딩된다
    • 예를 들어 많은 수의 50Gi PV로 프로비저닝된 클러스터는 100Gi를 요청하는 PVC와 일치하지 않는다. 100Gi PV가 클러스터에 추가되면 PVC를 바인딩할 수 있다.

사용

  • 파드는 클레임을 볼륨으로 사용하고, 클러스터는 클레임을 검사하여 바인딩된 볼륨을 찾고 해당 볼륨을 파드에 마운트 한다. 일단 클레임이 바인딩되면 PV는 사용자가 필요로 하는 한 사용자에게 속하게 된다.

반환

  • 사용자가 볼륨을 다 사용하고나면 리소스를 반환할 수 있는 API를 사용하여 PVC 오브젝트를 삭제할 수 있다.
  • 퍼시스턴트볼륨의 반환 정책은 볼륨에서 클레임을 해제한 후 볼륨에 수행할 작업을 클러스터에 알려준다.

반환 정책

  • Retain: 리소스를 수동으로 반환할 수 있게 하는 정책이다. PVC가 삭제되어도 PV는 여전히 존재하며, 따라서 다른 요청에 대해서는 사용이 불가능하다. 따라서 관리자가 수동으로 볼륨을 반환해야 한다.
  • Delete: PV와 외부 인프라와 관련된 스토리지 자산을 모두 삭제한다. 동적으로 프로비저닝 된 볼륨은 Storage Class의 반환 정책을 상속한다.

정리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# pv-definition.yaml     =>  # pvc-definition.yaml        =>  # pod-definition.yaml

apiVersion: v1               apiVersion: v1                   apiVersion: v1
kind: PersistentVolume       kind: PersistentVolumeClaim      kind: Pod
metadata:                    metadata:                        metadata:
  name: pv-voll                name: myclaim                    name: ramdom-number-generator
spec:                        spec:                            spec:
  accessModes:                 accessModes:                     containers:
  - ReadWriteOnce              - ReadWriteOnce                  - name: alpine
  capacity:                  resources:                           image: alpine
    storage: 1Gi               requests:                          command: ["/bin/sh", "-c"]
  hostPath:                      storage: 500Mi                   args: ["shuf -i 0-100 -n 1 >> /opt/number.out;"]
    path: /tmp/data                                               volumeMounts:
                                                                     - mountPath: /opt
                                                                       name: data-volume
                                                                     volumes:
                                                                     - name: data-volume
                                                                       persistentVolumeClaim:
                                                                         claimName: myclaim 
This post is licensed under CC BY 4.0 by the author.