쿠버네티스의 볼륨은 도커의 볼륨이 동작하는 방식을 기반으로 한다. 따라서 아래 도커의 볼륨 동작 방식에 대해 이해가 필요한 경우에는 아래 게시글을 보고 오는 것을 추천한다.
2024.03.11 - [Docker] - Docker) Storage in Docker
Volumes
Volumes & Mounts
도커의 컨테이너의 경우 클러스터가 삭제될 때 컨테이너가 처리하던 데이터도 함께 삭제된다. 이를 방지하기 위해 컨테이너로 데이터를 처리하고자 할 때는 컨테이너가 생성될 때 볼륨을 하나 붙여 컨테이너가 삭제된 후에도 데이터는 보존되도록 한다.
쿠버네티스의 파드도 마찬가지이다. 파드가 삭제되면 파드가 처리하던 파드 내의 데이터들도 함께 삭제 된다. 이를 방지하기 위해 파드에 볼륨을 붙일 수 있다.
아래는 0 ~ 100 사이의 난수를 `/opt/number.out` 에 출력하는 파드의 manifest 파일(.yaml)이다. 이 경우에 파드를 삭제하면 `/opt/number.out` 파일도 삭제 된다.
apiVersion: v1
kind: Pod
metadata:
name: random-number-generator
spec:
containers:
- image: alpine
name: alpine
command: ["/bin/sh/", "-c"]
args: ["shuf -i 0-100 -n 1 >> /opt/number.out;"]
volumeMounts:
- mountPath: /opt #Pod 내의 경로(/opt)에 해당 볼륨 마운팅
name: data-volume
volumes:
- name: data-volume
hostPath:
path: /data
type: Directory
# other cases - use PVC
# persistentVolumeClaim:
# claimName: [claim-name]
위의 경우는 단일 노드의 경우 괜찮지만, 다중 노드 클러스터에서는 권장되지 않는다. 파드는 모든 노드의 /data 경로를 볼륨으로 사용하며, 모든 노드의 /data 경로가 동일한 데이터를 담고 있다고 여기기 때문이다. → 외부 복제 클러스터 스토리지 솔루션을 사용하지 않는 한 문제가 됨
쿠버네티스는 여러 스토리지 솔루션을 지원한다.
- NFS, cluster affairs, Flocker, fiber channel, Ceph FS, scale io
- AWS, EBS, Azure desk(public cloud solutions) or file, or Google's Persistent Disk
Ex. AWS Elastic Block Store를 볼륨 옵션으로 사용하고자 한다면 아래와 같이 기존의 hostPath 필드 부분을 수정해야 한다.
volumes:
- name: data-volume
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4 #file system type
Persistent Volumes
PV(Persistent Volume)는 클러스터에 애플리케이션을 배포하는 사용자가 사용하도록 관리자가 구성한 클러스터 전체의 스토리지 볼륨 풀이다. 사용자는 영구 볼륨 할당을 사용하여 이 풀에서 스토리지를 선택할 수 있다.
`pv-definition.yaml`
apiVersion: v1
kind: PersistentVolume
metadata:
name: [pv-name] # ex. pv-vol1
spec:
accessModes: # ReadOnlyMany|ReadWriteOnce|ReadWriteMany
- ReadWriteOnce
capacity: # amount of storage to be reserved
storage: 1Gi
# volumeType
# 'hostPath' is not to be used in a production enviroment
awsElsaticBlockStore:
volumeID: <volume-id>
fsType: ext4
# other cases - use 'hostPath'
# hostPath:
# path: [path]
Create Persistent Volumes
kubectl create -f pv-definition.yaml
List Persistent Volumes
kubectl get persistentvolume
Persistent Volume Claims
💡 파드는 통신해야하는 DB의 타입에 따라 다르게 설정할 필요가 없다. PVC를 이용함으로써 어떠한 타입의 DB인지 신경쓰지 않아도 되게 된다. 이것을 내가 이해하기로는, 어떠한 클래스여도 통신할 수 있게끔 중간에 인터페이스가 존재하는 것과 유사하다. (실제 인터페이스의 구현체를 제공하는 것은 DB 벤더사의 역할이다.)
PV와 PVC는 네임스페이스 내의 별도의 두 오브젝트이다. 관리자는 일련의 PV를 생성하고, 사용자는 스토리지를 사용하기 위해 PVC를 생성한다.
PVC가 생성되면 쿠버네티스는 볼륨에 설정된 설정 및 요청에 기반으로 PV를 PVC에 바인딩한다.
모든 PVC는 단일 PV에 바인딩되고, 바인딩되지 않은 다른 PVC가 (이미 다른 PV에 바인딩 된) PV의 남은 용량을 활용하는 것은 불가능하다.
바인딩 프로세스 진행중에 쿠버네티스는 클레임의 요청에 따라 용량이 충분한 볼륨을 찾으려고 시도한다. (용량 외에도 액세스 모드, 볼륨 모드, 스토리지 클래스 등이 일치해야 한다.) - 😵 만약, 용량 외에 모든 옵션이 일치하고 더 나은 선택지가 없다면 PVC의 요청보다 큰 용량의 PV에 바인딩 될 수도 있다.
만약 하나의 Claim에 대해 일치하는 항목이 여러 개 있고(요청에 일치하는 볼륨이 여러 개인 경우), 특정 볼륨을 사용하고자 하는 경우 정확한 볼륨을 사용하기 위해 `labels`과 `selectors`를 사용할 수 있다.
만약 사용가능한 PV가 존재하지 않으면, 클러스터에 사용 가능한 PV가 생길 때 까지 PVC는 `Pending` 상태에 들어간다. 그러다 사용가능한 새로운 볼륨이 생성되면 자동으로 해당 볼륨에 바인딩된다.
Create PVCs
`pvc-definition.yaml`
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: [pvc-name] # ex. myclaim
spec:
accessModes:
- ReadWriteOnce
resources: # resources, request 모두 복수형이나 배열타입아님에 유의
requests:
storage: 500Mi
Create Persistent Volume Claim
kubectl create -f pvc-definition.yaml
List Persistent Volume Claims
kubectl get persistentvolumeclaim
생성된 직후 PVC는 `Pending` 상태에 머물다 자동으로 앞서 생성한 PV와 바인딩되며 Bound 상태로 변경되는 것을 볼 수 있다. (다른 사용 가능한 볼륨이 없다는 전제하에)
Cf. 해당 PV는 타 옵션은 모두 일치하나 용량이 PVC 요청보다 크다.
Delete PVCs
kubectl delete persistentvolumeclaim [pvc-name]
PVC가 삭제될 때 PV 상태를 정의하는 옵션 : `persistentVolumeReclaimPolicy`
- `Retain` : PVC 삭제 후 PV는 관리자에 의해 직접 삭제되기까지 삭제되지 않고 유지된다. 다른 PVC가 이를 사용할 수는 없다.
- `Delete` : PVC가 삭제되면 자동으로 같이 삭제 된다.
- `Recycle` : PVC가 삭제되면 다른 PVC에 사용가능해지기 전에 내부의 데이터가 모두 지워진다.
파드에서 사용되고 있는 경우 PVC를 삭제하면 `Terminating` 상태에 머물러 있는다.
- PVC가 사용되고 있는 파드를 삭제하면 PVC는 삭제되고, PV는 `persistentVolumeReclaimPolicy` 옵션에 따라 상태가 결정된다.
persistentVolumeReclaimPolicy: # [Retain|Delete|Recycle]
Using PVCs in Pods
ReplicaSet 또는 Deployment 에서도 마찬가지이다. 각각의 manifest 파일의 pod template 부분에 아래와 같이 명시하면 된다. (`containers[*].volumeMounts[*].mountPath`, `volumes[*].persistentVolumeClaim.claimName`)
`pod-definition.yaml`
apiVersion: v1
kind: Pod
metadata:
name: [pod-name]
spec:
containers:
- name: [container-name]
image: [image-name]
volumeMounts:
- mountPath: [mount-path]
name: [volume-name]
volumes:
- name: [volume-name]
persistentVolumeClaim:
claimName: [pvc-name]
'Kubernetes' 카테고리의 다른 글
k8s) Storage - 2. Storage Class (0) | 2024.03.11 |
---|---|
k8s) Security - 5. Network Policy(Ingress & Egress) (0) | 2024.03.10 |
k8s) Security - 4. Image Security, Security Contexts, (0) | 2024.03.10 |
k8s) Security - 3. Authorization(RBAC, Cluster Role, Service Account) (0) | 2024.03.10 |
k8s) Security - 2. KubeConfig, API Groups (0) | 2024.03.10 |