> For the complete documentation index, see [llms.txt](https://utm-1.gitbook.io/utm-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://utm-1.gitbook.io/utm-docs/dokumentaciya/utm-it/resheniya/monitoring/prometheus/monitoring-kafka/nastroika-jmx-exporter-dlya-kafka-v-docker-dva-nezavisimykh-klastera-kraft.md).

# Настройка JMX Exporter для Kafka в Docker (два независимых кластера KRaft)

## Настройка JMX Exporter для Kafka в Docker (два независимых кластера KRaft)

В этом руководстве описано, как развернуть два независимых Kafka‑кластера в режиме KRaft через Docker Compose, подключить к ним JMX Exporter для сбора метрик и настроить мониторинг через Prometheus, уже развёрнутый в Kubernetes.

### 1. Предварительные требования

* Сервер с Docker и Docker Compose.
* Доступ к кластеру Kubernetes с Prometheus.
* IP‑адрес сервера с Kafka: `192.168.4.11`.
* Два Kafka‑кластера с разными `CLUSTER_ID`:
  * Первый: `cp37kMegBDbLU59wm3QxrF` (образ `confluentinc/cp-kafka:7.7.7`).
  * Второй: `a411ihTyNdP54XyQ95hGwm` (образ `apache/kafka:4.1.1`).

### 2. Подготовка файлов на хосте

Создайте директорию для проекта и выполните:

bash

```bash
mkdir -p ./jmx-exporter
cd ./jmx-exporter

# Скачайте JMX Exporter
wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.18.0/jmx_prometheus_javaagent-0.18.0.jar


# Создайте конфигурацию JMX Exporter
cat > kafka-jmx-config.yaml << 'EOF'
hostPort: 9999
ssl: false
rules:
  - pattern: "kafka.server:<type=BrokerTopicMetrics, name=MessagesInPerSec, topic=(.*)><Count>"
    name: kafka_broker_topic_messages_in_per_sec
    labels:
      topic: "$1"
  - pattern: "kafka.server:<type=ReplicaManager, name=UnderReplicatedPartitions><Value>"
    name: kafka_replica_under_replicated_partitions
  - pattern: "java.lang:<type=Memory><HeapMemoryUsage><used>"
    name: jvm_memory_heap_used
  - pattern: ".*"
    name: jmx_$0
EOF
```

### 3. Docker Compose конфигурация (`compose.yaml`)

Создайте файл `compose.yaml` в корневой директории проекта:

yaml

```yaml
version: '3.8'


services:
  # Брокер 1: Confluent Kafka (utm-cp-kafka37) — отдельный кластер KRaft
  utm-cp-kafka37:
    image: confluentinc/cp-kafka:7.7.7
    container_name: utm-cp-kafka37
    ports:
      - "9094:9092"   # Kafka
      - "9095:9999"   # JMX порт (для диагностики)
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_PROCESS_ROLES: "broker,controller"
      KAFKA_NODE_ID: 1
      KAFKA_CONTROLLER_QUORUM_VOTERS: "1@utm-cp-kafka37:9093"
      KAFKA_CLUSTER_ID: "cp37kMegBDbLU59wm3QxrF"
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
      KAFKA_ADVERTISED_LISTENER: PLAINTEXT://192.168.4.11:9094
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OPTS: >-
        -javaagent:/opt/jmx-exporter/jmx_prometheus_javaagent-0.18.0.jar=9404:/opt/jmx-exporter/kafka-jmx-config.yaml
        -Dcom.sun.management.jmxremote
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.ssl=false
        -Djava.rmi.server.hostname=192.168.4.11
        -Djava.rmi.server.port=9095
    volumes:
      - ./jmx-exporter:/opt/jmx-exporter
    networks:
      - kafka-net


  # Брокер 2: Apache Kafka (utm-kafka41) — отдельный кластер KRaft
  utm-kafka41:
    image: apache/kafka:4.1.1
    container_name: utm-kafka41
    ports:
      - "19094:9092"  # Kafka
      - "19095:9999"  # JMX порт (для диагностики)
    environment:
      KAFKA_BROKER_ID: 2
      KAFKA_PROCESS_ROLES: "broker,controller"
      KAFKA_NODE_ID: 2
      KAFKA_CONTROLLER_QUORUM_VOTERS: "2@utm-kafka41:19093"
      KAFKA_CLUSTER_ID: "a411ihTyNdP54XyQ95hGwm"
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:19093
      KAFKA_ADVERTISED_LISTENER: PLAINTEXT://192.168.4.11:19094
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OPTS: >-
        -javaagent:/opt/jmx-exporter/jmx_prometheus_javaagent-0.18.0.jar=9405:/opt/jmx-exporter/kafka-jmx-config.yaml
        -Dcom.sun.management.jmxremote
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.ssl=false
        -Djava.rmi.server.hostname=192.168.4.11
        -Djava.rmi.server.port=19095
    volumes:
      - ./jmx-exporter:/opt/jmx-exporter
    networks:
      - kafka-net

networks:
  kafka-net:
    driver: bridge
```

### 4. Запуск Kafka‑кластеров

1. Создайте сеть (если ещё не создана):

   bash

   ```bash
   docker network create kafka-net
   ```
2. Запустите контейнеры:

   bash

   ```bash
   docker-compose -f compose.yaml up -d
   ```
3. Проверьте статус:

   bash

   ```bash
   docker ps --filter "name=utm-"
   ```

   Должны быть запущены: `utm-cp-kafka37` и `utm-kafka41`.

### 5. Проверка работы Kafka

1. Убедитесь, что каждый брокер работает как автономный кластер:

   bash

   ```bash
   # Для utm-cp-kafka37
   docker exec utm-cp-kafka37 kafka-metadata quorum --bootstrap-server localhost:9092

   # Для utm-kafka41
   docker exec utm-kafka41 kafka-metadata quorum --bootstrap-server localhost:9092
   ```

   В выводе должен быть только один узел (соответственно `1` или `2`).
2. Проверьте доступность Kafka:

   bash

   ```bash
   # Отправьте тестовое сообщение в utm-cp-kafka37
   docker exec utm-cp-kafka37 kafka-console-producer --bootstrap-server localhost:9092 --topic test << EOF
   Hello from cp-kafka37
   EOF

   # Прочитайте сообщение
   docker exec utm-cp-kafka37 kafka-console-consumer --bootstrap-server localhost:9092 --topic test --from-beginning --max-messages 1
   ```

   Аналогично для `utm-kafka41`.

### 6. Проверка JMX Exporter

1. Убедитесь, что JAR‑файл виден в контейнерах:

   bash

   ```bash
   docker exec utm-cp-kafka37 ls /opt/jmx-exporter/
   docker exec utm-kafka41 ls /opt/jmx-exporter/
   ```

   Должны быть: `jmx_prometheus_javaagent-0.18.0.jar`

### 7. Настройка Prometheus в Kubernetes

#### 7.1. Добавление job в конфигурацию Prometheus

Добавьте в `prometheus.yml` (или в ConfigMap, если Prometheus развёрнут через Helm) новый `scrape_config`:

yaml

```yaml
scrape_configs:
  - job_name: 'kafka-jmx'
    static_configs:
      - targets:
        - 192.168.4.11:9404  # JMX Exporter для utm-cp-kafka37
        - 192.168.4.11:9405  # JMX Exporter для utm-kafka41
    relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):(.*)'
        replacement: '${1}:${2}'
        target_label: instance
      - target_label: job
        replacement: 'kafka-jmx'  # фиксируем имя job
```

#### 7.2. Применение конфигурации

1. **Если Prometheus запущен как StatefulSet/Deployment**:

   bash

   ```bash
   kubectl edit configmap prometheus-config -n <namespace>
   # Внесите изменения, сохраните
   kubectl rollout restart deployment prometheus -n <namespace>
   ```
2. **Если используется Helm**:

   bash

   ```bash
   helm upgrade prometheus prometheus/prometheus \
     --namespace <namespace> \
     --set prometheus.configmap.extraConfig="scrape_configs: ..."
   ```
3. **Проверка загрузки конфигурации**:

   bash

   ```bash
   kubectl logs <prometheus-pod> -n <namespace> | grep "Reloaded"
   ```

   В логах должно появиться: `Reloaded configuration successfully`.

### 8. Проверка доступности метрик

#### 8.1. Через curl (с узла Kubernetes или любого сервера с доступом к 192.168.4.11)

Выполните:

bash

```bash
# Метрики первого брокера
curl http://192.168.4.11:9404/metrics | head -20

# Метрики второго брокера
curl http://192.168.4.11:9405/metrics | head -20
```

**Что ожидать в ответе**:

* Строки вида `# HELP kafka_broker_topic_messages_in_per_sec ...`
* Значения метрик: `kafka_broker_topic_messages_in_per_sec{topic="test"} 123`
* HTTP‑код `200 OK`

#### 8.2. Через интерфейс Prometheus

1. Откройте веб‑интерфейс Prometheus (`http://<prometheus-url>:9090`).
2. Перейдите в раздел **Status → Targets**.
3. Найдите цели:
   * `192.168.4.11:9404` (статус `UP`, job=`kafka-jmx`)
   * `192.168.4.11:9405` (статус `UP`, job=`kafka-jmx`)
4. Если статус `DOWN`, проверьте:
   * Доступность портов (`telnet 192.168.4.11 9404`).
   * Логи Prometheus: `kubectl logs <prometheus-pod> -n <namespace>`.

#### 8.3. Проверка конкретных метрик

В интерфейсе Prometheus выполните запросы:

1. **Количество сообщений в секунду по темам**:

   promql

   ```promql
   kafka_broker_topic_messages_in_per_sec
   ```

   *Ожидаемый результат*: графики с данными для каждого топика.
2. **Недостаточно реплицированных партиций**:

   promql

   ```promql
   kafka_replica_under_replicated_partitions
   ```

   *Ожидаемый результат*: `0` (если репликация работает корректно).
3. **Использование памяти JVM**:

   promql

   ```promql
   jvm_memory_heap_used
   ```

   *Ожидаемый результат*: значение в байтах (можно преобразовать в МБ: `jvm_memory_heap_used / 1024 / 1024`).
4. **Все метрики JMX**:

   promql

   ```promql
   {job="kafka-jmx"}
   ```

   *Ожидаемый результат*: список всех доступных метрик.

### 9. Устранение неполадок

#### 9.1. JMX Exporter не отвечает

**Симптомы**:

* `curl http://192.168.4.11:9404/metrics` возвращает `Connection refused`.
* В логах Kafka нет строки `Starting JMX exporter`.

**Действия**:

1. Проверьте, что JAR‑файл смонтирован:

   bash

   ```bash
   docker exec utm-cp-kafka37 ls /opt/jmx-exporter/
   ```
2. Убедитесь, что `KAFKA_OPTS` содержит корректный путь:

   bash

   ```bash
   docker exec utm-cp-kafka37 echo $KAFKA_OPTS
   ```
3. Проверьте логи Kafka:

   bash

   ```bash
   docker logs utm-cp-kafka37 | grep -i jmx
   ```

#### 9.2. Prometheus не видит цели

**Симптомы**:

* В `Targets` статус `DOWN`.
* Ошибка: `Get "http://192.168.4.11:9404/metrics": dial tcp 192.168.4.11:9404: connect: connection refused`.

**Действия**:

1. Проверьте доступность порта с узла Kubernetes:

   bash

   ```bash
   kubectl run -it --rm debug --image=busybox --restart=Never -- sh
   wget -qO- http://192.168.4.11:9404/metrics
   ```
2. Убедитесь, что фаервол разрешает трафик на порты `9404`/`9405`.
3. Проверьте конфигурацию `prometheus.yml` на опечатки.

#### 9.3. Метрики есть, но нет данных

**Симптомы**:

* Запросы в Prometheus возвращают пустые результаты.
* В `/metrics` метрики присутствуют, но значения `0`.

**Действия**:

1. Убедитесь, что в Kafka есть активность (отправьте тестовое сообщение).
2. Проверьте правила в `kafka-jmx-config.yaml` — соответствуют ли они реальным MBean‑именам.
3. Увеличьте `scrape_interval` в `prometheus.yml`, если метрики обновляются редко.

### 10. Итоговый чек‑лист

1. ✅ JAR‑файл `jmx_prometheus_javaagent-0.18.0.jar` скачан и смонтирован в контейнеры.
2. ✅ Kafka‑брокеры запущены в режиме KRaft как независимые кластеры.
3. ✅ JMX Exporter доступен по портам `9404` и `9405`.
4. ✅ Prometheus настроен на сбор метрик с этих портов.
5. ✅ В интерфейсе Prometheus видны цели (`Targets`) и метрики.
6. ✅ Выполнены тестовые запросы (например, `kafka_broker_topic_messages_in_per_sec`).
