1 - 볼륨

컨테이너 내의 디스크에 있는 파일은 임시적이며, 컨테이너에서 실행될 때 애플리케이션에 적지 않은 몇 가지 문제가 발생한다. 한 가지 문제는 컨테이너가 크래시될 때 파일이 손실된다는 것이다. kubelet은 컨테이너를 다시 시작하지만 초기화된 상태이다. 두 번째 문제는 Pod에서 같이 실행되는 컨테이너간에 파일을 공유할 때 발생한다. 쿠버네티스 볼륨 추상화는 이러한 문제를 모두 해결한다. 파드에 대해 익숙해지는 것을 추천한다.

배경

도커는 다소 느슨하고, 덜 관리되지만 볼륨이라는 개념을 가지고 있다. 도커 볼륨은 디스크에 있는 디렉터리이거나 다른 컨테이너에 있다. 도커는 볼륨 드라이버를 제공하지만, 기능이 다소 제한된다.

쿠버네티스는 다양한 유형의 볼륨을 지원한다. 파드는 여러 볼륨 유형을 동시에 사용할 수 있다. 임시 볼륨 유형은 파드의 수명을 갖지만, 퍼시스턴트 볼륨은 파드의 수명을 넘어 존재한다. 파드가 더 이상 존재하지 않으면, 쿠버네티스는 임시(ephemeral) 볼륨을 삭제하지만, 퍼시스턴트(persistent) 볼륨은 삭제하지 않는다. 볼륨의 종류와 상관없이, 파드 내의 컨테이너가 재시작되어도 데이터는 보존된다.

기본적으로 볼륨은 디렉터리이며, 일부 데이터가 있을 수 있으며, 파드 내 컨테이너에서 접근할 수 있다. 디렉터리의 생성 방식, 이를 지원하는 매체와 내용은 사용된 특정 볼륨의 유형에 따라 결정된다.

볼륨을 사용하려면, .spec.volumes 에서 파드에 제공할 볼륨을 지정하고 .spec.containers[*].volumeMounts 의 컨테이너에 해당 볼륨을 마운트할 위치를 선언한다. 컨테이너의 프로세스는 컨테이너 이미지의 최초 내용물과 컨테이너 안에 마운트된 볼륨(정의된 경우에 한함)으로 구성된 파일시스템을 보게 된다. 프로세스는 컨테이너 이미지의 최초 내용물에 해당되는 루트 파일시스템을 보게 된다. 쓰기가 허용된 경우, 해당 파일시스템에 쓰기 작업을 하면 추후 파일시스템에 접근할 때 변경된 내용을 보게 될 것이다. 볼륨은 이미지의 특정 경로에 마운트된다. 파드에 정의된 각 컨테이너에 대해, 컨테이너가 사용할 각 볼륨을 어디에 마운트할지 명시해야 한다.

볼륨은 다른 볼륨 안에 마운트될 수 없다 (하지만, 서브패스 사용에서 관련 메커니즘을 확인한다). 또한, 볼륨은 다른 볼륨에 있는 내용물을 가리키는 하드 링크를 포함할 수 없다.

볼륨 유형들

쿠버네티스는 여러 유형의 볼륨을 지원한다.

awsElasticBlockStore (사용 중단됨)

기능 상태: Kubernetes v1.17 [deprecated]

awsElasticBlockStore 볼륨은 아마존 웹 서비스 (AWS) EBS 볼륨을 파드에 마운트 한다. 파드를 제거할 때 지워지는 emptyDir 와는 다르게 EBS 볼륨의 내용은 유지되고, 볼륨은 마운트 해제만 된다. 이 의미는 EBS 볼륨에 데이터를 미리 채울 수 있으며, 파드 간에 데이터를 "전달(handed off)"할 수 있다.

awsElasticBlockStore 볼륨을 사용할 때 몇 가지 제한이 있다.

  • 파드가 실행 중인 노드는 AWS EC2 인스턴스여야 함
  • 이러한 인스턴스는 EBS 볼륨과 동일한 지역과 가용성 영역에 있어야 함
  • EBS는 볼륨을 마운트하는 단일 EC2 인스턴스만 지원함

AWS EBS 볼륨 생성하기

파드와 함께 EBS 볼륨을 사용하려면, 먼저 EBS 볼륨을 생성해야 한다.

aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2

클러스터를 띄운 영역과 생성하는 영역이 일치하는지 확인한다. 크기와 EBS 볼륨 유형이 사용에 적합한지 확인한다.

AWS EBS 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: test-ebs
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-ebs
      name: test-volume
  volumes:
  - name: test-volume
    # 이 AWS EBS 볼륨은 이미 존재해야 한다.
    awsElasticBlockStore:
      volumeID: "<volume-id>"
      fsType: ext4

EBS 볼륨이 파티션된 경우, 선택적 필드인 partition: "<partition number>" 를 제공하여 마운트할 파티션을 지정할 수 있다.

AWS EBS CSI 마이그레이션

기능 상태: Kubernetes v1.25 [stable]

awsElasticBlockStoreCSIMigration 기능이 활성화된 경우, 기존 인-트리 플러그인의 모든 플러그인 작업을 ebs.csi.aws.com 컨테이너 스토리지 인터페이스(CSI) 드라이버로 리디렉션한다. 이 기능을 사용하려면, 클러스터에 AWS EBS CSI 드라이버를 설치해야 한다.

AWS EBS CSI 마이그레이션 완료

기능 상태: Kubernetes v1.17 [alpha]

컨트롤러 관리자와 kubelet에 의해 로드되지 않도록 awsElasticBlockStore 스토리지 플러그인을 끄려면, InTreePluginAWSUnregister 플래그를 true 로 설정한다.

azureDisk (사용 중단됨)

기능 상태: Kubernetes v1.19 [deprecated]

azureDisk 볼륨 유형은 Microsoft Azure 데이터 디스크를 파드에 마운트한다.

더 자세한 내용은 azureDisk 볼륨 플러그인을 참고한다.

azureDisk CSI 마이그레이션

기능 상태: Kubernetes v1.24 [stable]

azureDiskCSIMigration 기능이 활성화된 경우, 기존 인-트리 플러그인의 모든 플러그인 작업을 disk.csi.azure.com 컨테이너 스토리지 인터페이스(CSI) 드라이버로 리다이렉트한다. 이 기능을 사용하려면, 클러스터에 Azure 디스크 CSI 드라이버 를 설치해야 한다.

azureDisk CSI 마이그레이션 완료

기능 상태: Kubernetes v1.21 [alpha]

컨트롤러 매니저 및 kubelet이 azureDisk 스토리지 플러그인을 로드하지 않도록 하려면, InTreePluginAzureDiskUnregister 플래그를 true로 설정한다.

azureFile (사용 중단됨)

기능 상태: Kubernetes v1.21 [deprecated]

azureFile 볼륨 유형은 Microsoft Azure 파일 볼륨(SMB 2.1과 3.0)을 파드에 마운트한다.

더 자세한 내용은 azureFile 볼륨 플러그인을 참고한다.

azureFile CSI 마이그레이션

기능 상태: Kubernetes v1.26 [stable]

azureFileCSIMigration 기능이 활성화된 경우, 기존 트리 내 플러그인에서 file.csi.azure.com 컨테이너 스토리지 인터페이스(CSI) 드라이버로 모든 플러그인 작업을 수행한다. 이 기능을 사용하려면, 클러스터에 Azure 파일 CSI 드라이버 를 설치하고 CSIMigrationAzureFile 기능 게이트를 활성화해야 한다.

Azure File CSI 드라이버는 동일한 볼륨을 다른 fsgroup에서 사용하는 것을 지원하지 않는다. Azurefile CSI 마이그레이션이 활성화된 경우, 다른 fsgroup에서 동일한 볼륨을 사용하는 것은 전혀 지원되지 않는다.

azureFile CSI 마이그레이션 완료

기능 상태: Kubernetes v1.21 [alpha]

컨트롤러 매니저 및 kubelet이 azureFile 스토리지 플러그인을 로드하지 않도록 하려면, InTreePluginAzureFileUnregister 플래그를 true로 설정한다.

cephfs

cephfs 볼륨은 기존 CephFS 볼륨을 파드에 마운트 할 수 있다. 파드를 제거할 때 지워지는 emptyDir 와는 다르게 cephfs 볼륨의 내용은 유지되고, 볼륨은 그저 마운트 해제만 된다. 이 의미는 cephfs 볼륨에 데이터를 미리 채울 수 있으며, 해당 데이터는 파드 간에 공유될 수 있다. cephfs 볼륨은 여러 작성자가 동시에 마운트할 수 있다.

더 자세한 내용은 CephFS 예시를 참조한다.

cinder (사용 중단됨)

기능 상태: Kubernetes v1.18 [deprecated]

cinder 볼륨 유형은 오픈스택 Cinder 볼륨을 파드에 마운트하는데 사용된다.

Cinder 볼륨 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: test-cinder
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-cinder-container
    volumeMounts:
    - mountPath: /test-cinder
      name: test-volume
  volumes:
  - name: test-volume
    # 이 오픈스택 볼륨은 이미 존재해야 한다.
    cinder:
      volumeID: "<volume id>"
      fsType: ext4

오픈스택 CSI 마이그레이션

기능 상태: Kubernetes v1.24 [stable]

Cinder의CSIMigration 기능은 Kubernetes 1.21부터 기본적으로 활성화되어 있다. 기존 트리 내 플러그인에서 cinder.csi.openstack.org 컨테이너 스토리지 인터페이스(CSI) 드라이버로 모든 플러그인 작업을 수행한다. 오픈스택 Cinder CSI 드라이버가 클러스터에 설치되어 있어야 한다.

컨트롤러 매니저 및 kubelet이 인-트리 Cinder 플러그인을 로드하지 않도록 하려면, InTreePluginOpenStackUnregister 기능 게이트를 활성화한다.

컨피그맵(configMap)

컨피그맵은 구성 데이터를 파드에 주입하는 방법을 제공한다. 컨피그맵에 저장된 데이터는 configMap 유형의 볼륨에서 참조되고 그런 다음에 파드에서 실행되는 컨테이너화된 애플리케이션이 소비한다.

컨피그맵을 참조할 때, 볼륨에 컨피그맵의 이름을 제공한다. 컨피그맵의 특정 항목에 사용할 경로를 사용자 정의할 수 있다. 다음 구성은 log-config 컨피그맵을 configmap-pod 라 부르는 파드에 마운트하는 방법을 보여준다.

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: test
      image: busybox:1.28
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: log-config
        items:
          - key: log_level
            path: log_level

log-config 컨피그맵은 볼륨으로 마운트되며, log_level 항목에 저장된 모든 컨텐츠는 파드의 /etc/config/log_level 경로에 마운트된다. 이 경로는 볼륨의 mountPathlog_level 로 키가 지정된 path 에서 파생된다.

downwardAPI

downwardAPI 볼륨은 애플리케이션에서 다운워드(downward) API 데이터를 사용할 수 있도록 한다. 볼륨 내에서 노출된 데이터를 일반 텍스트 형식의 읽기 전용 파일로 찾을 수 있다.

더 자세한 내용은 다운워드 API 예시 를 참고한다.

emptyDir

emptyDir 볼륨은 파드가 노드에 할당될 때 처음 생성되며, 해당 노드에서 파드가 실행되는 동안에만 존재한다. 이름에서 알 수 있듯이 emptyDir 볼륨은 처음에는 비어있다. 파드 내 모든 컨테이너는 emptyDir 볼륨에서 동일한 파일을 읽고 쓸 수 있지만, 해당 볼륨은 각각의 컨테이너에서 동일하거나 다른 경로에 마운트될 수 있다. 어떤 이유로든 노드에서 파드가 제거되면 emptyDir 의 데이터가 영구적으로 삭제된다.

emptyDir 의 일부 용도는 다음과 같다.

  • 디스크 기반의 병합 종류와 같은 스크레치 공간
  • 충돌로부터 복구하기위해 긴 계산을 검사점으로 지정
  • 웹 서버 컨테이너가 데이터를 처리하는 동안 컨텐츠 매니저 컨테이너가 가져오는 파일을 보관

emptyDir.medium 필드는 emptyDir 볼륨이 저장되는 곳을 제어한다. 기본 emptyDir 볼륨은 환경에 따라 디스크, SSD 또는 네트워크 스토리지와 같이 노드를 지원하는 모든 매체에 저장된다. emptyDir.medium 필드를 "Memory"로 설정하면, 쿠버네티스는 tmpfs(RAM 기반 파일시스템)를 대신 마운트한다. tmpfs는 매우 빠르지만, 디스크와 다르게 노드 재부팅시 tmpfs는 마운트 해제되고, 작성하는 모든 파일이 컨테이너 메모리 제한에 포함된다.

emptyDir 볼륨의 용량을 제한하는 기본 medium을 위해, 크기 제한을 명시할 수 있다. 스토리지는 노드 임시 스토리지로부터 할당된다. 만약 해당 공간이 다른 소스(예를 들어, 로그 파일이나 이미지 오버레이)에 의해 채워져있다면, emptyDir는 지정된 제한 이전에 용량을 다 쓰게 될 수 있다.

emptyDir 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: 500Mi

fc (파이버 채널)

fc 볼륨 유형은 기존 파이버 채널 블록 스토리지 볼륨을 파드에 마운트할 수 있게 한다. 볼륨 구성에서 targetWWNs 파라미터를 사용하여 단일 또는 다중 대상 월드 와이드 이름(WWN)을 지정할 수 있다. 만약 여러 WWN이 지정된 경우, targetWWN은 해당 WWN이 다중 경로 연결에서 온 것으로 예상한다.

더 자세한 내용은 파이버 채널 예시를 참고한다.

gcePersistentDisk (사용 중단됨)

기능 상태: Kubernetes v1.17 [deprecated]

gcePersistentDisk 볼륨은 구글 컴퓨트 엔진(GCE) 영구 디스크(PD)를 파드에 마운트한다. 파드를 제거할 때 지워지는 emptyDir 와는 다르게, PD의 내용은 유지되고, 볼륨은 마운트 해제만 된다. 이는 PD에 데이터를 미리 채울 수 있으며, 파드 간에 데이터를 공유할 수 있다는 것을 의미한다.

gcePersistentDisk 를 사용할 때 몇 가지 제한이 있다.

  • 파드가 실행 중인 노드는 GCE VM이어야 함
  • 이러한 VM은 영구 디스크와 동일한 GCE 프로젝트와 영역에 있어야 함

GCE 영구 디스크의 한 가지 기능은 영구 디스크에 대한 동시 읽기 전용 접근이다. gcePersistentDisk 볼륨을 사용하면 여러 사용자가 영구 디스크를 읽기 전용으로 동시에 마운트할 수 있다. 즉, PD를 데이터 세트로 미리 채운 다음 필요한 만큼 많은 파드에서 병렬로 제공할 수 있다. 불행히도, PD는 읽기-쓰기 모드에서 단일 사용자만 마운트할 수 있다. 동시 쓰기는 허용되지 않는다.

PD가 읽기 전용이거나 레플리카의 수가 0 또는 1이 아니라면 레플리카셋(ReplicaSet)으로 제어되는 파드가 있는 GCE 영구 디스크를 사용할 수 없다.

GCE 영구 디스크 생성하기

GCE 영구 디스크를 파드와 함께 사용하려면, 디스크를 먼저 생성해야 한다.

gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk

GCE 영구 디스크 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    # 이 GCE PD는 이미 존재해야 한다.
    gcePersistentDisk:
      pdName: my-data-disk
      fsType: ext4

리전 영구 디스크

리전 영구 디스크 기능을 사용하면 동일한 영역 내의 두 영역에서 사용할 수 있는 영구 디스크를 생성할 수 있다. 이 기능을 사용하려면 볼륨을 퍼시스턴트볼륨(PersistentVolume)으로 프로비저닝해야 한다. 파드에서 직접 볼륨을 참조하는 것은 지원되지 않는다.

리전 PD 퍼시스턴트볼륨을 수동으로 프로비저닝하기

GCE PD용 스토리지클래스를 사용해서 동적 프로비저닝이 가능하다. 퍼시스턴트볼륨을 생성하기 전에 영구 디스크를 생성해야만 한다.

gcloud compute disks create --size=500GB my-data-disk
  --region us-central1
  --replica-zones us-central1-a,us-central1-b

리전 영구 디스크 구성 예시

apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-volume
spec:
  capacity:
    storage: 400Gi
  accessModes:
  - ReadWriteOnce
  gcePersistentDisk:
    pdName: my-data-disk
    fsType: ext4
      nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        # 1.21 이전 버전에서는 failure-domain.beta.kubernetes.io/zone 키를 사용해야 한다.
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - us-central1-a
          - us-central1-b

GCE CSI 마이그레이션

기능 상태: Kubernetes v1.25 [stable]

GCE PD의 CSIMigration 기능이 활성화된 경우 기존 인-트리 플러그인에서 pd.csi.storage.gke.io 컨테이너 스토리지 인터페이스(CSI) 드라이버로 모든 플러그인 작업을 리디렉션한다. 이 기능을 사용하려면, 클러스터에 GCE PD CSI 드라이버 를 설치해야 한다.

GCE CSI 마이그레이션 완료

기능 상태: Kubernetes v1.21 [alpha]

컨트롤러 매니저와 kubelet이 gcePersistentDisk 스토리지 플러그인을 로드하는 것을 방지하려면, InTreePluginGCEUnregister 플래그를 true로 설정한다.

gitRepo (사용 중단됨)

gitRepo 볼륨은 볼륨 플러그인의 예시이다. 이 플러그인은 빈 디렉터리를 마운트하고 파드가 사용할 수 있도록 이 디렉터리에 git 리포지터리를 복제한다.

여기 gitRepo 볼륨의 예시가 있다.

apiVersion: v1
kind: Pod
metadata:
  name: server
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /mypath
      name: git-volume
  volumes:
  - name: git-volume
    gitRepo:
      repository: "git@somewhere:me/my-git-repository.git"
      revision: "22f1d8406d464b0c0874075539c1f2e96c253775"

glusterfs (제거됨)

쿠버네티스 1.30 는 glusterfs 볼륨 타입을 포함하지 않는다.

GlusterFS 인-트리 스토리지 드라이버는 쿠버네티스 1.25에서 사용 중단되었고 v1.26 릴리즈에서 완전히 제거되었다.

hostPath

hostPath 볼륨은 호스트 노드의 파일시스템에 있는 파일이나 디렉터리를 파드에 마운트 한다. 이것은 대부분의 파드들이 필요한 것은 아니지만, 일부 애플리케이션에 강력한 탈출구를 제공한다.

예를 들어, hostPath 의 일부 용도는 다음과 같다.

  • 도커 내부에 접근할 필요가 있는 실행중인 컨테이너. /var/lib/dockerhostPath 로 이용함
  • 컨테이너에서 cAdvisor의 실행. /syshostPath 로 이용함
  • 파드는 주어진 hostPath 를 파드가 실행되기 이전에 있어야 하거나, 생성해야 하는지 그리고 존재해야 하는 대상을 지정할 수 있도록 허용함

필요한 path 속성 외에도, hostPath 볼륨에 대한 type 을 마음대로 지정할 수 있다.

필드가 type 에 지원되는 값은 다음과 같다.

행동
빈 문자열 (기본값)은 이전 버전과의 호환성을 위한 것으로, hostPath 볼륨은 마운트 하기 전에 아무런 검사도 수행되지 않는다.
DirectoryOrCreate만약 주어진 경로에 아무것도 없다면, 필요에 따라 Kubelet이 가지고 있는 동일한 그룹과 소유권, 권한을 0755로 설정한 빈 디렉터리를 생성한다.
Directory주어진 경로에 디렉터리가 있어야 함
FileOrCreate만약 주어진 경로에 아무것도 없다면, 필요에 따라 Kubelet이 가지고 있는 동일한 그룹과 소유권, 권한을 0644로 설정한 빈 파일을 생성한다.
File주어진 경로에 파일이 있어야 함
Socket주어진 경로에 UNIX 소캣이 있어야 함
CharDevice주어진 경로에 문자 디바이스가 있어야 함
BlockDevice주어진 경로에 블록 디바이스가 있어야 함

다음과 같은 이유로 이 유형의 볼륨 사용시 주의해야 한다.

  • HostPath는 권한있는 시스템 자격 증명 (예 : Kubelet 용) 또는 권한있는 API (예 : 컨테이너 런타임 소켓)를 노출 할 수 있으며, 이는 컨테이너 이스케이프 또는 클러스터의 다른 부분을 공격하는 데 사용될 수 있다.
  • 동일한 구성(파드템플릿으로 생성한 것과 같은)을 가진 파드는 노드에 있는 파일이 다르기 때문에 노드마다 다르게 동작할 수 있다.
  • 기본 호스트에 생성된 파일 또는 디렉터리는 root만 쓸 수 있다. 프로세스를 특권을 가진(privileged) 컨테이너에서 루트로 실행하거나 hostPath 볼륨에 쓸 수 있도록 호스트의 파일 권한을 수정해야 한다.

hostPath 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 호스트의 디렉터리 위치
      path: /data
      # 이 필드는 선택 사항이다
      type: Directory

hostPath FileOrCreate 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: test-webserver
spec:
  containers:
  - name: test-webserver
    image: registry.k8s.io/test-webserver:latest
    volumeMounts:
    - mountPath: /var/local/aaa
      name: mydir
    - mountPath: /var/local/aaa/1.txt
      name: myfile
  volumes:
  - name: mydir
    hostPath:
      # 파일 디렉터리가 생성되었는지 확인한다.
      path: /var/local/aaa
      type: DirectoryOrCreate
  - name: myfile
    hostPath:
      path: /var/local/aaa/1.txt
      type: FileOrCreate

iscsi

iscsi 볼륨을 사용하면 기존 iSCSI (SCSI over IP) 볼륨을 파드에 마운트 할수 있다. 파드를 제거할 때 지워지는 emptyDir 와는 다르게 iscsi 볼륨의 내용은 유지되고, 볼륨은 그저 마운트 해제만 된다. 이 의미는 iscsi 볼륨에 데이터를 미리 채울 수 있으며, 파드간에 데이터를 공유할 수 있다는 것이다.

iSCSI 특징은 여러 고객이 읽기 전용으로 마운트할 수 있다는 것이다. 즉, 데이터셋으로 사전에 볼륨을 채운다음, 필요한 만큼 많은 파드에서 병렬로 제공할 수 있다. 불행하게도, iSCSI 볼륨은 읽기-쓰기 모드에서는 단일 고객만 마운트할 수 있다. 동시 쓰기는 허용되지 않는다.

더 자세한 내용은 iSCSI 예시를 본다.

local

local 볼륨은 디스크, 파티션 또는 디렉터리 같은 마운트된 로컬 스토리지 장치를 나타낸다.

로컬 볼륨은 정적으로 생성된 퍼시스턴트볼륨으로만 사용할 수 있다. 동적으로 프로비저닝된 것은 지원되지 않는다.

hostPath 볼륨에 비해 local 볼륨은 수동으로 파드를 노드에 예약하지 않고도 내구성과 휴대성을 갖춘 방식으로 사용된다. 시스템은 퍼시스턴트볼륨의 노드 어피니티를 확인하여 볼륨의 노드 제약 조건을 인식한다.

그러나 local 볼륨은 여전히 기본 노드의 가용성을 따르며 모든 애플리케이션에 적합하지는 않는다. 만약 노드가 비정상 상태가 되면 local 볼륨도 접근할 수 없게 되고, 파드를 실행할 수 없게 된다. local 볼륨을 사용하는 애플리케이션은 기본 디스크의 내구 특성에 따라 이러한 감소되는 가용성과 데이터 손실 가능성도 허용할 수 있어야 한다.

다음의 예시는 local 볼륨과 nodeAffinity 를 사용하는 퍼시스턴트볼륨을 보여준다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 100Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - example-node

local 볼륨을 사용하는 경우 퍼시스턴트볼륨 nodeAffinity 를 설정해야 합니다. 쿠버네티스 스케줄러는 퍼시스턴트볼륨 nodeAffinity 를 사용하여 파드를 올바른 노드로 스케줄한다.

퍼시스턴트볼륨의 volumeMode 을 "Block" (기본값인 "Filesystem"을 대신해서)으로 설정하면 로컬 볼륨을 원시 블록 장치로 노출할 수 있다.

로컬 볼륨을 사용할 때는 volumeBindingModeWaitForFirstConsumer 로 설정된 스토리지클래스(StorageClass)를 생성하는 것을 권장한다. 자세한 내용은 local 스토리지클래스(StorageClas) 예제를 참고한다. 볼륨 바인딩을 지연시키는 것은 퍼시스턴트볼륨클래임 바인딩 결정도 노드 리소스 요구사항, 노드 셀렉터, 파드 어피니티 그리고 파드 안티 어피니티와 같이 파드가 가질 수 있는 다른 노드 제약 조건으로 평가되도록 만든다.

로컬 볼륨 라이프사이클의 향상된 관리를 위해 외부 정적 프로비저너를 별도로 실행할 수 있다. 이 프로비저너는 아직 동적 프로비저닝을 지원하지 않는 것을 참고한다. 외부 로컬 프로비저너를 실행하는 방법에 대한 예시는 로컬 볼륨 프로비저너 사용자 가이드를 본다.

nfs

nfs 볼륨을 사용하면 기존 NFS (네트워크 파일 시스템) 볼륨을 파드에 마운트 할수 있다. 파드를 제거할 때 지워지는 emptyDir 와는 다르게 nfs 볼륨의 내용은 유지되고, 볼륨은 그저 마운트 해제만 된다. 이 의미는 NFS 볼륨에 데이터를 미리 채울 수 있으며, 파드 간에 데이터를 공유할 수 있다는 뜻이다. NFS는 여러 작성자가 동시에 마운트할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /my-nfs-data
      name: test-volume
  volumes:
  - name: test-volume
    nfs:
      server: my-nfs-server.example.com
      path: /my-nfs-volume
      readOnly: true

퍼시스턴트볼륨을 사용하여 NFS 볼륨을 마운트하는 예제는 NFS 예시를 본다.

persistentVolumeClaim

persistentVolumeClaim 볼륨은 퍼시스턴트볼륨을 파드에 마운트하는데 사용한다. 퍼시스턴트볼륨클레임은 사용자가 특정 클라우드 환경의 세부 내용을 몰라도 내구성이있는 스토리지 (GCE 퍼시스턴트디스크 또는 iSCSI 볼륨와 같은)를 "클레임" 할 수 있는 방법이다.

더 자세한 내용은 퍼시스턴트볼륨 예시를 본다.

portworxVolume (사용 중단됨)

기능 상태: Kubernetes v1.25 [deprecated]

portworxVolume 은 쿠버네티스와 하이퍼컨버지드(hyperconverged)를 실행하는 탄력적인 블록 스토리지 계층이다. Portworx는 서버의 스토리지를 핑거프린팅하고(fingerprints), 기능에 기반하여 계층화하고, 그리고 여러 서버에 걸쳐 용량을 집계한다. Portworx는 가상 머신 내 게스트 또는 베어 메탈 리눅스 노드 위에서 실행된다.

portworxVolume 은 쿠버네티스를 통해 동적으로 생성되거나 사전에 프로비전할 수 있으며 쿠버네티스 파드 내에서 참조할 수 있다. 다음은 사전에 프로비저닝된 Portworx 볼륨을 참조하는 파드의 예시이다.

apiVersion: v1
kind: Pod
metadata:
  name: test-portworx-volume-pod
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /mnt
      name: pxvol
  volumes:
  - name: pxvol
    # 이 Portworx 볼륨은 이미 존재해야 한다.
    portworxVolume:
      volumeID: "pxvol"
      fsType: "<fs-type>"

자세한 내용은 Portworx 볼륨 예제를 참고한다.

Portworx CSI 마이그레이션

기능 상태: Kubernetes v1.25 [beta]

Portworx를 위한 CSIMigration 기능이 쿠버네티스 1.23에 추가되었지만 알파 상태이기 때문에 기본적으로는 비활성화되어 있었다. v1.25 이후 이 기능은 베타 상태가 되었지만 여전히 기본적으로는 비활성화되어 있다. 이 기능은 사용 중인 트리 내(in-tree) 플러그인의 모든 동작을 pxd.portworx.com CSI 드라이버로 리다이렉트한다. 이 기능을 사용하려면, 클러스터에 Portworx CSI 드라이버가 설치되어 있어야 한다. 이 기능을 활성화시키기 위해서는 kube-controller-manager와 kubelet에 CSIMigrationPortworx=true를 설정해야 한다.

projected

Projected 볼륨은 여러 기존 볼륨 소스를 동일한 디렉터리에 매핑한다. 더 자세한 사항은 projected volumes를 참고한다.

rbd

rbd 볼륨을 사용하면 Rados Block Device(RBD) 볼륨을 파드에 마운트할 수 있다. 파드를 제거할 때 지워지는 emptyDir 와는 다르게 rbd 볼륨의 내용은 유지되고, 볼륨은 마운트 해제만 된다. 이 의미는 RBD 볼륨에 데이터를 미리 채울 수 있으며, 데이터를 공유할 수 있다는 것이다.

RBD의 특징은 여러 고객이 동시에 읽기 전용으로 마운트할 수 있다는 것이다. 즉, 데이터셋으로 볼륨을 미리 채운 다음, 필요한 만큼 많은 파드에서 병렬로 제공할수 있다. 불행하게도, RBD는 읽기-쓰기 모드에서 단일 고객만 마운트할 수 있다. 동시 쓰기는 허용되지 않는다.

더 자세한 내용은 RBD 예시를 참고한다.

RBD CSI 마이그레이션

기능 상태: Kubernetes v1.23 [alpha]

RBD를 위한 CSIMigration 기능이 활성화되어 있으면, 사용 중이 트리 내(in-tree) 플러그인의 모든 플러그인 동작을 rbd.csi.ceph.com CSI 드라이버로 리다이렉트한다. 이 기능을 사용하려면, 클러스터에 Ceph CSI 드라이버가 설치되어 있고 csiMigrationRBD 기능 게이트가 활성화되어 있어야 한다. (v1.24 릴리즈에서 csiMigrationRBD 플래그는 삭제되었으며 CSIMigrationRBD로 대체되었음에 주의한다.)

secret

secret 볼륨은 암호와 같은 민감한 정보를 파드에 전달하는데 사용된다. 쿠버네티스 API에 시크릿을 저장하고 쿠버네티스에 직접적으로 연결하지 않고도 파드에서 사용할 수 있도록 파일로 마운트 할 수 있다. secret 볼륨은 tmpfs(RAM 기반 파일시스템)로 지원되기 때문에 비 휘발성 스토리지에 절대 기록되지 않는다.

더 자세한 내용은 시크릿 구성하기를 참고한다.

vsphereVolume (사용 중단됨)

vsphereVolume 은 vSphere VMDK 볼륨을 파드에 마운트하는데 사용된다. 볼륨을 마운트 해제해도 볼륨의 내용이 유지된다. VMFS와 VSAM 데이터스토어를 모두 지원한다.

더 자세한 내용은 vSphere 볼륨 예제를 참고한다.

vSphere CSI 마이그레이션

기능 상태: Kubernetes v1.26 [stable]

쿠버네티스 1.30에서, 인-트리 vsphereVolume 타입을 위한 모든 작업은 csi.vsphere.vmware.com CSI 드라이버로 리다이렉트된다.

vSphere CSI 드라이버가 클러스터에 설치되어 있어야 한다. 인-트리 vsphereVolume 마이그레이션에 대한 추가 조언은 VMware의 문서 페이지 인-트리 vSphere 볼륨을 vSphere 컨테이너 스토리지 플러그인으로 마이그레이션하기를 참고한다. vSphere CSI 드라이버가 설치되어있지 않다면 볼륨 작업은 인-트리 vsphereVolume 타입으로 생성된 PV에서 수행될 수 없다.

vSphere CSI 드라이버로 마이그레이션하기 위해서는 vSphere 7.0u2 이상을 사용해야 한다.

v1.30 외의 쿠버네티스 버전을 사용 중인 경우, 해당 쿠버네티스 버전의 문서를 참고한다.

vSphere CSI 마이그레이션 완료

기능 상태: Kubernetes v1.19 [beta]

vsphereVolume 플러그인이 컨트롤러 관리자와 kubelet에 의해 로드되지 않도록 기능을 비활성화하려면, InTreePluginvSphereUnregister 기능 플래그를 true 로 설정해야 한다. 이를 위해서는 모든 워커 노드에 csi.vsphere.vmware.com CSI 드라이버를 설치해야 한다.

subPath 사용하기

때로는 단일 파드에서 여러 용도의 한 볼륨을 공유하는 것이 유용하다. volumeMounts.subPath 속성을 사용해서 root 대신 참조하는 볼륨 내의 하위 경로를 지정할 수 있다.

다음의 예시는 단일 공유 볼륨을 사용하여 LAMP 스택(리눅스 Apache MySQL PHP)이 있는 파드를 구성하는 방법을 보여준다. 이 샘플 subPath 구성은 프로덕션 용도로 권장되지 않는다.

PHP 애플리케이션의 코드와 자산은 볼륨의 html 폴더에 매핑되고 MySQL 데이터베이스는 볼륨의 mysql 폴더에 저장된다. 예를 들면 다음과 같다.

apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site
spec:
    containers:
    - name: mysql
      image: mysql
      env:
      - name: MYSQL_ROOT_PASSWORD
        value: "rootpasswd"
      volumeMounts:
      - mountPath: /var/lib/mysql
        name: site-data
        subPath: mysql
    - name: php
      image: php:7.0-apache
      volumeMounts:
      - mountPath: /var/www/html
        name: site-data
        subPath: html
    volumes:
    - name: site-data
      persistentVolumeClaim:
        claimName: my-lamp-site-data

subPath를 확장된 환경 변수와 함께 사용하기

기능 상태: Kubernetes v1.17 [stable]

subPathExpr 필드를 사용해서 다운워드 API 환경 변수로부터 subPath 디렉터리 이름을 구성한다. subPathsubPathExpr 속성은 상호 배타적이다.

이 예제는 PodsubPathExpr 을 사용해서 hostPath 볼륨 /var/log/pods 내에 pod1 디렉터리를 만든다. hostPath 볼륨은 downwardAPI 에서 Pod 이름을 사용한다. 호스트 디렉토리 /var/log/pods/pod1 은 컨테이너의 /logs 에 마운트된다.

apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: container1
    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    image: busybox:1.28
    command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
    volumeMounts:
    - name: workdir1
      mountPath: /logs
      # 변수 확장에는 괄호를 사용한다(중괄호 아님).
      subPathExpr: $(POD_NAME)
  restartPolicy: Never
  volumes:
  - name: workdir1
    hostPath:
      path: /var/log/pods

리소스

emptyDir 볼륨의 스토리지 매체(디스크나 SSD와 같은)는 kubelet root 디렉터리(보통 /var/lib/kubelet)를 보유한 파일시스템의 매체에 의해 결정 된다. emptyDir 또는 hostPath 볼륨이 사용할 수 있는 공간의 크기는 제한이 없으며, 컨테이너 간 또는 파드 간 격리는 없다.

리소스 사양을 사용한 공간 요청에 대한 자세한 내용은 리소스 관리 방법을 참고한다.

아웃-오브-트리(out-of-tree) 볼륨 플러그인

아웃-오브-트리 볼륨 플러그인에는 컨테이너 스토리지 인터페이스(CSI) 그리고 FlexVolume(사용 중단됨)이 포함된다. 이러한 플러그인을 사용하면 스토리지 벤더들은 플러그인 소스 코드를 쿠버네티스 리포지터리에 추가하지 않고도 사용자 정의 스토리지 플러그인을 만들 수 있다.

이전에는 모든 볼륨 플러그인이 "인-트리(in-tree)"에 있었다. "인-트리" 플러그인은 쿠버네티스 핵심 바이너리와 함께 빌드, 링크, 컴파일 및 배포되었다. 즉, 쿠버네티스(볼륨 플러그인)에 새로운 스토리지 시스템을 추가하려면 쿠버네티스 핵심 코드 리포지터리의 코드 확인이 필요했음을 의미한다.

CSI와 FlexVolume을 통해 쿠버네티스 코드 베이스와는 독립적으로 볼륨 플러그인을 개발하고, 쿠버네티스 클러스터의 확장으로 배포(설치) 할 수 있다.

아웃 오브 트리(out-of-tree) 볼륨 플러그인을 생성하려는 스토리지 벤더는 볼륨 플러그인 FAQ를 참조한다.

csi

컨테이너 스토리지 인터페이스(CSI)는 컨테이너 오케스트레이션 시스템(쿠버네티스와 같은)을 위한 표준 인터페이스를 정의하여 임의의 스토리지 시스템을 컨테이너 워크로드에 노출시킨다.

더 자세한 정보는 CSI 디자인 제안을 읽어본다.

CSI 호환 볼륨 드라이버가 쿠버네티스 클러스터에 배포되면 사용자는 csi 볼륨 유형을 사용해서 CSI 드라이버에 의해 노출된 볼륨에 연결하거나 마운트할 수 있다.

csi 볼륨은 세 가지 방법으로 파드에서 사용할 수 있다.

스토리지 관리자가 다음 필드를 사용해서 CSI 퍼시스턴트 볼륨을 구성할 수 있다.

  • driver: 사용할 볼륨 드라이버의 이름을 지정하는 문자열 값. 이 값은 CSI 사양에 정의된 CSI 드라이버가 GetPluginInfoResponse 에 반환하는 값과 일치해야 한다. 쿠버네티스에서 호출할 CSI 드라이버를 식별하고, CSI 드라이버 컴포넌트에서 CSI 드라이버에 속하는 PV 오브젝트를 식별하는데 사용한다.
  • volumeHandle: 볼륨을 식별하게 하는 고유한 문자열 값. 이 값은 CSI 사양에 정의된 CSI 드라이버가 CreateVolumeResponsevolume.id 필드에 반환하는 값과 일치해야 한다. 이 값은 볼륨을 참조할 때 CSI 볼륨 드라이버에 대한 모든 호출에 volume_id 값을 전달한다.
  • readOnly: 볼륨을 읽기 전용으로 "ControllerPublished" (연결)할지 여부를 나타내는 선택적인 불리언(boolean) 값. 기본적으로 false 이다. 이 값은 ControllerPublishVolumeRequestreadonly 필드를 통해 CSI 드라이버로 전달된다.
  • fsType: 만약 PV의 VolumeModeFilesystem 인 경우에 이 필드는 볼륨을 마운트하는 데 사용해야 하는 파일시스템을 지정하는 데 사용될 수 있다. 만약 볼륨이 포맷되지 않았고 포맷이 지원되는 경우, 이 값은 볼륨을 포맷하는데 사용된다. 이 값은 ControllerPublishVolumeRequest, NodeStageVolumeRequest 그리고 NodePublishVolumeRequestVolumeCapability 필드를 통해 CSI 드라이버로 전달된다.
  • volumeAttributes: 볼륨의 정적 속성을 지정하는 문자열과 문자열을 매핑한다. 이 매핑은 CSI 사양에 정의된 대로 CSI 드라이버의 CreateVolumeResponsevolume.attributes 필드에서 반환되는 매핑과 일치해야 한다. 이 매핑은 ControllerPublishVolumeRequest, NodeStageVolumeRequest, 그리고 NodePublishVolumeRequestvolume_context 필드를 통해 CSI 드라이버로 전달된다.
  • controllerPublishSecretRef: CSI의 ControllerPublishVolume 그리고 ControllerUnpublishVolume 호출을 완료하기 위해 CSI 드라이버에 전달하려는 민감한 정보가 포함된 시크릿 오브젝트에 대한 참조이다. 이 필드는 선택 사항이며, 시크릿이 필요하지 않은 경우 비어있을 수 있다. 만약 시크릿에 둘 이상의 시크릿이 포함된 경우에도 모든 시크릿이 전달된다. nodeExpandSecretRef: CSI NodeExpandVolume 호출을 완료하기 위해 CSI 드라이버에 전달하려는 민감한 정보를 포함하고 있는 시크릿에 대한 참조이다. 이 필드는 선택 사항이며, 시크릿이 필요하지 않은 경우 비어있을 수 있다. 오브젝트에 둘 이상의 시크릿이 포함된 경우에도, 모든 시크릿이 전달된다. 노드에 의해 시작된 볼륨 확장을 위한 시크릿 정보를 설정하면, kubelet은 NodeExpandVolume() 호출을 통해 CSI 드라이버에 해당 데이터를 전달한다. nodeExpandSecretRef 필드를 사용하기 위해, 클러스터는 쿠버네티스 버전 1.25 이상을 실행 중이어야 하며 모든 노드의 모든 kube-apiserver와 kubelet을 대상으로 CSINodeExpandSecret 기능 게이트를 활성화해야 한다. 또한 노드에 의해 시작된 스토리지 크기 조정 작업 시 시크릿 정보를 지원하거나 필요로 하는 CSI 드라이버를 사용해야 한다.
  • nodePublishSecretRef: CSI의 NodePublishVolume 호출을 완료하기 위해 CSI 드라이버에 전달하려는 민감한 정보가 포함 된 시크릿 오브젝트에 대한 참조이다. 이 필드는 선택 사항이며, 시크릿이 필요하지 않은 경우 비어있을 수 있다. 만약 시크릿 오브젝트에 둘 이상의 시크릿이 포함된 경우에도 모든 시크릿이 전달된다.
  • nodeStageSecretRef: CSI의 NodeStageVolume 호출을 완료하기위해 CSI 드라이버에 전달하려는 민감한 정보가 포함 된 시크릿 오브젝트에 대한 참조이다. 이 필드는 선택 사항이며, 시크릿이 필요하지 않은 경우 비어있을 수 있다. 만약 시크릿에 둘 이상의 시크릿이 포함된 경우에도 모든 시크릿이 전달된다.

CSI 원시(raw) 블록 볼륨 지원

기능 상태: Kubernetes v1.18 [stable]

외부 CSI 드라이버가 있는 벤더들은 쿠버네티스 워크로드에서 원시(raw) 블록 볼륨 지원을 구현할 수 있다.

CSI 설정 변경 없이 평소와 같이 원시 블록 볼륨 지원으로 퍼시스턴트볼륨/퍼시스턴트볼륨클레임 설정을 할 수 있다.

CSI 임시(ephemeral) 볼륨

기능 상태: Kubernetes v1.25 [stable]

파드 명세 내에서 CSI 볼륨을 직접 구성할 수 있다. 이 방식으로 지정된 볼륨은 임시 볼륨이며 파드가 다시 시작할 때 지속되지 않는다. 자세한 내용은 임시 볼륨을 참고한다.

CSI 드라이버의 개발 방법에 대한 더 자세한 정보는 쿠버네티스-csi 문서를 참조한다.

윈도우 CSI 프록시

기능 상태: Kubernetes v1.22 [stable]

CSI 노드 플러그인은 디스크 장치 검색 및 파일 시스템 마운트 같은 다양한 권한이 부여된 작업을 수행해야 한다. 이러한 작업은 호스트 운영 체제마다 다르다. 리눅스 워커 노드의 경우, 일반적으로 컨테이너형 CSI 노드 플러그인은 권한 있는 컨테이너로 배포된다. 윈도우 워커 노드의 경우, 각 윈도우 노드에 미리 설치해야 하는 커뮤니티판 스탠드얼론(stand-alone) 바이너리인 csi-proxy를 이용하여 컨테이너형 CSI 노드 플러그인에 대한 권한 있는 작업을 지원한다.

자세한 내용은 배포할 CSI 플러그인의 배포 가이드를 참고한다.

인-트리 플러그인으로부터 CSI 드라이버로 마이그레이션하기

기능 상태: Kubernetes v1.25 [stable]

CSIMigration 기능은 기존의 인-트리 플러그인에 대한 작업을 해당 CSI 플러그인(설치와 구성이 될 것으로 예상한)으로 유도한다. 결과적으로, 운영자는 인-트리 플러그인을 대체하는 CSI 드라이버로 전환할 때 기존 스토리지 클래스, 퍼시스턴트볼륨 또는 퍼시스턴트볼륨클레임(인-트리 플러그인 참조)에 대한 구성 변경을 수행할 필요가 없다.

지원되는 작업 및 기능은 프로비저닝/삭제, 연결/분리, 마운트/마운트 해제 그리고 볼륨 크기 재조정이 포함된다.

CSIMigration 을 지원하고 해당 CSI 드라이버가 구현된 인-트리 플러그인은 볼륨 유형들에 나열되어 있다.

다음 인-트리 플러그인은 윈도우 노드에서 퍼시스턴트볼륨을 지원한다.

flexVolume (사용 중단됨)

기능 상태: Kubernetes v1.23 [deprecated]

FlexVolume은 스토리지 드라이버와 인터페이싱하기 위해 exec 기반 모델을 사용하는 아웃-오브-트리 플러그인 인터페이스이다. FlexVolume 드라이버 바이너리 파일은 각 노드의 미리 정의된 볼륨 플러그인 경로에 설치되어야 하며, 일부 경우에는 컨트롤 플레인 노드에도 설치되어야 한다.

파드는 flexvolume 인-트리 볼륨 플러그인을 통해 FlexVolume 드라이버와 상호 작용한다. 더 자세한 내용은 FlexVolume README 문서를 참고한다.

호스트에 PowerShell 스크립트로 배포된 다음과 같은 FlexVolume 플러그인은 윈도우 노드를 지원한다.

마운트 전파(propagation)

마운트 전파를 통해 컨테이너가 마운트한 볼륨을 동일한 파드의 다른 컨테이너 또는 동일한 노드의 다른 파드로 공유할 수 있다.

볼륨 마운트 전파는 Container.volumeMountsmountPropagation 필드에 의해 제어된다. 그 값은 다음과 같다.

  • None - 이 볼륨 마운트는 호스트의 볼륨 또는 해당 서브디렉터리에 마운트된 것을 마운트 이후에 수신하지 않는다. 비슷한 방식으로, 컨테이너가 생성한 마운트는 호스트에서 볼 수 없다. 이것이 기본 모드이다.

    이 모드는 리눅스 커널 문서에 설명된 rshared 마운트 전파와 같다.

  • HostToContainer - 이 볼륨 마운트는 볼륨 또는 해당 서브디렉터리를 마운트한 정보를 수신한다.

    다시 말하면, 만약 호스트가 볼륨 마운트 내부에 다른 것을 마운트 하더라도 컨테이너가 마운트된 것을 볼 수 있다.

    마찬가지로 Bidirectional 마운트 전파가 있는 파드가 동일한 마운트가 된 경우에 파드에 HostToContainer 마운트 전파가 있는 컨테이너가 이를 볼 수 있다.

    이 모드는 리눅스 커널 문서에 설명된 rshared 마운트 전파와 같다.

  • Bidirectional - 이 볼륨 마운트는 HostToContainer 마운트와 동일하게 작동한다. 추가로 컨테이너에서 생성된 모든 볼륨 마운트는 동일한 볼륨을 사용하는 모든 파드의 모든 컨테이너와 호스트로 다시 전파된다.

    이 모드의 일반적인 유스 케이스로는 FlexVolume 또는 CSI 드라이버를 사용하는 파드 또는 hostPath 볼륨을 사용하는 호스트에 무언가를 마운트해야 하는 파드이다.

    이 모드는 리눅스 커널 문서에 설명된 rshared 마운트 전파와 같다.

구성

일부 배포판(CoreOS, RedHat/Centos, Ubuntu)에서 마운트 전파가 제대로 작동하려면 아래와 같이 도커에서의 마운트 공유를 올바르게 구성해야 한다.

도커의 systemd 서비스 파일을 편집한다. MountFlags 를 다음과 같이 설정한다.

MountFlags=shared

또는 MountFlags=slave 가 있으면 제거한다. 이후 도커 데몬을 재시작 한다.

sudo systemctl daemon-reload
sudo systemctl restart docker

다음 내용

퍼시스턴트 볼륨과 함께 워드프레스와 MySQL 배포하기의 예시를 따른다.

2 - 퍼시스턴트 볼륨

이 페이지에서는 쿠버네티스의 퍼시스턴트 볼륨 에 대해 설명한다. 볼륨에 대해 익숙해지는 것을 추천한다.

소개

스토리지 관리는 컴퓨트 인스턴스 관리와는 별개의 문제다. 퍼시스턴트볼륨 서브시스템은 사용자 및 관리자에게 스토리지 사용 방법에서부터 스토리지가 제공되는 방법에 대한 세부 사항을 추상화하는 API를 제공한다. 이를 위해 퍼시스턴트볼륨 및 퍼시스턴트볼륨클레임이라는 두 가지 새로운 API 리소스를 소개한다.

퍼시스턴트볼륨 (PV)은 관리자가 프로비저닝하거나 스토리지 클래스를 사용하여 동적으로 프로비저닝한 클러스터의 스토리지이다. 노드가 클러스터 리소스인 것처럼 PV는 클러스터 리소스이다. PV는 Volumes와 같은 볼륨 플러그인이지만, PV를 사용하는 개별 파드와는 별개의 라이프사이클을 가진다. 이 API 오브젝트는 NFS, iSCSI 또는 클라우드 공급자별 스토리지 시스템 등 스토리지 구현에 대한 세부 정보를 담아낸다.

퍼시스턴트볼륨클레임 (PVC)은 사용자의 스토리지에 대한 요청이다. 파드와 비슷하다. 파드는 노드 리소스를 사용하고 PVC는 PV 리소스를 사용한다. 파드는 특정 수준의 리소스(CPU 및 메모리)를 요청할 수 있다. 클레임은 특정 크기 및 접근 모드를 요청할 수 있다(예: ReadWriteOnce, ReadOnlyMany 또는 ReadWriteMany로 마운트 할 수 있음. AccessModes 참고).

퍼시스턴트볼륨클레임을 사용하면 사용자가 추상화된 스토리지 리소스를 사용할 수 있지만, 다른 문제들 때문에 성능과 같은 다양한 속성을 가진 퍼시스턴트볼륨이 필요한 경우가 일반적이다. 클러스터 관리자는 사용자에게 해당 볼륨의 구현 방법에 대한 세부 정보를 제공하지 않고 크기와 접근 모드와는 다른 방식으로 다양한 퍼시스턴트볼륨을 제공할 수 있어야 한다. 이러한 요구에는 스토리지클래스 리소스가 있다.

실습 예제와 함께 상세한 내용을 참고하길 바란다.

볼륨과 클레임 라이프사이클

PV는 클러스터 리소스이다. PVC는 해당 리소스에 대한 요청이며 리소스에 대한 클레임 검사 역할을 한다. PV와 PVC 간의 상호 작용은 다음 라이프사이클을 따른다.

프로비저닝

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

정적 프로비저닝

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

동적 프로비저닝

관리자가 생성한 정적 PV가 사용자의 퍼시스턴트볼륨클레임과 일치하지 않으면 클러스터는 PVC를 위해 특별히 볼륨을 동적으로 프로비저닝 하려고 시도할 수 있다. 이 프로비저닝은 스토리지클래스를 기반으로 한다. PVC는 스토리지 클래스를 요청해야 하며 관리자는 동적 프로비저닝이 발생하도록 해당 클래스를 생성하고 구성해야 한다. "" 클래스를 요청하는 클레임은 동적 프로비저닝을 효과적으로 비활성화한다.

스토리지 클래스를 기반으로 동적 스토리지 프로비저닝을 사용하려면 클러스터 관리자가 API 서버에서 DefaultStorageClass 어드미션 컨트롤러를 사용하도록 설정해야 한다. 예를 들어 API 서버 컴포넌트의 --enable-admission-plugins 플래그에 대한 쉼표로 구분되어 정렬된 값들의 목록 중에 DefaultStorageClass가 포함되어 있는지 확인하여 설정할 수 있다. API 서버 커맨드라인 플래그에 대한 자세한 정보는 kube-apiserver 문서를 확인하면 된다.

바인딩

사용자는 원하는 특정 용량의 스토리지와 특정 접근 모드로 퍼시스턴트볼륨클레임을 생성하거나 동적 프로비저닝의 경우 이미 생성한 상태다. 마스터의 컨트롤 루프는 새로운 PVC를 감시하고 일치하는 PV(가능한 경우)를 찾아 서로 바인딩한다. PV가 새 PVC에 대해 동적으로 프로비저닝된 경우 루프는 항상 해당 PV를 PVC에 바인딩한다. 그렇지 않으면 사용자는 항상 최소한 그들이 요청한 것을 얻지만 볼륨은 요청된 것을 초과할 수 있다. 일단 바인딩되면 퍼시스턴트볼륨클레임은 어떻게 바인딩되었는지 상관없이 배타적으로 바인딩된다. PVC 대 PV 바인딩은 일대일 매핑으로, 퍼시스턴트볼륨과 퍼시스턴트볼륨클레임 사이의 양방향 바인딩인 ClaimRef를 사용한다.

일치하는 볼륨이 없는 경우 클레임은 무한정 바인딩되지 않은 상태로 남아 있다. 일치하는 볼륨이 제공되면 클레임이 바인딩된다. 예를 들어 많은 수의 50Gi PV로 프로비저닝된 클러스터는 100Gi를 요청하는 PVC와 일치하지 않는다. 100Gi PV가 클러스터에 추가되면 PVC를 바인딩할 수 있다.

사용 중

파드는 클레임을 볼륨으로 사용한다. 클러스터는 클레임을 검사하여 바인딩된 볼륨을 찾고 해당 볼륨을 파드에 마운트한다. 여러 접근 모드를 지원하는 볼륨의 경우 사용자는 자신의 클레임을 파드에서 볼륨으로 사용할 때 원하는 접근 모드를 지정한다.

일단 사용자에게 클레임이 있고 그 클레임이 바인딩되면, 바인딩된 PV는 사용자가 필요로 하는 한 사용자에게 속한다. 사용자는 파드의 volumes 블록에 persistentVolumeClaim을 포함하여 파드를 스케줄링하고 클레임한 PV에 접근한다. 이에 대한 자세한 내용은 볼륨으로 클레임하기를 참고하길 바란다.

사용 중인 스토리지 오브젝트 보호

사용 중인 스토리지 오브젝트 보호 기능의 목적은 PVC에 바인딩된 파드와 퍼시스턴트볼륨(PV)이 사용 중인 퍼시스턴트볼륨클레임(PVC)을 시스템에서 삭제되지 않도록 하는 것이다. 삭제되면 이로 인해 데이터의 손실이 발생할 수 있기 때문이다.

사용자가 파드에서 활발하게 사용 중인 PVC를 삭제하면 PVC는 즉시 삭제되지 않는다. PVC가 더 이상 파드에서 적극적으로 사용되지 않을 때까지 PVC 삭제가 연기된다. 또한 관리자가 PVC에 바인딩된 PV를 삭제하면 PV는 즉시 삭제되지 않는다. PV가 더 이상 PVC에 바인딩되지 않을 때까지 PV 삭제가 연기된다.

PVC의 상태가 Terminating이고 Finalizers 목록에 kubernetes.io/pvc-protection이 포함되어 있으면 PVC가 보호된 것으로 볼 수 있다.

kubectl describe pvc hostpath
Name:          hostpath
Namespace:     default
StorageClass:  example-hostpath
Status:        Terminating
Volume:
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-class=example-hostpath
               volume.beta.kubernetes.io/storage-provisioner=example.com/hostpath
Finalizers:    [kubernetes.io/pvc-protection]
...

마찬가지로 PV 상태가 Terminating이고 Finalizers 목록에 kubernetes.io/pv-protection이 포함되어 있으면 PV가 보호된 것으로 볼 수 있다.

kubectl describe pv task-pv-volume
Name:            task-pv-volume
Labels:          type=local
Annotations:     <none>
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    standard
Status:          Terminating
Claim:
Reclaim Policy:  Delete
Access Modes:    RWO
Capacity:        1Gi
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /tmp/data
    HostPathType:
Events:            <none>

반환(Reclaiming)

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

Retain(보존)

Retain 반환 정책은 리소스를 수동으로 반환할 수 있게 한다. 퍼시스턴트볼륨클레임이 삭제되면 퍼시스턴트볼륨은 여전히 존재하며 볼륨은 "릴리스 된" 것으로 간주된다. 그러나 이전 요청자의 데이터가 여전히 볼륨에 남아 있기 때문에 다른 요청에 대해서는 아직 사용할 수 없다. 관리자는 다음 단계에 따라 볼륨을 수동으로 반환할 수 있다.

  1. 퍼시스턴트볼륨을 삭제한다. PV가 삭제된 후에도 외부 인프라(예: AWS EBS, GCE PD, Azure Disk 또는 Cinder 볼륨)의 관련 스토리지 자산이 존재한다.
  2. 관련 스토리지 자산의 데이터를 수동으로 삭제한다.
  3. 연결된 스토리지 자산을 수동으로 삭제한다.

동일한 스토리지 자산을 재사용하려는 경우, 동일한 스토리지 자산 정의로 새 퍼시스턴트볼륨을 생성한다.

Delete(삭제)

Delete 반환 정책을 지원하는 볼륨 플러그인의 경우, 삭제는 쿠버네티스에서 퍼시스턴트볼륨 오브젝트와 외부 인프라(예: AWS EBS, GCE PD, Azure Disk 또는 Cinder 볼륨)의 관련 스토리지 자산을 모두 삭제한다. 동적으로 프로비저닝된 볼륨은 스토리지클래스의 반환 정책을 상속하며 기본값은 Delete이다. 관리자는 사용자의 기대에 따라 스토리지클래스를 구성해야 한다. 그렇지 않으면 PV를 생성한 후 PV를 수정하거나 패치해야 한다. 퍼시스턴트볼륨의 반환 정책 변경을 참고하길 바란다.

Recycle(재활용)

기본 볼륨 플러그인에서 지원하는 경우 Recycle 반환 정책은 볼륨에서 기본 스크럽(rm -rf /thevolume/*)을 수행하고 새 클레임에 다시 사용할 수 있도록 한다.

그러나 관리자는 레퍼런스에 설명된 대로 쿠버네티스 컨트롤러 관리자 커맨드라인 인자(command line arguments)를 사용하여 사용자 정의 재활용 파드 템플릿을 구성할 수 있다. 사용자 정의 재활용 파드 템플릿에는 아래 예와 같이 volumes 명세가 포함되어야 한다.

apiVersion: v1
kind: Pod
metadata:
  name: pv-recycler
  namespace: default
spec:
  restartPolicy: Never
  volumes:
  - name: vol
    hostPath:
      path: /any/path/it/will/be/replaced
  containers:
  - name: pv-recycler
    image: "registry.k8s.io/busybox"
    command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/*  && test -z \"$(ls -A /scrub)\" || exit 1"]
    volumeMounts:
    - name: vol
      mountPath: /scrub

그러나 volumes 부분의 사용자 정의 재활용 파드 템플릿에 지정된 특정 경로는 재활용되는 볼륨의 특정 경로로 바뀐다.

퍼시스턴트볼륨 삭제 보호 파이널라이저(finalizer)

기능 상태: Kubernetes v1.23 [alpha]

퍼시스턴트볼륨에 파이널라이저를 추가하여, Delete 반환 정책을 갖는 퍼시스턴트볼륨이 기반 스토리지(backing storage)가 삭제된 이후에만 삭제되도록 할 수 있다.

새롭게 도입된 kubernetes.io/pv-controllerexternal-provisioner.volume.kubernetes.io/finalizer 파이널라이저는 동적으로 프로비전된 볼륨에만 추가된다.

kubernetes.io/pv-controller 파이널라이저는 인-트리 플러그인 볼륨에 추가된다. 다음은 이에 대한 예시이다.

kubectl describe pv pvc-74a498d6-3929-47e8-8c02-078c1ece4d78
Name:            pvc-74a498d6-3929-47e8-8c02-078c1ece4d78
Labels:          <none>
Annotations:     kubernetes.io/createdby: vsphere-volume-dynamic-provisioner
                 pv.kubernetes.io/bound-by-controller: yes
                 pv.kubernetes.io/provisioned-by: kubernetes.io/vsphere-volume
Finalizers:      [kubernetes.io/pv-protection kubernetes.io/pv-controller]
StorageClass:    vcp-sc
Status:          Bound
Claim:           default/vcp-pvc-1
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        1Gi
Node Affinity:   <none>
Message:         
Source:
    Type:               vSphereVolume (a Persistent Disk resource in vSphere)
    VolumePath:         [vsanDatastore] d49c4a62-166f-ce12-c464-020077ba5d46/kubernetes-dynamic-pvc-74a498d6-3929-47e8-8c02-078c1ece4d78.vmdk
    FSType:             ext4
    StoragePolicyName:  vSAN Default Storage Policy
Events:                 <none>

external-provisioner.volume.kubernetes.io/finalizer 파이널라이저는 CSI 볼륨에 추가된다. 다음은 이에 대한 예시이다.

Name:            pvc-2f0bab97-85a8-4552-8044-eb8be45cf48d
Labels:          <none>
Annotations:     pv.kubernetes.io/provisioned-by: csi.vsphere.vmware.com
Finalizers:      [kubernetes.io/pv-protection external-provisioner.volume.kubernetes.io/finalizer]
StorageClass:    fast
Status:          Bound
Claim:           demo-app/nginx-logs
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        200Mi
Node Affinity:   <none>
Message:         
Source:
    Type:              CSI (a Container Storage Interface (CSI) volume source)
    Driver:            csi.vsphere.vmware.com
    FSType:            ext4
    VolumeHandle:      44830fa8-79b4-406b-8b58-621ba25353fd
    ReadOnly:          false
    VolumeAttributes:      storage.kubernetes.io/csiProvisionerIdentity=1648442357185-8081-csi.vsphere.vmware.com
                           type=vSphere CNS Block Volume
Events:                <none>

특정 인-트리 볼륨 플러그인에 대해 CSIMigration{provider} 기능 플래그가 활성화되어 있을 때, kubernetes.io/pv-controller 파이널라이저는 external-provisioner.volume.kubernetes.io/finalizer 파이널라이저로 대체된다.

퍼시스턴트볼륨 예약

컨트롤 플레인은 클러스터에서 퍼시스턴트볼륨클레임을 일치하는 퍼시스턴트볼륨에 바인딩할 수 있다. 그러나, PVC를 특정 PV에 바인딩하려면, 미리 바인딩해야 한다.

퍼시스턴트볼륨클레임에서 퍼시스턴트볼륨을 지정하여, 특정 PV와 PVC 간의 바인딩을 선언한다. 퍼시스턴트볼륨이 존재하고 claimRef 필드를 통해 퍼시스턴트볼륨클레임을 예약하지 않은 경우, 퍼시스턴트볼륨 및 퍼시스턴트볼륨클레임이 바인딩된다.

바인딩은 노드 선호도(affinity)를 포함하여 일부 볼륨 일치(matching) 기준과 관계없이 발생한다. 컨트롤 플레인은 여전히 스토리지 클래스, 접근 모드 및 요청된 스토리지 크기가 유효한지 확인한다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-pvc
  namespace: foo
spec:
  storageClassName: "" # 빈 문자열은 명시적으로 설정해야 하며 그렇지 않으면 기본 스토리지클래스가 설정됨
  volumeName: foo-pv
  ...

이 메서드는 퍼시스턴트볼륨에 대한 바인딩 권한을 보장하지 않는다. 다른 퍼시스턴트볼륨클레임에서 지정한 PV를 사용할 수 있는 경우, 먼저 해당 스토리지 볼륨을 예약해야 한다. PV의 claimRef 필드에 관련 퍼시스턴트볼륨클레임을 지정하여 다른 PVC가 바인딩할 수 없도록 한다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: foo-pv
spec:
  storageClassName: ""
  claimRef:
    name: foo-pvc
    namespace: foo
  ...

이는 기존 PV를 재사용하는 경우를 포함하여 claimPolicyRetain 으로 설정된 퍼시스턴트볼륨을 사용하려는 경우에 유용하다.

퍼시스턴트 볼륨 클레임 확장

기능 상태: Kubernetes v1.24 [stable]

퍼시스턴트볼륨클레임(PVC) 확장 지원은 기본적으로 활성화되어 있다. 다음 유형의 볼륨을 확장할 수 있다.

  • azureDisk
  • azureFile
  • awsElasticBlockStore
  • cinder (deprecated)
  • csi
  • flexVolume (deprecated)
  • gcePersistentDisk
  • rbd
  • portworxVolume

스토리지 클래스의 allowVolumeExpansion 필드가 true로 설정된 경우에만 PVC를 확장할 수 있다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-vol-default
provisioner: vendor-name.example/magicstorage
parameters:
  resturl: "http://192.168.10.100:8080"
  restuser: ""
  secretNamespace: ""
  secretName: ""
allowVolumeExpansion: true

PVC에 대해 더 큰 볼륨을 요청하려면 PVC 오브젝트를 수정하여 더 큰 용량을 지정한다. 이는 기본 퍼시스턴트볼륨을 지원하는 볼륨의 확장을 트리거한다. 클레임을 만족시키기 위해 새로운 퍼시스턴트볼륨이 생성되지 않고 기존 볼륨의 크기가 조정된다.

CSI 볼륨 확장

기능 상태: Kubernetes v1.24 [stable]

CSI 볼륨 확장 지원은 기본적으로 활성화되어 있지만 볼륨 확장을 지원하려면 특정 CSI 드라이버도 필요하다. 자세한 내용은 특정 CSI 드라이버 문서를 참고한다.

파일시스템을 포함하는 볼륨 크기 조정

파일시스템이 XFS, Ext3 또는 Ext4 인 경우에만 파일시스템을 포함하는 볼륨의 크기를 조정할 수 있다.

볼륨에 파일시스템이 포함된 경우 새 파드가 ReadWrite 모드에서 퍼시스턴트볼륨클레임을 사용하는 경우에만 파일시스템의 크기가 조정된다. 파일시스템 확장은 파드가 시작되거나 파드가 실행 중이고 기본 파일시스템이 온라인 확장을 지원할 때 수행된다.

FlexVolumes(쿠버네티스 v1.23부터 사용 중단됨)는 드라이버의 RequiresFSResize 기능이 true로 설정된 경우 크기 조정을 허용한다. FlexVolume은 파드 재시작 시 크기를 조정할 수 있다.

사용 중인 퍼시스턴트볼륨클레임 크기 조정

기능 상태: Kubernetes v1.24 [stable]

이 경우 기존 PVC를 사용하는 파드 또는 디플로이먼트를 삭제하고 다시 만들 필요가 없다. 파일시스템이 확장되자마자 사용 중인 PVC가 파드에서 자동으로 사용 가능하다. 이 기능은 파드나 디플로이먼트에서 사용하지 않는 PVC에는 영향을 미치지 않는다. 확장을 완료하기 전에 PVC를 사용하는 파드를 만들어야 한다.

다른 볼륨 유형과 비슷하게 FlexVolume 볼륨도 파드에서 사용 중인 경우 확장할 수 있다.

볼륨 확장 시 오류 복구

사용자가 기반 스토리지 시스템이 제공할 수 있는 것보다 더 큰 사이즈를 지정하면, 사용자 또는 클러스터 관리자가 조치를 취하기 전까지 PVC 확장을 계속 시도한다. 이는 바람직하지 않으며 따라서 쿠버네티스는 이러한 오류 상황에서 벗어나기 위해 다음과 같은 방법을 제공한다.

기본 스토리지 확장에 실패하면, 클러스터 관리자가 수동으로 퍼시스턴트 볼륨 클레임(PVC) 상태를 복구하고 크기 조정 요청을 취소할 수 있다. 그렇지 않으면, 컨트롤러가 관리자 개입 없이 크기 조정 요청을 계속해서 재시도한다.

  1. 퍼시스턴트볼륨클레임(PVC)에 바인딩된 퍼시스턴트볼륨(PV)을 Retain 반환 정책으로 표시한다.
  2. PVC를 삭제한다. PV에는 Retain 반환 정책이 있으므로 PVC를 재생성할 때 데이터가 손실되지 않는다.
  3. 새 PVC를 바인딩할 수 있도록 PV 명세에서 claimRef 항목을 삭제한다. 그러면 PV가 Available 상태가 된다.
  4. PV 보다 작은 크기로 PVC를 다시 만들고 PVC의 volumeName 필드를 PV 이름으로 설정한다. 이것은 새 PVC를 기존 PV에 바인딩해야 한다.
  5. PV의 반환 정책을 복원하는 것을 잊지 않는다.

기능 상태: Kubernetes v1.23 [alpha]

클러스터에 RecoverVolumeExpansionFailure 기능 게이트가 활성화되어 있는 상태에서 PVC 확장이 실패하면 이전에 요청했던 값보다 작은 크기로의 확장을 재시도할 수 있다. 더 작은 크기를 지정하여 확장 시도를 요청하려면, 이전에 요청했던 값보다 작은 크기로 PVC의 .spec.resources 값을 수정한다. 이는 총 용량 제한(capacity constraint)으로 인해 큰 값으로의 확장이 실패한 경우에 유용하다. 만약 확장이 실패했다면, 또는 실패한 것 같다면, 기반 스토리지 공급자의 용량 제한보다 작은 값으로 확장을 재시도할 수 있다. .status.resizeStatus와 PVC의 이벤트를 감시하여 리사이즈 작업의 상태를 모니터할 수 있다.

참고: 이전에 요청했던 값보다 작은 크기를 요청했더라도, 새로운 값이 여전히 .status.capacity보다 클 수 있다. 쿠버네티스는 PVC를 현재 크기보다 더 작게 축소하는 것은 지원하지 않는다.

퍼시스턴트 볼륨의 유형

퍼시스턴트볼륨 유형은 플러그인으로 구현된다. 쿠버네티스는 현재 다음의 플러그인을 지원한다.

  • cephfs - CephFS 볼륨
  • csi - 컨테이너 스토리지 인터페이스 (CSI)
  • fc - Fibre Channel (FC) 스토리지
  • hostPath - HostPath 볼륨 (단일 노드 테스트 전용. 다중-노드 클러스터에서 작동하지 않음. 대신 로컬 볼륨 사용 고려)
  • iscsi - iSCSI (SCSI over IP) 스토리지
  • local - 노드에 마운트된 로컬 스토리지 디바이스
  • nfs - 네트워크 파일 시스템 (NFS) 스토리지
  • rbd - Rados Block Device (RBD) 볼륨

아래의 PersistentVolume 타입은 사용 중단되었다. 이 말인 즉슨, 지원은 여전히 제공되지만 추후 쿠버네티스 릴리스에서는 삭제될 예정이라는 것이다.

  • awsElasticBlockStore - AWS Elastic Block Store (EBS) (v1.17에서 사용 중단)
  • azureDisk - Azure Disk (v1.19에서 사용 중단)
  • azureFile - Azure File (v1.21에서 사용 중단)
  • cinder - Cinder (오픈스택 블록 스토리지) (v1.18에서 사용 중단)
  • flexVolume - FlexVolume (v1.23에서 사용 중단)
  • gcePersistentDisk - GCE Persistent Disk (v1.17에서 사용 중단)
  • portworxVolume - Portworx 볼륨 (v1.25에서 사용 중단)
  • vsphereVolume - vSphere VMDK 볼륨 (v1.19에서 사용 중단)

이전 쿠버네티스 버전은 아래의 인-트리 PersistentVolume 타입도 지원했었다.

  • photonPersistentDisk - Photon 컨트롤러 퍼시스턴트 디스크. (v1.15부터 사용 불가)
  • scaleIO - ScaleIO 볼륨 (v1.21부터 사용 불가)
  • flocker - Flocker 스토리지 (v1.25부터 사용 불가)
  • quobyte - Quobyte 볼륨 (v1.25부터 사용 불가)
  • storageos - StorageOS 볼륨 (v1.25부터 사용 불가)

퍼시스턴트 볼륨

각 PV에는 스펙과 상태(볼륨의 명세와 상태)가 포함된다. 퍼시스턴트볼륨 오브젝트의 이름은 유효한 DNS 서브도메인 이름이어야 한다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2

용량

일반적으로 PV는 특정 저장 용량을 가진다. 이것은 PV의 capacity 속성을 사용하여 설정된다. capacity가 사용하는 단위를 이해하려면 용어집에 있는 수량 항목을 참고한다.

현재 스토리지 용량 크기는 설정하거나 요청할 수 있는 유일한 리소스이다. 향후 속성에 IOPS, 처리량 등이 포함될 수 있다.

볼륨 모드

기능 상태: Kubernetes v1.18 [stable]

쿠버네티스는 퍼시스턴트볼륨의 두 가지 volumeModesFilesystemBlock을 지원한다.

volumeMode는 선택적 API 파라미터이다. FilesystemvolumeMode 파라미터가 생략될 때 사용되는 기본 모드이다.

volumeMode: Filesystem이 있는 볼륨은 파드의 디렉터리에 마운트 된다. 볼륨이 장치에 의해 지원되고 그 장치가 비어 있으면 쿠버네티스는 장치를 처음 마운트하기 전에 장치에 파일시스템을 만든다.

볼륨을 원시 블록 장치로 사용하려면 volumeMode의 값을 Block으로 설정할 수 있다. 이러한 볼륨은 파일시스템이 없는 블록 장치로 파드에 제공된다. 이 모드는 파드와 볼륨 사이에 파일시스템 계층 없이도 볼륨에 액세스하는 가장 빠른 방법을 파드에 제공하는 데 유용하다. 반면에 파드에서 실행되는 애플리케이션은 원시 블록 장치를 처리하는 방법을 알아야 한다. 파드에서 volumeMode: Block으로 볼륨을 사용하는 방법에 대한 예는 원시 블록 볼륨 지원를 참조하십시오.

접근 모드

리소스 제공자가 지원하는 방식으로 호스트에 퍼시스턴트볼륨을 마운트할 수 있다. 아래 표에서 볼 수 있듯이 제공자들은 서로 다른 기능을 가지며 각 PV의 접근 모드는 해당 볼륨에서 지원하는 특정 모드로 설정된다. 예를 들어 NFS는 다중 읽기/쓰기 클라이언트를 지원할 수 있지만 특정 NFS PV는 서버에서 읽기 전용으로 export할 수 있다. 각 PV는 특정 PV의 기능을 설명하는 자체 접근 모드 셋을 갖는다.

접근 모드는 다음과 같다.

ReadWriteOnce
하나의 노드에서 해당 볼륨이 읽기-쓰기로 마운트 될 수 있다. ReadWriteOnce 접근 모드에서도 파드가 동일 노드에서 구동되는 경우에는 복수의 파드에서 볼륨에 접근할 수 있다.
ReadOnlyMany
볼륨이 다수의 노드에서 읽기 전용으로 마운트 될 수 있다.
ReadWriteMany
볼륨이 다수의 노드에서 읽기-쓰기로 마운트 될 수 있다.
ReadWriteOncePod
볼륨이 단일 파드에서 읽기-쓰기로 마운트될 수 있다. 전체 클러스터에서 단 하나의 파드만 해당 PVC를 읽거나 쓸 수 있어야하는 경우 ReadWriteOncePod 접근 모드를 사용한다. 이 기능은 CSI 볼륨과 쿠버네티스 버전 1.22+ 에서만 지원된다.

퍼시스턴트 볼륨에 대한 단일 파드 접근 모드 소개 블로그 기사에서 이에 대해 보다 자세한 내용을 다룬다.

CLI에서 접근 모드는 다음과 같이 약어로 표시된다.

  • RWO - ReadWriteOnce
  • ROX - ReadOnlyMany
  • RWX - ReadWriteMany
  • RWOP - ReadWriteOncePod

중요! 볼륨이 여러 접근 모드를 지원하더라도 한 번에 하나의 접근 모드를 사용하여 마운트할 수 있다. 예를 들어 GCEPersistentDisk는 하나의 노드가 ReadWriteOnce로 마운트하거나 여러 노드가 ReadOnlyMany로 마운트할 수 있지만 동시에는 불가능하다.

Volume PluginReadWriteOnceReadOnlyManyReadWriteManyReadWriteOncePod
AWSElasticBlockStore---
AzureFile-
AzureDisk---
CephFS-
Cinder-(다중 부착(multi-attached)이 가능한 볼륨이라면)-
CSI드라이버에 의존드라이버에 의존드라이버에 의존드라이버에 의존
FC--
FlexVolume드라이버에 의존-
GCEPersistentDisk--
Glusterfs-
HostPath---
iSCSI--
NFS-
RBD--
VsphereVolume-- (파드를 배치할(collocated) 때 동작한다)-
PortworxVolume--

클래스

PV는 storageClassName 속성을 스토리지클래스의 이름으로 설정하여 지정하는 클래스를 가질 수 있다. 특정 클래스의 PV는 해당 클래스를 요청하는 PVC에만 바인딩될 수 있다. storageClassName이 없는 PV에는 클래스가 없으며 특정 클래스를 요청하지 않는 PVC에만 바인딩할 수 있다.

이전에는 volume.beta.kubernetes.io/storage-class 어노테이션이 storageClassName 속성 대신 사용되었다. 이 어노테이션은 아직까지는 사용할 수 있지만, 향후 쿠버네티스 릴리스에서 완전히 사용 중단(deprecated)이 될 예정이다.

반환 정책

현재 반환 정책은 다음과 같다.

  • Retain(보존) -- 수동 반환
  • Recycle(재활용) -- 기본 스크럽 (rm -rf /thevolume/*)
  • Delete(삭제) -- AWS EBS, GCE PD, Azure Disk 또는 OpenStack Cinder 볼륨과 같은 관련 스토리지 자산이 삭제됨

현재 NFS 및 HostPath만 재활용을 지원한다. AWS EBS, GCE PD, Azure Disk 및 Cinder 볼륨은 삭제를 지원한다.

마운트 옵션

쿠버네티스 관리자는 퍼시스턴트 볼륨이 노드에 마운트될 때 추가 마운트 옵션을 지정할 수 있다.

다음 볼륨 유형은 마운트 옵션을 지원한다.

  • awsElasticBlockStore
  • azureDisk
  • azureFile
  • cephfs
  • cinder (v1.18에서 사용 중단됨)
  • gcePersistentDisk
  • iscsi
  • nfs
  • rbd
  • vsphereVolume

마운트 옵션의 유효성이 검사되지 않는다. 마운트 옵션이 유효하지 않으면, 마운트가 실패한다.

이전에는 mountOptions 속성 대신 volume.beta.kubernetes.io/mount-options 어노테이션이 사용되었다. 이 어노테이션은 아직까지는 사용할 수 있지만, 향후 쿠버네티스 릴리스에서 완전히 사용 중단(deprecated)이 될 예정이다.

노드 어피니티(affinity)

PV는 노드 어피니티를 지정하여 이 볼륨에 접근할 수 있는 노드를 제한하는 제약 조건을 정의할 수 있다. PV를 사용하는 파드는 노드 어피니티에 의해 선택된 노드로만 스케줄링된다. 노드 어피니티를 명기하기 위해서는, PV의 .specnodeAffinity를 설정한다. 퍼시스턴트볼륨 API 레퍼런스에 해당 필드에 대해 보다 자세한 내용이 있다.

단계(Phase)

볼륨은 다음 단계 중 하나이다.

  • Available(사용 가능) -– 아직 클레임에 바인딩되지 않은 사용할 수 있는 리소스
  • Bound(바인딩) –- 볼륨이 클레임에 바인딩됨
  • Released(릴리스) –- 클레임이 삭제되었지만 클러스터에서 아직 리소스를 반환하지 않음
  • Failed(실패) –- 볼륨이 자동 반환에 실패함

CLI는 PV에 바인딩된 PVC의 이름을 표시한다.

퍼시스턴트볼륨클레임

각 PVC에는 스펙과 상태(클레임의 명세와 상태)가 포함된다. 퍼시스턴트볼륨클레임 오브젝트의 이름은 유효한 DNS 서브도메인 이름이어야 한다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

접근 모드

클레임은 특정 접근 모드로 저장소를 요청할 때 볼륨과 동일한 규칙을 사용한다.

볼륨 모드

클레임은 볼륨과 동일한 규칙을 사용하여 파일시스템 또는 블록 장치로 볼륨을 사용함을 나타낸다.

리소스

파드처럼 클레임은 특정 수량의 리소스를 요청할 수 있다. 이 경우는 스토리지에 대한 요청이다. 동일한 리소스 모델이 볼륨과 클레임 모두에 적용된다.

셀렉터

클레임은 볼륨 셋을 추가로 필터링하기 위해 레이블 셀렉터를 지정할 수 있다. 레이블이 셀렉터와 일치하는 볼륨만 클레임에 바인딩할 수 있다. 셀렉터는 두 개의 필드로 구성될 수 있다.

  • matchLabels - 볼륨에 이 값의 레이블이 있어야함
  • matchExpressions - 키, 값의 목록, 그리고 키와 값에 관련된 연산자를 지정하여 만든 요구 사항 목록. 유효한 연산자에는 In, NotIn, Exists 및 DoesNotExist가 있다.

matchLabelsmatchExpressions의 모든 요구 사항이 AND 조건이다. 일치하려면 모두 충족해야 한다.

클래스

클레임은 storageClassName 속성을 사용하여 스토리지클래스의 이름을 지정하여 특정 클래스를 요청할 수 있다. 요청된 클래스의 PV(PVC와 동일한 storageClassName을 갖는 PV)만 PVC에 바인딩될 수 있다.

PVC는 반드시 클래스를 요청할 필요는 없다. storageClassName""로 설정된 PVC는 항상 클래스가 없는 PV를 요청하는 것으로 해석되므로 클래스가 없는 PV(어노테이션이 없거나 ""와 같은 하나의 셋)에만 바인딩될 수 있다. storageClassName이 없는 PVC는 DefaultStorageClass 어드미션 플러그인이 켜져 있는지 여부에 따라 동일하지 않으며 클러스터에 따라 다르게 처리된다.

  • 어드미션 플러그인이 켜져 있으면 관리자가 기본 스토리지클래스를 지정할 수 있다. storageClassName이 없는 모든 PVC는 해당 기본값의 PV에만 바인딩할 수 있다. 기본 스토리지클래스 지정은 스토리지클래스 오브젝트에서 어노테이션 storageclass.kubernetes.io/is-default-classtrue로 설정하여 수행된다. 관리자가 기본값을 지정하지 않으면 어드미션 플러그인이 꺼져 있는 것처럼 클러스터가 PVC 생성에 응답한다. 둘 이상의 기본값이 지정된 경우 어드미션 플러그인은 모든 PVC 생성을 금지한다.
  • 어드미션 플러그인이 꺼져 있으면 기본 스토리지클래스에 대한 기본값 자체가 없다. storageClassName""으로 설정된 모든 PVC는 storageClassName이 마찬가지로 ""로 설정된 PV에만 바인딩할 수 있다. 하지만, storageClassName이 없는 PVC는 기본 스토리지클래스가 사용 가능해지면 갱신될 수 있다. PVC가 갱신되면 해당 PVC는 더 이상 storageClassName""로 설정된 PV와 바인딩되어있지 않게 된다.

더 자세한 정보는 retroactive default StorageClass assignment를 참조한다.

설치 방법에 따라 설치 중에 애드온 관리자가 기본 스토리지클래스를 쿠버네티스 클러스터에 배포할 수 있다.

PVC가 스토리지클래스를 요청하는 것 외에도 selector를 지정하면 요구 사항들이 AND 조건으로 동작한다. 요청된 클래스와 요청된 레이블이 있는 PV만 PVC에 바인딩될 수 있다.

이전에는 volume.beta.kubernetes.io/storage-class 어노테이션이 storageClassName 속성 대신 사용되었다. 이 어노테이션은 아직까지는 사용할 수 있지만, 향후 쿠버네티스 릴리스에서는 지원되지 않는다.

기본 스토리지클래스 할당 소급 적용하기

기능 상태: Kubernetes v1.26 [beta]

새로운 PVC를 위한 storageClassName을 설정하지 않고 퍼시스턴트볼륨클레임을 생성할 수 있으며, 이는 클러스터에 기본 스토리지클래스가 존재하지 않을 때에도 가능하다. 이 경우, 새로운 PVC는 정의된 대로 생성되며, 해당 PVC의 storageClassName은 기본값이 사용 가능해질 때까지 미설정 상태로 남는다.

기본 스토리지클래스가 사용 가능해지면, 컨트롤플레인은 storageClassName가 없는 PVC를 찾는다. storageClassName의 값이 비어있거나 해당 키 자체가 없는 PVC라면, 컨트롤플레인은 해당 PVC의 storageClassName가 새로운 기본 스토리지클래스와 일치하도록 설정하여 갱신한다. storageClassName""인 PVC가 있고, 기본 스토리지클래스를 설정한다면, 해당 PVC는 갱신되지 않는다.

기본 스토리지클래스가 존재할 때 storageClassName""로 설정된 PV와의 바인딩을 유지하고싶다면, 연결된 PVC의 storageClassName""로 설정해야 한다.

이 행동은 관리자가 오래된 기본 스토리지클래스를 삭제하고 새로운 기본 스토리지클래스를 생성하거나 설정하여 기본 스토리지클래스를 변경하는 데 도움이 된다. 기본값이 설정되어있지 않을 때의 이 작은 틈새로 인해 이 때 생성된 storageClassName가 없는 PVC는 아무런 기본값도 없이 생성될 수 있지만, 기본 스토리지클래스 할당 소급 적용에 의해 이러한 방식으로 기본값을 변경하는 것은 안전하다.

볼륨으로 클레임하기

클레임을 볼륨으로 사용해서 파드가 스토리지에 접근한다. 클레임은 클레임을 사용하는 파드와 동일한 네임스페이스에 있어야 한다. 클러스터는 파드의 네임스페이스에서 클레임을 찾고 이를 사용하여 클레임과 관련된 퍼시스턴트볼륨을 얻는다. 그런 다음 볼륨이 호스트와 파드에 마운트된다.

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

네임스페이스에 대한 참고 사항

퍼시스턴트볼륨 바인딩은 배타적이며, 퍼시스턴트볼륨클레임은 네임스페이스 오브젝트이므로 "다중" 모드(ROX, RWX)를 사용한 클레임은 하나의 네임스페이스 내에서만 가능하다.

hostPath 유형의 퍼시스턴트볼륨

hostPath 퍼시스턴트볼륨은 노드의 파일이나 디렉터리를 사용하여 네트워크 연결 스토리지를 에뮬레이션한다. hostPath 유형 볼륨의 예를 참고한다.

원시 블록 볼륨 지원

기능 상태: Kubernetes v1.18 [stable]

다음 볼륨 플러그인에 해당되는 경우 동적 프로비저닝을 포함하여 원시 블록 볼륨을 지원한다.

  • AWSElasticBlockStore
  • AzureDisk
  • CSI
  • FC (파이버 채널)
  • GCEPersistentDisk
  • iSCSI
  • Local volume
  • OpenStack Cinder
  • RBD (Ceph Block Device)
  • VsphereVolume

원시 블록 볼륨을 사용하는 퍼시스턴트볼륨

apiVersion: v1
kind: PersistentVolume
metadata:
  name: block-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  persistentVolumeReclaimPolicy: Retain
  fc:
    targetWWNs: ["50060e801049cfd1"]
    lun: 0
    readOnly: false

원시 블록 볼륨을 요청하는 퍼시스턴트볼륨클레임

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: block-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  resources:
    requests:
      storage: 10Gi

컨테이너에 원시 블록 장치 경로를 추가하는 파드 명세

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-block-volume
spec:
  containers:
    - name: fc-container
      image: fedora:26
      command: ["/bin/sh", "-c"]
      args: [ "tail -f /dev/null" ]
      volumeDevices:
        - name: data
          devicePath: /dev/xvda
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: block-pvc

블록 볼륨 바인딩

사용자가 퍼시스턴트볼륨클레임 스펙에서 volumeMode 필드를 사용하여 이를 나타내는 원시 블록 볼륨을 요청하는 경우 바인딩 규칙은 스펙의 일부분으로 이 모드를 고려하지 않은 이전 릴리스에 비해 약간 다르다. 사용자와 관리자가 원시 블록 장치를 요청하기 위해 지정할 수 있는 가능한 조합의 표가 아래 나열되어 있다. 이 테이블은 볼륨이 바인딩되는지 여부를 나타낸다. 정적 프로비저닝된 볼륨에 대한 볼륨 바인딩 매트릭스이다.

PV volumeModePVC volumeModeResult
지정되지 않음지정되지 않음BIND
지정되지 않음BlockNO BIND
지정되지 않음FilesystemBIND
Block지정되지 않음NO BIND
BlockBlockBIND
BlockFilesystemNO BIND
FilesystemFilesystemBIND
FilesystemBlockNO BIND
Filesystem지정되지 않음BIND

볼륨 스냅샷 및 스냅샷 지원에서 볼륨 복원

기능 상태: Kubernetes v1.20 [stable]

볼륨 스냅 샷은 아웃-오브-트리 CSI 볼륨 플러그인만 지원한다. 자세한 내용은 볼륨 스냅샷을 참조한다. 인-트리 볼륨 플러그인은 사용 중단 되었다. 볼륨 플러그인 FAQ에서 사용 중단된 볼륨 플러그인에 대해 확인할 수 있다.

볼륨 스냅샷에서 퍼시스턴트볼륨클레임 생성

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: restore-pvc
spec:
  storageClassName: csi-hostpath-sc
  dataSource:
    name: new-snapshot-test
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

볼륨 복제

볼륨 복제는 CSI 볼륨 플러그인만 사용할 수 있다.

기존 pvc에서 퍼시스턴트볼륨클레임 생성

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cloned-pvc
spec:
  storageClassName: my-csi-plugin
  dataSource:
    name: existing-src-pvc-name
    kind: PersistentVolumeClaim
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

볼륨 파퓰레이터(Volume populator)와 데이터 소스

기능 상태: Kubernetes v1.24 [beta]

쿠버네티스는 커스텀 볼륨 파퓰레이터를 지원한다. 커스텀 볼륨 파퓰레이터를 사용하려면, kube-apiserver와 kube-controller-manager에 대해 AnyVolumeDataSource 기능 게이트를 활성화해야 한다.

볼륨 파퓰레이터는 dataSourceRef라는 PVC 스펙 필드를 활용한다. 다른 PersistentVolumeClaim 또는 VolumeSnapshot을 가리키는 참조만 명시할 수 있는 dataSource 필드와는 다르게, dataSourceRef 필드는 동일 네임스페이스에 있는 어떠한 오브젝트에 대한 참조도 명시할 수 있다(단, PVC 외의 다른 코어 오브젝트는 제외). 기능 게이트가 활성화된 클러스터에서는 dataSource보다 dataSourceRef를 사용하는 것을 권장한다.

네임스페이스를 교차하는 데이터 소스

기능 상태: Kubernetes v1.26 [alpha]

쿠버네티스는 네임스페이스를 교차하는 볼륨 데이터 소스를 지원한다. 네임스페이스를 교차하는 볼륨 데이터 소스를 사용하기 위해서는, kube-apiserver, kube-controller-manager에 대해서 AnyVolumeDataSourceCrossNamespaceVolumeDataSource 기능 게이트를 활성화해야 한다. 또한, csi-provisioner에 대한 CrossNamespaceVolumeDataSource 기능 게이트도 활성화해야 한다.

CrossNamespaceVolumeDataSource 기능 게이트를 활성화하면 dataSourceRef 필드에 네임스페이스를 명시할 수 있다.

데이터 소스 참조

dataSourceRef 필드는 dataSource 필드와 거의 동일하게 동작한다. 둘 중 하나만 명시되어 있으면, API 서버는 두 필드에 같은 값을 할당할 것이다. 두 필드 모두 생성 이후에는 변경될 수 없으며, 두 필드에 다른 값을 넣으려고 시도하면 검증 에러가 발생할 것이다. 따라서 두 필드는 항상 같은 값을 갖게 된다.

dataSourceRef 필드와 dataSource 필드 사이에는 사용자가 알고 있어야 할 두 가지 차이점이 있다.

  • dataSource 필드는 유효하지 않은 값(예를 들면, 빈 값)을 무시하지만, dataSourceRef 필드는 어떠한 값도 무시하지 않으며 유효하지 않은 값이 들어오면 에러를 발생할 것이다. 유효하지 않은 값은 PVC를 제외한 모든 코어 오브젝트(apiGroup이 없는 오브젝트)이다.
  • dataSourceRef 필드는 여러 타입의 오브젝트를 포함할 수 있지만, dataSource 필드는 PVC와 VolumeSnapshot만 포함할 수 있다.

CrossNamespaceVolumeDataSource 기능이 활성화되어 있을 때, 추가적인 차이점이 존재한다:

  • dataSource 필드는 로컬 오브젝트만을 허용하지만, dataSourceRef 필드는 모든 네임스페이스의 오브젝트를 허용한다.
  • 네임스페이스가 명시되어 있을 때, dataSourcedataSourceRef는 동기화되지 않는다.

기능 게이트가 활성화된 클러스터에서는 dataSourceRef를 사용해야 하고, 그렇지 않은 클러스터에서는 dataSource를 사용해야 한다. 어떤 경우에서든 두 필드 모두를 확인해야 할 필요는 없다. 이렇게 약간의 차이만 있는 중복된 값은 이전 버전 호환성을 위해서만 존재하는 것이다. 상세히 설명하면, 이전 버전과 새로운 버전의 컨트롤러가 함께 동작할 수 있는데, 이는 두 필드가 동일하기 때문이다.

볼륨 파퓰레이터 사용하기

볼륨 파퓰레이터는 비어 있지 않은 볼륨(non-empty volume)을 생성할 수 있는 컨트롤러이며, 이 볼륨의 내용물은 커스텀 리소스(Custom Resource)에 의해 결정된다. 파퓰레이티드 볼륨(populated volume)을 생성하려면 dataSourceRef 필드에 커스텀 리소스를 기재한다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: populated-pvc
spec:
  dataSourceRef:
    name: example-name
    kind: ExampleDataSource
    apiGroup: example.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

볼륨 파퓰레이터는 외부 컴포넌트이기 때문에, 만약 적합한 컴포넌트가 설치되어 있지 않다면 볼륨 파퓰레이터를 사용하는 PVC에 대한 생성 요청이 실패할 수 있다. 외부 컨트롤러는 '컴포넌트가 없어서 PVC를 생성할 수 없음' 경고와 같은 PVC 생성 상태에 대한 피드백을 제공하기 위해, PVC에 대한 이벤트를 생성해야 한다.

알파 버전의 볼륨 데이터 소스 검증기를 클러스터에 설치할 수 있다. 해당 데이터 소스를 다루는 파퓰레이터가 등록되어 있지 않다면 이 컨트롤러가 PVC에 경고 이벤트를 생성한다. PVC를 위한 적절한 파퓰레이터가 설치되어 있다면, 볼륨 생성과 그 과정에서 발생하는 이슈에 대한 이벤트를 생성하는 것은 파퓰레이터 컨트롤러의 몫이다.

네임스페이스를 교차하는 볼륨 데이터 소스 사용하기

기능 상태: Kubernetes v1.26 [alpha]

네임스페이스 소유자가 참조를 받아들일 수 있도록 레퍼런스그랜트를 생성한다. dataSourceRef 필드를 사용하여 네임스페이스를 교차하는 볼륨 데이터 소스를 명시해서 파퓰레이트된 볼륨을 정의한다. 이 때, 원천 네임스페이스에 유효한 레퍼런스그랜트를 보유하고 있어야 한다:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-ns1-pvc
  namespace: default
spec:
  from:
  - group: ""
    kind: PersistentVolumeClaim
    namespace: ns1
  to:
  - group: snapshot.storage.k8s.io
    kind: VolumeSnapshot
    name: new-snapshot-demo
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-pvc
  namespace: ns1
spec:
  storageClassName: example
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  dataSourceRef:
    apiGroup: snapshot.storage.k8s.io
    kind: VolumeSnapshot
    name: new-snapshot-demo
    namespace: default
  volumeMode: Filesystem

포터블 구성 작성

광범위한 클러스터에서 실행되고 퍼시스턴트 스토리지가 필요한 구성 템플릿 또는 예제를 작성하는 경우 다음 패턴을 사용하는 것이 좋다.

  • 구성 번들(디플로이먼트, 컨피그맵 등)에 퍼시스턴트볼륨클레임 오브젝트를 포함시킨다.
  • 구성을 인스턴스화 하는 사용자에게 퍼시스턴트볼륨을 생성할 권한이 없을 수 있으므로 퍼시스턴트볼륨 오브젝트를 구성에 포함하지 않는다.
  • 템플릿을 인스턴스화 할 때 스토리지 클래스 이름을 제공하는 옵션을 사용자에게 제공한다.
    • 사용자가 스토리지 클래스 이름을 제공하는 경우 해당 값을 permanentVolumeClaim.storageClassName 필드에 입력한다. 클러스터에서 관리자가 스토리지클래스를 활성화한 경우 PVC가 올바른 스토리지 클래스와 일치하게 된다.
    • 사용자가 스토리지 클래스 이름을 제공하지 않으면 permanentVolumeClaim.storageClassName 필드를 nil로 남겨둔다. 그러면 클러스터에 기본 스토리지클래스가 있는 사용자에 대해 PV가 자동으로 프로비저닝된다. 많은 클러스터 환경에 기본 스토리지클래스가 설치되어 있거나 관리자가 고유한 기본 스토리지클래스를 생성할 수 있다.
  • 도구(tooling)에서 일정 시간이 지나도 바인딩되지 않는 PVC를 관찰하여 사용자에게 노출시킨다. 이는 클러스터가 동적 스토리지를 지원하지 않거나(이 경우 사용자가 일치하는 PV를 생성해야 함), 클러스터에 스토리지 시스템이 없음을 나타낸다(이 경우 사용자는 PVC가 필요한 구성을 배포할 수 없음).

다음 내용

API 레퍼런스

본 페이지에 기술된 API에 대해서 다음을 읽어본다.

3 - 프로젝티드 볼륨

이 페이지에서는 쿠버네티스의 프로젝티드 볼륨(projected volume) 에 대해 설명한다. 볼륨에 대해 익숙해지는 것을 추천한다.

들어가며

프로젝티드 볼륨은 여러 기존 볼륨 소스(sources)를 동일한 디렉토리에 매핑한다.

현재, 아래와 같은 볼륨 유형 소스를 프로젝트(project)할 수 있다.

모든 소스는 파드와 같은 네임스페이스에 있어야 한다. 자세한 내용은 올인원(all-in-one) 볼륨 문서를 참고한다.

시크릿, downwardAPI, 컨피그맵 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - downwardAPI:
          items:
            - path: "labels"
              fieldRef:
                fieldPath: metadata.labels
            - path: "cpu_limit"
              resourceFieldRef:
                containerName: container-test
                resource: limits.cpu
      - configMap:
          name: myconfigmap
          items:
            - key: config
              path: my-group/my-config

기본 권한이 아닌 모드 설정의 시크릿 구성 예시

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - secret:
          name: mysecret2
          items:
            - key: password
              path: my-group/my-password
              mode: 511

각 프로젝티드 볼륨 소스는 sources 아래의 스펙에 나열된다. 파라미터는 두 가지 예외를 제외하고 동일하다.

  • 시크릿의 경우 컨피그맵 명명법과 동일하도록 secretName 필드가 name으로 변경되었다.
  • defaultMode의 경우 볼륨 소스별 각각 명시할 수 없고 프로젝티드 수준에서만 명시할 수 있다. 그러나 위의 그림처럼 각 개별 프로젝션에 대해 mode를 명시적으로 지정할 수 있다.

서비스어카운트토큰 프로젝티드 볼륨

파드의 지정된 경로에 서비스어카운트토큰을 주입할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: sa-token-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    volumeMounts:
    - name: token-vol
      mountPath: "/service-account"
      readOnly: true
  serviceAccountName: default
  volumes:
  - name: token-vol
    projected:
      sources:
      - serviceAccountToken:
          audience: api
          expirationSeconds: 3600
          path: token

위 예시에는 파드에 주입된 서비스어카운트토큰이 포함된 프로젝티드 볼륨이 있다. 이 파드의 컨테이너는 서비스어카운트토큰을 사용하여 쿠버네티스 API 서버에 접근하고, 파드의 서비스어카운트로 인증할 수 있다. audience 필드는 토큰의 의도된 대상을 포함한다. 토큰 수신자는 토큰의 대상으로 지정된 식별자로 자신을 식별해야 하며, 그렇지 않으면 토큰을 거부해야 한다. 이 필드는 선택 사항으로, API 서버의 식별자로 기본 설정된다.

expirationSeconds는 서비스어카운트토큰의 예상 유효 기간이다. 기본값은 1시간이며 최소 10분 (600초) 이상이어야 한다. 관리자는 API 서버 옵션 --service-account-max-token-expiration으로 값을 지정하여 최대값을 제한할 수 있다. path 필드는 프로젝티드 볼륨의 마운트 지점에 대한 상대 경로를 지정한다.

시큐리티컨텍스트(SecurityContext) 상호작용

프로젝티드 서비스 어카운트 볼륨 내에서의 파일 퍼미션 처리에 대한 개선 제안을 통해, 프로젝티드 파일의 소유자 및 퍼미션이 올바르게 설정되도록 변경되었다.

리눅스

프로젝티드 볼륨과 파드 보안 컨텍스트RunAsUser가 설정된 리눅스 파드에서는 프로젝티드파일이 컨테이너 사용자 소유권을 포함한 올바른 소유권 집합을 가진다.

파드의 모든 컨테이너의 PodSecurityContext나 컨테이너 SecurityContextrunAsUser 설정이 동일하다면, kubelet은 serviceAccountToken 볼륨의 내용이 해당 사용자의 소유이며, 토큰 파일의 권한 모드는 0600로 설정됨을 보장한다.

윈도우

윈도우 파드에서 프로젝티드 볼륨과 파드 SecurityContextRunAsUsername이 설정된 경우, 윈도우에서 사용자 계정을 관리하는 방법으로 인하여 소유권이 적용되지 않는다. 윈도우는 보안 계정 관리자 (Security Account Manager)라는 데이터베이스 파일에 로컬 사용자 및 그룹 계정을 저장하고 관리한다. 컨테이너가 실행되는 동안 각 컨테이너는 호스트가 볼 수 없는 SAM 데이터베이스의 자체 인스턴스를 유지한다. 윈도우 컨테이너는 OS의 사용자 모드 부분을 호스트와 분리하여 실행하도록 설계되어 가상 SAM 데이터베이스를 유지 관리한다. 따라서 호스트에서 실행 중인 kubelet은 가상화된 컨테이너 계정에 대한 호스트 파일 소유권을 동적으로 구성할 수 없다. 호스트 머신의 파일을 컨테이너와 공유하려는 경우 C:\ 외부에 있는 자체 볼륨 마운트에 배치하는 것을 권장한다.

기본적으로, 프로젝티드 파일은 예제의 프로젝티드 볼륨 파일처럼 아래와 같은 소유권을 가진다.

PS C:\> Get-Acl C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt | Format-List

Path   : Microsoft.PowerShell.Core\FileSystem::C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt
Owner  : BUILTIN\Administrators
Group  : NT AUTHORITY\SYSTEM
Access : NT AUTHORITY\SYSTEM Allow  FullControl
         BUILTIN\Administrators Allow  FullControl
         BUILTIN\Users Allow  ReadAndExecute, Synchronize
Audit  :
Sddl   : O:BAG:SYD:AI(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200a9;;;BU)

ContainerAdministrator와 같은 모든 관리자인 사용자는 읽기, 쓰기 그리고 실행 권한을 갖게 되지만 관리자가 아닌 사용자는 읽기 및 실행 권한을 갖게 된다는 것을 의미한다.

4 - 임시 볼륨

이 문서는 쿠버네티스의 임시(ephemeral) 볼륨 에 대해 설명한다. 쿠버네티스 볼륨, 특히 퍼시스턴트볼륨클레임(PersistentVolumeClaim) 및 퍼시스턴트볼륨(PersistentVolume)에 대해 잘 알고 있는 것이 좋다.

일부 애플리케이션은 추가적인 저장소를 필요로 하면서도 재시작 시 데이터의 영구적 보존 여부는 신경쓰지 않을 수도 있다. 예를 들어, 캐싱 서비스는 종종 메모리 사이즈에 제약을 받으며 이에 따라 전반적인 성능에 적은 영향을 미치면서도 사용 데이터를 메모리보다는 느린 저장소에 간헐적으로 옮길 수도 있다.

또 다른 애플리케이션은 읽기 전용 입력 데이터를 파일에서 읽도록 되어 있으며, 이러한 데이터의 예시로는 구성 데이터 또는 비밀 키 등이 있다.

임시 볼륨 은 이러한 사용 사례를 위해 설계되었다. 임시 볼륨은 파드의 수명을 따르며 파드와 함께 생성 및 삭제되기 때문에, 일부 퍼시스턴트 볼륨이 어디에서 사용 가능한지에 제약되는 일 없이 파드가 중지 및 재시작될 수 있다.

임시 볼륨은 파드 명세에 인라인 으로 명시되며, 이로 인해 애플리케이션 배포 및 관리가 간편해진다.

임시 볼륨의 종류

쿠버네티스는 각 목적에 맞는 몇 가지의 임시 볼륨을 지원한다.

emptyDir, configMap, downwardAPI, secret로컬 임시 스토리지로서 제공된다. 이들은 각 노드의 kubelet에 의해 관리된다.

CSI 임시 볼륨은 써드파티 CSI 스토리지 드라이버에 의해 제공 되어야 한다.

일반 임시 볼륨은 써드파티 CSI 스토리지 드라이버에 의해 제공 될 수 있지만, 동적 프로비저닝을 지원하는 다른 스토리지 드라이버에 의해서도 제공될 수 있다. 일부 CSI 드라이버는 특히 CSI 임시 볼륨을 위해 만들어져서 동적 프로비저닝을 지원하지 않는데, 이러한 경우에는 일반 임시 볼륨 용으로는 사용할 수 없다.

써드파티 드라이버 사용의 장점은 쿠버네티스 자체적으로는 지원하지 않는 기능(예: kubelet에서 관리하는 디스크와 성능 특성이 다른 스토리지, 또는 다른 데이터 주입)을 제공할 수 있다는 것이다.

CSI 임시 볼륨

기능 상태: Kubernetes v1.25 [stable]

개념적으로, CSI 임시 볼륨은 configMap, downwardAPI, secret 볼륨 유형과 비슷하다. 즉, 스토리지는 각 노드에서 로컬하게 관리되며, 파드가 노드에 스케줄링된 이후에 다른 로컬 리소스와 함께 생성된다. 쿠버네티스에는 지금 단계에서는 파드를 재스케줄링하는 개념이 없다. 볼륨 생성은 실패하는 일이 거의 없어야 하며, 만약 실패할 경우 파드 시작 과정이 중단될 것이다. 특히, 스토리지 용량 인지 파드 스케줄링은 이러한 볼륨에 대해서는 지원되지 않는다. 또한 이러한 볼륨은 파드의 스토리지 자원 사용 상한에 제한받지 않는데, 이는 kubelet 자신이 관리하는 스토리지에만 강제할 수 있는 것이기 때문이다.

다음은 CSI 임시 스토리지를 사용하는 파드에 대한 예시 매니페스트이다.

kind: Pod
apiVersion: v1
metadata:
  name: my-csi-app
spec:
  containers:
    - name: my-frontend
      image: busybox:1.28
      volumeMounts:
      - mountPath: "/data"
        name: my-csi-inline-vol
      command: [ "sleep", "1000000" ]
  volumes:
    - name: my-csi-inline-vol
      csi:
        driver: inline.storage.kubernetes.io
        volumeAttributes:
          foo: bar

volumeAttributes은 드라이버에 의해 어떤 볼륨이 준비되는지를 결정한다. 이러한 속성은 각 드라이버별로 다르며 표준화되지 않았다. 더 자세한 사항은 각 CSI 드라이버 문서를 참고한다.

CSI 드라이버 제한 사항

CSI 임시 볼륨은 사용자로 하여금 volumeAttributes를 파드 스펙의 일부로서 CSI 드라이버에 직접 제공할 수 있도록 한다. 보통은 관리자만 사용할 수 있는 volumeAttributes를 허용하는 CSI 드라이버는 내장(inline) 임시 볼륨 내에서 사용하는 것이 적합하지 않다. 예를 들어, 일반적으로 스토리지클래스 내에 정의되어 있는 파라미터들은 내장 임시 볼륨 사용을 통해 사용자에게 노출되어서는 안 된다.

클러스터 관리자가 이처럼 파드 스펙 내장 임시 볼륨 사용이 가능한 CSI 드라이버를 제한하려면 다음을 수행할 수 있다.

  • CSIDriver 스펙의 volumeLifecycleModes에서 Ephemeral을 제거하여, 해당 드라이버가 내장 임시 볼륨으로 사용되는 것을 막는다.
  • 어드미션 웹훅을 사용하여 드라이버를 활용하는 방법을 제한한다.

일반 임시 볼륨

기능 상태: Kubernetes v1.23 [stable]

일반 임시 볼륨은 프로비저닝 후 일반적으로 비어 있는 스크래치 데이터에 대해 파드 별 디렉터리를 제공한다는 점에서 emptyDir 볼륨과 유사하다. 하지만 다음과 같은 추가 기능도 제공한다.

  • 스토리지는 로컬이거나 네트워크 연결형(network-attached)일 수 있다.
  • 볼륨의 크기를 고정할 수 있으며 파드는 이 크기를 초과할 수 없다.
  • 드라이버와 파라미터에 따라 볼륨이 초기 데이터를 가질 수도 있다.
  • 볼륨에 대한 일반적인 작업은 드라이버가 지원하는 범위 내에서 지원된다. 이와 같은 작업은 다음을 포함한다. 스냅샷, 복제, 크기 조정, 및 스토리지 용량 추적.

다음은 예시이다.

kind: Pod
apiVersion: v1
metadata:
  name: my-app
spec:
  containers:
    - name: my-frontend
      image: busybox:1.28
      volumeMounts:
      - mountPath: "/scratch"
        name: scratch-volume
      command: [ "sleep", "1000000" ]
  volumes:
    - name: scratch-volume
      ephemeral:
        volumeClaimTemplate:
          metadata:
            labels:
              type: my-frontend-volume
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "scratch-storage-class"
            resources:
              requests:
                storage: 1Gi

라이프사이클 및 퍼시스턴트볼륨클레임

핵심 설계 아이디어는 볼륨 클레임을 위한 파라미터는 파드의 볼륨 소스 내부에서 허용된다는 점이다. 레이블, 어노테이션 및 퍼시스턴트볼륨클레임을 위한 모든 필드가 지원된다. 이러한 파드가 생성되면, 임시 볼륨 컨트롤러는 파드가 속한 동일한 네임스페이스에 퍼시스턴트볼륨클레임 오브젝트를 생성하고 파드가 삭제될 때에는 퍼시스턴트볼륨클레임도 삭제되도록 만든다.

이는 볼륨 바인딩 및/또는 프로비저닝을 유발하는데, 스토리지클래스가 즉각적인(immediate) 볼륨 바인딩을 사용하는 경우에는 즉시, 또는 파드가 노드에 잠정적으로 스케줄링되었을 때 발생한다(WaitForFirstConsumer 볼륨 바인딩 모드). 일반 임시 볼륨에는 후자가 추천되는데, 이 경우 스케줄러가 파드를 할당하기에 적합한 노드를 선택하기가 쉬워지기 때문이다. 즉각적인 바인딩을 사용하는 경우, 스케줄러는 볼륨이 사용 가능해지는 즉시 해당 볼륨에 접근 가능한 노드를 선택하도록 강요받는다.

리소스 소유권 관점에서, 일반 임시 스토리지를 갖는 파드는 해당 임시 스토리지를 제공하는 퍼시스턴트볼륨클레임의 소유자이다. 파드가 삭제되면, 쿠버네티스 가비지 콜렉터는 해당 PVC를 삭제하는데, 스토리지 클래스의 기본 회수 정책이 볼륨을 삭제하는 것이기 때문에 PVC의 삭제는 보통 볼륨의 삭제를 유발한다. 회수 정책을 retain으로 설정한 스토리지클래스를 사용하여 준 임시(quasi-ephemeral) 로컬 스토리지를 생성할 수도 있는데, 이렇게 하면 스토리지의 수명이 파드의 수명보다 길어지며, 이러한 경우 볼륨 정리를 별도로 수행해야 함을 명심해야 한다.

이러한 PVC가 존재하는 동안은, 다른 PVC와 동일하게 사용될 수 있다. 특히, 볼륨 복제 또는 스냅샷 시에 데이터 소스로 참조될 수 있다. 또한 해당 PVC 오브젝트는 해당 볼륨의 현재 상태도 가지고 있다.

퍼시스턴트볼륨클레임 이름 정하기

자동으로 생성된 PVC의 이름은 규칙에 따라 정해진다. PVC의 이름은 파드 이름과 볼륨 이름의 사이를 하이픈(-)으로 결합한 형태이다. 위의 예시에서, PVC 이름은 my-app-scratch-volume가 된다. 이렇게 규칙에 의해 정해진 이름은 PVC와의 상호작용을 더 쉽게 만드는데, 이는 파드 이름과 볼륨 이름을 알면 PVC 이름을 별도로 검색할 필요가 없기 때문이다.

PVC 이름 규칙에 따라 서로 다른 파드 간 이름 충돌이 발생할 수 있으며("pod-a" 파드 + "scratch" 볼륨 vs. "pod" 파드 + "a-scratch" 볼륨 - 두 경우 모두 PVC 이름은 "pod-a-scratch") 또한 파드와 수동으로 생성한 PVC 간에도 이름 충돌이 발생할 수 있다.

이러한 충돌은 감지될 수 있는데, 이는 PVC가 파드를 위해 생성된 경우에만 임시 볼륨으로 사용되기 때문이다. 이러한 체크는 소유권 관계를 기반으로 한다. 기존에 존재하던 PVC는 덮어써지거나 수정되지 않는다. 대신에 충돌을 해결해주지는 않는데, 이는 적합한 PVC가 없이는 파드가 시작될 수 없기 때문이다.

보안

GenericEphemeralVolume 기능을 활성화하면 사용자가 파드를 생성할 수 있는 경우 PVC를 간접적으로 생성할 수 있도록 허용하며, 심지어 사용자가 PVC를 직접적으로 만들 수 있는 권한이 없는 경우에도 이를 허용한다. 클러스터 관리자는 이를 명심해야 한다. 이것이 보안 모델에 부합하지 않는다면, 어드미션 웹훅을 사용하여 일반 임시 볼륨을 갖는 파드와 같은 오브젝트를 거부해야 한다.

일반적인 PVC의 네임스페이스 쿼터는 여전히 적용되므로, 사용자가 이 새로운 메카니즘을 사용할 수 있도록 허용되었어도, 다른 정책을 우회하는 데에는 사용할 수 없다.

다음 내용

kubelet이 관리하는 임시 볼륨

로컬 임시 스토리지를 참고한다.

CSI 임시 볼륨

일반 임시 볼륨

5 - 스토리지 클래스

이 문서는 쿠버네티스의 스토리지클래스의 개념을 설명한다. 볼륨퍼시스턴트 볼륨에 익숙해지는 것을 권장한다.

소개

스토리지클래스는 관리자가 제공하는 스토리지의 "classes"를 설명할 수 있는 방법을 제공한다. 다른 클래스는 서비스의 품질 수준 또는 백업 정책, 클러스터 관리자가 정한 임의의 정책에 매핑될 수 있다. 쿠버네티스 자체는 클래스가 무엇을 나타내는지에 대해 상관하지 않는다. 다른 스토리지 시스템에서는 이 개념을 "프로파일"이라고도 한다.

스토리지클래스 리소스

각 스토리지클래스에는 해당 스토리지클래스에 속하는 퍼시스턴트볼륨을 동적으로 프로비저닝 할 때 사용되는 provisioner, parametersreclaimPolicy 필드가 포함된다.

스토리지클래스 오브젝트의 이름은 중요하며, 사용자가 특정 클래스를 요청할 수 있는 방법이다. 관리자는 스토리지클래스 오브젝트를 처음 생성할 때 클래스의 이름과 기타 파라미터를 설정하며, 일단 생성된 오브젝트는 업데이트할 수 없다.

관리자는 특정 클래스에 바인딩을 요청하지 않는 PVC에 대해서만 기본 스토리지클래스를 지정할 수 있다. 자세한 내용은 퍼시스턴트볼륨클레임 섹션을 본다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

프로비저너

각 스토리지클래스에는 PV 프로비저닝에 사용되는 볼륨 플러그인을 결정하는 프로비저너가 있다. 이 필드는 반드시 지정해야 한다.

볼륨 플러그인내부 프로비저너설정 예시
AWSElasticBlockStoreAWS EBS
AzureFileAzure 파일
AzureDiskAzure 디스크
CephFS--
CinderOpenStack Cinder
FC--
FlexVolume--
GCEPersistentDiskGCE PD
iSCSI--
NFS-NFS
RBDCeph RBD
VsphereVolumevSphere
PortworxVolumePortworx 볼륨
Local-Local

여기 목록에서 "내부" 프로비저너를 지정할 수 있다(이 이름은 "kubernetes.io" 가 접두사로 시작하고, 쿠버네티스와 함께 제공된다). 또한, 쿠버네티스에서 정의한 사양을 따르는 독립적인 프로그램인 외부 프로비저너를 실행하고 지정할 수 있다. 외부 프로비저너의 작성자는 코드의 수명, 프로비저너의 배송 방법, 실행 방법, (Flex를 포함한)볼륨 플러그인 등에 대한 완전한 재량권을 가진다. kubernetes-sigs/sig-storage-lib-external-provisioner 리포지터리에는 대량의 사양을 구현하는 외부 프로비저너를 작성하기 위한 라이브러리가 있다. 일부 외부 프로비저너의 목록은 kubernetes-sigs/sig-storage-lib-external-provisioner 리포지터리에 있다.

예를 들어, NFS는 내부 프로비저너를 제공하지 않지만, 외부 프로비저너를 사용할 수 있다. 타사 스토리지 업체가 자체 외부 프로비저너를 제공하는 경우도 있다.

리클레임 정책

스토리지클래스에 의해 동적으로 생성된 퍼시스턴트볼륨은 클래스의 reclaimPolicy 필드에 지정된 리클레임 정책을 가지는데, 이는 Delete 또는 Retain 이 될 수 있다. 스토리지클래스 오브젝트가 생성될 때 reclaimPolicy 가 지정되지 않으면 기본값은 Delete 이다.

수동으로 생성되고 스토리지클래스를 통해 관리되는 퍼시스턴트볼륨에는 생성 시 할당된 리클레임 정책이 있다.

볼륨 확장 허용

기능 상태: Kubernetes v1.11 [beta]

퍼시스턴트볼륨은 확장이 가능하도록 구성할 수 있다. 이 기능을 true 로 설정하면 해당 PVC 오브젝트를 편집하여 볼륨 크기를 조정할 수 있다.

다음 볼륨 유형은 기본 스토리지클래스에서 allowVolumeExpansion 필드가 true로 설정된 경우 볼륨 확장을 지원한다.

Table of Volume types and the version of Kubernetes they require
볼륨 유형요구되는 쿠버네티스 버전
gcePersistentDisk1.11
awsElasticBlockStore1.11
Cinder1.11
rbd1.11
Azure File1.11
Azure Disk1.11
Portworx1.11
FlexVolume1.13
CSI1.14 (alpha), 1.16 (beta)

마운트 옵션

스토리지클래스에 의해 동적으로 생성된 퍼시스턴트볼륨은 클래스의 mountOptions 필드에 지정된 마운트 옵션을 가진다.

만약 볼륨 플러그인이 마운트 옵션을 지원하지 않는데, 마운트 옵션을 지정하면 프로비저닝은 실패한다. 마운트 옵션은 클래스 또는 PV에서 검증되지 않는다. PV 마운트가 유효하지 않으면, 마운트가 실패하게 된다.

볼륨 바인딩 모드

volumeBindingMode 필드는 볼륨 바인딩과 동적 프로비저닝의 시작 시기를 제어한다. 설정되어 있지 않으면, Immediate 모드가 기본으로 사용된다.

Immediate 모드는 퍼시스턴트볼륨클레임이 생성되면 볼륨 바인딩과 동적 프로비저닝이 즉시 발생하는 것을 나타낸다. 토폴로지 제약이 있고 클러스터의 모든 노드에서 전역적으로 접근할 수 없는 스토리지 백엔드의 경우, 파드의 스케줄링 요구 사항에 대한 지식 없이 퍼시스턴트볼륨이 바인딩되거나 프로비저닝된다. 이로 인해 스케줄되지 않은 파드가 발생할 수 있다.

클러스터 관리자는 WaitForFirstConsumer 모드를 지정해서 이 문제를 해결할 수 있는데 이 모드는 퍼시스턴트볼륨클레임을 사용하는 파드가 생성될 때까지 퍼시스턴트볼륨의 바인딩과 프로비저닝을 지연시킨다. 퍼시스턴트볼륨은 파드의 스케줄링 제약 조건에 의해 지정된 토폴로지에 따라 선택되거나 프로비전된다. 여기에는 리소스 요구 사항, 노드 셀렉터, 파드 어피니티(affinity)와 안티-어피니티(anti-affinity) 그리고 테인트(taint)와 톨러레이션(toleration)이 포함된다.

다음 플러그인은 동적 프로비저닝과 WaitForFirstConsumer 를 지원한다.

다음 플러그인은 사전에 생성된 퍼시스턴트볼륨 바인딩으로 WaitForFirstConsumer 를 지원한다.

  • 위에서 언급한 모든 플러그인
  • Local

기능 상태: Kubernetes v1.17 [stable]
CSI 볼륨은 동적 프로비저닝과 사전에 생성된 PV에서도 지원되지만, 지원되는 토폴로지 키와 예시를 보려면 해당 CSI 드라이버에 대한 문서를 본다.

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  nodeSelector:
    kubernetes.io/hostname: kube-01
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

허용된 토폴로지

클러스터 운영자가 WaitForFirstConsumer 볼륨 바인딩 모드를 지정하면, 대부분의 상황에서 더 이상 특정 토폴로지로 프로비저닝을 제한할 필요가 없다. 그러나 여전히 필요한 경우에는 allowedTopologies 를 지정할 수 있다.

이 예시는 프로비전된 볼륨의 토폴로지를 특정 영역으로 제한하는 방법을 보여 주며 지원되는 플러그인의 zonezones 파라미터를 대체하는 데 사용해야 한다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
  - key: failure-domain.beta.kubernetes.io/zone
    values:
    - us-central-1a
    - us-central-1b

파라미터

스토리지 클래스에는 스토리지 클래스에 속하는 볼륨을 설명하는 파라미터가 있다. provisioner 에 따라 다른 파라미터를 사용할 수 있다. 예를 들어, 파라미터 type 에 대한 값 io1 과 파라미터 iopsPerGB 는 EBS에만 사용할 수 있다. 파라미터 생략 시 일부 기본값이 사용된다.

스토리지클래스에 대해 최대 512개의 파라미터를 정의할 수 있다. 키와 값을 포함하여 파라미터 오브젝터의 총 길이는 256 KiB를 초과할 수 없다.

AWS EBS

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4
  • type: io1, gp2, sc1, st1. 자세한 내용은 AWS 문서를 본다. 기본값: gp2.
  • zone (사용 중단(deprecated)): AWS 영역. zonezones 를 지정하지 않으면, 일반적으로 쿠버네티스 클러스터의 노드가 있는 모든 활성화된 영역에 걸쳐 볼륨이 라운드 로빈으로 조정된다. zonezones 파라미터를 동시에 사용해서는 안된다.
  • zones (사용 중단): 쉼표로 구분된 AWS 영역의 목록. zonezones 를 지정하지 않으면, 일반적으로 쿠버네티스 클러스터의 노드가 있는 모든 활성화된 영역에 걸쳐 볼륨이 라운드 로빈으로 조정된다. zonezones 파라미터를 동시에 사용해서는 안된다.
  • iopsPerGB: io1 볼륨 전용이다. 1초당 GiB에 대한 I/O 작업 수이다. AWS 볼륨 플러그인은 요청된 볼륨 크기에 곱셈하여 볼륨의 IOPS를 계산하고 이를 20,000 IOPS로 제한한다(AWS에서 지원하는 최대값으로, AWS 문서를 본다). 여기에는 문자열, 즉 10 이 아닌, "10" 이 필요하다.
  • fsType: fsType은 쿠버네티스에서 지원된다. 기본값: "ext4".
  • encrypted: EBS 볼륨의 암호화 여부를 나타낸다. 유효한 값은 "ture" 또는 "false" 이다. 여기에는 문자열, 즉 true 가 아닌, "true" 가 필요하다.
  • kmsKeyId: 선택 사항. 볼륨을 암호화할 때 사용할 키의 전체 Amazon 리소스 이름이다. 아무것도 제공되지 않지만, encrypted 가 true라면 AWS에 의해 키가 생성된다. 유효한 ARN 값은 AWS 문서를 본다.

GCE PD

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
  fstype: ext4
  replication-type: none
  • type: pd-standard 또는 pd-ssd. 기본값: pd-standard

  • zone (사용 중단): GCE 영역. zonezones 를 모두 지정하지 않으면, 쿠버네티스 클러스터의 노드가 있는 모든 활성화된 영역에 걸쳐 볼륨이 라운드 로빈으로 조정된다. zonezones 파라미터를 동시에 사용해서는 안된다.

  • zones (사용 중단): 쉼표로 구분되는 GCE 영역의 목록. zonezones 를 모두 지정하지 않으면, 쿠버네티스 클러스터의 노드가 있는 모든 활성화된 영역에 걸쳐 볼륨이 라운드 로빈으로 조정된다. zonezones 파라미터를 동시에 사용해서는 안된다.

  • fstype: ext4 또는 xfs. 기본값: ext4. 정의된 파일시스템 유형은 호스트 운영체제에서 지원되어야 한다.

  • replication-type: none 또는 regional-pd. 기본값: none.

replication-typenone 으로 설정하면 (영역) PD가 프로비전된다.

replication-typeregional-pd 로 설정되면, 지역 퍼시스턴트 디스크 가 프로비전된다. 이는 퍼시스턴트볼륨클레임과 스토리지클래스를 소모하는 파드를 생성할 때 지역 퍼시스턴트 디스크는 두개의 영역으로 프로비전되기에 volumeBindingMode: WaitForFirstConsumer 를 설정하는 것을 강력히 권장한다. 하나의 영역은 파드가 스케줄된 영역과 동일하다. 다른 영역은 클러스터에서 사용할 수 있는 영역에서 임의로 선택된다. 디스크 영역은 allowedTopologies 를 사용하면 더 제한할 수 있다.

NFS

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-nfs
provisioner: example.com/external-nfs
parameters:
  server: nfs-server.example.com
  path: /share
  readOnly: "false"
  • server: NFS 서버의 호스트네임 또는 IP 주소.
  • path: NFS 서버가 익스포트(export)한 경로.
  • readOnly: 스토리지를 읽기 전용으로 마운트할지 나타내는 플래그(기본값: false).

쿠버네티스에는 내장 NFS 프로비저너가 없다. NFS를 위한 스토리지클래스를 생성하려면 외부 프로비저너를 사용해야 한다. 예시는 다음과 같다.

OpenStack Cinder

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gold
provisioner: kubernetes.io/cinder
parameters:
  availability: nova
  • availability: 가용성 영역. 지정하지 않으면, 일반적으로 쿠버네티스 클러스터의 노드가 있는 모든 활성화된 영역에 걸쳐 볼륨이 라운드 로빈으로 조정된다.

vSphere

vSphere 스토리지 클래스에는 두 가지 유형의 프로비저닝 도구가 있다.

인-트리 프로비저닝 도구는 사용 중단되었다. CSI 프로비저닝 도구에 대한 자세한 내용은 쿠버네티스 vSphere CSI 드라이버vSphereVolume CSI 마이그레이션을 참고한다.

CSI 프로비저닝 도구

vSphere CSI 스토리지클래스 프로비저닝 도구는 Tanzu 쿠버네티스 클러스터에서 작동한다. 예시는 vSphere CSI 리포지터리를 참조한다.

vCP 프로비저닝 도구

다음 예시에서는 VMware 클라우드 공급자(vCP) 스토리지클래스 프로비저닝 도구를 사용한다.

  1. 사용자 지정 디스크 형식으로 스토리지클래스를 생성한다.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast
    provisioner: kubernetes.io/vsphere-volume
    parameters:
      diskformat: zeroedthick
    

    diskformat: thin, zeroedthickeagerzeroedthick. 기본값: "thin".

  2. 사용자 지정 데이터스토어에 디스크 형식으로 스토리지클래스를 생성한다.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast
    provisioner: kubernetes.io/vsphere-volume
    parameters:
        diskformat: zeroedthick
        datastore: VSANDatastore
    

    datastore: 또한, 사용자는 스토리지클래스에서 데이터스토어를 지정할 수 있다. 볼륨은 스토리지클래스에 지정된 데이터스토어에 생성되며, 이 경우 VSANDatastore 이다. 이 필드는 선택 사항이다. 데이터스토어를 지정하지 않으면, vSphere 클라우드 공급자를 초기화하는데 사용되는 vSphere 설정 파일에 지정된 데이터스토어에 볼륨이 생성된다.

  3. 쿠버네티스 내부 스토리지 정책을 관리한다.

    • 기존 vCenter SPBM 정책을 사용한다.

      vSphere 스토리지 관리의 가장 중요한 기능 중 하나는 정책 기반 관리이다. 스토리지 정책 기반 관리(Storage Policy Based Management (SPBM))는 광범위한 데이터 서비스와 스토리지 솔루션에서 단일 통합 컨트롤 플레인을 제공하는 스토리지 정책 프레임워크이다. SPBM을 통해 vSphere 관리자는 용량 계획, 차별화된 서비스 수준과 용량의 헤드룸(headroom) 관리와 같은 선행 스토리지 프로비저닝 문제를 극복할 수 있다.

      SPBM 정책은 storagePolicyName 파라미터를 사용하면 스토리지클래스에서 지정할 수 있다.

    • 쿠버네티스 내부의 가상 SAN 정책 지원

      Vsphere 인프라스트럭처(Vsphere Infrastructure (VI)) 관리자는 동적 볼륨 프로비저닝 중에 사용자 정의 가상 SAN 스토리지 기능을 지정할 수 있다. 이제 동적 볼륨 프로비저닝 중에 스토리지 기능의 형태로 성능 및 가용성과 같은 스토리지 요구 사항을 정의할 수 있다. 스토리지 기능 요구 사항은 가상 SAN 정책으로 변환된 퍼시스턴트 볼륨(가상 디스크)을 생성할 때 가상 SAN 계층으로 푸시된다. 가상 디스크는 가상 SAN 데이터 스토어에 분산되어 요구 사항을 충족시키게 된다.

      퍼시스턴트 볼륨 관리에 스토리지 정책을 사용하는 방법에 대한 자세한 내용은 볼륨의 동적 프로비저닝을 위한 스토리지 정책 기반 관리(SPBM)를 참조한다.

vSphere용 쿠버네티스 내에서 퍼시스턴트 볼륨 관리를 시도하는 vSphere 예시는 거의 없다.

Ceph RBD

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/rbd
parameters:
  monitors: 10.16.153.105:6789
  adminId: kube
  adminSecretName: ceph-secret
  adminSecretNamespace: kube-system
  pool: kube
  userId: kube
  userSecretName: ceph-secret-user
  userSecretNamespace: default
  fsType: ext4
  imageFormat: "2"
  imageFeatures: "layering"
  • monitors: 쉼표로 구분된 Ceph 모니터. 이 파라미터는 필수이다.

  • adminId: 풀에 이미지를 생성할 수 있는 Ceph 클라이언트 ID. 기본값은 "admin".

  • adminSecretName: adminId 의 시크릿 이름. 이 파라미터는 필수이다. 제공된 시크릿은 "kubernetes.io/rbd" 유형이어야 한다.

  • adminSecretNamespace: adminSecretName 의 네임스페이스. 기본값은 "default".

  • pool: Ceph RBD 풀. 기본값은 "rbd".

  • userId: RBD 이미지를 매핑하는 데 사용하는 Ceph 클라이언트 ID. 기본값은 adminId 와 동일하다.

  • userSecretName: RDB 이미지를 매핑하기 위한 userId 에 대한 Ceph 시크릿 이름. PVC와 동일한 네임스페이스에 존재해야 한다. 이 파라미터는 필수이다. 제공된 시크릿은 "kubernetes.io/rbd" 유형이어야 하며, 다음의 예시와 같이 생성되어야 한다.

    kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \
      --from-literal=key='QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ==' \
      --namespace=kube-system
    
  • userSecretNamespace: userSecretName 의 네임스페이스.

  • fsType: 쿠버네티스가 지원하는 fsType. 기본값: "ext4".

  • imageFormat: Ceph RBD 이미지 형식, "1" 또는 "2". 기본값은 "2".

  • imageFeatures: 이 파라미터는 선택 사항이며, imageFormat 을 "2"로 설정한 경우에만 사용해야 한다. 현재 layering 에서만 기능이 지원된다. 기본값은 ""이며, 기능이 설정되어 있지 않다.

Azure 디스크

Azure 비관리 디스크 스토리지 클래스

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/azure-disk
parameters:
  skuName: Standard_LRS
  location: eastus
  storageAccount: azure_storage_account_name
  • skuName: Azure 스토리지 계정 Sku 계층. 기본값은 없음.
  • location: Azure 스토리지 계정 지역. 기본값은 없음.
  • storageAccount: Azure 스토리지 계정 이름. 스토리지 계정이 제공되면, 클러스터와 동일한 리소스 그룹에 있어야 하며, location 은 무시된다. 스토리지 계정이 제공되지 않으면, 클러스터와 동일한 리소스 그룹에 새 스토리지 계정이 생성된다.

Azure 디스크 스토리지 클래스(v1.7.2부터 제공)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/azure-disk
parameters:
  storageaccounttype: Standard_LRS
  kind: managed
  • storageaccounttype: Azure 스토리지 계정 Sku 계층. 기본값은 없음.
  • kind: 가능한 값은 shared, dedicated, 그리고 managed (기본값) 이다. kindshared 인 경우, 모든 비관리 디스크는 클러스터와 동일한 리소스 그룹에 있는 몇 개의 공유 스토리지 계정에 생성된다. kinddedicated 인 경우, 클러스터와 동일한 리소스 그룹에서 새로운 비관리 디스크에 대해 새로운 전용 스토리지 계정이 생성된다. kindmanaged 인 경우, 모든 관리 디스크는 클러스터와 동일한 리소스 그룹에 생성된다.
  • resourceGroup: Azure 디스크를 만들 리소스 그룹을 지정한다. 기존에 있는 리소스 그룹 이름이어야 한다. 지정되지 않는 경우, 디스크는 현재 쿠버네티스 클러스터와 동일한 리소스 그룹에 배치된다.
  • 프리미엄 VM은 표준 LRS(Standard_LRS)와 프리미엄 LRS(Premium_LRS) 디스크를 모두 연결할 수 있는 반면에, 표준 VM은 표준 LRS(Standard_LRS) 디스크만 연결할 수 있다.
  • 관리되는 VM은 관리되는 디스크만 연결할 수 있고, 비관리 VM은 비관리 디스크만 연결할 수 있다.

Azure 파일

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azurefile
provisioner: kubernetes.io/azure-file
parameters:
  skuName: Standard_LRS
  location: eastus
  storageAccount: azure_storage_account_name
  • skuName: Azure 스토리지 계정 Sku 계층. 기본값은 없음.
  • location: Azure 스토리지 계정 지역. 기본값은 없음.
  • storageAccount: Azure 스토리지 계정 이름. 기본값은 없음. 스토리지 계정이 제공되지 않으면, 리소스 그룹과 관련된 모든 스토리지 계정이 검색되어 skuNamelocation 이 일치하는 것을 찾는다. 스토리지 계정이 제공되면, 클러스터와 동일한 리소스 그룹에 있어야 하며 skuNamelocation 은 무시된다.
  • secretNamespace: Azure 스토리지 계정 이름과 키가 포함된 시크릿 네임스페이스. 기본값은 파드와 동일하다.
  • secretName: Azure 스토리지 계정 이름과 키가 포함된 시크릿 이름. 기본값은 azure-storage-account-<accountName>-secret
  • readOnly: 스토리지가 읽기 전용으로 마운트되어야 하는지 여부를 나타내는 플래그. 읽기/쓰기 마운트를 의미하는 기본값은 false. 이 설정은 볼륨마운트(VolumeMounts)의 ReadOnly 설정에도 영향을 준다.

스토리지 프로비저닝 중에 마운트 자격증명에 대해 secretName 이라는 시크릿이 생성된다. 클러스터에 RBAC컨트롤러의 롤(role)들을 모두 활성화한 경우, clusterrole system:controller:persistent-volume-binder 에 대한 secret 리소스에 create 권한을 추가한다.

다중 테넌시 컨텍스트에서 secretNamespace 의 값을 명시적으로 설정하는 것을 권장하며, 그렇지 않으면 다른 사용자가 스토리지 계정 자격증명을 읽을 수 있기 때문이다.

Portworx 볼륨

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: portworx-io-priority-high
provisioner: kubernetes.io/portworx-volume
parameters:
  repl: "1"
  snap_interval:   "70"
  priority_io:  "high"
  • fs: 배치할 파일 시스템: none/xfs/ext4 (기본값: ext4)
  • block_size: Kbytes 단위의 블록 크기(기본값: 32).
  • repl: 레플리케이션 팩터 1..3 (기본값: 1)의 형태로 제공될 동기 레플리카의 수. 여기에는 문자열, 즉 0 이 아닌, "0" 이 필요하다.
  • priority_io: 볼륨이 고성능 또는 우선 순위가 낮은 스토리지에서 생성될 것인지를 결정한다 high/medium/low (기본값: low).
  • snap_interval: 스냅샷을 트리거할 때의 시각/시간 간격(분). 스냅샷은 이전 스냅샷과의 차이에 따라 증분되며, 0은 스냅을 비활성화 한다(기본값: 0). 여기에는 문자열, 즉 70 이 아닌, "70" 이 필요하다.
  • aggregation_level: 볼륨이 분배될 청크 수를 지정하며, 0은 집계되지 않은 볼륨을 나타낸다(기본값: 0). 여기에는 문자열, 즉 0 이 아닌, "0" 이 필요하다.
  • ephemeral: 마운트 해제 후 볼륨을 정리해야 하는지 혹은 지속적이어야 하는지를 지정한다. emptyDir 에 대한 유스케이스는 이 값을 true로 설정할 수 있으며, persistent volumes 에 대한 유스케이스인 카산드라와 같은 데이터베이스는 false로 설정해야 한다. true/false (기본값 false) 여기에는 문자열, 즉 true 가 아닌, "true" 가 필요하다.

Local

기능 상태: Kubernetes v1.14 [stable]
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

로컬 볼륨은 현재 동적 프로비저닝을 지원하지 않지만, 파드 스케줄링까지 볼륨 바인딩을 지연시키기 위해서는 스토리지클래스가 여전히 생성되어야 한다. 이것은 WaitForFirstConsumer 볼륨 바인딩 모드에 의해 지정된다.

볼륨 바인딩을 지연시키면 스케줄러가 퍼시스턴트볼륨클레임에 적절한 퍼시스턴트볼륨을 선택할 때 파드의 모든 스케줄링 제약 조건을 고려할 수 있다.

6 - 동적 볼륨 프로비저닝

동적 볼륨 프로비저닝을 통해 온-디맨드 방식으로 스토리지 볼륨을 생성할 수 있다. 동적 프로비저닝이 없으면 클러스터 관리자는 클라우드 또는 스토리지 공급자에게 수동으로 요청해서 새 스토리지 볼륨을 생성한 다음, 쿠버네티스에 표시하기 위해 PersistentVolume 오브젝트를 생성해야 한다. 동적 프로비저닝 기능을 사용하면 클러스터 관리자가 스토리지를 사전 프로비저닝 할 필요가 없다. 대신 사용자가 스토리지를 요청하면 자동으로 프로비저닝 한다.

배경

동적 볼륨 프로비저닝의 구현은 storage.k8s.io API 그룹의 StorageClass API 오브젝트를 기반으로 한다. 클러스터 관리자는 볼륨을 프로비전하는 볼륨 플러그인 (프로비저너라고도 알려짐)과 프로비저닝시에 프로비저너에게 전달할 파라미터 집합을 지정하는 StorageClass 오브젝트를 필요한 만큼 정의할 수 있다. 클러스터 관리자는 클러스터 내에서 사용자 정의 파라미터 집합을 사용해서 여러 가지 유형의 스토리지 (같거나 다른 스토리지 시스템들)를 정의하고 노출시킬 수 있다. 또한 이 디자인을 통해 최종 사용자는 스토리지 프로비전 방식의 복잡성과 뉘앙스에 대해 걱정할 필요가 없다. 하지만, 여전히 여러 스토리지 옵션들을 선택할 수 있다.

스토리지 클래스에 대한 자세한 정보는 여기에서 찾을 수 있다.

동적 프로비저닝 활성화하기

동적 프로비저닝을 활성화하려면 클러스터 관리자가 사용자를 위해 하나 이상의 스토리지클래스(StorageClass) 오브젝트를 사전 생성해야 한다. 스토리지클래스 오브젝트는 동적 프로비저닝이 호출될 때 사용할 프로비저너와 해당 프로비저너에게 전달할 파라미터를 정의한다. 스토리지클래스 오브젝트의 이름은 유효한 DNS 서브도메인 이름이어야 한다.

다음 매니페스트는 표준 디스크와 같은 퍼시스턴트 디스크를 프로비전하는 스토리지 클래스 "slow"를 만든다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard

다음 매니페스트는 SSD와 같은 퍼시스턴트 디스크를 프로비전하는 스토리지 클래스 "fast"를 만든다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

동적 프로비저닝 사용하기

사용자는 PersistentVolumeClaim 에 스토리지 클래스를 포함시켜 동적으로 프로비전된 스토리지를 요청한다. 쿠버네티스 v1.6 이전에는 volume.beta.kubernetes.io/storage-class 어노테이션을 통해 수행되었다. 그러나 이 어노테이션은 v1.9부터는 더 이상 사용하지 않는다. 사용자는 이제 PersistentVolumeClaim 오브젝트의 storageClassName 필드를 사용해야 한다. 이 필드의 값은 관리자가 구성한 StorageClass 의 이름과 일치해야 한다. (아래를 참고)

예를 들어 "fast" 스토리지 클래스를 선택하려면 다음과 같은 PersistentVolumeClaim 을 생성한다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi

이 클레임의 결과로 SSD와 같은 퍼시스턴트 디스크가 자동으로 프로비전 된다. 클레임이 삭제되면 볼륨이 삭제된다.

기본 동작

스토리지 클래스가 지정되지 않은 경우 모든 클레임이 동적으로 프로비전이 되도록 클러스터에서 동적 프로비저닝을 활성화 할 수 있다. 클러스터 관리자는 이 방법으로 활성화 할 수 있다.

관리자는 storageclass.kubernetes.io/is-default-class 어노테이션을 추가하여 특정 StorageClass 를 기본으로 표시할 수 있다. 기본 StorageClass 가 클러스터에 존재하고 사용자가 storageClassName 를 지정하지 않은 PersistentVolumeClaim 을 작성하면, DefaultStorageClass 어드미션 컨트롤러가 디폴트 스토리지 클래스를 가리키는 storageClassName 필드를 자동으로 추가한다.

클러스터에는 최대 하나의 default 스토리지 클래스가 있을 수 있다. 그렇지 않은 경우 storageClassName 을 명시적으로 지정하지 않은 PersistentVolumeClaim 을 생성할 수 없다.

토폴로지 인식

다중 영역 클러스터에서 파드는 한 지역 내 여러 영역에 걸쳐 분산될 수 있다. 파드가 예약된 영역에서 단일 영역 스토리지 백엔드를 프로비전해야 한다. 볼륨 바인딩 모드를 설정해서 수행할 수 있다.

7 - 볼륨 스냅샷

쿠버네티스에서 VolumeSnapshot 은 스토리지 시스템 볼륨 스냅샷을 나타낸다. 이 문서는 이미 쿠버네티스 퍼시스턴트 볼륨에 대해 잘 알고 있다고 가정한다.

소개

API 리소스 PersistentVolumePersistentVolumeClaim 가 사용자와 관리자를 위해 볼륨을 프로비전할 때 사용되는 것과 유사하게, VolumeSnapshotContentVolumeSnapshot API 리소스는 사용자와 관리자를 위한 볼륨 스냅샷을 생성하기 위해 제공된다.

VolumeSnapshotContent 는 관리자가 프로비져닝한 클러스터 내 볼륨의 스냅샷이다. 퍼시스턴트볼륨이 클러스터 리소스인 것처럼 이것 또한 클러스터 리소스이다.

VolumeSnapshot 은 사용자가 볼륨의 스냅샷을 요청할 수 있는 방법이다. 이는 퍼시스턴트볼륨클레임과 유사하다.

VolumeSnapshotClass 을 사용하면 VolumeSnapshot 에 속한 다른 속성을 지정할 수 있다. 이러한 속성은 스토리지 시스템에의 동일한 볼륨에서 가져온 스냅샷마다 다를 수 있으므로 PersistentVolumeClaim 의 동일한 StorageClass 를 사용하여 표현할 수는 없다.

볼륨 스냅샷은 쿠버네티스 사용자에게 완전히 새로운 볼륨을 생성하지 않고도 특정 시점에 볼륨의 콘텐츠를 복사하는 표준화된 방법을 제공한다. 예를 들어, 데이터베이스 관리자는 이 기능을 사용하여 수정 사항을 편집 또는 삭제하기 전에 데이터베이스를 백업할 수 있다.

사용자는 이 기능을 사용할 때 다음 사항을 알고 있어야 한다.

  • API 오브젝트인 VolumeSnapshot, VolumeSnapshotContent, VolumeSnapshotClass 는 핵심 API가 아닌, CRDs 이다.
  • VolumeSnapshot 은 CSI 드라이버에서만 사용할 수 있다.
  • 쿠버네티스 팀은 VolumeSnapshot 의 배포 프로세스 일부로써, 컨트롤 플레인에 배포할 스냅샷 컨트롤러와 CSI 드라이버와 함께 배포할 csi-snapshotter라는 사이드카 헬퍼(helper) 컨테이너를 제공한다. 스냅샷 컨트롤러는 VolumeSnapshotVolumeSnapshotContent 오브젝트를 관찰하고 VolumeSnapshotContent 오브젝트의 생성 및 삭제에 대한 책임을 진다. 사이드카 csi-snapshotter는 VolumeSnapshotContent 오브젝트를 관찰하고 CSI 엔드포인트에 대해 CreateSnapshotDeleteSnapshot 을 트리거(trigger)한다.
  • 스냅샷 오브젝트에 대한 강화된 검증을 제공하는 검증 웹훅 서버도 있다. 이는 CSI 드라이버가 아닌 스냅샷 컨트롤러 및 CRD와 함께 쿠버네티스 배포판에 의해 설치되어야 한다. 스냅샷 기능이 활성화된 모든 쿠버네티스 클러스터에 설치해야 한다.
  • CSI 드라이버에서의 볼륨 스냅샷 기능 유무는 확실하지 않다. 볼륨 스냅샷 서포트를 제공하는 CSI 드라이버는 csi-snapshotter를 사용할 가능성이 높다. 자세한 사항은 CSI 드라이버 문서를 확인하면 된다.
  • CRDs 및 스냅샷 컨트롤러는 쿠버네티스 배포 시 설치된다.

볼륨 스냅샷 및 볼륨 스냅샷 컨텐츠의 라이프사이클

VolumeSnapshotContents 은 클러스터 리소스이다. VolumeSnapshots 은 이러한 리소스의 요청이다. VolumeSnapshotContentsVolumeSnapshots의 상호 작용은 다음과 같은 라이프사이클을 따른다.

프로비저닝 볼륨 스냅샷

스냅샷을 프로비저닝할 수 있는 방법에는 사전 프로비저닝 혹은 동적 프로비저닝의 두 가지가 있다: .

사전 프로비전

클러스터 관리자는 많은 VolumeSnapshotContents 을 생성한다. 그들은 클러스터 사용자들이 사용 가능한 스토리지 시스템의 실제 볼륨 스냅샷 세부 정보를 제공한다. 이것은 쿠버네티스 API에 있고 사용 가능하다.

동적

사전 프로비저닝을 사용하는 대신 퍼시스턴트볼륨클레임에서 스냅샷을 동적으로 가져오도록 요청할 수 있다. 볼륨스냅샷클래스는 스냅샷 실행 시 스토리지 제공자의 특정 파라미터를 명세한다.

바인딩

스냅샷 컨트롤러는 사전 프로비저닝과 동적 프로비저닝된 시나리오에서 VolumeSnapshot 오브젝트와 적절한 VolumeSnapshotContent 오브젝트와의 바인딩을 처리한다. 바인딩은 1:1 매핑이다.

사전 프로비저닝된 경우, 볼륨스냅샷은 요청된 볼륨스냅샷컨텐츠 오브젝트가 생성될 때까지 바인드되지 않은 상태로 유지된다.

스냅샷 소스 보호로서의 퍼시스턴트 볼륨 클레임

이 보호의 목적은 스냅샷이 생성되는 동안 사용 중인 퍼시스턴트볼륨클레임 API 오브젝트가 시스템에서 지워지지 않게 하는 것이다 (데이터 손실이 발생할 수 있기 때문에).

퍼시스턴트볼륨클레임이 스냅샷을 생성할 동안에는 해당 퍼시스턴트볼륨클레임은 사용 중인 상태이다. 스냅샷 소스로 사용 중인 퍼시스턴트볼륨클레임 API 오브젝트를 삭제한다면, 퍼시스턴트볼륨클레임 오브젝트는 즉시 삭제되지 않는다. 대신, 퍼시스턴트볼륨클레임 오브젝트 삭제는 스냅샷이 준비(readyToUse) 혹은 중단(aborted) 상태가 될 때까지 연기된다.

삭제

VolumeSnapshot 를 삭제하면 삭제 과정이 트리거되고, DeletionPolicy 가 이어서 실행된다. DeletionPolicyDelete 라면, 기본 스토리지 스냅샷이 VolumeSnapshotContent 오브젝트와 함께 삭제될 것이다. DeletionPolicyRetain 이라면, 기본 스트리지 스냅샷과 VolumeSnapshotContent 둘 다 유지된다.

볼륨 스냅샷

각각의 볼륨 스냅샷은 스펙과 상태를 포함한다.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: new-snapshot-test
spec:
  volumeSnapshotClassName: csi-hostpath-snapclass
  source:
    persistentVolumeClaimName: pvc-test

persistentVolumeClaimName 은 스냅샷을 위한 퍼시스턴트볼륨클레임 데이터 소스의 이름이다. 이 필드는 동적 프로비저닝 스냅샷이 필요하다.

볼륨 스냅샷은 volumeSnapshotClassName 속성을 사용하여 볼륨스냅샷클래스의 이름을 지정하여 특정 클래스를 요청할 수 있다. 아무것도 설정하지 않으면, 사용 가능한 경우 기본 클래스가 사용될 것이다.

사전 프로비저닝된 스냅샷의 경우, 다음 예와 같이 volumeSnapshotContentName을 스냅샷 소스로 지정해야 한다. 사전 프로비저닝된 스냅샷에는 volumeSnapshotContentName 소스 필드가 필요하다.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: test-snapshot
spec:
  source:
    volumeSnapshotContentName: test-content

볼륨 스냅샷 컨텐츠

각각의 볼륨스냅샷컨텐츠는 스펙과 상태를 포함한다. 동적 프로비저닝에서는, 스냅샷 공통 컨트롤러는 VolumeSnapshotContent 오브젝트를 생성한다. 예시는 다음과 같다.

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotContent
metadata:
  name: snapcontent-72d9a349-aacd-42d2-a240-d775650d2455
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    volumeHandle: ee0cfb94-f8d4-11e9-b2d8-0242ac110002
  sourceVolumeMode: Filesystem
  volumeSnapshotClassName: csi-hostpath-snapclass
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default
    uid: 72d9a349-aacd-42d2-a240-d775650d2455

volumeHandle 은 스토리지 백엔드에서 생성되고 볼륨 생성 중에 CSI 드라이버가 반환하는 볼륨의 고유 식별자이다. 이 필드는 스냅샷을 동적 프로비저닝하는 데 필요하다. 이것은 스냅샷의 볼륨 소스를 지정한다.

사전 프로비저닝된 스냅샷의 경우, (클러스터 관리자로서) 다음과 같이 VolumeSnapshotContent 오브젝트를 생성해야 한다.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  name: new-snapshot-content-test
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
  sourceVolumeMode: Filesystem
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default

snapshotHandle 은 스토리지 백엔드에서 생성된 볼륨 스냅샷의 고유 식별자이다. 이 필드는 사전 프로비저닝된 스냅샷에 필요하다. VolumeSnapshotContent 가 나타내는 스토리지 시스템의 CSI 스냅샷 id를 지정한다.

sourceVolumeMode 은 스냅샷이 생성된 볼륨의 모드를 나타낸다. sourceVolumeMode 필드의 값은 Filesystem 또는 Block 일 수 있다. 소스 볼륨 모드가 명시되어 있지 않으면, 쿠버네티스는 해당 스냅샷의 소스 볼륨 모드를 알려지지 않은 상태(unknown)로 간주하여 스냅샷을 처리한다.

volumeSnapshotRef은 상응하는 VolumeSnapshot의 참조이다. VolumeSnapshotContent이 이전에 프로비전된 스냅샷으로 생성된 경우, volumeSnapshotRef에서 참조하는 VolumeSnapshot은 아직 존재하지 않을 수도 있음에 주의한다.

스냅샷의 볼륨 모드 변환하기

클러스터에 설치된 VolumeSnapshots API가 sourceVolumeMode 필드를 지원한다면, 인증되지 않은 사용자가 볼륨의 모드를 변경하는 것을 금지하는 기능이 API에 있는 것이다.

클러스터가 이 기능을 지원하는지 확인하려면, 다음 명령어를 실행한다.

$ kubectl get crd volumesnapshotcontent -o yaml

사용자가 기존 VolumeSnapshot으로부터 PersistentVolumeClaim을 생성할 때 기존 소스와 다른 볼륨 모드를 지정할 수 있도록 하려면, VolumeSnapshot와 연관된 VolumeSnapshotContentsnapshot.storage.kubernetes.io/allowVolumeModeChange: "true" 어노테이션을 추가해야 한다.

이전에 프로비전된 스냅샷의 경우에는, 클러스터 관리자가 spec.sourceVolumeMode를 추가해야 한다.

이 기능이 활성화된 예시 VolumeSnapshotContent 리소스는 다음과 같을 것이다.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  name: new-snapshot-content-test
  annotations:
    - snapshot.storage.kubernetes.io/allowVolumeModeChange: "true"
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
  sourceVolumeMode: Filesystem
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default

스냅샷을 위한 프로비저닝 볼륨

PersistentVolumeClaim 오브젝트의 dataSource 필드를 사용하여 스냅샷 데이터로 미리 채워진 새 볼륨을 프로비저닝할 수 있다.

보다 자세한 사항은 볼륨 스냅샷 및 스냅샷에서 볼륨 복원에서 확인할 수 있다.

8 - 볼륨 스냅샷 클래스

이 문서는 쿠버네티스의 볼륨스냅샷클래스(VolumeSnapshotClass) 개요를 설명한다. 볼륨 스냅샷스토리지 클래스의 숙지를 추천한다.

소개

스토리지클래스(StorageClass)는 관리자가 볼륨을 프로비저닝할 때 제공하는 스토리지의 "클래스"를 설명하는 방법을 제공하는 것처럼, 볼륨스냅샷클래스는 볼륨 스냅샷을 프로비저닝할 때 스토리지의 "클래스"를 설명하는 방법을 제공한다.

VolumeSnapshotClass 리소스

각 볼륨스냅샷클래스에는 클래스에 속하는 볼륨스냅샷을 동적으로 프로비전 할 때 사용되는 driver, deletionPolicy 그리고 parameters 필드를 포함한다.

볼륨스냅샷클래스 오브젝트의 이름은 중요하며, 사용자가 특정 클래스를 요청할 수 있는 방법이다. 관리자는 볼륨스냅샷클래스 오브젝트를 처음 생성할 때 클래스의 이름과 기타 파라미터를 설정하고, 오브젝트가 생성된 이후에는 업데이트할 수 없다.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-hostpath-snapclass
driver: hostpath.csi.k8s.io
deletionPolicy: Delete
parameters:

관리자는snapshot.storage.kubernetes.io/is-default-class: "true" 어노테이션을 추가하여 바인딩할 특정 클래스를 요청하지 않는 볼륨스냅샷에 대한 기본 볼륨스냅샷클래스를 지정할 수 있다.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-hostpath-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
driver: hostpath.csi.k8s.io
deletionPolicy: Delete
parameters:

드라이버

볼륨 스냅샷 클래스에는 볼륨스냅샷의 프로비저닝에 사용되는 CSI 볼륨 플러그인을 결정하는 드라이버를 가지고 있다. 이 필드는 반드시 지정해야 한다.

삭제정책(DeletionPolicy)

볼륨 스냅샷 클래스는 삭제정책을 가지고 있다. 바인딩된 볼륨스냅샷 오브젝트를 삭제할 때 VolumeSnapshotContent의 상황을 구성할 수 있다. 볼륨 스냅샷 클래스의 삭제정책은 Retain 또는 Delete 일 수 있다. 이 필드는 반드시 지정해야 한다.

삭제정책이 Delete 인 경우 기본 스토리지 스냅샷이 VolumeSnapshotContent 오브젝트와 함께 삭제된다. 삭제정책이 Retain 인 경우 기본 스냅샷과 VolumeSnapshotContent 모두 유지된다.

파라미터

볼륨 스냅샷 클래스에는 볼륨 스냅샷 클래스에 속하는 볼륨 스냅샷을 설명하는 파라미터를 가지고 있다. driver 에 따라 다른 파라미터를 사용할 수 있다.

9 - CSI 볼륨 복제하기

이 문서에서는 쿠버네티스의 기존 CSI 볼륨 복제의 개념을 설명한다. 볼륨을 숙지하는 것을 추천한다.

소개

CSI 볼륨 복제 기능은 dataSource 필드에 기존 PVC를 지정하는 지원을 추가해서 사용자가 볼륨(Volume)을 복제하려는 것을 나타낸다.

복제는 표준 볼륨처럼 소비할 수 있는 쿠버네티스 볼륨의 복제본으로 정의된다. 유일한 차이점은 프로비저닝할 때 "새" 빈 볼륨을 생성하는 대신에 백엔드 장치가 지정된 볼륨의 정확한 복제본을 생성한다는 것이다.

쿠버네티스 API의 관점에서 복제를 구현하면 새로운 PVC 생성 중에 기존 PVC를 데이터 소스로 지정할 수 있는 기능이 추가된다. 소스 PVC는 바인딩되어 있고, 사용 가능해야 한다(사용 중이 아니어야 함).

사용자는 이 기능을 사용할 때 다음 사항을 알고 있어야 한다.

  • 복제 지원(VolumePVCDataSource)은 CSI 드라이버에서만 사용할 수 있다.
  • 복제 지원은 동적 프로비저너만 사용할 수 있다.
  • CSI 드라이버는 볼륨 복제 기능을 구현했거나 구현하지 않았을 수 있다.
  • PVC는 대상 PVC와 동일한 네임스페이스에 있는 경우에만 복제할 수 있다(소스와 대상은 동일한 네임스페이스에 있어야 함).
  • 복제는 서로 다른 스토리지 클래스에 대해서도 지원된다.
    • 대상 볼륨은 소스와 동일하거나 다른 스토리지 클래스여도 된다.
    • 기본 스토리지 클래스를 사용할 수 있으며, 사양에 storageClassName을 생략할 수 있다.
  • 동일한 VolumeMode 설정을 사용하는 두 볼륨에만 복제를 수행할 수 있다(블록 모드 볼륨을 요청하는 경우에는 반드시 소스도 블록 모드여야 한다).

프로비저닝

동일한 네임스페이스에서 기존 PVC를 참조하는 dataSource를 추가하는 것을 제외하고는 다른 PVC와 마찬가지로 복제가 프로비전된다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: clone-of-pvc-1
    namespace: myns
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: cloning
  resources:
    requests:
      storage: 5Gi
  dataSource:
    kind: PersistentVolumeClaim
    name: pvc-1

그 결과로 지정된 소스 pvc-1 과 동일한 내용을 가진 clone-of-pvc-1 이라는 이름을 가지는 새로운 PVC가 생겨난다.

사용

새 PVC를 사용할 수 있게 되면, 복제된 PVC는 다른 PVC와 동일하게 소비된다. 또한, 이 시점에서 새롭게 생성된 PVC는 독립된 오브젝트이다. 원본 dataSource PVC와는 무관하게 독립적으로 소비하고, 복제하고, 스냅샷의 생성 또는 삭제를 할 수 있다. 이는 소스가 새롭게 생성된 복제본에 어떤 방식으로든 연결되어 있지 않으며, 새롭게 생성된 복제본에 영향 없이 수정하거나, 삭제할 수도 있는 것을 의미한다.

10 - 스토리지 용량

스토리지 용량은 제한이 있으며, 파드가 실행되는 노드의 상황에 따라 달라질 수 있다. 예를 들어, 일부 노드에서 NAS(Network Attached Storage)에 접근할 수 없는 경우가 있을 수 있으며, 또는 각 노드에 종속적인 로컬 스토리지를 사용하는 경우일 수도 있다.

기능 상태: Kubernetes v1.24 [stable]

이 페이지에서는 쿠버네티스가 어떻게 스토리지 용량을 추적하고 스케줄러가 남아 있는 볼륨을 제공하기 위해 스토리지 용량이 충분한 노드에 파드를 스케줄링하기 위해 이 정보를 어떻게 사용하는지 설명한다. 스토리지 용량을 추적하지 않으면, 스케줄러는 볼륨을 제공할 충분한 용량이 없는 노드를 선정할 수 있으며, 스케줄링을 여러 번 다시 시도해야 한다.

시작하기 전에

쿠버네티스 v1.30 버전은 스토리지 용량 추적을 위한 클러스터-수준 API를 지원한다. 이를 사용하려면, 스토리지 용량 추적을 지원하는 CSI 드라이버를 사용하고 있어야 한다. 사용 중인 CSI 드라이버가 이를 지원하는지, 지원한다면 어떻게 사용하는지를 알아보려면 해당 CSI 드라이버의 문서를 참고한다. 쿠버네티스 v1.30 버전을 사용하고 있지 않다면, 해당 버전 쿠버네티스 문서를 참고한다.

API

이 기능에는 다음 두 가지 API 확장이 있다.

  • CSIStorageCapacity 오브젝트: CSI 드라이버가 설치된 네임스페이스에 CSI 드라이버가 이 오브젝트를 생성한다. 각 오브젝트는 하나의 스토리지 클래스에 대한 용량 정보를 담고 있으며, 어떤 노드가 해당 스토리지에 접근할 수 있는지를 정의한다.
  • CSIDriverSpec.StorageCapacity 필드: true로 설정하면, 쿠버네티스 스케줄러가 CSI 드라이버를 사용하는 볼륨의 스토리지 용량을 고려하게 된다.

스케줄링

다음과 같은 경우 쿠버네티스 스케줄러에서 스토리지 용량 정보를 사용한다.

  • 파드가 아직 생성되지 않은 볼륨을 사용하고,
  • 해당 볼륨은 CSI 드라이버를 참조하고 WaitForFirstConsumer 볼륨 바인딩 모드를 사용하는 스토리지클래스(StorageClass)를 사용하고,
  • 드라이버의 CSIDriver 오브젝트에 StorageCapacity 속성이 true로 설정되어 있다.

이 경우 스케줄러는 파드에 제공할 충분한 스토리지가 있는 노드만 고려한다. 이 검사는 아주 간단한데, 볼륨의 크기를 노드를 포함하는 토폴로지를 가진 CSIStorageCapacity 오브젝트에 나열된 용량과 비교한다.

볼륨 바인딩 모드가 Immediate 인 볼륨의 경우에는 스토리지 드라이버는 볼륨을 사용하는 파드와 관계없이 볼륨을 생성할 위치를 정한다. 볼륨을 생성한 후에, 스케줄러는 볼륨을 사용할 수 있는 노드에 파드를 스케줄링한다.

CSI 임시 볼륨의 경우에는 볼륨 유형이 로컬 볼륨이고 큰 자원이 필요하지 않은 특정 CSI 드라이버에서만 사용된다는 가정하에, 항상 스토리지 용량을 고려하지 않고 스케줄링한다.

리스케줄링

WaitForFirstConsumer 볼륨을 가진 파드에 대해 노드가 선정되었더라도 아직은 잠정적인 결정이다. 다음 단계에서 선정한 노드에서 볼륨을 사용할 수 있어야 한다는 힌트를 주고 CSI 스토리지 드라이버에 볼륨 생성을 요청한다

쿠버네티스는 시간이 지난 스토리지 용량 정보를 기반으로 노드를 선정할 수도 있으므로, 볼륨을 실제로 생성하지 않을 수도 있다. 그런 다음 노드 선정이 재설정되고 쿠버네티스 스케줄러가 파드를 위한 노드를 찾는 것을 재시도한다.

제한사항

스토리지 용량 추적은 첫 시도에 스케줄링이 성공할 가능성을 높이지만, 스케줄러가 시간이 지난 정보를 기반으로 결정해야 할 수도 있기 때문에 이를 보장하지는 않는다. 일반적으로 스토리지 용량 정보가 없는 스케줄링과 동일한 재시도 메커니즘으로 스케줄링 실패를 처리한다.

스케줄링이 영구적으로 실패할 수 있는 한 가지 상황은 파드가 여러 볼륨을 사용하는 경우이다. 토폴로지 세그먼트에 하나의 볼륨이 이미 생성되어 다른 볼륨에 충분한 용량이 남아 있지 않을 수 있다. 이러한 상황을 복구하려면 용량을 늘리거나 이미 생성된 볼륨을 삭제하는 등의 수작업이 필요하다.

다음 내용

11 - 노드 별 볼륨 한도

이 페이지는 다양한 클라우드 공급자들이 제공하는 노드에 연결할 수 있는 최대 볼륨 수를 설명한다.

Google, Amazon 그리고 Microsoft와 같은 클라우드 공급자는 일반적으로 노드에 연결할 수 있는 볼륨 수에 제한이 있다. 쿠버네티스가 이러한 제한을 준수하는 것은 중요하다. 그렇지 않으면, 노드에서 예약된 파드가 볼륨이 연결될 때까지 멈추고 기다릴 수 있다.

쿠버네티스 기본 한도

쿠버네티스 스케줄러에는 노드에 연결될 수 있는 볼륨 수에 대한 기본 한도가 있다.

클라우드 서비스노드 당 최대 볼륨
Amazon Elastic Block Store (EBS)39
Google Persistent Disk16
Microsoft Azure Disk Storage16

사용자 정의 한도

KUBE_MAX_PD_VOLS 환경 변수의 값을 설정한 후, 스케줄러를 시작하여 이러한 한도를 변경할 수 있다. CSI 드라이버는 절차가 다를 수 있으므로, 한도를 사용자 정의하는 방법에 대한 문서를 참고한다.

기본 한도보다 높은 한도를 설정한 경우 주의한다. 클라우드 공급자의 문서를 참조하여 노드가 실제로 사용자가 설정한 한도를 지원할 수 있는지 확인한다.

한도는 전체 클러스터에 적용되므로, 모든 노드에 영향을 준다.

동적 볼륨 한도

기능 상태: Kubernetes v1.17 [stable]

다음 볼륨 유형에 대해 동적 볼륨 한도가 지원된다.

  • Amazon EBS
  • Google Persistent Disk
  • Azure Disk
  • CSI

인-트리(in-tree) 볼륨 플러그인으로 관리되는 볼륨의 경우, 쿠버네티스는 자동으로 노드 유형을 결정하고 노드에 적절한 최대 볼륨 수를 적용한다. 예를 들면, 다음과 같다.

  • Google Compute Engine에서는, 노드 유형에 따라 최대 127개의 볼륨까지 노드에 연결할 수 있다.

  • M5, C5, R5, T3와 Z1D 인스턴스 유형의 Amazon EBS 디스크의 경우, 쿠버네티스는 25개의 볼륨만 노드에 연결할 수 있도록 허용한다. Amazon Elastic Compute Cloud (EC2)의 다른 인스턴스 유형의 경우, 쿠버네티스는 노드에 39개의 볼륨을 연결할 수 있도록 허용한다.

  • Azure에서는, 노드 유형에 따라 최대 64개의 디스크를 노드에 연결할 수 있다. 더 자세한 내용은 Azure의 가상 머신 크기를 참고한다.

  • CSI 스토리지 드라이버가 NodeGetInfo 를 사용해서 노드에 대한 최대 볼륨 수를 알린다면, kube-scheduler는 그 한도를 따른다.

자세한 내용은 CSI 명세를 참고한다.

  • CSI 드라이버로 마이그레이션된 인-트리 플러그인으로 관리되는 볼륨의 경우, 최대 볼륨 수는 CSI 드라이버가 보고한 개수이다.

12 - 볼륨 헬스 모니터링

기능 상태: Kubernetes v1.21 [alpha]

CSI 볼륨 헬스 모니터링을 통해 CSI 드라이버는 기본 스토리지 시스템에서 비정상적인 볼륨 상태를 감지하고 이를 PVC 또는 파드의 이벤트로 보고한다.

볼륨 헬스 모니터링

쿠버네티스 볼륨 헬스 모니터링 은 쿠버네티스가 CSI(Container Storage Interface)를 구현하는 방법의 일부다. 볼륨 헬스 모니터링 기능은 외부 헬스 모니터 컨트롤러와 kubelet, 2가지 컴포넌트로 구현된다.

CSI 드라이버가 컨트롤러 측의 볼륨 헬스 모니터링 기능을 지원하는 경우, CSI 볼륨에서 비정상적인 볼륨 상태가 감지될 때 관련 퍼시스턴트볼륨클레임(PersistentVolumeClaim, PVC) 이벤트가 보고된다.

외부 헬스 모니터 컨트롤러는 노드 장애 이벤트도 감시한다. enable-node-watcher 플래그를 true로 설정하여 노드 장애 모니터링을 활성화할 수 있다. 외부 헬스 모니터가 노드 장애 이벤트를 감지하면, 컨트롤러는 이 PVC를 사용하는 파드가 장애 상태인 노드에 있음을 나타내는 이벤트가 PVC에 보고된다고 알린다.

CSI 드라이버가 노드 측에서 볼륨 헬스 모니터링 기능을 지원하는 경우, CSI 볼륨에서 비정상적인 볼륨 상태가 감지되면 PVC를 사용하는 모든 파드에서 이벤트가 보고된다. 그리고, 볼륨 헬스 정보는 kubelet VolumeStats 메트릭 형태로 노출된다. 새로운 kubelet_volume_stats_health_status_abnormal 메트릭이 추가되었다. 이 메트릭은 namespacepersistentvolumeclaim 2개의 레이블을 포함한다. 카운터는 1 또는 0이다. 카운터가 1이면 볼륨이 정상적이지 않음을, 0이면 정상적임을 의미한다. 더 많은 정보는 KEP를 참고한다.

다음 내용

이 기능을 구현한 CSI 드라이버를 확인하려면 CSI 드라이버 문서를 참고한다.

13 - 윈도우 스토리지

이 페이지는 윈도우 운영 체제에서의 스토리지 개요를 제공한다.

퍼시스턴트 스토리지

윈도우는 계층 구조의 파일시스템 드라이버를 사용하여 컨테이너 레이어를 마운트하고 NTFS 기반 파일시스템의 복제본을 생성한다. 컨테이너 내의 모든 파일 경로는 해당 컨테이너 컨텍스트 내에서만 인식 가능하다.

  • 도커를 사용할 때, 볼륨 마운트는 컨테이너 내의 디렉토리로만 지정할 수 있으며, 개별 파일로는 지정할 수 없다. 이 제약 사항은 containerd에는 적용되지 않는다.
  • 볼륨 마운트는 파일 또는 디렉토리를 호스트 파일시스템으로 투영(project)할 수 없다.
  • 윈도우 레지스트리와 SAM 데이터케이스에 쓰기 권한이 항상 필요하기 때문에, 읽기 전용 파일시스템은 지원되지 않는다. 다만, 읽기 전용 볼륨은 지원된다.
  • 볼륨 사용자-마스크 및 퍼미션은 사용할 수 있다. 호스트와 컨테이너 간에 SAM이 공유되지 않기 때문에, 둘 간의 매핑이 존재하지 않는다. 모든 퍼미션은 해당 컨테이너 컨텍스트 내에서만 처리된다.

결과적으로, 윈도우 노드에서는 다음 스토리지 기능이 지원되지 않는다.

  • 볼륨 서브패스(subpath) 마운트: 윈도우 컨테이너에는 전체 볼륨만 마운트할 수 있다.
  • 시크릿을 위한 서브패스 볼륨 마운팅
  • 호스트 마운트 투영(projection)
  • 읽기 전용 루트 파일시스템 (매핑된 볼륨은 여전히 readOnly를 지원한다)
  • 블록 디바이스 매핑
  • 메모리를 스토리지 미디어로 사용하기 (예를 들어, emptyDir.mediumMemory로 설정하는 경우)
  • uid/gid, 사용자 별 리눅스 파일시스템 권한과 같은 파일시스템 기능
  • DefaultMode을 이용하여 시크릿 퍼미션 설정하기 (UID/GID 의존성 때문에)
  • NFS 기반 스토리지/볼륨 지원
  • 마운트된 볼륨 확장하기 (resizefs)

쿠버네티스 볼륨을 사용하여 데이터 지속성(persistence) 및 파드 볼륨 공유 요구 사항이 있는 복잡한 애플리케이션을 쿠버네티스에 배포할 수 있다. 특정 스토리지 백엔드 또는 프로토콜과 연관된 퍼시스턴트 볼륨의 관리는 볼륨 프로비저닝/디프로비저닝/리사이징, 쿠버네티스 노드로의 볼륨 연결(attaching) 및 해제(detaching), 데이터를 보존해야 하는 파드 내 개별 컨테이너로의 볼륨 마운트 및 해제 같은 동작을 포함한다.

볼륨 관리 구성 요소는 쿠버네티스 볼륨 플러그인 형태로 제공된다. 윈도우는 다음의 광역 쿠버네티스 볼륨 플러그인 클래스를 지원한다.

인-트리(In-tree) 볼륨 플러그인

다음의 인-트리 플러그인은 윈도우 노드에서의 퍼시스턴트 스토리지를 지원한다.