Bestem passende størrelse for en Kafka-klynge i Kubernetes
Merk. overs.: I denne artikkelen deler Banzai Cloud et eksempel på hvordan dets egendefinerte verktøy kan brukes for å gjøre Kafka enklere å bruke i Kubernetes. Følgende instruksjoner illustrerer hvordan du kan bestemme den optimale størrelsen på infrastrukturen din og konfigurere Kafka selv for å oppnå den nødvendige gjennomstrømningen.
Apache Kafka er en distribuert strømmeplattform for å lage pålitelige, skalerbare og høyytelses sanntidsstrømmesystemer. Dens imponerende evner kan utvides ved hjelp av Kubernetes. For dette har vi utviklet Open Source Kafka-operatør og et verktøy som heter Supertubes. De lar deg kjøre Kafka på Kubernetes og bruke dens ulike funksjoner, for eksempel finjustering av meglerkonfigurasjonen, metrisk-basert skalering med rebalansering, rackbevissthet, "myk" (grasiøs) utrulling av oppdateringer osv.
Prøv Supertubes i klyngen din:
curl https://getsupertubes.sh | sh и supertubes install -a --no-democluster --kubeconfig <path-to-eks-cluster-kubeconfig-file>
Eller ta kontakt dokumentasjon. Du kan også lese om noen av egenskapene til Kafka, arbeidet med dette er automatisert ved hjelp av Supertubes og Kafka-operatøren. Vi har allerede skrevet om dem på bloggen:
Når du bestemmer deg for å distribuere en Kafka-klynge på Kubernetes, vil du sannsynligvis bli møtt med utfordringen med å bestemme den optimale størrelsen på den underliggende infrastrukturen og behovet for å finjustere Kafka-konfigurasjonen for å møte gjennomstrømningskravene. Den maksimale ytelsen til hver megler bestemmes av ytelsen til de underliggende infrastrukturkomponentene, som minne, prosessor, diskhastighet, nettverksbåndbredde, etc.
Ideelt sett bør meglerkonfigurasjonen være slik at alle infrastrukturelementer brukes til maksimal kapasitet. Men i det virkelige liv er dette oppsettet ganske komplekst. Det er mer sannsynlig at brukere vil konfigurere meglere for å maksimere bruken av én eller to komponenter (disk, minne eller prosessor). Generelt sett viser en megler maksimal ytelse når konfigurasjonen lar den tregeste komponenten brukes i sin fulle grad. På denne måten kan vi få en grov ide om belastningen en megler kan håndtere.
Teoretisk kan vi også estimere antall meglere som kreves for å håndtere en gitt belastning. Imidlertid er det i praksis så mange konfigurasjonsalternativer på forskjellige nivåer at det er svært vanskelig (om ikke umulig) å evaluere den potensielle ytelsen til en bestemt konfigurasjon. Det er med andre ord svært vanskelig å planlegge en konfigurasjon basert på en gitt ytelse.
For Supertubes-brukere tar vi vanligvis følgende tilnærming: vi starter med en viss konfigurasjon (infrastruktur + innstillinger), måler deretter ytelsen, justerer meglerinnstillingene og gjentar prosessen på nytt. Dette skjer inntil den tregeste komponenten av infrastrukturen er fullt utnyttet.
På denne måten får vi en klarere ide om hvor mange meglere en klynge trenger for å håndtere en viss belastning (antall meglere avhenger også av andre faktorer, som minimum antall meldingsreplikaer for å sikre robusthet, antall partisjoner ledere osv.). I tillegg får vi innsikt i hvilke infrastrukturkomponenter som krever vertikal skalering.
Denne artikkelen vil snakke om trinnene vi tar for å få mest mulig ut av de tregeste komponentene i innledende konfigurasjoner og måle gjennomstrømningen til en Kafka-klynge. En svært spenstig konfigurasjon krever minst tre løpende meglere (min.insync.replicas=3), fordelt på tre forskjellige tilgjengelighetssoner. For å konfigurere, skalere og overvåke Kubernetes-infrastrukturen bruker vi vår egen containeradministrasjonsplattform for hybridskyer - Rørledning. Den støtter lokalt (bart metall, VMware) og fem typer skyer (Alibaba, AWS, Azure, Google, Oracle), samt enhver kombinasjon av dem.
Tanker om Kafka-klyngeinfrastruktur og konfigurasjon
For eksemplene nedenfor valgte vi AWS som skyleverandør og EKS som Kubernetes-distribusjon. En lignende konfigurasjon kan implementeres ved hjelp av P.K.E. - Kubernetes-distribusjon fra Banzai Cloud, sertifisert av CNCF.
disk
Amazon tilbyr ulike EBS volumtyper. I kjernen gp2 и io1 Det finnes imidlertid SSD-stasjoner for å sikre høy gjennomstrømning gp2 bruker akkumulerte kreditter (I/O-kreditter), så vi foretrakk typen io1, som gir jevn høy gjennomstrømning.
Forekomsttyper
Kafkas ytelse er svært avhengig av operativsystemets sidebuffer, så vi trenger instanser med nok minne for meglere (JVM) og sidebuffer. Forekomst c5.2xlarge - en god start, siden den har 16 GB minne og optimalisert for å jobbe med EBS. Ulempen er at den kun er i stand til å gi maksimal ytelse i ikke mer enn 30 minutter hver 24. time. Hvis arbeidsmengden krever topp ytelse over lengre tid, kan det være lurt å vurdere andre forekomsttyper. Det var akkurat det vi gjorde, og stoppet ved c5.4xlarge. Det gir maksimal gjennomstrømning inn 593,75 Mb/s. Maksimal gjennomstrømning av et EBS-volum io1 høyere enn instansen c5.4xlarge, så det tregeste elementet i infrastrukturen er sannsynligvis I/O-gjennomstrømmingen av denne instanstypen (som belastningstestene våre også bør bekrefte).
nettverk
Nettverksgjennomstrømningen må være stor nok sammenlignet med ytelsen til VM-forekomsten og disken, ellers blir nettverket en flaskehals. I vårt tilfelle, nettverksgrensesnittet c5.4xlarge støtter hastigheter på opptil 10 Gb/s, som er betydelig høyere enn I/O-gjennomstrømningen til en VM-forekomst.
Implementering av megler
Meglere bør distribueres (planlagt i Kubernetes) til dedikerte noder for å unngå å konkurrere med andre prosesser for CPU-, minne-, nettverks- og diskressurser.
Java-versjon
Det logiske valget er Java 11 fordi det er kompatibelt med Docker i den forstand at JVM korrekt bestemmer prosessorene og minnet som er tilgjengelig for beholderen der megleren kjører. Når du vet at CPU-grenser er viktige, setter JVM internt og transparent antall GC-tråder og JIT-tråder. Vi brukte Kafka-bildet banzaicloud/kafka:2.13-2.4.0, som inkluderer Kafka versjon 2.4.0 (Scala 2.13) på Java 11.
Hvis du vil lære mer om Java/JVM på Kubernetes, sjekk ut våre følgende innlegg:
Det er to nøkkelaspekter ved å konfigurere meglerminne: innstillinger for JVM og for Kubernetes pod. Minnegrensen som er satt for en pod må være større enn den maksimale haugstørrelsen slik at JVM har plass til Java-metaspacet som ligger i dets eget minne og for operativsystemets sidebuffer som Kafka aktivt bruker. I våre tester lanserte vi Kafka-meglere med parametere -Xmx4G -Xms2G, og minnegrensen for poden var 10 Gi. Vær oppmerksom på at minneinnstillinger for JVM kan hentes automatisk ved å bruke -XX:MaxRAMPercentage и -X:MinRAMPercentage, basert på minnegrensen for poden.
Megler prosessor innstillinger
Generelt sett kan du forbedre ytelsen ved å øke parallelliteten ved å øke antall tråder brukt av Kafka. Jo flere prosessorer tilgjengelig for Kafka, jo bedre. I testen vår startet vi med en grense på 6 prosessorer og økte gradvis (gjennom iterasjoner) antallet til 15. I tillegg satte vi num.network.threads=12 i meglerinnstillingene for å øke antall tråder som mottar data fra nettverket og sender det. Da de umiddelbart oppdaget at følgemeglerne ikke kunne motta kopier raskt nok, reiste de num.replica.fetchers til 4 for å øke hastigheten som følgermeglere replikerte meldinger fra ledere med.
Last generasjonsverktøy
Du bør sørge for at den valgte lastgeneratoren ikke går tom for kapasitet før Kafka-klyngen (som blir benchmarked) når sin maksimale belastning. Med andre ord er det nødvendig å foreta en foreløpig vurdering av egenskapene til lastgenereringsverktøyet, og også velge instanstyper for det med et tilstrekkelig antall prosessorer og minne. I dette tilfellet vil verktøyet vårt produsere mer belastning enn Kafka-klyngen kan håndtere. Etter mange eksperimenter bestemte vi oss for tre eksemplarer c5.4xlarge, som hver hadde en generator i gang.
Referansemåling
Ytelsesmåling er en iterativ prosess som inkluderer følgende stadier:
sette opp infrastruktur (EKS-klynge, Kafka-klynge, lastgenereringsverktøy, samt Prometheus og Grafana);
generere en belastning for en viss periode for å filtrere tilfeldige avvik i de innsamlede ytelsesindikatorene;
justering av meglerens infrastruktur og konfigurasjon basert på observerte ytelsesindikatorer;
gjenta prosessen til det nødvendige nivået av Kafka-klyngegjennomstrømning er oppnådd. Samtidig må den være konsekvent reproduserbar og vise minimale variasjoner i gjennomstrømming.
Den neste delen beskriver trinnene som ble utført under testklynge-benchmarking-prosessen.
Verktøy
Følgende verktøy ble brukt til raskt å distribuere en grunnlinjekonfigurasjon, generere belastninger og måle ytelse:
Banzai Cloud Pipeline for organisering av en EKS-klynge fra Amazon c Prometheus (for å samle Kafka og infrastrukturberegninger) og grafana (for å visualisere disse beregningene). Vi utnyttet integrert в Rørledning tjenester som gir forent overvåking, sentralisert logginnsamling, sårbarhetsskanning, katastrofegjenoppretting, sikkerhet i bedriftsklasse og mye mer.
Sangrenel — et verktøy for belastningsteste en Kafka-klynge.
Supertubes CLI for den enkleste måten å sette opp en Kafka-klynge på Kubernetes. Zookeeper, Kafka-operatør, Envoy og mange andre komponenter er installert og riktig konfigurert for å kjøre en produksjonsklar Kafka-klynge på Kubernetes.
For installasjon superrør CLI bruk instruksjonene som følger med her.
EKS klynge
Forbered en EKS-klynge med dedikerte arbeidernoder c5.4xlarge i forskjellige tilgjengelighetssoner for pods med Kafka-meglere, samt dedikerte noder for lastgeneratoren og overvåkingsinfrastrukturen.
For hvert emne er replikeringsfaktoren 3 – minimum anbefalt verdi for svært tilgjengelige produksjonssystemer.
Last generasjonsverktøy
Vi lanserte tre eksemplarer av lastgeneratoren (hver skrev i et eget emne). For belastningsgeneratorer må du angi nodetilhørighet slik at de bare planlegges på nodene som er tildelt dem:
Lastgeneratoren genererer meldinger på 512 byte lange og publiserer dem til Kafka i grupper på 500 meldinger.
Ved å bruke et argument -required-acks=all Publikasjonen anses som vellykket når alle synkroniserte kopier av meldingen er mottatt og bekreftet av Kafka-meglere. Dette betyr at i benchmarken målte vi ikke bare hastigheten på ledere som mottar meldinger, men også deres følgere som replikerte meldinger. Hensikten med denne testen er ikke å evaluere forbrukernes lesehastighet (forbrukere) nylig mottatte meldinger som fortsatt forblir i OS-sidebufferen, og sammenligningen med lesehastigheten til meldinger som er lagret på disken.
Lastgeneratoren kjører 20 arbeidere parallelt (-workers=20). Hver arbeider inneholder 5 produsenter som deler arbeiderens tilknytning til Kafka-klyngen. Som et resultat har hver generator 100 produsenter, og de sender alle meldinger til Kafka-klyngen.
Overvåke helsen til klyngen
Under belastningstesting av Kafka-klyngen overvåket vi også helsen for å sikre at det ikke var noen pod-omstart, ingen replikaer som ikke var synkroniserte, og maksimal gjennomstrømning med minimale svingninger:
Lastgeneratoren skriver standardstatistikk om antall publiserte meldinger og feilprosent. Feilprosenten bør forbli den samme 0,00%.
Cruise Control, distribuert av kafka-operatør, gir et dashbord der vi også kan overvåke tilstanden til klyngen. For å se dette panelet gjør du:
supertubes cluster cruisecontrol show -n kafka --kubeconfig <path-to-eks-cluster-kubeconfig-file>
ISR nivå (antall "synkroniserte" replikaer) krympe og ekspansjon er lik 0.
Måleresultater
3 meglere, meldingsstørrelse - 512 byte
Med partisjoner jevnt fordelt på tre meglere, var vi i stand til å oppnå ytelse ~500 Mb/s (omtrent 990 tusen meldinger per sekund):
Minneforbruket til den virtuelle JVM-maskinen oversteg ikke 2 GB:
Diskgjennomstrømning nådde maksimal I/O-nodegjennomstrømning på alle tre forekomstene som meglerne kjørte på:
Fra dataene om minnebruk av noder, følger det at systembuffring og caching tok ~10-15 GB:
3 meglere, meldingsstørrelse - 100 byte
Etter hvert som meldingsstørrelsen reduseres, synker gjennomstrømningen med omtrent 15–20 %: tiden som brukes på å behandle hver melding, påvirker den. I tillegg er prosessorbelastningen nesten doblet.
Siden meglernoder fortsatt har ubrukte kjerner, kan ytelsen forbedres ved å endre Kafka-konfigurasjonen. Dette er ikke en lett oppgave, så for å øke gjennomstrømmingen er det bedre å jobbe med større meldinger.
4 meglere, meldingsstørrelse - 512 byte
Du kan enkelt øke ytelsen til en Kafka-klynge ved ganske enkelt å legge til nye meglere og opprettholde en balanse av partisjoner (dette sikrer at belastningen er jevnt fordelt mellom meglere). I vårt tilfelle, etter å ha lagt til en megler, økte klyngegjennomstrømningen til ~580 Mb/s (~1,1 millioner meldinger per sekund). Veksten viste seg å være mindre enn forventet: Dette forklares hovedsakelig av ubalansen mellom partisjoner (ikke alle meglere jobber på toppen av sine evner).
Minneforbruket til JVM-maskinen holdt seg under 2 GB:
Arbeidet til meglere med stasjoner ble påvirket av ubalansen mellom partisjoner:
Funn
Den iterative tilnærmingen presentert ovenfor kan utvides til å dekke mer komplekse scenarier som involverer hundrevis av forbrukere, ompartisjonering, rullende oppdateringer, omstart av pod osv. Alt dette lar oss vurdere grensene for Kafka-klyngens evner under ulike forhold, identifisere flaskehalser i driften og finne måter å bekjempe dem.
Vi utviklet Supertubes for raskt og enkelt å distribuere en klynge, konfigurere den, legge til/fjerne meglere og emner, svare på varsler og sikre at Kafka generelt fungerer som den skal på Kubernetes. Målet vårt er å hjelpe deg med å konsentrere deg om hovedoppgaven («generere» og «konsumere» Kafka-meldinger), og overlate alt det harde arbeidet til Supertubes og Kafka-operatøren.
Hvis du er interessert i Banzai Cloud-teknologier og Open Source-prosjekter, abonner på selskapet på GitHub, Linkedin eller Twitter.