High Availability

You can configure Control Center for an Active/Active high-availability deployment.

Considerations:
  • For Control Center 2.5 and later, alerts and triggers are automatically replicated between Control Center instances when you enable the alerts replication job. For details, see the configuration step below.

  • For a Confluent Ansible example of Control Center Active/Active high-availability setup, see the cp-ansible sample inventory.

  • For a CFK example of Control Center Active/Active high-availability setup, see the confluent-kubernetes-examples sample.

To configure Control Center Active/Active high-availability, use the following steps:

  1. Configure two instances of Control Center for your Kafka cluster.

  2. For every Kafka broker and KRaft controller, you must add and configure two HttpExporters.

    Consider the following example HttpExporter configurations:

    confluent.telemetry.exporter._c3-1.client.base.url=http://{C3-1-internal-dns-hostname}:9090/api/v1/otlp
    
    confluent.telemetry.exporter._c3-2.client.base.url=http://{C3-2-internal-dns-hostname}:9090/api/v1/otlp
    
    • Replace {C3-1-internal-dns-hostname} and {C3-2-internal-dns-hostname} with the internal DNS hostnames (or IP addresses) of the corresponding Control Center instances.

  3. For every Kafka broker and KRaft controller, add the following configurations:

    #common configs
    
    confluent.telemetry.metrics.collector.interval.ms=60000
    confluent.telemetry.remoteconfig._confluent.enabled=false
    confluent.consumer.lag.emitter.enabled=true
    metric.reporters=io.confluent.telemetry.reporter.TelemetryReporter
    
    # instance 1 configs
    
    confluent.telemetry.exporter._c3.type=http
    confluent.telemetry.exporter._c3.enabled=true
    confluent.telemetry.exporter._c3.client.base.url=http://{C3-1-internal-dns-hostname}:9090/api/v1/otlp
    confluent.telemetry.exporter._c3.client.compression=gzip
    confluent.telemetry.exporter._c3.api.key=dummy
    confluent.telemetry.exporter._c3.api.secret=dummy
    confluent.telemetry.exporter._c3.buffer.pending.batches.max=80
    confluent.telemetry.exporter._c3.buffer.batch.items.max=4000
    confluent.telemetry.exporter._c3.buffer.inflight.submissions.max=10
    confluent.telemetry.exporter._c3.metrics.include=io.confluent.kafka.server.request.(?!.*delta).*|io.confluent.kafka.server.server.broker.state|io.confluent.kafka.server.replica.manager.leader.count|io.confluent.kafka.server.request.queue.size|io.confluent.kafka.server.broker.topic.failed.produce.requests.rate.1.min|io.confluent.kafka.server.tier.archiver.total.lag|io.confluent.kafka.server.request.total.time.ms.p99|io.confluent.kafka.server.broker.topic.failed.fetch.requests.rate.1.min|io.confluent.kafka.server.broker.topic.total.fetch.requests.rate.1.min|io.confluent.kafka.server.partition.caught.up.replicas.count|io.confluent.kafka.server.partition.observer.replicas.count|io.confluent.kafka.server.tier.tasks.num.partitions.in.error|io.confluent.kafka.server.broker.topic.bytes.out.rate.1.min|io.confluent.kafka.server.request.total.time.ms.p95|io.confluent.kafka.server.controller.active.controller.count|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.total|io.confluent.kafka.server.request.total.time.ms.p999|io.confluent.kafka.server.controller.active.broker.count|io.confluent.kafka.server.request.handler.pool.request.handler.avg.idle.percent.rate.1.min|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.rate.1.min|io.confluent.kafka.server.controller.unclean.leader.elections.rate.1.min|io.confluent.kafka.server.replica.manager.partition.count|io.confluent.kafka.server.controller.unclean.leader.elections.total|io.confluent.kafka.server.partition.replicas.count|io.confluent.kafka.server.broker.topic.total.produce.requests.rate.1.min|io.confluent.kafka.server.controller.offline.partitions.count|io.confluent.kafka.server.socket.server.network.processor.avg.idle.percent|io.confluent.kafka.server.partition.under.replicated|io.confluent.kafka.server.log.log.start.offset|io.confluent.kafka.server.log.tier.size|io.confluent.kafka.server.log.size|io.confluent.kafka.server.tier.fetcher.bytes.fetched.total|io.confluent.kafka.server.request.total.time.ms.p50|io.confluent.kafka.server.tenant.consumer.lag.offsets|io.confluent.kafka.server.session.expire.listener.zookeeper.expires.rate.1.min|io.confluent.kafka.server.log.log.end.offset|io.confluent.kafka.server.broker.topic.bytes.in.rate.1.min|io.confluent.kafka.server.partition.under.min.isr|io.confluent.kafka.server.partition.in.sync.replicas.count|io.confluent.telemetry.http.exporter.batches.dropped|io.confluent.telemetry.http.exporter.items.total|io.confluent.telemetry.http.exporter.items.succeeded|io.confluent.telemetry.http.exporter.send.time.total.millis|io.confluent.kafka.server.controller.leader.election.rate.(?!.*delta).*|io.confluent.telemetry.http.exporter.batches.failed
    
    # instance 2 configs
    
    confluent.telemetry.exporter._c3-2.type=http
    confluent.telemetry.exporter._c3-2.enabled=true
    confluent.telemetry.exporter._c3-2.client.compression=gzip
    confluent.telemetry.exporter._c3-2.api.key=dummy
    confluent.telemetry.exporter._c3-2.api.secret=dummy
    confluent.telemetry.exporter._c3-2.buffer.pending.batches.max=80
    confluent.telemetry.exporter._c3-2.buffer.batch.items.max=4000
    confluent.telemetry.exporter._c3-2.buffer.inflight.submissions.max=10
    confluent.telemetry.exporter._c3-2.client.base.url=http://{C3-2-internal-dns-hostname}:9090/api/v1/otlp
    confluent.telemetry.exporter._c3-2.metrics.include=io.confluent.kafka.server.request.(?!.*delta).*|io.confluent.kafka.server.server.broker.state|io.confluent.kafka.server.replica.manager.leader.count|io.confluent.kafka.server.request.queue.size|io.confluent.kafka.server.broker.topic.failed.produce.requests.rate.1.min|io.confluent.kafka.server.tier.archiver.total.lag|io.confluent.kafka.server.request.total.time.ms.p99|io.confluent.kafka.server.broker.topic.failed.fetch.requests.rate.1.min|io.confluent.kafka.server.broker.topic.total.fetch.requests.rate.1.min|io.confluent.kafka.server.partition.caught.up.replicas.count|io.confluent.kafka.server.partition.observer.replicas.count|io.confluent.kafka.server.tier.tasks.num.partitions.in.error|io.confluent.kafka.server.broker.topic.bytes.out.rate.1.min|io.confluent.kafka.server.request.total.time.ms.p95|io.confluent.kafka.server.controller.active.controller.count|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.total|io.confluent.kafka.server.request.total.time.ms.p999|io.confluent.kafka.server.controller.active.broker.count|io.confluent.kafka.server.request.handler.pool.request.handler.avg.idle.percent.rate.1.min|io.confluent.kafka.server.session.expire.listener.zookeeper.disconnects.rate.1.min|io.confluent.kafka.server.controller.unclean.leader.elections.rate.1.min|io.confluent.kafka.server.replica.manager.partition.count|io.confluent.kafka.server.controller.unclean.leader.elections.total|io.confluent.kafka.server.partition.replicas.count|io.confluent.kafka.server.broker.topic.total.produce.requests.rate.1.min|io.confluent.kafka.server.controller.offline.partitions.count|io.confluent.kafka.server.socket.server.network.processor.avg.idle.percent|io.confluent.kafka.server.partition.under.replicated|io.confluent.kafka.server.log.log.start.offset|io.confluent.kafka.server.log.tier.size|io.confluent.kafka.server.log.size|io.confluent.kafka.server.tier.fetcher.bytes.fetched.total|io.confluent.kafka.server.request.total.time.ms.p50|io.confluent.kafka.server.tenant.consumer.lag.offsets|io.confluent.kafka.server.session.expire.listener.zookeeper.expires.rate.1.min|io.confluent.kafka.server.log.log.end.offset|io.confluent.kafka.server.broker.topic.bytes.in.rate.1.min|io.confluent.kafka.server.partition.under.min.isr|io.confluent.kafka.server.partition.in.sync.replicas.count|io.confluent.telemetry.http.exporter.batches.dropped|io.confluent.telemetry.http.exporter.items.total|io.confluent.telemetry.http.exporter.items.succeeded|io.confluent.telemetry.http.exporter.send.time.total.millis|io.confluent.kafka.server.controller.leader.election.rate.(?!.*delta).*|io.confluent.telemetry.http.exporter.batches.failed
    
  4. On each Control Center instance, enable the alerts replication job so that alerts and triggers are automatically replicated between instances. Add the following configuration to the Control Center properties file:

    confluent.controlcenter.prometheus.alertmanager.yaml.refresh.enabled=true
    

    This setting is available in Control Center 2.5 and later. For the full list of configuration properties, see Control Center Configuration Reference for Confluent Platform.