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로 제출.
PR 목록
- PR #12884 Unify IOException handling in cert generation paths open
- PR #12885 Use Cluster CA to establish trust in Cruise Control client in CO open