아래와 같은 명령을 사용하면 EmptyDir 볼륨을 포함한 디플로이먼트를 적용한 후 emptyDir 볼륨이 마운트된 위치에 파일을 생성하고 컨테이너를 강제 종료해 파드가 재구동되어도 파일이 남아있는지 확인할 수 있다.
kubectlapply-fsleep-with-emptydir.yamlkubectlexecdeploy/sleep--ls/datakubectlexecdeploy/sleep--sh-c'echo ch05 > /data/file.txt; ls /data'# 컨테이너 ID 확인kubectlgetpod-lapp=sleep-ojsonpath='{.items[0].status.containerStatuses[0].containerID}'# 컨테이느 프로세스 강제 종료kubectlexecdeploy/sleep--killall5# 변경된 컨테이너 ID 확인kubectlgetpod-lapp=sleep-ojsonpath='{.items[0].status.containerStatuses[0].containerID}'kubectlexecdeploy/sleep--cat/data/file.txt
볼륨과 마운트로 노드에 데이터 저장
데이터를 특정 노드에 고정시킬지 말지 결정해야 한다. 만약 특정 노드에 고정시키면 기존 파드를 대체할 새로운 파드가 동일 노드에만 배치되야 한다.
노드의 디스크를 가리키는 볼륨인 호스트 경로 볼륨은 파드에 정의되며 컨테이너 파일 시스템에 마운트되는 형태로 사용된다.
쿠버네티스가 클러스터의 모든 노드에 동일한 데이터를 복제해주지는 않는다.
파드가 항상 같은 노드에서 동작하는 한 볼륨의 생애 주기가 노드의 디스크와 같아진다.
아래는 원주율 계산 결과를 반환하는 웹 애플리케이션의 프록시 파드를 정의한 디플로이먼트로, 컨테이너에서 /data/nginx/cache 디렉토리에 데이터를 저장하면 노드의 /volumes/nginx/cache 디렉토리에 실제로 데이터가 기록되도록 정의했다.
apiVersion:apps/v1kind:Deploymentmetadata:name:pi-proxylabels:app:pi-proxyspec:selector:matchLabels:app:pi-proxytemplate:metadata:labels:app:pi-proxyspec:containers: - image:nginx:1.17-alpinename:nginxports: - containerPort:80name:httpvolumeMounts: - name:configmountPath:"/etc/nginx/"readOnly:true - name:cache-volumemountPath:/data/nginx/cache# 프록시의 캐시 저장 경로volumes: - name:configconfigMap:name:pi-proxy-configmap - name:cache-volumehostPath:path:/volumes/nginx/cache# 사용할 노드의 디렉토리type:DirectoryOrCreate# 디렉터리가 없으면 생성
위 디플로이먼트를 적용하면 컨테이너가 종료될 때 대체 파드가 기존 파드와 같은 노드에 뜨기만 하면 같은 볼륨을 그대로 사용할 수 있다.
하지만 대부분의 경우 노드를 여러 개 두고 운영하고, 항상 같은 노드에서 수행하도록 강제하면 노드가 고장났을 때 애플리케이션을 실행할 수 없으므로 안정성이 떨어지게 된다.
노드 파일 시스템 전체에 접근할 수 있는 파드를 띄울 수 있다면 누구든지 호스트경로 볼륨에 사용하는 노드 상의 디렉터리에 접근할 수 있게 된다. 애플리케이션이 침투당해 공격자가 컨테이너에서 명령을 실행할 수 있다면 노드의 디스크 전체를 장악당할 수 있다.
아래는 모든 노드 파일 시스템에 접근 가능하도록 만든 디플로이먼트 예시와, 명령을 통해 내부 데이터를 조회하는 명령 예시이다.
# 클러스터의 첫 노드에 레이블 부여kubectllabelnode $(kubectlgetnodes-ojsonpath='{.items[0].metadata.name}') kiamol=ch05# 레이블 셀렉터로 노드 조회kubectlgetnodes-lkiamol=ch05# 레이블이 부여된 노드의 로컬 볼륨 사용하도록 영구 볼륨 배치kubectlapply-fpersistentVolume.yaml
파드는 PV에 직접 접근하지 못하며 PVC에 볼륨 사용을 요청해야 한다.
PVC는 파드가 사용하는 스토리지 추상이며, 애플리케이션에서 사용할 스토리지를 요청한다. PVC는 요구 조건이 일치하는 영구 볼륨과 함께 쓰이며, 자세한 볼륨 정보는 PV에 위임한다.
PV와 PVC는 일대일 관계이며 하나의 PVC에 연결된 PV는 다른 PVC와 연결될 수 없다.
아래는 앞서 생성한 로컬 볼륨과 요구 조건이 일치하는 PVC 정의이다. 스토리지 유형을 지정하지 않으면 현재 존재하는 PV 중 요구사항과 일치하는 것을 자동으로 찾아준다.
apiVersion:v1kind:PersistentVolumeClaimmetadata:name:postgres-pvcspec:accessModes: - ReadWriteOnce# 접근 유형resources:requests:storage:40Mi# 스토리지 용량storageClassName:""# 스토리지 유형
# PVC 생성kubectlapply-fpersistentVolumeClaim.yaml# PVC 목록 확인 / STATUS가 BOUND이면 PV에 연결되어 사용중임을 의미kubectlgetpvc# PV 목록 확인 / STATUS가 BOUND이면 PVC에 연결되어 사용중임을 의미kubectlgetpv