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