워크벤치가 만드는 워크로드(모델 · 앱 · 실험) 의 엔드포인트는 무작위로 생성되므로, TLS 가 동작하려면 인증서에 와일드카드 SAN 과 워크벤치 서브도메인 SAN 이 함께 있어야 한다.
CN : cml.apps.cdp.mycompany.com
SAN : *.cml.apps.cdp.mycompany.com
SAN : cml.apps.cdp.mycompany.com
와일드카드는 한 단계 서브도메인만 커버하므로 *.company.com 인증서로는 *.cml.apps.company.com 을 보호할 수 없다. 워크벤치 엔드포인트가 한 단계 더 깊어 전용 인증서를 따로 발급해야 하는 이유다.
정적 서브도메인(static subdomain) 을 정해 두면 워크벤치 생성 전에 인증서를 미리 발급할 수 있다. 정하지 않으면 ml-1234abc-123 같은 ID 가 자동 생성돼 띄워 봐야 도메인이 확정되므로 발급이 번거롭다.
적용 흐름은 프로비저닝 시 Enable TLS 선택 → .crt/.key 확보 → ECS 는 cml_utils.sh upload-cert 로 업로드(또는 cml-tls-secret 이름의 secret 생성) → 루트 CA 를 Site Administration 의 Root CA configuration 에 업로드 순이다.
Cloudera AI 는 암호화된 개인키를 지원하지 않는다.
head -5 /opt/cloudera/certs/ingress.key
-----BEGIN ENCRYPTED PRIVATE KEY----- 이거나 Proc-Type: 4,ENCRYPTED · DEK-Info: 줄이 있으면 암호가 걸린 키다. -----BEGIN RSA PRIVATE KEY----- 헤더는 양쪽 다 가능하므로 확실하게는 빈 암호로 읽히는지 본다.
openssl rsa -in ingress.key -check -noout -passin pass: # "RSA key ok" 면 평문
openssl pkey -in ingress.key -noout -passin pass: 2>&1 # RSA 가 아닐 수도 있으니 범용 확인
openssl rsa -in ingress.key -out ingress-nopass.key # 암호 해제
AI Registry 는 별도 Istio 게이트웨이로 동작해 공유 인증서를 쓸 수 없고, 단일 FQDN 전용(와일드카드 금지, 기존 Cloudera 인증서와도 달라야 함) 인증서가 필요하다. 그 FQDN 은 Cloudera AI → AI Registries → 해당 레지스트리 → Details → Domain 에 표시된 값을 글자 그대로 써야 한다.
kubectl get gateway -A -o yaml | grep -i -B25 "ingress-default-cert-mr" \
| grep -iE "hosts:|registry|model|credentialName"
kubectl get virtualservice -A | grep -i -E "registry|mr"
kubectl get secret ingress-default-cert-mr -n istio-ingress \
-o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -subject -ext subjectAltName -dates
cd /root/certs
DOMAIN="<Details 의 Domain 값 그대로>"
cat > mr.cnf <<EOF
[req]
prompt = no
distinguished_name = dn
req_extensions = req_ext
[dn]
CN = ${DOMAIN}
[req_ext]
subjectAltName = DNS:${DOMAIN}
EOF
openssl genrsa -out mr.key 2048 # 평문 키
openssl req -new -key mr.key -out mr.csr -config mr.cnf
openssl x509 -req -in mr.csr \
-CA rootCA.pem -CAkey rootCA.key -CAcreateserial \
-out mr.crt -days 825 -sha256 \
-extfile <(printf "subjectAltName=DNS:${DOMAIN}\nextendedKeyUsage=serverAuth\nbasicConstraints=CA:FALSE\nkeyUsage=digitalSignature,keyEncipherment")
# 세 가지 모두 통과해야 한다
openssl x509 -in mr.crt -noout -subject -ext subjectAltName
openssl verify -CAfile rootCA.pem mr.crt
diff <(openssl x509 -in mr.crt -noout -modulus | openssl md5) \
<(openssl rsa -in mr.key -noout -modulus | openssl md5)
업로드는 ECS 마스터에서 한다.
scp /root/certs/mr.crt /root/certs/mr.key root@<ecs-master>:/root/certs/
cd /opt/cloudera/parcels/ECS/bin/
./cml_utils.sh upload-cert-cair -c /root/certs/mr.crt -k /root/certs/mr.key
# 엔드포인트가 새 인증서를 내려주는지
echo | openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
curl -v --cacert /root/certs/rootCA.pem https://${DOMAIN}/ 2>&1 | grep -E "subject:|issuer:|SSL certificate verify|HTTP/"
# 옛 인증서가 계속 나오면 게이트웨이 재시작
kubectl rollout restart deployment -n istio-ingress
model-registry-ml-14d13b18-ecd.apps.<cluster> 처럼 인스턴스 ID 가 박힌 도메인이 이상해 보여 modelregistry.apps.<cluster> 로 인증서를 다시 만들었는데, 그 호스트에서 내려오는 인증서는 CN=apps.<cluster> 에 issuer 도 예전 것이었다. 즉 그 호스트는 전용 AI Registry 게이트웨이가 아니라 와일드카드 ingress 의 catch-all 로 떨어지고 있었고, 자동 생성된 ID 형태가 오히려 진짜 Domain 이었을 가능성이 크다.
for H in model-registry-ml-<id>.apps.<cluster> modelregistry.apps.<cluster>; do
echo "== $H =="
echo | openssl s_client -connect ${H}:443 -servername ${H} 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
done
새로 만든 인증서(오늘 날짜, CN 이 그 도메인) 를 내려주는 쪽이 진짜 도메인이다.
모델 아티팩트를 저장할 S3 호환 스토리지(또는 Ozone) 가 환경에 등록되지 않은 경우가 가장 많고, 그다음이 노드 리소스 부족(kubectl describe pod 의 스케줄 실패 이벤트), TLS · 루트 CA 불일치로 ingress 라우트가 잡히지 않는 경우, 워크벤치와 AI Registry 의 버전 호환 문제다.
실제 Domain 확정과 그 도메인으로 재발급한 인증서의 적용 결과는 대화에 남아 있지 않다.