Storage in Docker


Container Storage 관련된 내용은 07. Docker Storage 을 살펴보자.

Volume Driver Plugins in Docker

Container 내에서 저장공간을 사용하기 위해 Volume 을 마운팅할 때 Volume Driver 가 사용된다. 기본적으로 Local Driver Plugin 을 사용하고 다양한 Driver 가 존재한다. RexRay Driver 의 경우 AWS EBS 와 S3 를 Volume 으로 사용할 때 쓰인다.

docker run -it \
  --name mysql
  --volume-driver rexray/ebs
  --mount src=ebs-vol,target=/var/lib/mysql
  mysql

Docker Container 를 실행할 때 Volume Driver 를 지정해줄 수 있다.

Container Storage Interface (CSI)

K8s 가 CRI 를 통해 Docker 외에도 rkt, cri-o 등을 Container Runtime 으로 사용할 수 있듯이 Container Storage 를 위한 Interface 를 CSI 로 제공한다. CSI 는 K8s 에만 종속적인 것이 아닌 Universal Standard 이기에 Storage Provider 들이 CSI 를 기준으로 작성한 코드가 Mesos 같은 다른 Container Orchestration 툴에도 적용될 수 있다.

Ephemeral Volumes


emptyDir

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - image: alpine
    name: alpine
    command: ["/bin/sh", "-c"]
    args: ["shuf -i 0-100 -n 1 >> /opt/number.out;"]
    volumeMounts:
    - mountPath: /opt
      name: temp-storage
  volumes:
  - name: temp-storage
    emptyDir: {}

Pod 가 생성될 때 빈 디렉터리로 시작하고 모든 컨테이너가 데이터를 읽고 쓸 수 있다. Pod 삭제 시 데이터도 삭제된다.

hostPath

apiVersion: v1
kind: Pod
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

Pod 내 Container 에게 Volume 을 마운팅해주기 위해 위와 같이 설정할 수 있다. 위 내용은 Node 의 /data 디렉터리를 Volume 으로 사용하고 Container 내 /opt 디렉터리와 마운팅하겠다는 의미다. hostPath 의 경우 Pod 가 재시작 시 다른 Node 에 Scheduling 되는 상황이 발생할 수 있기 때문에 Ephemeral Volume 이라고 생각할 수 있다.

Persistent Volumes


apiVersion: v1
kind: Pod
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
    awsElasticBlockStore:
      volumeID: <volume-id>
      fsType: ext4

Node 의 디렉터리를 Volume 으로 사용하는 것은 앞서 설명하였듯이 동일한 Node 에서 Pod 가 재시작한다는 보장이 없기 때문에 EBS 등의 Storage 를 사용하는 것이 더 합리적이다.

Persistent Volumes

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-vol1
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 1Gi
  awsElasticBlockStore:
    volumeID: <volume-id>
    fsType: ext4

각 Pod Definition 마다 Volume 을 설정하게 되면 관리포인트가 늘어나기 때문에 이상적이지 않다. 때문에 Pod 가 각자 필요한 만큼 나눠서 쓸 수 있는 Persistent Volume 을 사용할 수 있다.

PV 의 주요 필드는 아래와 같다.

  1. capacity
    • PV 의 스토리지 용량을 정의한다
    • PVC 는 이 용량을 요청하여 사용할 수 있다
  2. accessModes
    • PV 의 접근 모드를 정의한다
      • ReadWriteOnce: 하나의 Node 에서 읽기/쓰기가 가능
      • ReadOnlyMany: 여러 Node 에서 읽기만 가능
      • ReadWriteMany: 여러 Node 에서 읽기/쓰기가 가능
  3. storageClassName
    • PV 에 적용되는 StorageClass 를 정의한다
    • 위 예시에선 awsElasticBlockStore 를 사용한다
  4. persistentVolumeReclaimPolicy
    • PVC 가 제거된 후 PV 를 어떻게 처리할지 정의한다
      • Retain: 데이터를 보존하고 불필요 시 관리자가 수동으로 정리한다
      • Recycle: 데이터를 삭제하고 PV 를 재사용한다
      • Delete: PV 와 데이터를 모두 제거한다

Persistent Volume Claims

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

생성된 Persistent Volume 을 사용하기 위해선 Persistent Volume Claim 을 생성해줘야 한다. Persistent Volume Claim 은 Storage Capacity, Access Mode 등을 비교하여 적절한 Persistent Volume 을 찾고 바인딩된다. 만약 요구사항에 맞는 Persistent Volume 이 존재하지 않을 경우 PVC 는 Pending State 로 기다리게 된다.

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

PVC 가 생성된 이후 Pod 와 마운팅하기 위해선 위와 같이 설정해주면 된다.

Storage Class


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

AWS EBS 등을 PV 로 사용하려면 AWS EBS 를 미리 생성해두어야 한다. 이를 Static Provisioning 이라 하는데 PVC 가 PV 를 요구할 때 자동으로 EBS 를 생성해주는 것을 Dynamic Provisioning 이라 하며 Storage Class 를 통해 이뤄낼 수 있다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: google-storage       
  resources:
    requests:
      storage: 500Mi

SC 를 생성한 이후 PVC 가 SC 를 참조할 수 있도록 설정해주면 된다.

References