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