kubernetes pv and pvc
데이터 보존
docker
에서도 컨테이너의 데이터를 영속적으로 저장하기 위해서는 호스트의 영역을 공유하는 방식을 이용했다. kubernetes
에서도 호스트에 위치한 디렉터리를 각 포드와 공유함으로써 데이터를 보존하는 것이 가능하다. 하지만 쿠버네티스는 클러스터 환경이기 때문에, 운영상의 이유(장애 등)로 워커 노드 중 다른 노드로 포드가 배정 되었을 경우에는 호스트의 저장공간을 접근할 수 없게 된다. 따라서 어느 노드에서도 접근해 사용할 수 있는 Persistent Volume
을 사용한다.
Type 1. Local Volume (hostPath, emptyDir)
hostPath
hostPath
는 워커노드의 호스트와 볼륨을 공유하기 위해 사용한다. CAdvisor와 같은 모니터링 툴을 사용하는 경우가 아니라면 권장되는
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: my-container
image: busybox
args: [ "tail", "-f", "/dev/null" ]
volumeMounts:
- name: my-hostpath-volume
mountPath: /etc/data # 포드의 /etc/data를 호스트의 /tmp에 연결
volumes:
- name: my-hostpath-volume
hostPath:
path: /tmp
1
2
3
kubectl apply -f ./docs/Kubernetes/Kubernetes_yarm_files/4_pv_pvc/hostpath-pod.yaml
kubectl exec -it hostpath-pod -- touch /etc/data/mydata
emptyDir
emptyDir
는 포드가 실행되는 도중에만 필요한 휘발성 데이터를 각 컨테이너가 함께 사용할 수 있도록 볼륨을 공유하기 위해 사용한다. 포드가 삭제되면 emptyDir
에 저장되어 있던 데이터도 함께 삭제된다.
- 한 컨테이너가 파일을 관리하고, 한 컨테이너가 그 파일을 사용하는 경우에 유용하게 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: Pod
metadata:
name: emptydir-pod
spec:
containers:
- name: content-creator
image: alicek106/alpine-wget:latest
args: ["tail", "-f", "/dev/null"]
volumeMounts:
- name: my-emptydir-volume
mountPath: /data # 1. 컨테이너가 파일을 생성하는 영역
- name: apache-webserver
image: httpd:2
volumeMounts:
- name: my-emptydir-volume
mountPath: /usr/local/apache2/htdocs/ # 2. 아파치 웹서버에서 접근
volumes:
- name: my-emptydir-volume
emptyDir: {}
1
2
3
4
5
6
7
8
9
10
11
kubectl apply -f emptydir-pod.yaml
kubectl exec -it emptydir-pod -c content-creator sh
/ # echo Hello, Kubernetes! >> /data/test.html
/ # exit
kubectl describe pod emptydir-pod | grep IP
kubectl run -i tty --rm debug \
--image=alicek106/ubuntu:curl --restart=Never -- curl 172.17.0.8/test.html
Hello, Kubernetes!
Type 2. 네트워크 볼륨
쿠버네티스는 네트워크 볼륨의 위치에 상관없이, 네트워크로 접근만 가능하다면 어느곳에서든지 포드에 마운트 시킬 수 있다. 네트워크 볼륨을 선택하는 기준은 1) 데이터 읽고 쓰는 속도, 2) 마운트 방식(1:1, 1:n), 3) 구축비용 등이 있다.
NFS
NFS(Network File System)
는 하나의 서버만으로 간편하게 사용할 수 있으며, NFS를 마치 로컬 스토리지 처럼 사용할 수 있다는 장점이 있다.
NFS 서버
: 영속적인 데이터가 실제로 저장되는 네트워크 스토리지 서버NFS 클라이언트
: NFS 서버에 마운트해 스토리지에 파일을 읽고 쓰는 역할을 한다.
Type 3. PV, PVC를 이용한 볼륨관리
PV, PVC는 왜 사용하나?
위의 NFS
같이 쿠버네티스에서 지원하는 대부분의 볼륨타입은 포드나 디플로이먼트 YAML 파일에서 직접 정의해서 사용할 수 있다. 하지만 이런 방식을 사용하면 네트워크 볼륨으로서 NFS를 명시했으므로 다른 볼륨을 사용할 수 없게된다. 흔히 말하는 결합도가 높아지는
상황인 것이다. 이를 해결하기 위해 PV와 PVC를 사용한다.
PV(Persistent Volume)
와 PVC(Persistent Volume Claim)
은 포드(yaml)가 세부적인 사항을 몰라도 볼륨을 사용할 수 있도록 추상화해주는 역할을 담당한다.
Pod <-> PVC(개발자) <-> PV(인프라관리자) <-> 네트워크 볼륨
의 모양이라고 생각하면 쉽다.
1
2
3
1) 인프라 관리자는 네트워크 볼륨의 정보를 이용해 PV 리소스를 미리 생성해 둔다.
2) 사용자는 포드 yaml에는 외부볼륨이 필요하다는 PV claim을 명시하고, 생성한다.
3) 쿠버네티스는 미리 만들어둔 PV 리소스와 PVC가 요구한 사항이 일치하면 매칭(bind) 시켜준다.
PV, PVC 사용하기 (AWS EBS활용)
핵심은 외부 네트워크 볼륨을 쿠버네티스에 등록하고, 어플리케이션을 배포하려는 사용자(개발자) 입장에서 PVC를 사용해보는 것이다.
1) AWS에서 EBS(Elastic Block Stroe) 생성
이때 주의할 점은 EBS의 가용영역과 리전은 쿠버네티스 워커노드와 동일한 곳에 있어야 한다는 것이다!
1
2
3
4
5
6
7
8
9
10
export VOLUME_ID=$(aws ec2 create-volume --size 5 \
--region ap-northeast-2 \
--availability-zone ap-northeast-2a \
--volume-type gp2 \
--tag-specifications \
'ResourceType=volume,Tags=[{Key=KubernetesCluster,Value=mycluster.k8s.local}]' \
| jq '.VolumeId' -r)
echo VOLUME_ID
2) EBS 볼륨으로 쿠버네티스 PV(Persistent Volume) 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: PersistentVolume
metadate:
name: ebs-pv
spec:
capacity:
storage: 5Gi # 볼륨의 크기는 5G
accessModels:
- ReadWriteOnce # 하나의 포드(인스턴스)에 의해서만 마운트 가능
awsElasticBlockStore: # EBS 마운트를 위한 항목정의
fsType: ext4
volumeID: <VOLUME_ID>
1
2
3
cat ebs-pv.yaml | sed "s/<VOLUME_ID>/$VOLUME_ID/g" | kubectl apply -f -
kubectl get pv # 생성된 pv 확인
3) 개발자 입장(사용자)에서 PVC(Persistent Volume Claim)생성 후 포드에 사용명시 여기서 PVC의 accessMode와 resources는 볼륨의 요구사항으로 해당조건을 만족하는 PV와 연결되어야 한다는 것을 의미한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-ebs-pvc # 1. pvc 생성
spec:
storageClassName: " "
accessModes:
- ReadWriteOnce # 2-1. RWO인 PV와 연결
resources:
requests:
storage: 5Gi # 2-2. 볼륨 크기가 최소 5G인 PV와 연결
---
apiVersion: v1
kind: Pod
metadata:
- name: ebs-mount-container
spec:
containers:
- name: ebs-mount-container
image: busybox
args: ["tail", "-f", "/dev/null"]
volumeMounts:
- name: ebs-volume
mountPath: /mnt
volumes:
- name: ebs-volume
persistentVolumeClaim:
claimName: my-ebs-pvc # 3. my-ebs-pvc라는 이름의 pvc를 사용