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

Bemærk. overs.: I denne artikel deler Banzai Cloud et eksempel på, hvordan dets brugerdefinerede værktøjer kan bruges til at gøre Kafka nemmere at bruge i Kubernetes. De følgende instruktioner illustrerer, hvordan du kan bestemme den optimale størrelse af din infrastruktur og konfigurere Kafka selv for at opnå den nødvendige gennemstrømning.

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

Apache Kafka er en distribueret streamingplatform til at skabe pålidelige, skalerbare og højtydende realtidsstreamingsystemer. Dens imponerende muligheder kan udvides ved hjælp af Kubernetes. Til dette har vi udviklet Open Source Kafka-operatør og et værktøj kaldet Superrør. De giver dig mulighed for at køre Kafka på Kubernetes og bruge dens forskellige funktioner, såsom finjustering af mæglerkonfigurationen, metrisk-baseret skalering med rebalancering, rack-bevidsthed, "blød" (yndefuld) udrulning af opdateringer mv.

Prøv Supertubes i din klynge:

curl https://getsupertubes.sh | sh и supertubes install -a --no-democluster --kubeconfig <path-to-eks-cluster-kubeconfig-file>

Eller kontakt dokumentation. Du kan også læse om nogle af mulighederne i Kafka, hvor arbejdet er automatiseret ved hjælp af Supertubes og Kafka-operatøren. Vi har allerede skrevet om dem på bloggen:

Når du beslutter dig for at implementere en Kafka-klynge på Kubernetes, vil du sandsynligvis blive stillet over for udfordringen med at bestemme den optimale størrelse af den underliggende infrastruktur og behovet for at finjustere din Kafka-konfiguration for at opfylde gennemløbskravene. Den maksimale ydeevne for hver mægler bestemmes af ydeevnen af ​​de underliggende infrastrukturkomponenter, såsom hukommelse, processor, diskhastighed, netværksbåndbredde osv.

Ideelt set bør mæglerkonfigurationen være sådan, at alle infrastrukturelementer bruges til deres maksimale kapacitet. Men i det virkelige liv er denne opsætning ret kompleks. Det er mere sandsynligt, at brugere vil konfigurere mæglere til at maksimere brugen af ​​en eller to komponenter (disk, hukommelse eller processor). Generelt viser en mægler maksimal ydeevne, når dens konfiguration tillader den langsomste komponent at blive brugt i sit fulde omfang. På denne måde kan vi få en nogenlunde idé om den belastning, som en mægler kan håndtere.

Teoretisk kan vi også estimere antallet af mæglere, der skal til for at håndtere en given belastning. Men i praksis er der så mange konfigurationsmuligheder på forskellige niveauer, at det er meget svært (hvis ikke umuligt) at evaluere den potentielle ydeevne af en bestemt konfiguration. Det er med andre ord meget svært at planlægge en konfiguration baseret på en given ydeevne.

For Supertubes-brugere tager vi normalt følgende tilgang: vi starter med en vis konfiguration (infrastruktur + indstillinger), måler derefter dens ydeevne, justerer mæglerindstillingerne og gentager processen igen. Dette sker, indtil den langsomste komponent af infrastrukturen er fuldt udnyttet.

På denne måde får vi en klarere idé om, hvor mange mæglere en klynge har brug for for at håndtere en bestemt belastning (antallet af mæglere afhænger også af andre faktorer, såsom minimumsantallet af beskedreplikaer for at sikre robusthed, antallet af partitioner ledere osv.). Derudover får vi indsigt i, hvilke infrastrukturkomponenter der kræver vertikal skalering.

Denne artikel vil tale om de trin, vi tager for at få mest muligt ud af de langsomste komponenter i indledende konfigurationer og måle gennemløbet af en Kafka-klynge. En meget robust konfiguration kræver mindst tre kørende mæglere (min.insync.replicas=3), fordelt på tre forskellige tilgængelighedszoner. For at konfigurere, skalere og overvåge Kubernetes-infrastrukturen bruger vi vores egen containerstyringsplatform til hybridskyer - Pipeline. Det understøtter on-premise (bare metal, VMware) og fem typer skyer (Alibaba, AWS, Azure, Google, Oracle) såvel som enhver kombination af dem.

Tanker om Kafka-klyngeinfrastruktur og -konfiguration

Til eksemplerne nedenfor valgte vi AWS som cloud-udbyder og EKS som Kubernetes-distribution. En lignende konfiguration kan implementeres vha P.K.E. - Kubernetes distribution fra Banzai Cloud, certificeret af CNCF.

disk

Amazon tilbyder forskellige EBS volumen typer. I kernen gp2 и io1 der er dog SSD-drev for at sikre høj gennemstrømning gp2 bruger akkumulerede kreditter (I/O-kreditter), så vi foretrak typen io1, som tilbyder ensartet høj gennemstrømning.

Forekomsttyper

Kafkas ydeevne er meget afhængig af operativsystemets sidecache, så vi har brug for instanser med nok hukommelse til mæglerne (JVM) og sidecache. Forekomst c5.2xlarge - en god start, da den har 16 GB hukommelse og optimeret til at arbejde med EBS. Dens ulempe er, at den kun er i stand til at yde maksimal ydeevne i højst 30 minutter hver 24. time. Hvis din arbejdsbyrde kræver maksimal ydeevne over en længere periode, kan du overveje andre instanstyper. Det var præcis, hvad vi gjorde, og stoppede ved c5.4xlarge. Det giver maksimal gennemstrømning ind 593,75 Mb/s. Maksimal gennemstrømning af et EBS-volumen io1 højere end tilfældet c5.4xlarge, så det langsomste element i infrastrukturen er sandsynligvis I/O-gennemstrømningen af ​​denne instanstype (hvilket vores belastningstest også burde bekræfte).

netværk

Netværksgennemstrømningen skal være stor nok i forhold til ydeevnen af ​​VM-instansen og disken, ellers bliver netværket en flaskehals. I vores tilfælde netværksgrænsefladen c5.4xlarge understøtter hastigheder på op til 10 Gb/s, hvilket er væsentligt højere end I/O-gennemstrømningen for en VM-instans.

Mæglerimplementering

Mæglere bør implementeres (planlagt i Kubernetes) til dedikerede noder for at undgå at konkurrere med andre processer for CPU, hukommelse, netværk og diskressourcer.

Java version

Det logiske valg er Java 11, fordi det er kompatibelt med Docker i den forstand, at JVM korrekt bestemmer de processorer og hukommelse, der er tilgængelig for den container, som mægleren kører i. Ved at vide, at CPU-grænser er vigtige, indstiller JVM internt og transparent antallet af GC-tråde og JIT-tråde. Vi brugte Kafka-billedet banzaicloud/kafka:2.13-2.4.0, som inkluderer Kafka version 2.4.0 (Scala 2.13) på Java 11.

Hvis du gerne vil lære mere om Java/JVM på Kubernetes, så tjek vores følgende indlæg:

Indstillinger for mæglerhukommelse

Der er to nøgleaspekter ved konfiguration af mæglerhukommelse: indstillinger for JVM og for Kubernetes pod. Hukommelsesgrænsen, der er sat for en pod, skal være større end den maksimale heapstørrelse, så JVM'en har plads til Java-metaspacet, som ligger i dens egen hukommelse, og til operativsystemets sidecache, som Kafka aktivt bruger. I vores test lancerede vi Kafka-mæglere med parametre -Xmx4G -Xms2G, og hukommelsesgrænsen for poden var 10 Gi. Bemærk venligst, at hukommelsesindstillinger for JVM kan opnås automatisk vha -XX:MaxRAMPercentage и -X:MinRAMPercentage, baseret på hukommelsesgrænsen for poden.

Mægler processor indstillinger

Generelt kan du forbedre ydeevnen ved at øge paralleliteten ved at øge antallet af tråde, der bruges af Kafka. Jo flere processorer der er tilgængelige for Kafka, jo bedre. I vores test startede vi med en grænse på 6 processorer og hævede gradvist (gennem iterationer) deres antal til 15. Derudover satte vi num.network.threads=12 i mæglerindstillingerne for at øge antallet af tråde, der modtager data fra netværket og sender dem. Da de med det samme opdagede, at follower-mæglerne ikke kunne modtage replikaer hurtigt nok, rejste de num.replica.fetchers til 4 for at øge hastigheden, hvormed follower-mæglere replikerede beskeder fra ledere.

Indlæs Genereringsværktøj

Du bør sikre dig, at den valgte belastningsgenerator ikke løber tør for kapacitet, før Kafka-klyngen (som er ved at blive benchmarked) når sin maksimale belastning. Med andre ord er det nødvendigt at foretage en foreløbig vurdering af belastningsgenereringsværktøjets muligheder og også vælge instanstyper til det med et tilstrækkeligt antal processorer og hukommelse. I dette tilfælde vil vores værktøj producere mere belastning, end Kafka-klyngen kan klare. Efter mange eksperimenter slog vi os til tre eksemplarer c5.4xlarge, som hver havde en generator kørende.

Benchmarking

Præstationsmåling er en iterativ proces, der omfatter følgende faser:

  • opsætning af infrastruktur (EKS-klynge, Kafka-klynge, belastningsgenereringsværktøj samt Prometheus og Grafana);
  • generere en belastning i en vis periode for at filtrere tilfældige afvigelser i de indsamlede præstationsindikatorer;
  • justering af mæglerens infrastruktur og konfiguration baseret på observerede præstationsindikatorer;
  • gentagelse af processen, indtil det nødvendige niveau af Kafka-klyngegennemløb er opnået. Samtidig skal den være konsekvent reproducerbar og demonstrere minimale variationer i gennemløb.

Det næste afsnit beskriver de trin, der blev udført under testklyngebenchmarking-processen.

Værktøj

Følgende værktøjer blev brugt til hurtigt at implementere en baseline-konfiguration, generere belastninger og måle ydeevne:

  • Banzai Cloud Pipeline for at organisere en EKS-klynge fra Amazon c Prometheus (for at indsamle Kafka- og infrastrukturmålinger) og grafana (for at visualisere disse målinger). Vi udnyttede det integreret в Pipeline tjenester, der leverer fødereret overvågning, centraliseret logindsamling, sårbarhedsscanning, gendannelse af katastrofer, sikkerhed i virksomhedskvalitet og meget mere.
  • Sangrenel — et værktøj til belastningstest af en Kafka-klynge.
  • Grafana-dashboards til visualisering af Kafka-metrik og infrastruktur: Kubernetes Kafka, Node eksportør.
  • Supertubes CLI for den nemmeste måde at opsætte en Kafka-klynge på Kubernetes. Zookeeper, Kafka-operatør, Envoy og mange andre komponenter er installeret og korrekt konfigureret til at køre en produktionsklar Kafka-klynge på Kubernetes.
    • Til installation superrør CLI brug den medfølgende vejledning her.

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

EKS klynge

Forbered en EKS-klynge med dedikerede arbejdsknudepunkter c5.4xlarge i forskellige tilgængelighedszoner for pods med Kafka-mæglere, samt dedikerede noder til belastningsgeneratoren og overvågningsinfrastrukturen.

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 at køre, skal du aktivere dens integrerede overvågningstjeneste — hun vil indsætte Prometheus og Grafana i en klynge.

Kafka systemkomponenter

Installer Kafka-systemkomponenter (Zookeeper, kafka-operatør) i EKS ved hjælp af supertubes CLI:

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

Kafka klynge

Som standard bruger EKS EBS-volumener af typen gp2, så du skal oprette en separat lagerklasse baseret på volumener io1 til Kafka-klynge:

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

Indstil parameteren for mæglere min.insync.replicas=3 og implementer broker pods på noder i tre forskellige tilgængelighedszoner:

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 kørte tre belastningsgeneratorer parallelt. Hver af dem skriver til deres eget emne, det vil sige, vi har brug for tre emner i alt:

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 replikationsfaktoren 3 – den mindste anbefalede værdi for højt tilgængelige produktionssystemer.

Indlæs Genereringsværktøj

Vi lancerede tre kopier af belastningsgeneratoren (hver skrev i et separat emne). For load generator pods skal du indstille nodeaffinitet, så de kun er planlagt på de noder, der er allokeret til 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

Et par punkter at bemærke:

  • Belastningsgeneratoren genererer meddelelser på 512 bytes i længden og udgiver dem til Kafka i batches på 500 meddelelser.
  • Ved at bruge et argument -required-acks=all Udgivelsen anses for at være vellykket, når alle synkroniserede replikaer af meddelelsen modtages og bekræftes af Kafka-mæglere. Det betyder, at vi i benchmark ikke kun målte hastigheden på ledere, der modtager beskeder, men også deres følgere, der replikerer beskeder. Formålet med denne test er ikke at evaluere forbrugernes læsehastighed (forbrugere) nyligt modtagne beskeder, der stadig forbliver i OS-sidecachen, og dens sammenligning med læsehastigheden af ​​beskeder, der er gemt på disken.
  • Belastningsgeneratoren kører 20 arbejdere parallelt (-workers=20). Hver arbejder indeholder 5 producenter, der deler arbejderens tilknytning til Kafka-klyngen. Som følge heraf har hver generator 100 producenter, og de sender alle beskeder til Kafka-klyngen.

Overvågning af klyngens sundhed

Under belastningstest af Kafka-klyngen overvågede vi også dens helbred for at sikre, at der ikke var nogen pod-genstarter, ingen replikaer, der ikke var synkroniseret, og maksimal gennemstrømning med minimale udsving:

  • Belastningsgeneratoren skriver standardstatistik over antallet af publicerede meddelelser og fejlprocenten. Fejlprocenten bør forblive den samme 0,00%.
  • Fartpilot, implementeret af kafka-operatør, giver et dashboard, hvor vi også kan overvåge klyngens tilstand. For at se dette panel skal du gøre:
    supertubes cluster cruisecontrol show -n kafka --kubeconfig <path-to-eks-cluster-kubeconfig-file>
  • ISR niveau (antal "synkroniserede" replikaer) krympning og ekspansion er lig med 0.

Måleresultater

3 mæglere, beskedstørrelse - 512 bytes

Med partitioner jævnt fordelt på tre mæglere var vi i stand til at opnå ydeevne ~500 Mb/s (ca. 990 tusind beskeder pr. sekund):

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

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

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

Hukommelsesforbruget på den virtuelle JVM-maskine oversteg ikke 2 GB:

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

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

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

Diskgennemløb nåede den maksimale I/O-nodegennemstrømning på alle tre forekomster, som mæglerne kørte på:

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

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

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

Fra dataene om hukommelsesbrug af noder, følger det, at systembuffring og caching tog ~10-15 GB:

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

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

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

3 mæglere, beskedstørrelse - 100 bytes

Efterhånden som beskedstørrelsen falder, falder gennemstrømningen med cirka 15-20 %: den tid, der bruges på at behandle hver besked, påvirker den. Derudover er processorbelastningen næsten fordoblet.

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

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

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

Da mæglernoder stadig har ubrugte kerner, kan ydeevnen forbedres ved at ændre Kafka-konfigurationen. Dette er ikke en nem opgave, så for at øge gennemstrømningen er det bedre at arbejde med større beskeder.

4 mæglere, beskedstørrelse - 512 bytes

Du kan nemt øge ydeevnen af ​​en Kafka-klynge ved blot at tilføje nye mæglere og opretholde en balance mellem partitioner (dette sikrer, at belastningen er jævnt fordelt mellem mæglere). I vores tilfælde, efter at have tilføjet en mægler, steg klyngens gennemløb til ~580 Mb/s (~1,1 millioner beskeder pr. sekund). Væksten viste sig at være mindre end forventet: Dette forklares hovedsageligt af ubalancen mellem partitioner (ikke alle mæglere arbejder på toppen af ​​deres evner).

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

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

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

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

Hukommelsesforbruget for JVM-maskinen forblev under 2 GB:

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

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

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

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

Mægleres arbejde med drev blev påvirket af ubalancen mellem partitioner:

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

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

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

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

Fund

Den iterative tilgang præsenteret ovenfor kan udvides til at dække mere komplekse scenarier, der involverer hundredvis af forbrugere, ompartitionering, rullende opdateringer, pod-genstarter osv. Alt dette giver os mulighed for at vurdere grænserne for Kafka-klyngens muligheder under forskellige forhold, identificere flaskehalse i dens drift og finde måder at bekæmpe dem på.

Vi har designet Supertubes til hurtigt og nemt at implementere en klynge, konfigurere den, tilføje/fjerne mæglere og emner, reagere på advarsler og sikre, at Kafka generelt fungerer korrekt på Kubernetes. Vores mål er at hjælpe dig med at koncentrere dig om hovedopgaven (“generere” og “forbruge” Kafka-beskeder), og overlade alt det hårde arbejde til Supertubes og Kafka-operatøren.

Hvis du er interesseret i Banzai Cloud-teknologier og Open Source-projekter, kan du abonnere på virksomheden på GitHub, LinkedIn eller Twitter.

PS fra oversætteren

Læs også på vores blog:

Kilde: www.habr.com

Tilføj en kommentar