Configures a Kafka cluster using the `Kafka` custom resource.

The `config` properties are one part of the overall configuration for the resource.
Use the `config` properties to configure Kafka broker options as keys.

.Example Kafka configuration
[source,yaml,subs="+attributes"]
----
apiVersion: {KafkaApiVersion}
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    version: {DefaultKafkaVersion}
    metadataVersion: {DefaultKafkaMetadataVersion}
    # ...
    config:
      auto.create.topics.enable: "false"
      offsets.topic.replication.factor: 3
      transaction.state.log.replication.factor: 3
      transaction.state.log.min.isr: 2
      default.replication.factor: 3
      min.insync.replicas: 2
# ...
----

The values can be one of the following JSON types:

* String
* Number
* Boolean

*Exceptions*

You can specify and configure the options listed in the {ApacheKafkaBrokerConfig}.

However, Strimzi takes care of configuring and managing options related to the following, which cannot be changed:

* Security (encryption, authentication, and authorization)
* Listener configuration
* Broker ID configuration
* Configuration of log data directories
* Inter-broker communication
* ZooKeeper connectivity

Properties with the following prefixes cannot be set:

* `advertised.`
* `authorizer.`
* `broker.`
* `controller`
* `cruise.control.metrics.reporter.bootstrap.`
* `cruise.control.metrics.topic`
* `host.name`
* `inter.broker.listener.name`
* `listener.`
* `listeners.`
* `log.dir`
* `password.`
* `port`
* `process.roles`
* `sasl.`
* `security.`
* `servers,node.id`
* `ssl.`
* `super.user`
* `zookeeper.clientCnxnSocket`
* `zookeeper.connect`
* `zookeeper.set.acl`
* `zookeeper.ssl`

If the `config` property contains an option that cannot be changed, it is disregarded, and a warning message is logged to the Cluster Operator log file.
All other supported options are forwarded to Kafka, including the following exceptions to the options configured by Strimzi:

* Any `ssl` configuration for xref:con-common-configuration-ssl-reference[supported TLS versions and cipher suites]
* Configuration for the `zookeeper.connection.timeout.ms` property to set the maximum time allowed for establishing a ZooKeeper connection
* Cruise Control metrics properties: 
** `cruise.control.metrics.topic.num.partitions`
** `cruise.control.metrics.topic.replication.factor`
** `cruise.control.metrics.topic.retention.ms`
** `cruise.control.metrics.topic.auto.create.retries`
** `cruise.control.metrics.topic.auto.create.timeout.ms`
** `cruise.control.metrics.topic.min.insync.replicas`
* Controller properties:
** `controller.quorum.election.backoff.max.ms`
** `controller.quorum.election.timeout.ms`
** `controller.quorum.fetch.timeout.ms`

[id='property-kafka-brokerRackInitImage-{context}']
= Configuring rack awareness and init container images

Rack awareness is enabled using the `rack` property.
When rack awareness is enabled, Kafka broker pods use init container to collect the labels from the Kubernetes cluster nodes.
The container image for this init container can be specified using the `brokerRackInitImage` property. 
If the `brokerRackInitImage` field is not provided, the images used are prioritized as follows:

. Container image specified in `STRIMZI_DEFAULT_KAFKA_INIT_IMAGE` environment variable in the Cluster Operator configuration.
. `{DockerKafkaInit}` container image.

.Example `brokerRackInitImage` configuration
[source,yaml,subs=attributes+]
----
apiVersion: {KafkaApiVersion}
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
    rack:
      topologyKey: topology.kubernetes.io/zone
    brokerRackInitImage: my-org/my-image:latest
    # ...
----

NOTE: Overriding container images is recommended only in special situations, such as when your network does not allow access to the container registry used by Strimzi. 
In such cases, you should either copy the Strimzi images or build them from the source. 
Be aware that if the configured image is not compatible with Strimzi images, it might not work properly.

[id='property-kafka-logging-{context}']
= Logging

Kafka has its own configurable loggers, which include the following:

* `log4j.logger.org.apache.zookeeper`
* `log4j.logger.kafka`
* `log4j.logger.org.apache.kafka`
* `log4j.logger.kafka.request.logger`
* `log4j.logger.kafka.network.Processor`
* `log4j.logger.kafka.server.KafkaApis`
* `log4j.logger.kafka.network.RequestChannel$`
* `log4j.logger.kafka.controller`
* `log4j.logger.kafka.log.LogCleaner`
* `log4j.logger.state.change.logger`
* `log4j.logger.kafka.authorizer.logger`

Kafka uses the Apache `log4j` logger implementation.

Use the `logging` property to configure loggers and logger levels.

You can set the log levels by specifying the logger and level directly (inline) or use a custom (external) ConfigMap.
If a ConfigMap is used, you set `logging.valueFrom.configMapKeyRef.name` property to the name of the ConfigMap containing the external logging configuration. Inside the ConfigMap, the logging configuration is described using `log4j.properties`. Both `logging.valueFrom.configMapKeyRef.name` and `logging.valueFrom.configMapKeyRef.key` properties are mandatory. A ConfigMap using the exact logging configuration specified is created with the custom resource when the Cluster Operator is running, then recreated after each reconciliation. If you do not specify a custom ConfigMap, default logging settings are used. If a specific logger value is not set, upper-level logger settings are inherited for that logger.
For more information about log levels, see {ApacheLoggers}.

Here we see examples of `inline` and `external` logging.
The `inline` logging specifies the root logger level.
You can also set log levels for specific classes or loggers by adding them to the loggers property.

.Inline logging
[source,yaml,subs="+quotes,attributes"]
----
apiVersion: {KafkaApiVersion}
kind: Kafka
spec:
  # ...
  kafka:
    # ...
    logging:
      type: inline
      loggers:
        kafka.root.logger.level: INFO
        log4j.logger.kafka.coordinator.transaction: TRACE
        log4j.logger.kafka.log.LogCleanerManager: DEBUG
        log4j.logger.kafka.request.logger: DEBUG
        log4j.logger.io.strimzi.kafka.oauth: DEBUG
        log4j.logger.org.openpolicyagents.kafka.OpaAuthorizer: DEBUG
  # ...
----

NOTE: Setting a log level to `DEBUG` may result in a large amount of log output and may have performance implications.

.External logging
[source,yaml,subs="+quotes,attributes"]
----
apiVersion: {KafkaApiVersion}
kind: Kafka
spec:
  # ...
  logging:
    type: external
    valueFrom:
      configMapKeyRef:
        name: customConfigMap
        key: kafka-log4j.properties
  # ...
----

Any available loggers that are not configured have their level set to `OFF`.

If Kafka was deployed using the Cluster Operator,
changes to Kafka logging levels are applied dynamically.

If you use external logging, a rolling update is triggered when logging appenders are changed.

.Garbage collector (GC)

Garbage collector logging can also be enabled (or disabled) using the xref:con-common-configuration-garbage-collection-reference[`jvmOptions` property].
