Contribution · Strimzi · Kafka Operator

Strimzi — IOException 처리 일관성 (GH-12847)

Strimzi Kafka Operator의 cert 생성 경로에서 KafkaClusterIOExceptionRuntimeException으로 던져 reconciliation을 실패시키고, CruiseControl·ClusterCa#maybeCopyOrGenerateClientCert는 warning만 로그하고 빈 secret data / null CertAndKey로 진행해 호출자(KafkaExporter 등)가 NPE에 닿는 비대칭을 통일.

문제 — GH-12847

세 경로가 같은 조건(cert 생성 중 IOException)에 다르게 반응:

  • KafkaCluster#generatePerBrokerKafkaSecretsForPoolIOExceptionRuntimeException으로 wrap → reconciliation 실패, 문제 가시화.
  • CruiseControl#generateCertificatesSecret — warning만 로그하고 continue → 빈 dataSecret 생성, 바로 다음 줄 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를 만들어 maybeCopyOrGenerateClientCertRuntimeException(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-operatorKafkaListener.getConnectionSecretData가 Cluster CA Secret의 ca.crtssl.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 목록

관련 자료