Cloudera Flow Management(CFM) Kubernetes Operator 는 NiFi 와 NiFi Registry 를 쿠버네티스 CR 로 선언해 배포하는 오퍼레이터다. 직접 StatefulSet 을 짜는 대신 Nifi 리소스 하나를 적용하면 오퍼레이터가 파드 · 서비스 · ConfigMap · Ingress 를 만들어 준다.
선행 조건은 세 가지다 — 쿠버네티스 1.23 이상(또는 OpenShift 4.10 이상), cert-manager(오퍼레이터 웹훅용), 그리고 CFM 라이선스 파일. 폐쇄망이면 여기에 이미지 사전 반입이 더해진다.
| 방법 | CRD 설치 | 비고 |
|---|---|---|
helm install (차트 tgz) |
--set installCRDs=true 를 줘야 설치됨 |
빠뜨리면 Nifi kind 를 인식하지 못한다 |
cfmctl install |
자동 | 내부적으로 Helm 을 사용한다 |
두 방법은 같은 Helm 릴리스를 대상으로 하므로 섞어서 쓰면 충돌한다. Helm 으로 먼저 깔아 둔 상태에서 cfmctl install 을 같은 버전으로 실행하면 이렇게 거부된다.
Error: upgrade must be for a newer version. existing-version: X.Y.Z-bNNN, new-version: X.Y.Z-bNNN
helm uninstall cfm-operator -n cfm-operator-system 으로 기존 릴리스를 지운 뒤 한쪽 방법으로만 진행한다.
cfmctl install \
--license ./license.txt \
--image-repository harbor.example.local/cfm/cfm-operator \
--image-tag ${OPERATOR_TAG} \
--namespace cfm-operator-system
--license 에는 Cloudera 에서 발급한 CFM 라이선스 JSON 파일 경로를 준다. CDP 구독 라이선스와 별개의 파일이며, 없으면 오퍼레이터가 기동하지 않는다.
cfmctl airgap 같은 번들 생성 명령은 없다. 폐쇄망이면 차트 tgz 와 이미지를 따로 반입한 뒤 --image-repository 로 내부 레지스트리를 가리킨다.
kubectl apply -f nifi.yaml 이 이 메시지로 실패하면 CRD 가 없거나 버전이 다르다.
error: resource mapping not found for name: "my-nifi" ...
no matches for kind "Nifi" in version "cfm.cloudera.com/v1beta1"
ensure CRDs are installed first
API 버전은 오퍼레이터 버전마다 다르다. 문서 예시를 그대로 복사하면 자주 어긋난다. 클러스터에 실제로 등록된 버전을 확인해 매니페스트를 맞춘다.
kubectl get crd | grep cfm.cloudera.com
kubectl get crd nifis.cfm.cloudera.com -o jsonpath='{.spec.versions[*].name}'; echo
kubectl explain nifi.spec --api-version=cfm.cloudera.com/v1alpha1
CRD 가 아예 없으면 차트에서 빠진 것이다. 차트 tgz 만 있는 상태에서 CRD 만 먼저 넣어야 한다면 아래로 확인한다.
helm template cfm-operator ./cfm-operator-${VERSION}.tgz --set installCRDs=true \
| grep -A2 'kind: CustomResourceDefinition'
apiVersion: cfm.cloudera.com/v1alpha1
kind: Nifi
metadata:
name: my-nifi
namespace: my-nifi
spec:
replicas: 1
image:
repository: harbor.example.local/cfm/cfm-nifi-k8s
tag: ${NIFI_IMAGE_TAG}
pullSecret: docker-pull-secret
tiniImage:
repository: harbor.example.local/cfm/cfm-tini
tag: ${OPERATOR_TAG}
pullSecret: docker-pull-secret
hostName: nifi.example.local
uiConnection:
type: Ingress
annotations:
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/affinity-mode: persistent
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
resources:
nifi:
requests: { cpu: "1", memory: 2Gi }
limits: { cpu: "4", memory: 4Gi }
hostName 은 실제로 해석되는 이름이어야 한다. Cloudera 문서의 OpenShift 예시에 있는 mynifi.[***OPENSHIFT ROUTER DOMAIN***] 을 그대로 두면 NiFi 가 부팅 중에 자기 주소를 확정하지 못한다.
pullSecret 은 해당 네임스페이스 안에 있어야 한다. 다른 네임스페이스의 시크릿은 참조되지 않는다.
파드가 CrashLoopBackOff 로 돌면 컨테이너가 여럿이므로 로그를 컨테이너별로 본다.
kubectl -n my-nifi get pod
kubectl -n my-nifi describe pod my-nifi-0 | grep -A10 'State:\|Events:'
# NiFi 본체
kubectl -n my-nifi logs my-nifi-0 -c nifi --previous
# 부트스트랩 로그 사이드카
kubectl -n my-nifi logs my-nifi-0 -c bootstrap-log --previous
# 오퍼레이터가 생성한 설정 확인
kubectl -n my-nifi get cm my-nifi-nifi-properties -o yaml \
| egrep 'nifi.web.https.host|nifi.cluster.node.address|nifi.remote.input.host'
여기서 치환되지 않은 자리표시자(<<FQDN>> 같은 값)가 남아 있으면 spec.hostName 이 제대로 반영되지 않은 것이다.
컨테이너가 계속 죽으면 kubectl exec 도 들어가지 않는다. 이때는 임시 디버그 컨테이너를 붙이거나, PVC 를 다른 파드에 마운트해 내용만 확인한다.
kubectl -n my-nifi get sts my-nifi -o jsonpath='{.spec.volumeClaimTemplates[*].metadata.name}'; echo
kubectl -n my-nifi debug -it my-nifi-0 --image=busybox:1.36 --target=nifi
원본 대화에서는 오퍼레이터 설치까지는 끝났으나 my-nifi-0 파드가 반복적으로 죽는 상태에서 기록이 끊긴다. 남은 확인 지점은 아래와 같다.
uiConnection.type: Ingress 는 HTTPS 를 전제한다. ssl-passthrough 를 쓰려면 ingress-nginx 컨트롤러에 --enable-ssl-passthrough 가 켜져 있어야 한다. 켜져 있지 않으면 Ingress 는 만들어지지만 실제 연결이 되지 않는다. 시험 단계에서는 uiConnection.type: Service 로 바꿔 포트 포워딩으로 먼저 확인하는 편이 빠르다.replicas 2 이상)는 별도 ZooKeeper 를 요구하는 버전이 있다. 단일 노드로 먼저 띄워 본다.flow.xml.gz 를 들고 있으면 새 설정과 충돌한다. 시험 중이라면 PVC 를 지우고 다시 만든다.