Contribution · Strimzi · Kafka Operator
Strimzi — IOException 처리 일관성 (GH-12847)
Strimzi Kafka Operator의 cert 생성 경로에서 KafkaCluster만 IOException → RuntimeException으로 던져 reconciliation을 실패시키고, CruiseControl·ClusterCa#maybeCopyOrGenerateClientCert는 warning만 로그하고 빈 secret data / null CertAndKey로 진행해 호출자(KafkaExporter 등)가 NPE에 닿는 비대칭을 통일.
문제 — GH-12847
세 경로가 같은 조건(cert 생성 중 IOException)에 다르게 반응:
KafkaCluster#generatePerBrokerKafkaSecretsForPool—IOException을RuntimeException으로 wrap → reconciliation 실패, 문제 가시화.CruiseControl#generateCertificatesSecret— warning만 로그하고 continue → 빈data의Secret생성, 바로 다음 줄ccCerts.get(...).caCertGeneration()에서 NPE.ClusterCa#maybeCopyOrGenerateClientCert— warning만 로그하고null반환 → 호출자(KafkaExporter,EntityOperator,EntityTopicOperator,EntityUserOperator,CaReconciler)가caCertGeneration()호출에서 NPE.
수정 (PR #12884)
CruiseControl·ClusterCa의 catch 블록에서 기존 warning 로그는 유지한 채 RuntimeException을 throw하도록 한 줄씩 추가. KafkaCluster 패턴과 동일한 동작이 되어 silent 빈 secret / NPE 경로가 사라지고 reconciliation이 fast-fail.
회귀 테스트는 ClusterCaRenewalTest#testClientCertGenerationFailureSurfacesAsRuntimeException으로 추가 — generateSignedCert에서 IOException을 throw하는 anonymous subclass를 만들어 maybeCopyOrGenerateClientCert가 RuntimeException(cause = 원본 IOException)을 던지는지 검증. 기존 130개 테스트(ClusterCaRenewalTest, CruiseControlTest, KafkaExporterTest, EntityOperatorTest, EntityUserOperatorTest, EntityTopicOperatorTest, CaReconcilerTest) 모두 그대로 통과.
두 번째 — Cruise Control client trust via Cluster CA (GH-12442)
Cluster Operator의 Cruise Control 클라이언트(CruiseControlApiImpl)가 CC 서버 Secret을 PemTrustSet으로 만들어 트러스트했음 — 즉 CC 서버 공개키를 핀하는 형태. Cluster CA 롤 + CC 서버 cert 회전 사이에 열린 rebalance 연결은 새 서버 cert를 못 믿어 실패. KafkaResources.clusterCaCertificateSecretName(...)을 fetch해 CA 기반 트러스트로 전환 — CA가 sign한 새 서버 cert가 자동으로 신뢰됨. PR #12885로 제출.
세 번째 — MM2 Grafana 대시보드 SMR 라벨 (GH-12870)
MirrorMaker 2 Grafana 대시보드(packaging/examples/metrics/strimzi-metrics-reporter/grafana-dashboards/strimzi-kafka-mirror-maker-2.json)의 replication-consumer lag 패널 두 개가 Strimzi Metrics Reporter 환경에서 빈 그래프를 그림. PromQL 필터가 JMX Exporter 시절 라벨 표기(clientid=~".*replication-consumer\"", 값 끝에 escaped quote)에 묶여 있어 SMR이 내보내는 라벨(client_id, unquoted)과 매칭이 안 됨. 같은 파일의 producer-side {{clientid}} legend 한 곳까지 같은 SMR 컨벤션으로 정리. examples/ 트리는 릴리스 때만 갱신된다는 컨벤션에 맞춰 packaging/examples/만 수정. PR #12889로 제출.
네 번째 — KAO ssl.truststore.crt CA 번들 (kafka-access-operator GH-124)
kafka-access-operator의 KafkaListener.getConnectionSecretData가 Cluster CA Secret의 ca.crt만 ssl.truststore.crt에 담아, CA 키 교체 중 Secret에 이전/신규 CA(ca-<notAfter>.crt)가 함께 존재해도 클라이언트는 한쪽만 신뢰 → 롤 진행 중 접속 실패. Cluster CA Secret의 모든 .crt 엔트리를 sorted key 순으로 번들로 묶어 ssl.truststore.crt에 담음. 개별 엔트리가 chain이면 trust anchor만 포함(중간 인증서는 핸드셰이크에서 브로커가 내려줌), ca.p12·ca.password 등 비-.crt 엔트리는 무시. PR #143으로 제출.
PR 목록
- PR #12884 Unify IOException handling in cert generation paths merged
- PR #12885 Use Cluster CA to establish trust in Cruise Control client in CO merged
- PR #12889 Fix MM2 Grafana dashboards for Strimzi Metrics Reporter merged
- KAO PR #143 Bundle all cluster CAs in ssl.truststore.crt open · awaiting triage