Skip to main content Link Menu Expand (external link) Document Search Copy Copied

볼륨

쿠버네티스에서 볼륨은 컨테이너가 데이터를 저장되는 공간이며 파드의 생명 주기 동안 유지된다. 파드 내 여러 컨테이너가 동일 볼륨을 공유할 수 있고, 파드가 삭제되면 볼륨도 함께 삭제된다.

emptyDir

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: redis
    image: redis
EOF
pod/redis created
 
kubectl get po -A
NAMESPACE     NAME                              READY   STATUS              RESTARTS   AGE
default       redis                             0/1     ContainerCreating   0          5s
 
# 테스트 데이터 생성
kubectl exec -it redis -- sh -c "echo hello > /data/hello.txt"
kubectl exec -it redis -- cat /data/hello.txt
hello
 
# 파드 킬
kubectl exec -it redis -- kill 1
 
kubectl get po
NAME    READY   STATUS    RESTARTS      AGE
redis   1/1     Running   1 (10s ago)   10s
 
# 사라진 데이터 확인
kubectl exec -it redis -- cat /data/hello.txt
cat: /data/hello.txt: No such file or directory
 
kubectl exec -it redis -- ls -l /data
command terminated with exit code 1
total 0

임의의 레디스 파드를 생성 후 kill -> 파드가 재시작 테스트

hostPath

hostPath는 호스트 노드의 특정 로컬 디렉터리를 마운트하여 파드 내부에서 직접 사용하는 방식

1번 워커 노드 로컬 디스크 경로로 테스트해본다.

apiVersion: v1
kind: Pod
metadata:
  name: hostpath-test
spec:
  nodeSelector:
    kubernetes.io/hostname: 1번 워커노드
  containers:
  - name: busybox
    image: busybox
    command: ["sleep", "3600"]
    volumeMounts:
    - mountPath: "/mnt/data"
      name: my-volume
  volumes:
  - name: my-volume
    hostPath:
      path: "/data"
      type: DirectoryOrCreate

파드를 워커 노드 1번에 고정하기 위해 노드셀렉터를 사용한다. 1번 노드의 /data 디렉터리를 컨테이너 내부 /mnt/data에 마운트하도록 정의한다.

k get po
NAME            READY   STATUS    RESTARTS   AGE
hostpath-test   1/1     Running   0          8s
 
kubectl exec -it hostpath-test -- sh
 
/ # echo "hostPath test" > /mnt/data/test.txt
/ # cat /mnt/data/test.txt
hostPath test

파드에서 데이터를 쓰고 1번 워커 노드에서 확인하면

[ec2-user@1번 워커노드 ~]$ ls -l /data/
total 4
-rw-r--r--. 1 root root 14 Feb 17 17:07 test.txt
 
# 파드 삭제
kubectl delete pod hostpath-test
pod "hostpath-test" deleted
 
[ec2-user@1번 워커노드 ~]$ ls -l /data/
total 4
-rw-r--r--. 1 root root 14 Feb 17 17:07 test.txt

Local path provisioner

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.31/deploy/local-path-storage.yaml
 
kubectl get pod -n local-path-storage -o wide
NAME                                     READY   STATUS    RESTARTS   AGE     IP              NODE                                              NOMINATED NODE   READINESS GATES
local-path-provisioner-84967477f-7bg7g   1/1     Running   0          2m37s   192.168.1.201   ip-[워커노드].ap-northeast-2.compute.internal       <none>           <none>
 
kubectl describe cm -n local-path-storage local-path-config
Name:         local-path-config
Namespace:    local-path-storage
Labels:       <none>
Annotations:  <none>
 
Data
====
config.json:
----
{
        "nodePathMap":[
        {
                "node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
                "paths":["/opt/local-path-provisioner"]
        }
        ]
}
 
helperPod.yaml:
----
apiVersion: v1
kind: Pod
metadata:
  name: helper-pod
spec:
  priorityClassName: system-node-critical
  tolerations:
    - key: node.kubernetes.io/disk-pressure
      operator: Exists
      effect: NoSchedule
  containers:
  - name: helper-pod
    image: busybox
    imagePullPolicy: IfNotPresent
 
setup:
----
#!/bin/sh
set -eu
mkdir -m 0777 -p "$VOL_DIR"
 
teardown:
----
#!/bin/sh
set -eu
rm -rf "$VOL_DIR"
 
 
BinaryData
====
 
Events:  <none>
 
kubectl get sc
NAME         PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2          kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  29h
local-path   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  3m47s
 
kubectl get sc local-path
NAME         PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  3m55s
# pvc
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: localpath-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 1Gi
EOF
 
kubectl get pv
Normal  WaitForFirstConsumer  13s (x3 over 42s)  persistentvolume-controller  waiting for first consumer to be created before binding
# 파드
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  terminationGracePeriodSeconds: 3
  containers:
  - name: app
    image: centos
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo \$(date -u) >> /data/out.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: localpath-claim
EOF

파드를 생성해주고 나면

kubectl get pod,pv,pvc
NAME      READY   STATUS    RESTARTS   AGE
pod/app   1/1     Running   0          5m44s
 
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pvc-55aa6c67-5fc5-4994-a2ea-c005a89f0482   1Gi        RWO            Delete           Bound    default/localpath-claim   local-path     <unset>                          5m41s
 
NAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/localpath-claim   Bound    pvc-55aa6c67-5fc5-4994-a2ea-c005a89f0482   1Gi        RWO            local-path     <unset>
kubectl describe pv
...
Node Affinity:
  Required Terms:
    Term 0:        kubernetes.io/hostname in [ip-1번 워커노드.ap-northeast-2.compute.internal]
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /opt/local-path-provisioner/pvc-55aa6c67-5fc5-4994-a2ea-c005a89f0482_default_localpath-claim
    HostPathType:  DirectoryOrCreate
    ...
kubectl exec -it app -- tail -f /data/out.txt
Mon Feb 17 17:33:43 UTC 2025
Mon Feb 17 17:33:48 UTC 2025
Mon Feb 17 17:33:53 UTC 2025
Mon Feb 17 17:33:58 UTC 2025
Mon Feb 17 17:34:03 UTC 2025
Mon Feb 17 17:34:08 UTC 2025
Mon Feb 17 17:34:13 UTC 2025
Mon Feb 17 17:34:18 UTC 2025
Mon Feb 17 17:34:23 UTC 2025
Mon Feb 17 17:34:28 UTC 2025
Mon Feb 17 17:34:33 UTC 2025
Mon Feb 17 17:34:38 UTC 2025
 
[ec2-user@ ~]$ sudo ls /opt/local-path-provisioner/
pvc-55aa6c67-5fc5-4994-a2ea-c005a89f0482_default_localpath-claim
kubectl delete pod app
pod "app" deleted
 
kubectl get pod,pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pvc-55aa6c67-5fc5-4994-a2ea-c005a89f0482   1Gi        RWO            Delete           Bound    default/localpath-claim   local-path     <unset>                          10m
 
NAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/localpath-claim   Bound    pvc-55aa6c67-5fc5-4994-a2ea-c005a89f0482   1Gi        RWO            local-path     <unset>                 10m
 
# 파드 재생성 후~
kubectl exec -it app -- head /data/out.txt
kubectl exec -it app -- tail -f /data/out.txt
Mon Feb 17 17:27:07 UTC 2025
Mon Feb 17 17:27:12 UTC 2025
Mon Feb 17 17:27:17 UTC 2025
Mon Feb 17 17:27:22 UTC 2025
Mon Feb 17 17:27:27 UTC 2025
Mon Feb 17 17:27:32 UTC 2025
Mon Feb 17 17:27:37 UTC 2025
Mon Feb 17 17:27:42 UTC 2025
Mon Feb 17 17:27:47 UTC 2025
Mon Feb 17 17:27:52 UTC 2025
Mon Feb 17 17:36:18 UTC 2025
Mon Feb 17 17:36:23 UTC 2025
Mon Feb 17 17:36:28 UTC 2025
Mon Feb 17 17:36:33 UTC 2025
Mon Feb 17 17:36:38 UTC 2025
Mon Feb 17 17:36:43 UTC 2025
Mon Feb 17 17:36:48 UTC 2025
Mon Feb 17 17:36:53 UTC 2025
Mon Feb 17 17:38:52 UTC 2025
Mon Feb 17 17:38:57 UTC 2025