[Retry, k8s] 23. 컨피그 & 스토리지 API - 볼륨
카테고리: KUBERNETES
태그: kubernetes
🔔 볼륨(Volume), 영구 볼륨(Persistent Volume), 영구 볼륨 클레임(PV Claim)의 차이
시작하기 전 선행 작업 및 확인해야할 내용
- https://revenge1005.github.io/kubernetes/ch03-6-1/
- https://revenge1005.github.io/kubernetes/ch03-6-2/
- https://revenge1005.github.io/kubernetes/ch03-6-3/
(1) 볼륨
-
미리 준비된 사용 가능한 볼륨(호스트볼륨/nfs/iSCSi/Ceph) 등을 매니페스트에 직접 지정하여 사용할 수 있는 것이다.
-
사용자가 설정된 볼륨을 사용할 수 있지만, 쿠버네티스에서 신규 볼륨을 생성하거나 기존 볼륨을 삭제하는 작업은 할 수 없다.
-
매니페스트에서 볼륨 리소스를 생성하는 것도 불가능하다.
(2) 영구 볼륨
-
영구 볼륨은 외부 영구 스토리지 시스템과 연계하여 신규 볼륨을 생성하거나 기존 볼륨을 삭제하는 등의 작업이 가능하다.
-
구체적으로는 매니페스트에서 영구 볼륨 리소스를 별도도로 생성하는 형태다.
-
영구 볼륨과 볼륨은 같은 플러그인을 제공한다.
-
영구 볼륨 플로그인에서는 볼륨 생성 및 삭제 같은 라이프사이클을 처리할 수 있지만, 볼륨 플러그인의 경우에는 기존에 있는 볼륨만 사용할 수 있다.
(3) 영구 볼륨 클레임
-
생성된 영구 볼륨 리소스를 할당하는 리소스
-
영구 볼륨은 클러스터에 볼륨을 등록만 하기 때문에 실제 파드에서 사용하려면 영구 볼륨 클레임을 정의하고 사용해야 한다.
-
동적 프로비저닝 기능을 사용한 경우에는 영구 볼륨 클레임이 사용된 시점에 영구 볼륨을 동적으로 생성할 수 있어 순서가 바뀌었다고 느낄 수도 있다.
(4) 볼륨
k8s에서는 볼륨을 추상화하여 파드와 느슨하게 결합된 리소스로 정의하고 있다.
📜 emptyDir
-
파드가 노드에 할당될 때 생성되는 파드용 임시 디스크 영역으로, 파드가 노드에서 제거(또는 종료)되면 삭제된다.
-
emptyDir은 처음에 비어 있으며, 파드 내의 모든 컨테이너가 emptyDir 볼륨에 있는 동일한 파일을 읽고 쓸 수 있다.
-
호스트 볼륨(컨테이너용 임시 디스크 영역)을 컨테이너 볼륨에 매핑하지만, 호스트의 임의 영역을 마운트하거나 호스트에 있는 파일을 참조할 수는 없다.

【emptyDir 볼륨을 마운트하는 파드 예제】
$ cat <<EOF > sample-emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir
spec:
containers:
- image: nginx:1.16
name: nginx-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
EOF
$ kubectl exec -it sample-emptydir -- df -h | grep /cache
/dev/mapper/ubuntu--vg-ubuntu--lv 9.8G 6.7G 2.6G 73% /cache
【용량 제한을둔 emptyDir 볼륨을 마운트하는 파드 예제】
- emptyDir을 사용한 볼륨에 “emptyDir.sizeLimit”로 리소스 제한을 할 수 있다.
$ cat <<EOF > sample-emptydir-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir-limit
spec:
containers:
- image: nginx:1.16
name: nginx-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 128Mi
EOF
# 150MB 파일을 생성
$ kubectl exec -it sample-emptydir-limit -- dd if=/dev/zero of=/cache/dummy bs=1M count=150
# 할당된 영역에 대해 용량이 초과로 Evict(축출)되는 것을 확인할 수 있다.
$ kubectl get pod --watch
NAME READY STATUS RESTARTS AGE
sample-emptydir-limit 1/1 Running 0 3m
sample-emptydir-limit 1/1 Evicted 0 3m41s
$ kubectl describe pod sample-emptydir-limit
~(생략)~
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Evicted 5m37s kubelet Usage of EmptyDir volume "cache-volume" exceeds the limit "128Mi".
Normal Killing 5m37s kubelet Stopping container nginx-container
【고속 메모리 영역을 사용한 emptyDir 볼륨을 마운트하는 파드 예제】
-
emptydir은 호스트상의 디스크 영역뿐만 아니라 고속 tmpfs 메모리 영역을 사용할 수도 있다.
-
메모리 영역을 사용하려면 “emptyDir.medium”에 Memory를 지정한다.
$ cat <<EOF > sample-emptydir-memory.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir-memory
spec:
containers:
- image: nginx:1.16
name: nginx-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
medium: Memory
sizeLimit: 128Mi
EOF
# 쿠버네티스 노드의 tmpfs 영역이 할당된 것을 확인
$ kubectl exec -it sample-emptydir-memory -- df -h | grep /cache
tmpfs 128M 0 128M 0% /cache
【메모리 리소스 제한과 emptyDir을 같이 사용한 예제】
-
emptyDir 메모리 영역에서 사용하는 용량은 컨테이너에 대한 메모리 사용 상한 설정 “resource.limits.memory”에도 영향을 준다.
-
이 매니페스트는 128Mi까지 tmpfs 영역을 사용할 수있는 점은 같지만, 컨테이너가 사용할 수 있는 메모리 상한이 설정되어 있다.
-
emptyDir도 이 제한이 예외가 아니라서 70MB 파일을 작성하는 단계에서 OOM(Out of Memory)에 의해 파드가 정지되는 점에 주의.
$ cat <<EOF > sample-emptydir-memory-with-memory-limits.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir-memory-with-memory-limits
spec:
containers:
- image: nginx:1.16
name: nginx-container
resources:
limits:
memory: 64Mi
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
medium: Memory
sizeLimit: 128Mi
EOF
# 70MB 파일을 /cache/dummy에 생성
$ kubectl exec -it sample-emptydir-memory-with-memory-limits -- dd if=/dev/zero of=/cache/dummy bs=1M
command terminated with exit code 137
# 파드 상태 모니터링(별도 터미널에서 파일 생성 전에 실행)
$ kubectl get pod --watch
NAME READY STATUS RESTARTS AGE
sample-emptydir-memory-with-memory-limits 1/1 Running 1 48s
sample-emptydir-memory-with-memory-limits 0/1 OOMKilled 0 20s
📜 hostPath
-
쿠버네티스 노드상의 파일 시스템에서 파일이나 디렉터리를 파드에 마운트하는 볼륨 유형
-
type은 “Directory/DirectroyOrCreate/File/Socket/BlockDevice 등”을 선택할 수 있으고, DirectroyOrCreate와 Directory의 차이는 디렉터리가 존재하지 않을 경우 생성하고 기동하는지 여부에 있다.
-
보안상의 이유로 안전하지 않은 컨테이너가 업로드될 수 있으므로 사용하지 않는 것을 권장한다.

【hostPath 볼륨을 마운트하는 파드 예제】
$ cat <<EOF > sample-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-hostpath
spec:
containers:
- image: nginx:1.16
name: nginx-container
volumeMounts:
- mountPath: /srv
name: hostpath-sample
volumes:
- name: hostpath-sample
hostPath:
path: /etc
type: DirectoryOrCreate
EOF
# 호스트 OS 이미지 확인 - (호스트의 /etc가 생성한 파드의 /srv에 마운트된 것을 확인)
$ kubectl exec -it sample-hostpath -- cat /srv/os-release | grep PRETTY_NAME
PRETTY_NAME="Ubuntu 22.04.2 LTS"
# 컨테이너 OS 이미지 확인
$ kubectl exec -it sample-hostpath -- cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
📜 downwardAPI
-
파드 정보 등을 파일로 배치하기 위한 플러그인
-
환경 변수 fieldRef와 resourceFieldRef의 사용 방법과 같다.
$ cat <<EOF > sample-downward-api.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-downward-api
spec:
containers:
- name: nginx-container
image: nginx:1.16
volumeMounts:
- name: downward-api-volume
mountPath: /srv
volumes:
- name: downward-api-volume
downwardAPI:
items:
- path: "podname"
fieldRef:
fieldPath: metadata.name
- path: "cpu-request"
resourceFieldRef:
containerName: nginx-container
resource: requests.cpu
EOF
# sample-downward-api 파드의 /srv 아래 파일 확인
$ kubectl exec -it sample-downward-api -- ls /srv
cpu-request podname
📜 projected
-
시크릿/컨피그맵/downwardAPI/serviceAccountToken의 볼륨 마운트를 하나의 디렉터리에 통합하는 플러그인
-
시크릿 인증 정보와 컨피그맵 설정 파일 하나의 디렉터리에 배치하고 싶을 경우 사용할 수 있다.
$ cat <<EOF > sample-projected.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-projected
spec:
containers:
- name: nginx-container
image: nginx:1.16
volumeMounts:
- name: projected-volume
mountPath: /srv
volumes:
- name: projected-volume
projected:
sources:
- secret:
name: sample-db-auth
items:
- key: username
path: secret/username.txt
- configMap:
name: sample-configmap
items:
- key: nginx.conf
path: configmap/nginx.conf
- downwardAPI:
items:
- path: "podname"
fieldRef:
fieldPath: metadata.name
EOF
# /srv 디렉터리 확인
$ kubectl exec -it sample-projected -- ls /srv
configmap podname secret
# /srv/configmap 디렉터리 확인
$ kubectl exec -it sample-projected -- ls /srv/configmap
nginx.conf
# /srv/secret 디렉터리 확인
$ kubectl exec -it sample-projected -- ls /srv/secret
username.txt
댓글 남기기