영구 볼륨 및 동적 프로비저닝


이 페이지에서는 Kubernetes의 영구 볼륨 및 클레임과 Google Kubernetes Engine(GKE)에서의 사용을 간략하게 설명합니다. 이 페이지에서는 Compute Engine 영구 디스크에서 지원하는 스토리지를 집중적으로 설명합니다.

이 페이지는 스토리지를 생성 및 할당하고 데이터 보안, 보호, 액세스, 권한을 구성 및 관리하는 스토리지 전문가를 대상으로 합니다. Google Cloud 콘텐츠에서 참조하는 일반적인 역할 및 예시 작업에 대해 자세히 알아보려면 일반 GKE Enterprise 사용자 역할 및 작업을 참조하세요.

PersistentVolumes

PersistentVolume 리소스는 클러스터의 내구성 있는 스토리지 관리에 사용됩니다. GKE에서 PersistentVolume은 일반적으로 영구 디스크로 지원됩니다.

대신 NFS와 같은 다른 스토리지 솔루션을 사용할 수 있습니다. Filestore는 Google Cloud의 NFS 솔루션입니다. Filestore 인스턴스를 GKE 클러스터의 NFS PV 솔루션으로 설정하는 방법은 Filestore 문서에서 Filestore CSI 드라이버로 Filestore 인스턴스 액세스를 참조하세요.

Kubernetes에서 PersistentVolume 수명 주기를 관리합니다. PersistentVolume을 동적으로 프로비저닝할 수 있습니다. 따라서 백업 스토리지를 수동으로 만들고 삭제할 필요가 없습니다.

PersistentVolume 리소스는 포드와 독립적으로 존재하는 클러스터 리소스입니다. 다시 말해 PersistentVolume에서 표시하는 디스크와 데이터는 클러스터가 변경되고 포드가 삭제되고 다시 생성돼도 계속 존재합니다. PersistentVolume 리소스는 PersistentVolumeClaims를 통해 동적으로 프로비저닝하거나 클러스터 관리자가 명시적으로 만들 수 있습니다.

PersistentVolume 리소스에 대한 자세한 내용은 Kubernetes 영구 볼륨 문서Persistent Volume API 참조를 확인하세요.

PersistentVolumeClaims

PersistentVolumeClaimPersistentVolume 리소스에 대한 요청 및 클레임입니다. PersistentVolumeClaim 객체는 PersistentVolume에 대해 특정 크기, 액세스 모드, StorageClass를 요청합니다. 요청을 충족하는 PersistentVolume이 존재하거나 프로비저닝될 수 있다면 PersistentVolumeClaim이 해당 PersistentVolume에 결합됩니다.

포드는 클레임을 볼륨으로 사용합니다. 클러스터는 신청을 검사하여 결합된 볼륨을 찾고 포드의 볼륨을 마운트합니다.

이동성은 PersistentVolumesPersistentVolumeClaims를 사용할 때의 또 다른 장점입니다. PersistentVolume은 실제 지원 스토리지 인터페이스이므로 다양한 클러스터와 환경에서 동일한 포드 사양을 쉽게 사용할 수 있습니다.

StorageClasses

Compute Engine 영구 디스크 컨테이너 스토리지 인터페이스(CSI) 드라이버와 같은 볼륨 구현은 StorageClass 리소스를 통해 구성됩니다.

GKE는 균형 있는 영구 디스크 유형(ext4)을 사용하는 기본 StorageClass를 만듭니다. PersistentVolumeClaimStorageClassName을 지정하지 않으면 기본 StorageClass가 사용됩니다. 제공된 기본 StorageClass를 자체 StorageClass로 대체할 수 있습니다. 자세한 내용은 기본 StorageClass 변경을 참조하세요.

고유한 StorageClass 리소스를 만들어 다양한 스토리지 클래스를 설명할 수 있습니다. 예를 들어 등급은 서비스 품질 수준 또는 백업 정책에 매핑될 수 있습니다. 이 개념은 다른 스토리지 시스템에서 '프로필'이라고도 합니다.

Windows 노드 풀이 있는 클러스터를 사용할 경우 Windows에서 기본 fstype(ext4)이 지원되지 않으므로 StorageClass를 만들고 PersistentVolumeClaimStorageClassName을 지정해야 합니다. Compute Engine 영구 디스크를 사용 중인 경우에는 NTFS를 파일 스토리지 유형으로 사용해야 합니다.

StorageClass를 정의할 때는 프로비저닝 도구를 나열해야 합니다. GKE에서는 다음 프로비저닝 도구 중 하나를 사용하는 것이 좋습니다.

PersistentVolume 동적 프로비저닝

대부분의 경우 PersistentVolume 객체를 직접 구성하거나 Compute Engine 영구 디스크를 만들 필요가 없습니다. 대신 PersistentVolumeClaim을 만들면 Kubernetes가 영구 디스크를 자동으로 프로비저닝합니다.

다음 매니페스트는 액세스 모드가 단일 노드에 의한 읽기-쓰기로 마운트되는 것을 허용하는 30기비바이트(GiB) 스토리지의 디스크에 대한 요청을 설명합니다. 또한 PersistentVolumeClaim을 볼륨으로 사용하는 포드를 만듭니다.

# pvc-pod-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi
  storageClassName: standard-rwo
---
kind: Pod
apiVersion: v1
metadata:
  name: pod-demo
spec:
  volumes:
    - name: pvc-demo-vol
      persistentVolumeClaim:
       claimName: pvc-demo
  containers:
    - name: pod-demo
      image: nginx
      resources:
        limits:
          cpu: 10m
          memory: 80Mi
        requests:
          cpu: 10m
          memory: 80Mi
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: pvc-demo-vol

kubectl apply -f pvc-pod-demo.yaml로 이 PersistentVolumeClaim 객체를 만들면 Kubernetes가 해당 PersistentVolume 객체를 동적으로 생성합니다.

standard-rwo 스토리지 클래스는 볼륨 바인딩 모드 WaitForFirstConsumer를 사용하므로 PersistentVolume은 포드가 볼륨을 사용하도록 예약될 때까지 생성되지 않습니다.

다음 예시에서는 생성된 PersistentVolume을 보여줍니다.

apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    pv.kubernetes.io/provisioned-by: pd.csi.storage.gke.io
  finalizers:
  - kubernetes.io/pv-protection
  - external-attacher/pd-csi-storage-gke-io
  name: pvc-c9a44c07-cffa-4cd8-b92b-15bac9a9b984
  uid: d52af557-edf5-4f96-8e89-42a3008209e6
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 30Gi
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: pvc-demo
    namespace: default
    uid: c9a44c07-cffa-4cd8-b92b-15bac9a9b984
  csi:
    driver: pd.csi.storage.gke.io
    csi.storage.k8s.io/fstype: ext4
    volumeAttributes:
      storage.kubernetes.io/csiProvisionerIdentity: 1660085000920-8081-pd.csi.storage.gke.io
    volumeHandle: projects/xxx/zones/us-central1-c/disks/pvc-c9a44c07-cffa-4cd8-b92b-15bac9a9b984
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.gke.io/zone
          operator: In
          values:
          - us-central1-c
  persistentVolumeReclaimPolicy: Delete
  storageClassName: standard-rwo
  volumeMode: Filesystem
status:
  phase: Bound

스토리지 클래스 standard-rwo를 바꾸지 않았다고 가정하면 이 PersistentVolume은 새로운 빈 Compute Engine 영구 디스크에서 지원됩니다.

영구 스토리지 삭제

기본적으로 Compute Engine 영구 디스크와 같이 동적으로 프로비저닝된 볼륨에 대해 PersistentVolumeClaim을 삭제하면 PersistentVolume 객체와 실제 지원 디스크가 모두 삭제됩니다. 이 동작은 StorageClass 및 PersistentVolume의 회수 정책에 따라 제어되며, 기본값인 Delete 또는 Retain으로 설정할 수 있습니다. 자세한 내용은 회수 관련 Kubernetes 문서를 참조하세요.

영구 스토리지를 삭제할 때 데이터 손실을 방지하거나 완화하기 위해서는 배포된 워크로드 및 데이터를 포함하여 Backup for GKE를 사용 설정하고 GKE 클러스터의 일반 백업을 예약하는 것이 좋습니다.

클러스터 삭제 중 영구 스토리지 관리

GKE 클러스터가 삭제되면 GKE가 Delete 또는 Retain 회수 정책으로 PersistentVolume 리소스를 보관합니다.

클러스터를 삭제할 때 PersistentVolume 리소스를 삭제하려면 PersistentVolumeClaim 리소스 네임스페이스를 수동으로 삭제하여 Delete 정책으로 PersistentVolume 객체에 대해 삭제를 트리거할 수 있습니다. 개별 PersistentVolumeClaim 리소스를 삭제할 수도 있습니다. 그러나 GKE는 이러한 삭제 활동이 완료될 때까지 기다리지 않고 클러스터 삭제를 시작합니다. 따라서 네임스페이스를 삭제하고 즉시 클러스터를 삭제하는 경우 Delete 정책에 따라 PersistentVolume 리소스가 삭제되지 않을 수 있습니다.

클러스터 삭제 후에도 Google Cloud 콘솔에서 남은 PersistentVolume 리소스를 볼 수 있습니다.

사용하지 않는 PersistentVolume 리소스와 같이 사용하지 않는 리소스를 보려면 유휴 리소스에 대한 권장사항을 참조하세요.

액세스 모드

PersistentVolume 리소스는 다음과 같은 액세스 모드를 지원합니다.

  • ReadWriteOnce: 볼륨은 단일 노드에 의한 읽기-쓰기로 마운트될 수 있습니다.
  • ReadOnlyMany: 볼륨은 여러 노드에 의한 읽기 전용으로 마운트될 수 있습니다.
  • ReadWriteMany: 볼륨은 여러 노드에 의한 읽기-쓰기로 마운트될 수 있습니다. Compute Engine 영구 디스크가 지원하는 PersistentVolume 리소스는 이 액세스 모드를 지원하지 않습니다.

Compute Engine 영구 디스크를 ReadOnlyMany로 사용

ReadWriteOnce는 영구 디스크의 가장 일반적인 사용 사례이며 대부분의 애플리케이션에서 기본 액세스 모드로 사용됩니다. Compute Engine 영구 디스크는 ReadOnlyMany 모드도 지원하므로 여러 애플리케이션이나 같은 애플리케이션의 여러 복제본이 동시에 같은 디스크를 사용할 수 있습니다. 예시 사용 사례에서는 여러 복제본에 정적 콘텐츠를 제공합니다.

자세한 내용은 여러 리더가 있는 영구 디스크 사용을 참조하세요.

기존 영구 디스크를 PersistentVolume으로 사용

동적으로 프로비저닝된 PersistentVolume은 생성 시 비어 있습니다. 데이터가 채워진 기존 Compute Engine 영구 디스크가 있는 경우 해당 PersistentVolume 리소스를 수동으로 만들어 클러스터에 도입할 수 있습니다. 영구 디스크는 클러스터 노드와 동일한 영역에 있어야 합니다.

기존 영구 디스크가 지원하는 영구 볼륨을 만드는 방법의 예시를 참조하세요.

배포와 StatefulSet 비교

PersistentVolumeClaim 또는 VolumeClaim 템플릿을 각각 배포 또는 StatefulSets 같은 상위 수준 컨트롤러에서 사용할 수 있습니다.

배포는 스테이트리스(Stateless) 애플리케이션을 위해 설계되었으므로 배포의 모든 복제본은 동일한 PersistentVolumeClaim을 공유합니다. 생성된 복제본 포드는 서로 동일하므로 ReadWriteMany 모드인 볼륨만 이 설정에서 작동할 수 있습니다.

ReadWriteOnce 볼륨을 사용하는 복제본이 하나 있는 배포라도 권장되지 않습니다. 기본 배포 전략에서 재생성 시 첫 번째 포드를 내리기 전에 두 번째 포드를 만들기 때문입니다. ReadWriteOnce 볼륨이 이미 사용 중이므로 두 번째 포드가 시작될 수 없고 두 번째 포드가 아직 시작되지 않아 첫 번째 포드를 삭제할 수 없으므로 배포가 교착 상태로 실패할 수 있습니다. 대신 ReadWriteOnce 볼륨과 함께 StatefulSet을 사용합니다.

StatefulSet은 복제본당 고유한 볼륨이 필요한 스테이트풀(Stateful) 애플리케이션 배포에 권장되는 방법입니다. StatefulSet을 PersistentVolumeClaim 템플릿과 함께 사용하면 각 복제본 포드에 연결된 고유한 PersistentVolumeClaim으로 자동 확장되는 애플리케이션을 사용할 수 있습니다.

리전 영구 디스크

리전 영구 디스크는 동일한 리전 내 두 영역 간에 데이터를 복제하는 멀티 영역 리소스이며 영역 영구 디스크와 비슷하게 사용할 수 있습니다. 영역에 장애가 발생하거나 한 영역의 클러스터 노드를 예약할 수 없는 상태가 되면 Kubernetes는 이 볼륨을 사용하여 워크로드를 다른 영역으로 장애 조치할 수 있습니다. 리전 영구 디스크를 사용하여 GKE에 가용성이 높은 스테이트풀(Stateful) 워크로드용 솔루션을 빌드할 수 있습니다. 개발자는 기본 영역과 장애 조치 영역이 워크로드 실행에 충분한 리소스 용량으로 구성되어 있는지 확인해야 합니다.

리전 SSD 영구 디스크는 고가용성과 고성능이 모두 필요한 데이터베이스 같은 애플리케이션을 위한 옵션입니다. 자세한 내용은 블록 스토리지 성능 비교를 참조하세요.

영역 영구 디스크와 마찬가지로 리전 영구 디스크를 필요에 따라 동적으로 프로비저닝하거나 클러스터 관리자가 사전에 수동으로 프로비저닝할 수 있습니다. 리전 영구 디스크를 추가하는 방법은 리전 영구 디스크 프로비저닝을 참조하세요.

영구 디스크의 영역

영역 영구 디스크는 영역 리소스이고 리전 영구 디스크는 멀티 영역 리소스입니다. 클러스터에 영구 스토리지를 추가할 때 영역을 지정하지 않으면 GKE는 단일 영역에 디스크를 할당합니다. GKE는 영역을 무작위로 선택합니다. 영구 디스크가 프로비저닝되면 디스크를 참조하는 모든 포드가 영구 디스크와 동일한 영역에 예약됩니다. 하지만 포드 또는 배포는 본질적으로 기존 영구 디스크 영역을 인식하지 않습니다. 포드가 기존 영구 디스크로 올바르게 예약되었는지 확인하려면 포드 또는 배포 사양에서 nodeAffinity와 같은 영역별 배치 메서드를 사용하여 적합한 영역을 타겟팅합니다.

볼륨 바인딩 모드 WaitForFirstConsumer

클러스터에서 영구 디스크를 동적으로 프로비저닝할 경우 StorageClass에서 WaitForFirstConsumer 볼륨 binding 모드를 설정하는 것이 좋습니다. 이 설정은 Kubernetes가 포드가 예약되는 영역과 동일한 영역에 영구 디스크를 프로비저닝하도록 지시하며, 안티어피니티 및 노드 선택기와 같은 포드 예약 제약조건을 준수합니다. 영역에서 안티어피니티를 사용하면 StatefulSet 포드가 해당 디스크와 함께 여러 영역에 분산될 수 있습니다.

다음은 WaitForFirstConsumer를 설정하는 영역 영구 디스크를 프로비저닝하는 데 사용되는 StorageClass의 예시입니다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-balanced
  csi.storage.k8s.io/fstype: ext4
volumeBindingMode: WaitForFirstConsumer

리전 영구 디스크를 사용하는 예시는 리전 영구 디스크 프로비저닝을 참조하세요.

다음 단계