Налаштування кластера Apache Kafka для веб-застосунку
Kafka — це не просто черга повідомлень. Це розподілений журнал з гарантіями упорядкованості, репліцією та можливістю відтворення подій з будь-якої точки. Для веб-застосунку це означає: асинхронну обробку подій, розв'язку між сервісами, журнал аудиту, event sourcing, аналітику в реальному часі.
Одиночний брокер підходить тільки для розробки. Виробничий кластер — мінімум 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
# Утримання
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]
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=UA"
# Підписуємо 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, тест продуктивності.
День 4 — інтеграція моніторингу (JMX Exporter + Prometheus + Grafana), налаштування алертів на under-replicated partitions та consumer lag.
День 5 — тестування сценаріїв відмови: вимкнення одного брокера, перевірка що кластер продовжує роботу, відновлення.
Додатково: налаштування Kafka Schema Registry та Kafka Connect додає ще 2–3 дні кожен.







