OpenEBS Local PV hostpath 는 기본적으로 노드의 /var/openebs/local 아래에 볼륨 디렉터리를 만든다. 대부분의 온프레미스 노드는 /var 가 루트 볼륨 위에 있는 작은 파티션이라, 이 기본값을 그대로 두면 PVC 사용량이 루트 디스크를 갉아먹는다. 별도 디스크를 마운트한 경로로 옮기는 방법과 함께 바꿔야 하는 곳을 정리한다.
Local PV hostpath 의 basePath 는 StorageClass 의 cas.openebs.io/config 애너테이션에 들어 있다. 프로비저너는 PVC 가 참조한 StorageClass 의 이 값을 읽어 디렉터리를 만든다.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: openebs-hostpath
annotations:
openebs.io/cas-type: local
cas.openebs.io/config: |
- name: StorageType
value: "hostpath"
- name: BasePath
value: "/opt/openebs/localpv"
provisioner: openebs.io/local
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
volumeBindingMode: WaitForFirstConsumer 는 반드시 유지한다. hostpath 볼륨은 특정 노드에 묶이므로, 파드가 어느 노드로 스케줄될지 정해지기 전에 볼륨을 만들면 파드와 볼륨이 다른 노드에 놓여 마운트가 실패한다.
Helm 으로 설치할 때는 이 애너테이션을 직접 쓰는 대신 차트 값으로 지정한다. 차트가 같은 애너테이션을 만들어 준다.
localpv-provisioner:
hostpathClass:
enabled: true
name: openebs-hostpath
basePath: /opt/openebs/localpv
차트 버전에 따라 키 경로가 localpv-provisioner.hostpathClass.basePath 가 아닐 수 있다. 설치 전에 실제 값 트리를 확인한다.
helm show values openebs/openebs | grep -n -A5 -i 'hostpath\|basePath'
프로비저너 디플로이먼트의 OPENEBS_IO_BASE_PATH 환경변수는 StorageClass 에 BasePath 가 없을 때 쓰이는 기본값이다. StorageClass 에 값을 넣었다면 그쪽이 이긴다. 두 곳이 다르면 어느 쪽이 적용됐는지 헷갈리므로 맞춰 두는 편이 낫다.
OpenEBS 의 다른 컴포넌트(NDM 등)는 볼륨 데이터와 별개로 노드 작업 디렉터리를 쓴다. 기본값이 /var/openebs 라서, basePath 만 옮기고 이쪽을 두면 루트 파티션 사용이 완전히 사라지지 않는다.
varDirectoryPath:
baseDir: /opt/openebs/var
이 키 역시 차트 구성에 따라 존재하지 않을 수 있다 (확인 필요). NDM 을 쓰지 않는 구성이라면 아예 비활성화하는 편이 단순하다.
경로는 프로비저너가 자동으로 만들지 않는 경우가 있다. 모든 워커 노드에 미리 만들어 둔다.
mkdir -p /opt/openebs/localpv /opt/openebs/var
chmod 755 /opt/openebs /opt/openebs/localpv /opt/openebs/var
노드마다 경로가 다르면 스케줄된 노드에 따라 성공과 실패가 갈린다. 반드시 모든 노드에 같은 경로를 만든다.
SELinux 가 enforcing 이면 컨텍스트도 맞춘다. /var 밖의 새 경로는 기본 컨텍스트가 컨테이너 접근을 허용하지 않는다.
semanage fcontext -a -t container_file_t "/opt/openebs(/.*)?"
restorecon -Rv /opt/openebs
해당 경로의 파일 시스템 종류를 미리 확인한다. 별도 디스크를 마운트했다고 생각했는데 실제로는 루트에 그냥 디렉터리만 있는 경우가 흔하다.
df -hT /opt/openebs
stat -f -c '%T' /opt/openebs
findmnt -T /opt/openebs
PVC 를 하나 만들어 실제 디렉터리가 어디에 생기는지 본다.
kubectl get pv -o custom-columns=\
NAME:.metadata.name,PATH:.spec.local.path,NODE:.spec.nodeAffinity.required.nodeSelectorTerms[0].matchExpressions[0].values
PVC 가 Pending 에서 멈추면 이벤트를 본다.
kubectl describe pvc <PVC>
kubectl -n openebs logs -l name=openebs-localpv-provisioner --tail=100
WaitForFirstConsumer 를 쓰면 파드가 생기기 전까지는 Pending 이 정상이다. 파드를 만들었는데도 바인딩되지 않을 때만 문제로 본다.
이미 볼륨이 만들어진 뒤에 basePath 를 바꾸면 기존 PV 는 옛 경로를 그대로 가리킨다. PV 스펙의 spec.local.path 는 불변이므로, 옮기려면 데이터를 복사한 뒤 PV·PVC 를 다시 만들어야 한다. 경로는 처음 설치할 때 정하는 것이 사실상 유일한 기회다.
reclaimPolicy: Delete 로 두면 PVC 를 지울 때 노드의 디렉터리도 지워진다. 실수로 지운 뒤 되돌릴 방법이 없으므로, 중요한 데이터에는 Retain 을 쓰는 StorageClass 를 따로 만들어 둔다.