1. 배경
쿠버네티스를 운영하다 보면 PV,PVC 등의 퍼시스턴트 볼륨을 관리하는 일이 필수적으로 발생합니다. 일반 hostPath, EmptyDir 등의 볼륨은 기본적으로 사용할 수 있지만, 볼륨의 한계는 명확합니다. 데이터의 지속성, 컨테이너 간의 데이터 공유, 백업의 한계 등, 하지만 퍼시스턴트 볼륨을 사용하게 되면 하나의 쿠버네티스 리소스로 관리되어 라이프사이클을 갖게 되며, 동적 프로비저닝, 외부 스토리지 사용 등의 볼륨의 한계를 넘어 사용할 수 있어 대부분의 운영 단계에서 권장되어 사용됩니다.
이러한 퍼시스턴트 볼륨을 관리하면서 외부 스토리지를 사용하여(예를 들어 Weka Storage,NFS,AWS EBS 등) Persistent Volume를 만들고 관리하기 위해서는 CSI Driver(csi-wekaFS )를 설치 해야합니다. 제가 20년도 weka-csi
를 이용하여 운영할 당시에는 당시 csi-wekaFS가 릴리즈 된 지 얼마 안 된 시기여서 PV 생성, 운영 단계에서 오류가 많이 발생했습니다. 그 당시 문제를 파악하기 위해 어떠한 로그를 봐야 되는지 정확히 알지 못했습니다. CSI Driver의 구조는 어떻게 이루 어지 알아야 각 단계에서 문제가 발생하였을 때 어떤 로그를 봐야 되는지 알 수 있습니다. 이를 위하여 공부한 내용을 기록합니다.
2. CSI Driver 구조
CSI Driver는 기본적으로 Controller Plugin과 Node Plugin으로 나눠집니다. 일반적으로 CSI를 설치 했을 때 파드를 조회하면 다음과 같이 controller라고 적혀있는 파드와 node라는 이름의 파드를 볼 수 있습니다. Controller plugin는 Deployment나 Statefulset으로 생성되고 Node Plugin의 경우 Daemonset으로 모든 노드에 파드로 생성됩니다.
In-tree vs Out-Tree
쿠버네티스에서 네트워크 나 볼륨 플러그인을 개발할 때 주로 In-tree,Out-Of-Tree 두 가지 모델을 사용합니다. 간략하게 In-tree 모델은 쿠버네티스 코어에 포함된 드라이버를(코드베이스) 직접 사용합니다. 그렇기 때문에 새로운 드라이버를 설치하려면 쿠버네티스 코어의 코드 수정 후 컴파일 및 배포를 해야 하는 어려운 점이 있었습니다. 이러한 문제점 때문에 Out-Tree 모델, 즉 쿠버네티스의 코어와 별개로 외부에서 개발하고 관리됩니다. 이를 통해 쿠버네티스 코어를 수정하지 않고 개발 및 관리됩니다. 그렇기 때문에 현재는 대부분 Out-of-Tree 모델로 확장하는 추세입니다.
2-1. Controller
Controller 파드를 살펴보면 여러개의 컨테이터로 구성되어 있습니다. 그 중 한 개(컨트롤러이름의 컨테이너)에는 특정 스토리지 시스템의 CSI Driver가 존재하여 해당 스토리지 시스템과 통신 당담하며, 이를 통해 쿠버네티스와 통합하여, 생성, 마운트, 원마운트 등의 작업을 수행합니다(아래 그림의 vsphere-csi-controller
). 이와 Kubernetes에서 CSI Driver를 개발하기 위하여 필요한 기능을 표준화 하여 제공하는 Sidecar 컨테이너로 구성되어 있습니다.(아래 그림의 csi-attacher
)
실제로 vsphere-csi-controller
파드 내부를 확인하면 스토리지와 통신을 위한 sock 파일을 확인 할 수 있습니다.
2-2. Sidear Container 종류
external-provisoner
: external-provisioner는 Kubernetes API 서버를 모니터링하며 PVC 객체를 감지하여 그에 따를 스토리지 볼륨을 생성하기 위해 CSI 엔드포인트에 대해 CrerateVolume을 호출합니다. 볼륨은 PVC 생성 요청 트리거에 따라 생성이 되는데, PVC 스펙의 StorageClass를 참조하여 provisioner를 확인합니다. 이후 GetPluginInfo를 호출하여 해당 provisioner와 매치되는 엔드포인트를 불러와 생성합니다.
external-attacher
: external-attacher는 Kubernetes API 서버를 모니터링 하여 VolumeAttachment 객체를 감지합니다. 이를 통해 볼륨을 특정 노드나 파드에 볼륨을 attach/deattach 합니다.
external-resizer
: external-resizer는 Kubernetes API서버의를 모니터링하여 PVC의 edit이나 ControllerExpandVolume 감지하여, 볼륨의 리사이즈 기능을 지원합니다.
그 외의 쿠버네티스의 livenessprobe
기능을 활용하여 드라이버의 Health상태를 확인하는 livenessprobe sidecar
, 볼륨 스냅숏 기능을 지원하는 external-snaphost
등이 존재합니다.(Sidecar container Document)
2-2. Node Plugin
Node Plugin 영역은 Daemonset을 통해 모든 노드에 파드가 생성되니다. 파드 내부에는 CSI Node service역할(해당 노드의 Kubelet과 통신하여 볼륨을 파드와 연결/해제 작업을 통해 사용할 수 있도록 함)과 node-driver-registrar라는
사이드카 컨테이너가 존재합니다.
node-driver-registrar
는 각 노드의 kubelet과 통신하여, CSI Driver를 노드에 등록합니다. 이를 위해 Unix domain socket을 hostPath로 노드와 공유하여 socket을 저장합니다.
'Kubernetes' 카테고리의 다른 글
서비스 메쉬란?(Linkerd vs Istio) (1) | 2024.04.11 |
---|---|
Kubernetes Pod의 컨테이너는 어떻게 Localhost로 통신 할 수 있을까? (0) | 2024.02.04 |
Github Action/ Argo CD를 이용한 CI/CD 구성 (0) | 2024.01.14 |
ETCD MultiMaster Backup/Restore(CronJob 생성) (1) | 2023.11.14 |
Velero를 이용한 쿠버네티스 Backup (0) | 2023.10.12 |