k8s - Role, Volume!
Volume
k8s 는 기본적으로 stateless 앱 컨테이너를 관리한다.
하지만 DB, Storage 같은 서비스 특성에 따라 데이터를 영구 보관해야 하는 경우가 있다.k8s 에서도 restart 시 데이터가 지워지지 않도록 Volume 을 설정할 수 있다.
상용 클라우드 서비스에서
awsElasticBlockStore,azureDisk,gcePersistentDisk등 클라우드 자체 볼륨 서비스도 제공한다.
k8s 에서 사용할 수 있는 Volume 플러그인이 굉장히 많은데 아래 두가지만 알아본다.
- emptyDir
- hostPath
emptyDir 은 Pod 가 실행되는 노드의 디스크를 임시로 컨테이너 볼륨으로 할당해 사용한다. Pod 가 사라지때 emptyDir 도 같이 사라진다.
배치나 학습과 같은 오랜 시간이 걸릴 때 임시데이터 저장용으로 사용한다.
1 | apiVersion: v1 |
hostPath 또한 노드의 디스크를 컨테이너 볼륨으로 사용하지만 Pod 가 종료되더라도 데이터가 남는다.
중요 데이터를 보존하는 역할로 사용하거나 노드의 시스템 디렉토리를 마운트해서 모니터링 용도로 사용할 수 있다.
1 | apiVersion: v1 |
type 으로는 아래와 같은 값들이 올 수 있다.
DirectoryOrCreate: 경로에 디렉토리가 없으면 755 권한으로 생성DirectoryFileOrCreateFileSocket,CharDevice,BlockDevice등
PV, PVC
위의 spec.volumes 속성은 해당 k8s 서비스에 임의의 저장공간을 할당하지만,PersistentVolume 을 만들면 다른 서비스도 사용할 수 있는 저장공간을 만들 수 있다.
이때 사용하는 k8s 리소스 종류가 아래 2가지
PV(PersistentVolume)
Volume 자체를 뜻함PVC(PersistentVolumeClaim)
사용자가 PV 에 하는 요청(사용 용량, rw 모드 등)
PV 와 PVC 의 매핑은 1:1 관계이다.
대부분의 경우 클러스터 관리자가PV을 생성하고, 개발자가PVC를 생성한다.
manifast
PV 와 PVC 를 생성하고 서로 연결한다.
1 | # pv-hostpath.yaml |
PV 의 persistentVolumeReclaimPolicy 종류는 아래 3개.
- Delete:
PVC삭제시 볼륨도 같이 삭제됨, 기본반환정책이Delete. - Retain:
PVC삭제되어도PV는 그대로 보존,PVC를 다시 생성해서 재사용 가능. - Recycle: deprecated 됨,
PV의 데이터들을 삭제하고 다시 새로운PVC에서PV를 사용할 수 있도록 함.
여기선 persistentVolumeReclaimPolicy 가 Delete 임으로 PVC 가 해제되면 PV 도 같이 삭제된다.
1 | # pvc-hostpath.yaml |
PVC 의 accessModes 종류는 아래 3개
ReadWriteOnce: 노드 하나에만 볼륨을 읽기/쓰기하도록 마운트할 수 있음ReadOnlyMany: 여러 개 노드에서 읽기 전용으로 마운트할 수 있음ReadWriteMany: 여러 개 노드에서 읽기/쓰기 가능하도록 마운트할 수 있음
PV 의 clameRef 를 통해 request 하는 PVC 를 제한할 수 있다.
.metadata.labels.location필드를 사용해 조건식으로PVC를 매핑할 수 도 있으니 참고
PVC 의 resources 속성을 보면 PV 의 용량보다 적어도 상관 없는 이유는 조건에 따라 용량이 조금 오바되어도 상관없는 정책이 있기 때문
1 | # pv 생성 |
PV 에 PVC 에 연결 된 후 STATUS 상태가 Available -> Bound 로 변경됨을 확인.
Pod 에서 PVC 사용
파드에서 PVC 사용하기 위해서 마찬가지로 volumeMounts, volumes 속성을 사용한다.
1 | apiVersion: apps/v1 |
PV 생명주기
PV(볼륨) 가 생성되고 삭제되는 과정은 아래 그림과 같다.
1. Provisioning, PV 를 만드는 단계
아래 2가지 방법이 있다.
static방법:PV를 미리 만들어 두고 사용dynamic방법: 요청이 있을 때마다PV를 만듬
2. Binding, PV 를 PVC 와 연결하는 단계PVC 에서 원하는 스토리지의 용량과 접근방법을 명시해 요청시 알맞은 PV 가 할당된다.
3. Using, PVC 와 PV 가 바인딩 되어 사용되는 단계Pod 가 PVC 를 볼륨으로 인식해서 실제 디스크에 읽기/쓰기 진행,PVC 가 사용되는 동안 시스템에서 임의로 삭제할 수 없음
스토리지 오브젝트 보호(Storage Objectin Use Protection) 단계라고도 한다.
사용중인 데이터 스토리지를 임의로 삭제하면 치명적인 결과가 발생할 수 있으므로
4. Reclaiming, 사용이 끝난 PVC 와 PV 가 삭제되는 단계
사용중이던 PVC 를 제거, PV 반환 정책에 의해 저장공간이 삭제되거나 유지됨.
StorageClass
위에서 PV 는 클러스터 관리자가 수동으로 생성한다 하였는데 이러한 과정이 번거로울 수 있다.
또한 개발자가 Pod 를 생성할 때 얼만큼의 용량을 설정해 PVC 를 만들지 모름으로 미리 PV 를 생성해 놓기도 애매하다.
StorageClass 는 관리자의 개입없이 동적으로 PV 생성을 지원한다.
아래는 AWS EBS 를 통해 StorageClass 를 사용하는 예.
1 | apiVersion: storage.k8s.io/v1 |
- provisioner
스토리지 제공자,aws-ebs외에도 여러 상용 클러스터에서provisioner를 지원함 - volumeBindingMode
Immediate: PVC 생성시 바인딩WaitForFirstConsumer: PVC 와 이를 사용하는 Pod 생성시 바인딩
- parameters
provisioner종류별로 상이함
k8s v1.23부터EBS, EFS로StorageClass를 생성하려면 별도의CSI 드라이버설치가 필요하다.
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/ebs-csi.html
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/efs-csi.html
rancher
베어메탈 클러스터를 구성했다면 로컬 스토리지를 provisioner 로 사용하기 위한 별도 설정을 지정해줘야 한다.
이때 로컬 스토리지 provisioner 로 rancher 를 많이 사용한다.
1 | curl https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.24/deploy/local-path-storage.yaml -o local-storage.yaml |
local-path 라는 이름으로 StorageClass 가 생성됨을 볼 수 있다.
데모로 아래 PVC 와 Deployment 를 생성
1 | # test-rancher.yaml |
1 | kubectl apply -f test-rancher.yaml |
/opt/local-path-provisioner 위치(혹은 개인설정한 위치)로 이동해 PV 가 생성되고 그 안에 로그파일이 있는지 확인.
기본적으로 설정되는 /opt/local-path-provisioner 경로를 변경하고 싶다면 nodePathMap 에 원하는 경로로 변경
1 | data: |
CRD
k8s 는 기본적으로 Pod, Service, Deployment 등 다양한 리소스를 제공하지만, 사용자의 요구사항에 딱 맞는 리소스가 없을 수 있다.
이때 CRD(CustomResourceDefinition) 를 사용하면 사용자가 직접 리소스를 정의하여 k8s API 를 확장할 수 있다.
CRD 자체는 단순히 데이터 형식을 정의하고 etcd 에 저장하는 역할만 수행한다.
실제로 리소스가 생성되었을 때 특정 동작(파드 생성, 설정 변경 등)을 수행하려면 Controller 를 별도로 구현해야 한다.
이러한 CRD + Custom Controller 구조를 Operator 패턴 이라고 한다.
CRD 생성
아래는 CronTab 이라는 이름의 커스텀 리소스를 정의하는 yaml 파일이다.
1 | apiVersion: apiextensions.k8s.io/v1 |
Custom Resource 생성
위에서 정의한 CRD 를 기반으로 실제 리소스를 생성할 수 있다.
1 | apiVersion: stable.example.com/v1 |
이렇게 생성된 리소스는 kubectl get crontab 명령어로 조회할 수 있다.