Manage TLS Certificates for Confluent Platform Using Confluent for Kubernetes

This topic describes how to manage Transport Layer Security (TLS) certificates for Confluent Platform using Confluent for Kubernetes (CFK).

Requirements and considerations

  • Plan rotation before certificate expiry.

  • There should be an overlap window between new and old certificates during the renewal process.

  • Test the rotation process first in a lower-tier, non-production environment.

Rotate user-provided server certificates

In CFK, to rotate user-provided certificates that have been provided as Kubernetes secrets, you can update the contents of the Kubernetes secrets.

For example, to rotate the server certificates that you provided in .pem files:

  1. Update the server.pem certificate and server-key.pem certificate private key.

  2. Update the Kubernetes secret using the following command:

    kubectl create secret generic component-tls \
    --from-file=fullchain.pem=server.pem \
    --from-file=cacerts.pem=ca.pem \
    --from-file=privkey.pem=server-key.pem \
    --save-config --dry-run=client -oyaml | \
    kubectl apply -f -
    

CFK watches for secret changes, detects that the content has changed, and performs a rolling restart of the component to configure the new server certificate.

Note that CFK only watches the secrets provided in the .pem format. This feature is not supported for the secrets provided in the .jks format.

Secret updates and safe rolling restarts

Confluent for Kubernetes (CFK) now treats secret updates for Kafka and KRaft similarly to ConfigMap updates when deciding whether to roll brokers.

Previously, changes to secrets (for example, TLS certificates) caused the Kubernetes StatefulSet controller to roll pods directly, without CFK’s under-replicated partition (URP) safety checks. This could lead to URPs and cluster instability during certificate rotation and other secret changes. CFK now tracks referenced secrets and performs an operator-controlled roll with URP checks when they change, providing the same safety guarantees as for ConfigMap-triggered rolls.

Approaches to updating secrets

There are two ways to update secrets in CFK:

Create a new secret and update references

Create a new secret with updated values and modify the Kafka or KRaft CR spec to reference the new secret name. This is treated as a specification change, which triggers a safe rolling restart with URP checks and proper wait conditions.

Update existing secret content

Update the content of an existing secret without changing its name. Prior to version 3.2, this approach was unsafe because it caused the StatefulSet controller to roll pods directly without CFK’s URP safety checks. Starting in version 3.2, CFK now tracks secret content changes and performs an operator-controlled roll with URP checks, providing the same safety guarantees as specification-based changes.

Both approaches now trigger safe rolling restarts with URP checks.

How secret tracking works

CFK automatically discovers all secrets referenced in the Kafka or KRaft custom resource (CR) spec (for example, TLS, listener, and authentication secrets) and tracks their Kubernetes resourceVersion values. When any tracked secret changes:

  • CFK detects the change during reconciliation.

  • CFK marks a rolling restart as required and updates the StatefulSet template with a partitioned rolling strategy.

  • The operator-controlled roll runs one broker at a time, with URP and cluster-health checks between pod restarts.

This ensures that certificate rotation and other secret updates follow the same safe roll pattern as other configuration changes.

Controlling which secrets are tracked

You can fine-tune which secrets trigger a rolling restart using annotations on the Kafka or KRaft CR.

  • platform.confluent.io/additional-tracked-secrets

    Add a comma-separated list of extra secret names to track, beyond those discovered automatically from the spec.

    annotations:
      platform.confluent.io/additional-tracked-secrets: "custom-secret-1,custom-secret-2"
    

    Use this when additional secrets are mounted or consumed in ways that are not explicitly referenced in the CR spec but should still trigger a safe roll when they change.

  • platform.confluent.io/exclude-tracked-secrets

    Add a comma-separated list of secret names that should not trigger a roll, even if they are referenced in the spec.

    annotations:
      platform.confluent.io/exclude-tracked-secrets: "monitoring-creds,logging-secret"
    

    Use this for secrets that do not affect runtime broker behavior, change frequently, or are only used by components that do not require a pod restart.

Warning

Updating the platform.confluent.io/additional-tracked-secrets or platform.confluent.io/exclude-tracked-secrets annotations on an existing cluster changes the tracked secret set and triggers a rolling restart. Configure these annotations when you create the cluster to avoid unnecessary rolls.

Viewing tracked secrets

The final list of secrets currently being tracked and their versions is available in the platform.confluent.io/tracked-secrets-versions annotation on the Kafka or KRaft CR. This annotation is automatically maintained by CFK and shows the resource version of each tracked secret.

Rotate certificate authority for user-provided certificates

You can rotate the certificate authority (CA) that you provided as Kubernetes secrets using the steps described in this section.

The examples use the .pem files for providing certificates.

Step 1. Append new certificate authority

  1. Append the new intermediate/root CA to the ca.pem file. It co-exists with the old intermediate/root CA.

    file name: ca.pem
    content:
    -----BEGIN CERTIFICATE-----
    <old root CA certificate>
    -----END CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    <new root CA certificate>
    -----END CERTIFICATE-----
    
  2. Update the secret:

    kubectl create secret generic component-tls \
    --from-file=fullchain.pem=server.pem \
    --from-file=cacerts.pem=ca.pem \
    --from-file=privkey.pem=server-key.pem \
    --save-config --dry-run=client -oyaml | \
    kubectl apply -f -
    

CFK watches for secret changes, detects that the content has changed, and performs a rolling restart for the component to configure the new root CA for use alongside the old root CA.

If this CA is for Kafka and the dynamic loading is enabled, the cluster does not roll.

Step 2. Generate server certificates with new certificate authority

  1. Generate the new server certificates with the new CA, and replace the server.pem certificate and the server-key.pem certificate private key.

  2. Update the Kubernetes secret:

    kubectl create secret generic component-tls \
    --from-file=fullchain.pem=server.pem \
    --from-file=cacerts.pem=ca.pem \
    --from-file=privkey.pem=server-key.pem \
    --save-config --dry-run=client -oyaml | \
    kubectl apply -f -
    

CFK watches for secret changes, detects that the content has changed, and performs a rolling restart for the component to configure the new server certificate.

If this certificate is for Kafka and the dynamic loading is enabled, the cluster does not roll.

Rotate certificate authority used for auto-generated certificates

In CFK, you can provide a certificate authority (CA) for Confluent Platform components to use for auto-generated certificates.

CA certificate rotation is a critical security operation that replaces an existing CA with a new one while maintaining service availability.

Follow the steps described in this section to renew the truststore and auto-generated certificates. This process maintains service availability throughout without downtime.

Wait for each step to complete before moving to the next step.

Important considerations

  • Do not apply both force-managed-truststore-renewal and force-managed-cert-renewal annotations simultaneously.

  • Always renew truststores for all components before renewing certificates.

  • Wait for each component’s rollout to complete before proceeding.

  • Plan rotation before certificate expiry.

  • Securely store and manage CA private keys.

  • Test the rotation process in a non-production environment first.

Step 1. Update CFK configuration

  1. Create CA certificates.

    Create your old (if it does not already exist) and new CA certificates.

  2. Create Kubernetes or Vault secrets for the CA certificates.

    For example:

    # Create secret for new CA
    kubectl -n <namespace> create secret tls ca-pair-sslcerts-new \
      --cert=new/ca.pem --key=new/ca-key.pem
    
  3. Update your CFK configuration to include both old and new CA certificates.

    caCertificate and oldCaCertificate support both secretRef (Kubernetes secret) and directoryPathInContainer (Vault directory path). When both are provided, directoryPathInContainer is used.

    For example:

    managedCerts:
      enabled: true
      caCertificate:
        secretRef: ca-pair-sslcerts-new  # Your new CA secret
      oldCaCertificate:
        secretRef: ca-pair-sslcerts      # Your old CA secret
    
  4. Apply the configuration.

    helm upgrade --install -f values.yaml operator confluent-for-kubernetes \
      --namespace <namespace>
    

Step 2. Renew truststore

  1. Apply the truststore renewal annotation to each Confluent Platform component.

    kubectl annotate <Component CR type> <Component CR name> platform.confluent.io/force-managed-truststore-renewal="true"
    
  2. Verify that all components truststores now have dual CAs, both old and new CA.

    kubectl exec <pod-name> -- keytool -list \
      -keystore /mnt/sslcerts/truststore.jks \
      -storepass mystorepassword | grep -c "Certificate fingerprint"
    

    You should see two certificates in each truststore.

Step 3. Renew certificates

  1. Apply the certificate renewal annotation to each Confluent Platform component.

    kubectl annotate <Component CR type> <Component CR name> platform.confluent.io/force-managed-cert-renewal="true"
    
  2. Verify that all certificates are now signed by the new CA:

    kubectl exec <pod-name> -- openssl x509 -in /mnt/sslcerts/tls.crt -text -noout | grep "Issuer:"
    

    The issuer should show your new CA.

Manage auto-generated certificates

To manage auto-generated certificates in Confluent for Kubernetes (CFK), use the following annotations in the Confluent Platform component CRs.

  • Force a renewal of auto-generated certificates:

    kubectl annotate <Component CR type> <Component CR name> \
      platform.confluent.io/force-managed-cert-renewal="true"
    

    The annotation triggers a reconciliation on the Confluent Platform component. The process causes the certificates to be renewed, and the component to be rolled.

    After the certificates are renewed, the annotation is reset to false.

  • Add additional custom SAN for auto-generated certificates. This will be added to SANs defined at the global level in managedCerts.sans in the CFK Helm values (in values.yaml).

    kubectl annotate secret ca-pair-sslcerts \
      platform.confluent.io/managed-cert-add-sans="<Comma separated list of SANs>"
    

    For example, the following annotation will add the SANs, kafka.operator, kafka.operator.local, to auto-generated certificates for Kafka:

    kubectl annotate secret ca-pair-sslcerts \
      platform.confluent.io/managed-cert-add-sans="kafka.operator, kafka.operator.local"
    

    After the annotation is set, use the platform.confluent.io/force-managed-cert-renewal="true" annotation to force a renewal of certificates. If not forced, SANs will be updated during the next reconciliation.

  • Specify the Kubernetes secret name for the CA certificates at the CR level. This will override the global config defined in managedCerts.caCertificate in the CFK Helm values (in values.yaml). This can be used even if managedCerts.enable is set to false.

    kubectl annotate <Component CR type> <Component CR name> \
      platform.confluent.io/managed-cert-ca-pair-secret=<Secret name>
    

    The secret should have tls.crt and tls.key with the CA certificate and key.

  • Configure the optional settings for auto-generated certificates at the CR level:

    kubectl annotate <Component CR type> <Component CR name> \
      platform.confluent.io/managed-cert-duration-in-days=<Number of days>
    
    kubectl annotate <Component CR type> <Component CR name> \
      platform.confluent.io/managed-cert-renew-before-in-days=<Number of days>
    

    For example:

    kubectl annotate kafka kafka platform.confluent.io/managed-cert-duration-in-days=60
    
    kubectl annotate kafka kafka platform.confluent.io/managed-cert-renew-before-in-days=30
    

    After the annotations are set, use the platform.confluent.io/force-managed-cert-renewal="true" to force a renewal of certificates.