Obs. övers.: I denna artikel delar Banzai Cloud med sig av ett exempel pÄ hur deras specialverktyg kan underlÀtta driften av Kafka inom Kubernetes. Instruktionerna visar hur man kan bestÀmma den optimala storleken pÄ infrastrukturen och konfigurera Kafka för att uppnÄ önskad kapacitet.

Apache Kafka Àr en distribuerad strömmande plattform för skapande av pÄlitliga, skalbara och högpresterande realtids-system. Dess imponerande funktioner kan förstÀrkas med hjÀlp av Kubernetes. För detta har vi utvecklat och ett verktyg som kallas . De möjliggör driftsÀttning av Kafka i Kubernetes och utnyttja dess olika funktioner, sÄsom finjustering av broker-konfiguration, skalning baserad pÄ metrics med ombalansering, rack awareness, "mjuk" (graceful) uppgradering av versioner m.m.
Testa Supertubes i din kluster:
curl https://getsupertubes.sh | sh och supertubes install -a --no-democluster --kubeconfigEller kontakta . Det gÄr ocksÄ att lÀsa om vissa funktioner av Kafka, vars hantering Àr automatiserad med hjÀlp av Supertubes och Kafka-operatorn. Vi har redan skrivit om dem i bloggen:
- ;
- ;
- ;
- ;
- ;
- ;
- .
NÀr du beslutar att sÀtta upp en Kafka-kluster i Kubernetes kommer du sÀkert att stöta pÄ problemet att bestÀmma den optimala storleken pÄ den grundlÀggande infrastrukturen och behovet av att finjustera Kafka-konfigurationen för att möta kapacitetskraven. Den maximala prestandan för varje broker bestÀms av prestandan hos infrastrukturens komponenter, sÄsom minne, processor, diskens hastighet, nÀtverkskapacitet osv.
I idealfallet bör brokerkonfigurationen vara sÄdan att alla infrastrukturella element anvÀnds maximalt. Men i verkliga livet Àr en sÄdan instÀllning ganska svÄr. Det Àr mer sannolikt att anvÀndare konfigurerar brokerinstÀllningar för att maximera anvÀndningen av en eller tvÄ komponenter (disk, minne eller processor). Generellt visar en broker maximal prestanda nÀr dess konfiguration tillÄter den lÄngsammaste komponenten att utnyttjas fullt ut. PÄ sÄ sÀtt kan vi fÄ en ungefÀrlig uppfattning om den belastning som en broker kan hantera.
Teoretiskt kan vi Àven uppskatta antalet brokers som behövs för att hantera en viss belastning. Men i praktiken Àr det sÄ mÄnga konfigurationsalternativ pÄ olika nivÄer att det Àr ganska svÄrt (om inte omöjligt) att bedöma den potentiella prestandan hos en viss konfiguration. Med andra ord Àr det mycket utmanande att planera en konfiguration med utgÄngspunkt frÄn en viss förvÀntad prestanda.
För anvÀndare av Supertubes tillÀmpar vi vanligtvis följande metod: vi börjar med en viss konfiguration (infrastruktur + instÀllningar), mÀter dess prestanda, justerar brokerinstÀllningarna och upprepar processen. Detta pÄgÄr tills potentialen hos den lÄngsammaste infrastrukturella komponenten Àr helt utnyttjad.
Genom denna metod fÄr vi en klarare uppfattning om hur mÄnga brokers som krÀvs för klustret för att hantera en viss belastning (antalet brokers beror ocksÄ pÄ andra faktorer, sÄsom minimalt antal meddelandekopior för att sÀkerstÀlla redundans, antalet partitionledare osv.). Dessutom fÄr vi en uppfattning om vilken infrastrukturell komponent som bör skalas vertikalt.
I den hĂ€r artikeln kommer vi att diskutera de steg vi tar för att "fĂ„ ut allt" frĂ„n de lĂ„ngsammaste komponenterna i initiala konfigurationer och mĂ€ta klustrets genomströmning i Kafka. En högt tillförlitlig konfiguration krĂ€ver minst tre aktiva brokers (min.insync.replicas=3), spridda över tre olika tillgĂ€nglighetszoner. För att konfigurera, skala och övervaka Kubernetes-infrastrukturen anvĂ€nder vi vĂ„r egen containerhanteringsplattform för hybridmoln â . Den stöder on-premise (bare metal, VMware) och fem typer av moln (Alibaba, AWS, Azure, Google, Oracle), samt alla tĂ€nkbara kombinationer av dem.
Tankar kring infrastruktur och konfiguration av Kafka-klustret
För exemplen nedan har vi valt AWS som molnleverantör och EKS som Kubernetes-distribution. En liknande konfiguration kan realiseras med â en Kubernetes-distribution frĂ„n Banzai Cloud, certifierad av CNCF.
Enhet
Amazon erbjuder olika . I grunden gp2 och io1 baseras pÄ SSD-enheter, men för att sÀkerstÀlla hög genomströmning gp2 förbrukar ackumulerade krediter (I/O credits), dÀrför föredrog vi en typ io1, som erbjuder stabil hög genomströmning.
Typer av instanser
Kafkas prestanda beror starkt pÄ operativsystemets sid-cache, sÄ vi behöver instanser med tillrÀckligt med minne för mÀklare (JVM) och sid-cache. Instansen c5.2xlarge Àr en bra början, eftersom den har 16 GB minne och . Nackdelen Àr att den kan leverera maximal prestanda under högst 30 minuter om dygnet. Om arbetsbelastningen krÀver maximal prestanda under lÀngre perioder bör vi övervÀga andra typer av instanser. Och sÄ gjorde vi, nÀr vi stannade vid c5.4xlarge. Den erbjuder maximal genomströmning pÄ 593,75 MB/s. Den maximala genomströmningen för EBS-volymen io1 Àr högre Àn för instansen c5.4xlarge, sÄ den lÄngsammaste delen av infrastrukturen Àr uppenbarligen I/O-genomströmningen för den hÀr instansen (vilket ocksÄ bör bekrÀftas av resultaten av vÄra belastningstester).
NĂ€tverk
NÀtverksbandbredden mÄste vara tillrÀckligt stor jÀmfört med instansens VM-prestanda och disken, annars blir nÀtverk den svaga lÀnken. I vÄrt fall stöder nÀtverksgrÀnssnittet c5.4xlarge hastigheter upp till 10 Gb/s, vilket Àr betydligt mer Àn I/O-genomströmningen för VM-instansen.
Distribuering av mÀklare
MÀklarna bör distribueras (planeras i Kubernetes) pÄ dedikerade noder för att undvika konkurrens med andra processer om CPU-, minnes-, nÀtverks- och diskresurser.
Java-version
Ett rimligt val Àr Java 11, eftersom det Àr kompatibelt med Docker pÄ sÄ sÀtt att JVM korrekt identifierar de processorer och det minne som Àr tillgÀngligt för den container dÀr mÀklaren körs. Med vetskap om att CPU-grÀnser Àr viktiga, stÀller JVM internt och transparent in antalet GC-trÄdar och JIT-kompilatortrÄdar. Vi anvÀnde bilden Kafka banzaicloud/kafka:2.13-2.4.0, som inkluderar version 2.4.0 av Kafka (Scala 2.13) pÄ Java 11.
Om du vill veta mer om Java/JVM pÄ Kubernetes, kolla gÀrna pÄ vÄra följande publikationer:
- ;
- .
MÀklarnas minnesinstÀllningar
Det finns tvÄ viktiga aspekter av att konfigurera mÀklarens minne: instÀllningar för JVM och för Kubernetes-poden. GrÀnsen för minnet som sÀtts för podden bör vara större Àn det maximala heap-storleken, sÄ att JVM har utrymme för Java-metaplatsen, som ligger i sin egen minne, och för operativsystemets sid cache, som Kafka aktivt anvÀnder. I vÄra tester körde vi Kafka-mÀklare med parametrarna -Xmx4G -Xms2G, medan minnesgrÀnsen för podden var 10 Gi. Observera att minnesinstÀllningar för JVM automatiskt kan fÄs med -XX:MaxRAMPercentage och -X:MinRAMPercentage, baserat pÄ minnesgrÀnsen för podden.
MÀklarnas processorinstÀllningar
Generellt sett kan prestandan ökas genom att öka parallellismen genom att öka antalet trÄdar som Kafka anvÀnder. Ju fler processorer som Àr tillgÀngliga för Kafka, desto bÀttre. I vÄrt test började vi med en begrÀnsning pÄ 6 processorer och ökade successivt (i iterationer) antalet till 15. Dessutom stÀllde vi in num.network.threads=12 i mÀklarens instÀllningar för att öka antalet trÄdar som tar emot data frÄn nÀtverket och skickar dem. Vi upptÀckte omedelbart att följarna inte kunde ta emot repliker tillrÀckligt snabbt, sÄ vi ökade num.replica.fetchers till 4 för att öka hastigheten med vilken följarna replikerade meddelanden frÄn ledarna.
Belastningstestverktyg
Det Àr viktigt att sÀkerstÀlla att potentialen hos den valda belastningsgeneratorn inte tar slut innan Kafka-klustret (vars prestanda mÀts) nÄr sin maximala belastning. Med andra ord Àr det nödvÀndigt att göra en förhandsutvÀrdering av belastningsgeneratorns kapabiliteter samt vÀlja instanser med tillrÀckligt med processorer och minne. Under dessa förhÄllanden kommer vÄrt verktyg att generera mer belastning Àn vad Kafka-klustret kan hantera. Efter flera tester har vi valt att anvÀnda tre instanser c5.4xlarge, dÀr varje instans körde en generator.
Benchmarking
PrestandamÀtning Àr en iterativ process som involverar följande steg:
- konfigurering av infrastrukturen (EKS-kluster, Kafka-kluster, belastningsgenerator och Àven Prometheus och Grafana);
- generering av belastning under en viss tidsperiod för att filtrera bort slumpmÀssiga avvikelser i de insamlade prestandamÄtten;
- justering av infrastrukturen och brokerkonfigurationen baserat pÄ observerade prestandaindikatorer;
- upprepning av processen tills den önskade genomströmningen i Kafka-klustret uppnÄs. Det ska ocksÄ vara stabilt reproducerbart och visa minimala variationer i genomströmning.
I nÀsta avsnitt beskrivs stegen som utfördes under benchmarking-processen av testklustret.
Verktyg
För snabb distribution av en grundkonfiguration, belastningsgenerering och prestandamÀtning anvÀndes följande verktyg:
- för att organisera EKS-klustret frÄn Amazon med (för insamling av Kafka och infrastrukturmetrik) och (för visualisering av dessa metrik). Vi anvÀnde integrerade pÄ tjÀnster som erbjuder federativ övervakning, centraliserad logginsamlning, sÄrbarhetsskanning, ÄterstÀllning efter driftstopp, företagsklassens sÀkerhet och mycket mer.
- â ett verktyg för belastningstestning av Kafka-klustret.
- Grafana-paneler för visualisering av Kafka- och infrastrukturmetrik: , .
- Supertubes CLI för den enklaste konfigurationen av ett Kafka-kluster i Kubernetes. Zookeeper, Kafka-operator, Envoy och mÄnga andra komponenter installeras och konfigureras korrekt för att köra ett produktionsklart Kafka-kluster i Kubernetes.
- För installation supertubes CLI anvÀnd instruktionerna som anges .

EKS-kluster
Förbered EKS-klustret med dedikerade noder c5.4xlarge i olika tillgÀnglighetszoner för poddar med Kafka-brokers samt dedikerade noder för lastgenerering och övervakningsinfrastruktur.
banzai cluster create -f https://raw.githubusercontent.com/banzaicloud/kafka-operator/master/docs/benchmarks/infrastructure/cluster_eks_202001.jsonNĂ€r EKS-klustret Ă€r igĂ„ng, aktivera dess integrerade â den kommer att installera Prometheus och Grafana i klustret.
Systemkomponenter för Kafka
Installera systemkomponenter för Kafka (Zookeeper, kafka-operator) i EKS med hjÀlp av supertubes CLI:
supertubes install -a --no-democluster --kubeconfigKafka-kluster
Som standard anvÀnds EBS-volymer av typen gp2, sÄ det Àr nödvÀndigt att skapa en sÀrskild lagringsklass baserad pÄ volymer io1 för Kafka-klustret:
kubectl create -f - <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "50"
fsType: ext4
volumeBindingMode: WaitForFirstConsumer
EOF StÀll in parametern för brokerns min.insync.replicas=3 och distribuera poddar för brokers pÄ noder i tre olika tillgÀnglighetszoner:
supertubes cluster create -n kafka --kubeconfig -f https://raw.githubusercontent.com/banzaicloud/kafka-operator/master/docs/benchmarks/infrastructure/kafka_202001_3brokers.yaml --wait --timeout 600Ămnen
Vi körde samtidigt tre instanser av lastgeneratorn. Var och en skriver till sitt eget Àmne, totalt behöver vi alltsÄ tre Àmnen:
supertubes cluster topic create -n kafka --kubeconfig -f -<<EOF
apiVersion: kafka.banzaicloud.io/v1alpha1
kind: KafkaTopic
metadata:
name: perftest1
spec:
name: perftest1
partitions: 12
replicationFactor: 3
retention.ms: '28800000'
cleanup.policy: delete
EOF
supertubes cluster topic create -n kafka --kubeconfig -f -<<EOF
apiVersion: kafka.banzaicloud.io/v1alpha1
kind: KafkaTopic
metadata:
name: perftest2
spec:
name: perftest2
partitions: 12
replicationFactor: 3
retention.ms: '28800000'
cleanup.policy: delete
EOF
supertubes cluster topic create -n kafka --kubeconfig -f -<<EOF
apiVersion: kafka.banzaicloud.io/v1alpha1
kind: KafkaTopic
metadata:
name: perftest3
spec:
name: perftest3
partitions: 12
replicationFactor: 3
retention.ms: '28800000'
cleanup.policy: delete
EOFFör varje Ă€mne Ă€r faktorn för replikering 3 â det minimi rekommenderade vĂ€rdet för hög tillgĂ€nglighet i produktionssystem.
Belastningstestverktyg
Vi startade tre instanser av belastningstestgeneratorn (varje instans skrev till en separat topic). För belastningstestgeneratorns poddar mÄste node affinity anges sÄ att de endast schemalÀggs pÄ de reserverade noderna:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: loadtest
name: perf-load1
namespace: kafka
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: loadtest
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: loadtest
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nodepool.banzaicloud.io/name
operator: In
values:
- loadgen
containers:
- args:
- -brokers=kafka-0:29092,kafka-1:29092,kafka-2:29092,kafka-3:29092
- -topic=perftest1
- -required-acks=all
- -message-size=512
- -workers=20
image: banzaicloud/perfload:0.1.0-blog
imagePullPolicy: Always
name: sangrenel
resources:
limits:
cpu: 2
memory: 1Gi
requests:
cpu: 2
memory: 1Gi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30NÄgra punkter att tÀnka pÄ:
- Belastningstestgeneratorn genererar meddelanden pÄ 512 byte och publicerar dem i Kafka i batcher om 500 meddelanden.
- Med hjÀlp av argumentet
-required-acks=allanses publiceringen vara lyckad nÀr alla synkroniserade repliker av meddelandet har mottagits och bekrÀftats av Kafka-brokers. Det innebÀr att vi i benchmarket mÀtte inte bara hastigheten hos ledarna som tar emot meddelanden, utan ocksÄ deras efterföljare som replikerar meddelanden. MÄlet med detta test Àr inte att utvÀrdera hastigheten hos konsumenterna (consumers) för nyligen mottagna meddelanden, som fortfarande ligger i operativsystemets sidcache, och dess jÀmförelse med hastigheten för att lÀsa meddelanden som lagras pÄ disk. - Belastningstestgeneratorn kör parallellt 20 arbetare (
-workers=20). Varje arbetare innehÄller 5 producenter som gemensamt anvÀnder arbetarnas anslutning till Kafka-klustret. Totalt har varje generator 100 producenter och alla skickar meddelanden till Kafka-klustret.
Ăvervakning av klustrets tillstĂ„nd
Under load testing of the Kafka cluster, we also monitored its health to ensure there were no pod restarts, unsynchronized replicas, and maximum throughput with minimal fluctuations:
- The load generator writes standard statistics on the number of published messages and the error rate. The error percentage should remain at
0,00%. - , deployed by kafka-operator, provides a monitoring dashboard where we can also observe the state of the cluster. To view this dashboard, execute:
supertubes cluster cruisecontrol show -n kafka --kubeconfig - The ISR level (number of 'in-sync' replicas) is equal to 0 for shrink and expansion.
Measurement results
3 brokers, message size â 512 bytes
With partitions evenly distributed across three brokers, we managed to achieve a performance of ~500 MB/s (approximately 990 thousand messages per second):



The memory consumption by the JVM virtual machine did not exceed 2 GB:



Disk throughput reached the maximum I/O throughput of the node across all three instances where the brokers were running:



From the data on memory usage by the nodes, it can be seen that system buffering and caching took ~10-15 GB:



3 brokers, message size â 100 bytes
With the reduction in message size, the throughput decreases by approximately 15-20%: this is affected by the time spent processing each message. Additionally, the CPU load nearly doubled.



Since there are still unused cores on the broker nodes, performance can be improved by modifying the Kafka configuration. This is a complex task, so to increase throughput, it is better to work with larger messages.
4 brokers, message size â 512 bytes
It is easy to increase the performance of the Kafka cluster simply by adding new brokers and maintaining partition balance (this ensures an even distribution of load among brokers). In our case, after adding a broker, the cluster throughput increased to ~580 MB/s (~1.1 million messages per second). The increase was less than expected: this is mainly explained by the imbalance of partitions (not all brokers are operating at peak capacity).




JVM-maskinens minnesanvÀndning har hÄllits under 2 GB:




Brokers arbete med lagringsenheter har pÄverkats av en obalans i partitioner:




Slutsatser
Den iterativa metoden som presenteras ovan kan utvidgas för att inkludera mer komplexa scenarier med hundratals konsumenter, ompartitionering, rullande uppdateringar, omstarter av poddar etc. Detta gör att vi kan bedöma grÀnserna för Kafkas klusterkapacitet under olika förhÄllanden, identifiera flaskhalsar i dess prestanda och hitta sÀtt att ÄtgÀrda dem.
Vi har utvecklat Supertubes för snabb och enkel distribution av klustret, dess konfiguration, tillÀgg/borttagning av brokers och teman, reagere pÄ aviseringar och sÀkerstÀlla en korrekt funktion av Kafka i Kubernetes i stort. VÄrt mÄl Àr att hjÀlpa till att koncentrera sig pÄ huvuduppgiften ("generera" och "konsumera" Kafka-meddelanden), medan allt det tunga arbetet överlÄts till Supertubes och Kafka-operatören.
Om du Àr intresserad av Banzai Clouds teknik och Open Source-projekt, följ företaget pÄ , eller .
P.S. frÄn översÀttaren
LÀs Àven i vÄr blogg:
- «»;
- «»;
- «».
KĂ€lla: habr.com
