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 를 지정해줄 수 있다.

CSI, Container Storage Interface

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 를 사용하는 것이 더 합리적이다.

PersistentVolume

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-vol1
spec:
  capacity:         # PV 의 스토리지 용량
    storage: 1Gi
  accessModes:      # PV 의 접근 모드
  - ReadWriteOnce   # 'ReadWriteOnce | ReadOnlyMany | ReadWriteMany|ReadWriteOncePod' 몇 대의 Node 가 PV 에 읽고 쓰는지
  storageClassName: awsElasticBlockStore # PV 를 구현하는 StorageClass
  persistentVolumeReclaimPolicy: Recycle # 'Retain | Recycle | Delete' PVC 제거 후 PV 처리 여부

PersistentVolumeClaim

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 Classes


StorageClass

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     
  resources:
    requests:
      storage: 500Mi
  storageClassName: google-storage # google-storage SC 의 500Mi RWO PV 생성

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

References