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.

Bestem passende størrelse for en Kafka-klynge i Kubernetes

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:

Minneinnstillinger for megler

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.
  • Grafana-dashbord for visualisering av Kafka-beregninger og infrastruktur: Kubernetes Kafka, Nodeeksportør.
  • 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.

Bestem passende størrelse for en Kafka-klynge i Kubernetes

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.

banzai cluster create -f https://raw.githubusercontent.com/banzaicloud/kafka-operator/master/docs/benchmarks/infrastructure/cluster_eks_202001.json

Når EKS-klyngen er oppe og går, aktiver den integrerte overvåkingstjeneste — hun vil distribuere Prometheus og Grafana i en klynge.

Kafka systemkomponenter

Installer Kafka-systemkomponenter (Zookeeper, kafka-operatør) i EKS ved å bruke supertubes CLI:

supertubes install -a --no-democluster --kubeconfig <path-to-eks-cluster-kubeconfig-file>

Kafka-klynge

Som standard bruker EKS EBS-volumer av typen gp2, så du må opprette en egen lagringsklasse basert på volumer io1 for Kafka-klyngen:

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

Angi parameteren for meglere min.insync.replicas=3 og distribuer meglerpods på noder i tre forskjellige tilgjengelighetssoner:

supertubes cluster create -n kafka --kubeconfig <path-to-eks-cluster-kubeconfig-file> -f https://raw.githubusercontent.com/banzaicloud/kafka-operator/master/docs/benchmarks/infrastructure/kafka_202001_3brokers.yaml --wait --timeout 600

Emner

Vi kjørte tre lastgeneratorforekomster parallelt. Hver av dem skriver til sitt eget emne, det vil si at vi trenger tre emner totalt:

supertubes cluster topic create -n kafka --kubeconfig <path-to-eks-cluster-kubeconfig-file> -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 <path-to-eks-cluster-kubeconfig-file> -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 <path-to-eks-cluster-kubeconfig-file> -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
EOF

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:

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: 30

Noen punkter å merke seg:

  • 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):

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Minneforbruket til den virtuelle JVM-maskinen oversteg ikke 2 GB:

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Diskgjennomstrømning nådde maksimal I/O-nodegjennomstrømning på alle tre forekomstene som meglerne kjørte på:

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Fra dataene om minnebruk av noder, følger det at systembuffring og caching tok ~10-15 GB:

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

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.

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

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).

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Minneforbruket til JVM-maskinen holdt seg under 2 GB:

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Arbeidet til meglere med stasjoner ble påvirket av ubalansen mellom partisjoner:

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

Bestem passende størrelse for en Kafka-klynge i Kubernetes

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.

PS fra oversetter

Les også på bloggen vår:

Kilde: www.habr.com

Legg til en kommentar