// Module included in the following assemblies:
//
// assembly-storage.adoc

[id='ref-jbod-storage-{context}']
= JBOD storage

[role="_abstract"]
JBOD storage allows you to configure your Kafka cluster to use multiple disks or volumes. 
This approach provides increased data storage capacity for Kafka nodes, and can lead to performance improvements.
A JBOD configuration is defined by one or more volumes, each of which can be either xref:ref-ephemeral-storage-{context}[ephemeral] or xref:ref-persistent-storage-{context}[persistent]. 
The rules and constraints for JBOD volume declarations are the same as those for ephemeral and persistent storage. 
For example, you cannot decrease the size of a persistent storage volume after it has been provisioned, nor can you change the value of `sizeLimit` when the type is `ephemeral`.

NOTE: JBOD storage is supported for *Kafka only*, not for ZooKeeper.

To use JBOD storage, you set the storage type configuration in the `Kafka` resource to `jbod`.
If you are using node pools, you can also specify `jbod` in the storage configuration for nodes belonging to a specific node pool.

The `volumes` property allows you to describe the disks that make up your JBOD storage array or configuration. 

.Example JBOD storage configuration
[source,yaml,subs="attributes+"]
----
apiVersion: {KafkaApiVersion}
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    storage:
      type: jbod
      volumes:
      - id: 0
        type: persistent-claim
        size: 100Gi
        deleteClaim: false
      - id: 1
        type: persistent-claim
        size: 100Gi
        deleteClaim: false
  # ...
----

The IDs cannot be changed once the JBOD volumes are created.
You can add or remove volumes from the JBOD configuration.

[id='ref-jbod-storage-pvc-{context}']
== PVC resource for JBOD storage

When persistent storage is used to declare JBOD volumes, it creates a PVC with the following name:

`data-_id_-_cluster-name_-kafka-_idx_`::

PVC for the volume used for storing data for the Kafka broker pod `_idx_`.
The `_id_` is the ID of the volume used for storing data for Kafka broker pod.

== Mount path of Kafka log directories

The JBOD volumes are used by Kafka brokers as log directories mounted into the following path:

[source,shell,subs="+quotes,attributes"]
----
/var/lib/kafka/data-_id_/kafka-log__idx__
----

Where `_id_` is the ID of the volume used for storing data for Kafka broker pod `_idx_`. For example `/var/lib/kafka/data-0/kafka-log0`.

== Configuring the storage volume used to store the KRaft metadata log

In KRaft mode, a copy of the Kafka cluster's metadata log is stored on every node, including brokers and controllers. 
Each node uses one of its data volumes for the KRaft metadata log. 
By default, the log is stored on the volume with the lowest ID. 
However, you can specify another volume using the `kraftMetadata` property.

For controller-only nodes, which don't handle data, storage is used only used for the metadata log. 
The metadata log is always stored only on one volume, so using JBOD storage with multiple volumes does not improve the performance or increase the available disk space. 

Meanwhile, broker nodes or nodes combining broker and controller roles share the same volume for storing both the metadata log and partition replica data.
This sharing optimizes disk utilization.  
They can also utilize JBOD storage with multiple volumes so that one of the volumes is shared by the metadata log and partition replica data and any additional volumes are used for partition replica data only. 

Changing the volume that stores the metadata log triggers a rolling update of nodes in the cluster.
This process involves deleting the old metadata log and creating a new one in the new location. 
If `kraftMetadata` isn't specified on any volume, adding a new volume with a lower ID also triggers an update and relocation of the metadata log.

NOTE: JBOD storage in KRaft mode is considered early-access in Apache Kafka 3.7.x.

.Example JBOD storage configuration using volume with ID 1 to store the KRaft metadata
[source,yaml,subs="attributes+"]
----
apiVersion: {KafkaApiVersion}
kind: KafkaNodePool
metadata:
  name: pool-a
  # ...
spec:
  storage:
    type: jbod
    volumes:
    - id: 0
      type: persistent-claim
      size: 100Gi
      deleteClaim: false
    - id: 1
      type: persistent-claim
      size: 100Gi
      kraftMetadata: shared
      deleteClaim: false
  # ...
----
