티스토리 뷰

Infrastructure/Kubernetes

[CKA] Storage

dev_jun 2022. 8. 3. 18:54

Container Storage Interface(CSI)

Container Runtime Interface(CRI)

  • Kubernetes와 같은 Orchestration Solution이 Docker와 같은 Container Runtime과 통신하는 방법을 정의하는 표준

Container Network Interface(CNI)

  • network 인터페이스로, CNI 표준을 기반으로 플러그인을 개발하여 Kuberntes와 함께 솔루션을 사용할 수 있다.

Container Storage Interface(CSI)

  • 여러 storage 솔루션을 위한 인터페이스
  • CSI는 Kubernetes 고유의 표준은 아니다.
  • 예를 들어, CSI에 따르면, pod가 생성되고 volume이 필요한 경우 container orchestration인 kubernetes가 volume 생성 RPC를 호출하여 volume과 같은 세부 정보 집합을 전달해야한다. storage driver는 이 RPC를 구현하고, 해당 요청을 처리하여 storage array에 새 volume을 프로비저닝하고 결과를 반환해야한다. 이와 마찬가지로 volume을 삭제할 때 volume 삭제 RPC를 호출하고 storage driver는 volume array에서 해제하는 코드를 구현해야한다.

Volume

도커 컨테이너는 본질적으로 일시적이기 때문에 해당 컨테이너가 유지되는 동안만 사용할 수 있다. 컨테이너를 삭제할 경우 컨테이너에서 사용한 데이터가 유실되는 단점이 있는데 이러한 단점을 보완하기 위한 기술이 Volume이다.

Volume을 사용하면, 컨테이너에 의해 처리된 데이터는 volume에 배치되기 때문에 데이터가 영구적으로 유지된다.

쿠버네티스에서는 어떨까?

도커와 마찬가지로 쿠버네티스에서 생성된 pod는 본질적으로 일시적이다. pod를 생성하여 데이터를 처리한 후 삭제하면 pod에서 처리한 데이터도 삭제된다.

Volume 생성

apiVersion: v1
kind: Volume
metadata:
  name: random-number-generator
spec:
  containers:
  - image: alpine
    name: alpine
    command: ["/bin/sh", "-c"]
    args: ["shuf -i 0-100 -n 1 >> /opt/number.out;"]
    volumeMounts:
    - mountPath: /opt
      name: data-volume

  volumes:
  - name: data-volume
    hostPath:
      path: /data
      type: Directory

위와 같이 작성하면 볼륨에서 생성된 파일이 내 노드의 디렉토리 데이터에 저장된다. 볼륨이 생성되면 컨테이너에서 액세스하기 위해 컨테이너 내부의 디렉토리에 볼륨을 마운트한다.

volumeMounts 필드를 사용하여 데이터 볼륨을 컨테이너 내의 /opt 디렉토리에 마운트한다.

pod가 삭제되더라도 임의의 번호를 가진 파일은 여전히 host에 있다.

host path 옵션을 사용하여 디렉토리를 구성했기 때문에 호스트에는 volume에 대한 storage 공간이 있다. 하지만 이는 단일 노드에서는 정상적으로 작동하지만 다중 노드 클러스터에서의 사용은 적합하지 않다. 이는 다중 노드 클러스터 환경에서는 pod가 모든 node에서 /data 디렉토리를 사용하고, 모든 노드가 동일한 데이터를가질것이기 때문이다.

따라서 hostPath 옵션을 사용하여 다중 노드 클러스터 환경을 구성해야한다면 EBS와 같은 솔루션을 사용하는 것을 추천한다.

Persistent Volume

  • 영구 볼륨은 애플리케이션을 배포하는 사용자가 사용하도록 구성한 클러스터 전체 스토리지 볼륨 풀이다.
  • 관리자가 큰 pool의 storage를 생성하고, 사용자들이 필요한만큼 조각으로 사용하는 방식
  • 영구 볼륨을 사용하기 위해선 영구 볼륨 클레임이 필요하다. 영구 볼륨 클레임을 사용하여 스토리지 볼륨 풀에서 영구 볼륨을 선택할 수 있다.
apiVersion: v1
kind: PersistentVolme
metadata:
  name: pv-voll
spec:
  accessModes:
    - ReadWriteOnce # ReadOnlyMany, ReadWriteOnce, ReadWriteMany 모드가 있다.
  capacity:
    storage: 1Gi
  hostPath:
    path: /tmp/data
# 클라우드를 사용하는 경우 
# awsElasticBlockStore:
#   volumeID: <volume-id>
#   fsType: ext4
  • kubectl create -f pv-definition.yaml
  • kubect get persistentvolume

Persistent Volume Claims

PV와 PVC는 쿠버네티스 네임스페이스에서 다른 객체이다.

관리자는 PV를 생성하고, 유저는 storage에 사용할 PVC를 생성한다. PVC가 생성되면 쿠버네티스는 PV를 생성할 때의 설정에 따라서 PV와 PVC를 바인딩한다. 모든 PVC는 하나의 PV와 바인딩된다. 바인딩을 하는 동안에 쿠버네티스는 클레임에 의해 요청되는대로 충분한 용량을 가진 PV나 다른 기타 요청 속성(Access Mode, Volume Modes, Storage Class, Selector, etc)을 찾으려고 한다.

그러나 여러개의 PV의 설정에서 매칭되는 클레임이 하나라면 PV의 label과 PVC의 selector 기능을 사용하여 매칭시킬 수 있다.

또한, PV의 용량은 큰데, PVC의 용량은 작다면 더 작은 클레임이 더 큰 볼륨에 바인딩 될 수 있다. 하지만 PV와 PVC는 일대일 매칭이기 때문에 다른 클레임이 PV의 남은 용량을 사용할 수는 없다.

사용 가능한 볼륨이 없는 경우, 클러스터에서 새 볼륨을 사용할 수 있게 될 때 까지 Pending 상태로 유지된다.

# pvc-definition.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

PV와 PVC가 매칭되어있는 상태에서 PVC가 삭제되면 매칭되었던 PV는 어떻게 될까? 이 또한 persistentVolumeReclaimPolicy 필드의 옵션으로 선택할 수 있다.

  • Retain: default로 Retain 로 설정되는데, 이는 관리자가 삭제하기 전까지는 PV가 남아있는 것을 뜻한다.
  • Delete: PVC가 삭제되면 곧 PV도 삭제된다.
  • Recycle: 이 경우 다른 claim에서 사용할 수 있도록 하기 전에 volume의 데이터를 scrub한다.

참고) PVC가 생성되면 POD definition file에서 volumes 필드에 persistentVolumeClaim 필드를 지정하여 PVC를 지정할 수 있다. 이는 ReplicaSet이나 Deployment에서도 동일하다.

Storage Class

Static Provisioning

Google Cloud와 같은 서비스를 사용한다면, PV 생성 전에 Google Cloud disk를 생성해주어야 한다. 수동으로 Google cloud disk를 provisioning 해준 후 수동으로 PV를 정의하는데, 이때 생성한 google cloud disk와 이름을 매칭시켜 생성해야한다. 이것을 static provisioning 이라고 한다.

하지만 이것은 수동으로 작업을 해주어야 하기 때문에 불편하다. 이 작업을 도와주는 것이 storage class이다.

storage class

storage class를 사용하면 google cloud에서 storage를 자동으로 provisioning하고 claim이 발생할때 pod에 연결할 수 있는 Google storage와 같은 임시 저장소를 정의할 수 있다. 이것을 dynamic provisioning of volumes 라고 부른다.

이것은 다음과 같이 생성할 수 있다.

# sc-definition.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: google-storage
provisioner: kubernetes.io/gce-pd

Storage class가 생성되면 storage가 자동으로 생성된다.

pvc가 정의한 storage class를 사용하도록 하려면 pvc definition file에 storage class name을 지정한다. → storageClassName: google-storage

이 방법을 통해 pvc는 다음에 pvc가 생성될 때 사용할 storage class를 알 수 있다.

이 클래스와 연결된 storage class는 정의된 provisioning을 사용하여 GCP에 필요한 크기의 새 디스크를 provisioning한 다음 pv를 생성한 뒤, pvc를 해당 volume에 바인딩한다. 따라서 여전히 pv가 생성된다. 이제는 pv를 직접 생성할 필요가 없다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함