Apache Kafka na VPS — instalacja i konfiguracja message brokera
Opublikowano: 10 kwietnia 2026 · Kategoria: VPS / Streaming
Apache Kafka to rozproszony dziennik zdarzeń, który obsługuje miliony wiadomości na sekundę. W odróżnieniu od klasycznych brokerów wiadomości (RabbitMQ, ActiveMQ), Kafka przechowuje wszystkie wiadomości na dysku przez skonfigurowany czas — konsumenci mogą je odczytać wielokrotnie, replay zdarzeń jest wbudowany w architekturę. Ten artykuł pokazuje pełny setup Kafka na VPS z Ubuntu: instalację z ZooKeeper (klasyczny) lub KRaft (nowy, bez ZooKeepera), konfigurację topicow i partycji, przykłady producenta i konsumenta w Pythonie oraz monitoring przez JMX.
Wymagania i przygotowanie VPS
Kafka jest napisana w Javie i Scali — wymaga JVM. Minimum dla brokera dev/test to 2 GB RAM, dla produkcji 4-8 GB. Kafka intensywnie korzysta z OS page cache, więc im więcej RAM tym lepiej. Dysk: NVMe SSD bardzo poprawia throughput — Kafka to IO-intensive workload.
# Zainstaluj Java 21 (LTS) sudo apt update && sudo apt install -y openjdk-21-jdk # Sprawdz wersje java -version # Pobierz Kafka (sprawdz aktualna wersje na kafka.apache.org) wget https://downloads.apache.org/kafka/3.7.0/kafka_2.13-3.7.0.tgz tar -xzf kafka_2.13-3.7.0.tgz sudo mv kafka_2.13-3.7.0 /opt/kafka # Dodaj do PATH echo 'export PATH=$PATH:/opt/kafka/bin' >> ~/.bashrc source ~/.bashrc # Utworz uzytkownika systemowego sudo useradd -r -d /opt/kafka -s /bin/false kafka sudo chown -R kafka:kafka /opt/kafka
Opcja A — KRaft mode (bez ZooKeeper, Kafka 3.3+)
KRaft (Kafka Raft) to nowy tryb działania — od Kafka 3.3 jest production-ready, od 4.0 ZooKeeper jest usunięty. KRaft eliminuje zależność od ZooKeepera, upraszcza konfigurację i obniża latencję failover. Rekomendowany dla nowych instalacji.
# Wygeneruj unikalny cluster ID
KAFKA_CLUSTER_ID="$(/opt/kafka/bin/kafka-storage.sh random-uuid)"
# /opt/kafka/config/kraft/server.properties - edytuj kluczowe parametry:
# node.id=1
# listeners=PLAINTEXT://:9092,CONTROLLER://:9093
# advertised.listeners=PLAINTEXT://TWOJ_IP:9092
# log.dirs=/opt/kafka/data/kraft-combined-logs
# Formatuj storage (jednorazowo)
/opt/kafka/bin/kafka-storage.sh format \
-t ${KAFKA_CLUSTER_ID} \
-c /opt/kafka/config/kraft/server.properties
# Uruchom brokera
/opt/kafka/bin/kafka-server-start.sh \
/opt/kafka/config/kraft/server.properties Opcja B — tryb klasyczny z ZooKeeper
# Uruchom ZooKeeper (w tle) /opt/kafka/bin/zookeeper-server-start.sh \ -daemon /opt/kafka/config/zookeeper.properties # Edytuj /opt/kafka/config/server.properties: # broker.id=0 # listeners=PLAINTEXT://:9092 # advertised.listeners=PLAINTEXT://TWOJ_IP:9092 # log.dirs=/opt/kafka/data/kafka-logs # zookeeper.connect=localhost:2181 # Uruchom brokera Kafka /opt/kafka/bin/kafka-server-start.sh \ -daemon /opt/kafka/config/server.properties # Sprawdz czy brokerzy sa zarejestrowane w ZooKeeper /opt/kafka/bin/zookeeper-shell.sh localhost:2181 ls /brokers/ids
Systemd service dla Kafka
# /etc/systemd/system/kafka.service [Unit] Description=Apache Kafka After=network.target [Service] Type=simple User=kafka Environment="KAFKA_HEAP_OPTS=-Xmx2G -Xms2G" 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 LimitNOFILE=65536 [Install] WantedBy=multi-user.target # Aktywuj serwis sudo systemctl daemon-reload sudo systemctl enable --now kafka sudo systemctl status kafka
Topics i partycje — zarządzanie
Topic to nazwana kategoria wiadomości, podzielona na partycje. Każda partycja to uporządkowany, immutowalny log z offsetem. Replikacja (replication-factor) zapewnia odporność na awarie brokerów.
# Utwórz topic z 3 partycjami i replikacją 1 (single-broker) /opt/kafka/bin/kafka-topics.sh \ --bootstrap-server localhost:9092 \ --create \ --topic orders \ --partitions 3 \ --replication-factor 1 # Lista topicow /opt/kafka/bin/kafka-topics.sh \ --bootstrap-server localhost:9092 \ --list # Szczegóły topica /opt/kafka/bin/kafka-topics.sh \ --bootstrap-server localhost:9092 \ --describe \ --topic orders # Zmien retencje na 7 dni (168h = 604800000ms) /opt/kafka/bin/kafka-configs.sh \ --bootstrap-server localhost:9092 \ --entity-type topics \ --entity-name orders \ --alter \ --add-config retention.ms=604800000 # Usun topic (musi byc delete.topic.enable=true w server.properties) /opt/kafka/bin/kafka-topics.sh \ --bootstrap-server localhost:9092 \ --delete \ --topic orders
Producer i consumer — kafka-python
Biblioteka kafka-python to najpopularniejszy klient Kafka dla Pythona. Poniżej kompletny
przykład producenta i konsumenta grupowego.
pip install kafka-python
# producer.py
from kafka import KafkaProducer
import json
import time
producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8'),
key_serializer=lambda k: k.encode('utf-8') if k else None,
# Gwarancja dostarczenia: 0=fire-and-forget, 1=leader-ack, all=all-replicas
acks='all',
# Batch i kompresja
batch_size=16384,
compression_type='gzip',
linger_ms=5,
)
for i in range(100):
order = {
'order_id': i,
'product': 'hosting-plan-A',
'amount': 49.99,
'timestamp': time.time()
}
# Klucz decyduje do ktorej partycji trafi wiadomosc
future = producer.send('orders', key=str(i), value=order)
record_metadata = future.get(timeout=10)
print(f"Partition: {record_metadata.partition}, Offset: {record_metadata.offset}")
producer.flush()
producer.close() # consumer.py — konsumpcja grupowa
from kafka import KafkaConsumer
import json
consumer = KafkaConsumer(
'orders',
bootstrap_servers=['localhost:9092'],
group_id='order-processor-group',
auto_offset_reset='earliest', # 'latest' = tylko nowe wiadomosci
enable_auto_commit=True,
auto_commit_interval_ms=1000,
value_deserializer=lambda m: json.loads(m.decode('utf-8')),
key_deserializer=lambda k: k.decode('utf-8') if k else None,
)
print("Consumer started, waiting for messages...")
for message in consumer:
print(
f"Topic: {message.topic} | "
f"Partition: {message.partition} | "
f"Offset: {message.offset} | "
f"Key: {message.key} | "
f"Value: {message.value}"
) Consumer groups — skalowanie równoległe
Consumer group to mechanizm poziomego skalowania. Każda partycja topica jest przypisana do dokładnie jednego konsumenta w grupie — więc uruchamiając N instancji konsumenta w tej samej grupie, osiągasz N-krotny throughput (do liczby partycji). Konsumenci z różnych grup czytają ten sam topic niezależnie — idealne dla fan-out.
# Sprawdz lag consumer group (ile wiadomosci nie zostalo przetworzone) /opt/kafka/bin/kafka-consumer-groups.sh \ --bootstrap-server localhost:9092 \ --group order-processor-group \ --describe # Output: # GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG # order-processor-group orders 0 50 50 0 # order-processor-group orders 1 48 50 2 # order-processor-group orders 2 50 50 0 # Reset offsetu (replay od poczatku) /opt/kafka/bin/kafka-consumer-groups.sh \ --bootstrap-server localhost:9092 \ --group order-processor-group \ --topic orders \ --reset-offsets \ --to-earliest \ --execute
Kafka vs RabbitMQ — porównanie
| Cecha | Apache Kafka | RabbitMQ |
|---|---|---|
| Model | Distributed log (pull) | Message queue (push) |
| Retencja wiadomości | Konfigurowalny czas (dni/tygodnie) | Do potwierdzenia przez konsumenta |
| Throughput | Miliony msg/s (partycjonowanie) | Tysiące-setki tysięcy msg/s |
| Replay zdarzeń | Tak — reset offset do dowolnego miejsca | Nie (dead letter queue, ograniczone) |
| Routing | Prosty (topic + key) | Zaawansowany (exchanges, binding, routing key) |
| Latencja | Wyższa (batch + disk) | Niższa (in-memory, push) |
| Złożoność setupu | Wyższa (JVM, ZooKeeper lub KRaft) | Prosta (Erlang, jeden plik config) |
| Najlepszy dla | Event sourcing, streaming, analytics, audit log | Task queues, RPC, złożony routing |
Monitoring — JMX i kluczowe metryki
Kafka eksponuje metryki przez JMX. Narzędzie kafka-exporter (Prometheus) lub JMX Exporter pozwala zbierać je do Grafany. Kluczowe metryki do monitorowania:
- kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec — liczba wiadomości per sekundę (throughput producenta)
- kafka.consumer:type=consumer-fetch-manager-metrics,records-lag-max — maksymalny lag konsumenta (liczba nieprzetworzone wiadomości)
- kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions — partycje z niewystarczającą replikacją (powinno być 0)
- kafka.controller:type=KafkaController,name=ActiveControllerCount — powinno być 1 (jeden aktywny kontroler)
- os.linux.disk.io — Kafka jest IO-intensive, monitoruj I/O wait
# Uruchom kafka-exporter (Prometheus metryki na :9308)
docker run -d \
-p 9308:9308 \
danielqsj/kafka-exporter \
--kafka.server=localhost:9092
# Kluczowe zapytania Prometheus
# Lag konsumenta grupowego:
kafka_consumergroup_lag{topic="orders",consumergroup="order-processor-group"}
# Throughput:
rate(kafka_topic_partition_current_offset{topic="orders"}[5m])