Настройка Apache Kafka кластера для веб-приложения
Kafka — это не просто очередь сообщений. Это распределённый лог с гарантиями упорядоченности, репликацией и возможностью воспроизведения событий с любой точки. Для веб-приложения это означает: асинхронная обработка событий, развязка между сервисами, аудит-лог, event sourcing, real-time аналитика.
Одиночный брокер подходит только для разработки. Продуктивный кластер — минимум 3 брокера с репликацией.
Выбор режима: KRaft vs ZooKeeper
С Kafka 3.3+ KRaft-режим (без ZooKeeper) стал production-ready и является рекомендуемым. Для новых установок — только KRaft.
Кластер из 3 узлов в KRaft-режиме:
- kafka-1: controller + broker
- kafka-2: controller + broker
- kafka-3: controller + broker
Установка на примере Ubuntu 22.04
# Java — обязательно
apt install -y openjdk-21-jdk-headless
# Скачиваем Kafka
KAFKA_VERSION=3.7.0
SCALA_VERSION=2.13
wget https://downloads.apache.org/kafka/${KAFKA_VERSION}/kafka_${SCALA_VERSION}-${KAFKA_VERSION}.tgz
tar -xzf kafka_${SCALA_VERSION}-${KAFKA_VERSION}.tgz -C /opt/
ln -s /opt/kafka_${SCALA_VERSION}-${KAFKA_VERSION} /opt/kafka
useradd -r -s /bin/false kafka
chown -R kafka:kafka /opt/kafka
mkdir -p /var/log/kafka /data/kafka
chown kafka:kafka /var/log/kafka /data/kafka
Конфигурация KRaft (на каждом узле)
/opt/kafka/config/kraft/server.properties — разные для каждого узла:
# Узел 1 (аналогично для 2 и 3 с изменением node.id и advertised.listeners)
node.id=1
process.roles=broker,controller
controller.quorum.voters=1@kafka-1:9093,2@kafka-2:9093,3@kafka-3:9093
listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
advertised.listeners=PLAINTEXT://kafka-1.internal:9092
inter.broker.listener.name=PLAINTEXT
controller.listener.names=CONTROLLER
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
# Хранилище
log.dirs=/data/kafka
num.recovery.threads.per.data.dir=4
# Производительность
num.io.threads=16
num.network.threads=8
socket.send.buffer.bytes=1048576
socket.receive.buffer.bytes=1048576
socket.request.max.bytes=104857600
# Репликация
default.replication.factor=3
min.insync.replicas=2
num.partitions=6
offsets.topic.replication.factor=3
transaction.state.log.replication.factor=3
transaction.state.log.min.isr=2
# Retention
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
# Сжатие
compression.type=lz4
Инициализация хранилища (один раз):
# Генерируем кластерный UUID (один раз, одинаковый для всех узлов)
CLUSTER_UUID=$(kafka-storage.sh random-uuid)
# На каждом узле форматируем хранилище
kafka-storage.sh format \
-t $CLUSTER_UUID \
-c /opt/kafka/config/kraft/server.properties
Systemd unit
[Unit]
Description=Apache Kafka
After=network.target
[Service]
Type=simple
User=kafka
Environment="KAFKA_HEAP_OPTS=-Xmx4g -Xms4g"
Environment="KAFKA_JVM_PERFORMANCE_OPTS=-server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -Djava.awt.headless=true"
ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/kraft/server.properties
ExecStop=/opt/kafka/bin/kafka-server-stop.sh
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Настройка TLS между брокерами и клиентами
Без TLS весь трафик идёт в открытом виде. Минимум — TLS для внешних клиентов.
# Генерируем CA и сертификаты для каждого брокера
keytool -keystore kafka-1.keystore.jks -alias kafka-1 \
-keyalg RSA -validity 365 \
-genkey -storepass changeit \
-dname "CN=kafka-1.internal, OU=Kafka, O=Company, L=City, ST=State, C=RU"
# Подписываем CA
keytool -keystore kafka-1.keystore.jks -alias kafka-1 \
-certreq -file kafka-1.csr -storepass changeit
openssl x509 -req -CA ca.crt -CAkey ca.key \
-in kafka-1.csr -out kafka-1-signed.crt \
-days 365 -CAcreateserial
Добавляем в server.properties:
listeners=PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9094,CONTROLLER://0.0.0.0:9093
ssl.keystore.location=/etc/kafka/ssl/kafka-1.keystore.jks
ssl.keystore.password=changeit
ssl.key.password=changeit
ssl.truststore.location=/etc/kafka/ssl/kafka.truststore.jks
ssl.truststore.password=changeit
ssl.client.auth=required
ssl.enabled.protocols=TLSv1.3,TLSv1.2
Мониторинг — JMX + Prometheus
# kafka-jmx-exporter.yml — конфигурация для JMX Exporter
startDelaySeconds: 0
hostPort: 127.0.0.1:9999
lowercaseOutputName: true
rules:
- pattern: kafka.server<type=BrokerTopicMetrics, name=MessagesInPerSec><>OneMinuteRate
name: kafka_server_broker_topic_messages_in_per_sec
- pattern: kafka.server<type=ReplicaManager, name=UnderReplicatedPartitions><>Value
name: kafka_server_under_replicated_partitions
- pattern: kafka.controller<type=KafkaController, name=ActiveControllerCount><>Value
name: kafka_controller_active_count
- pattern: kafka.network<type=RequestMetrics, name=TotalTimeMs, request=Produce><>99thPercentile
name: kafka_network_produce_total_time_ms_p99
Ключевые метрики для алертинга:
-
kafka_server_under_replicated_partitions > 0— потеря реплики -
kafka_controller_active_count != 1— проблема с контроллером - consumer lag > порога — консьюмер отстаёт
Первоначальное тестирование
# Создаём тестовый топик
kafka-topics.sh --bootstrap-server kafka-1:9092 \
--create --topic test-topic \
--partitions 6 --replication-factor 3
# Проверяем репликацию
kafka-topics.sh --bootstrap-server kafka-1:9092 \
--describe --topic test-topic
# Тест производительности продюсера
kafka-producer-perf-test.sh \
--topic test-topic \
--num-records 1000000 \
--record-size 1024 \
--throughput -1 \
--producer-props bootstrap.servers=kafka-1:9092,kafka-2:9092,kafka-3:9092 \
acks=all compression.type=lz4
# Тест потребителя
kafka-consumer-perf-test.sh \
--bootstrap-server kafka-1:9092 \
--topic test-topic \
--messages 1000000 \
--group perf-test-group
Таймлайн проекта
День 1 — подготовка инфраструктуры: 3 VM/сервера с отдельными дисками для данных Kafka (не системный раздел), настройка DNS, открытие портов 9092/9093/9094 между узлами.
День 2 — установка Java, Kafka, генерация кластерного UUID, форматирование хранилищ, настройка systemd, запуск кластера.
День 3 — настройка TLS, создание продуктивных топиков с правильными partition/replication factor, тест производительности.
День 4 — интеграция мониторинга (JMX Exporter + Prometheus + Grafana), настройка алертов на under-replicated partitions и consumer lag.
День 5 — тестирование сценариев отказа: выключение одного брокера, проверка что кластер продолжает работу, восстановление.
Дополнительно: настройка Kafka Schema Registry и Kafka Connect добавляет ещё 2–3 дня каждый.







