Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Notă. transl.: În acest articol, Banzai Cloud oferă un exemplu despre modul în care instrumentele sale personalizate pot fi folosite pentru a face Kafka mai ușor de utilizat în Kubernetes. Următoarele instrucțiuni ilustrează modul în care puteți determina dimensiunea optimă a infrastructurii dvs. și puteți configura Kafka în sine pentru a obține debitul necesar.

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Apache Kafka este o platformă de streaming distribuită pentru crearea de sisteme de streaming în timp real fiabile, scalabile și de înaltă performanță. Capacitățile sale impresionante pot fi extinse folosind Kubernetes. Pentru asta ne-am dezvoltat Operator Kafka cu sursă deschisă și un instrument numit Supertuburi. Acestea vă permit să rulați Kafka pe Kubernetes și să utilizați diferitele sale caracteristici, cum ar fi reglarea fină a configurației brokerului, scalarea bazată pe metrici cu reechilibrare, conștientizarea rack-ului, „soft” (graţios) lansarea de actualizări etc.

Încercați Supertubes în clusterul dvs.:

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

Sau contactați documentație. De asemenea, puteți citi despre unele dintre capacitățile Kafka, lucru cu care este automatizat folosind Supertubes și operator Kafka. Despre ele am scris deja pe blog:

Când decideți să implementați un cluster Kafka pe Kubernetes, probabil că vă veți confrunta cu provocarea de a determina dimensiunea optimă a infrastructurii de bază și nevoia de a vă ajusta configurația Kafka pentru a îndeplini cerințele de debit. Performanța maximă a fiecărui broker este determinată de performanța componentelor infrastructurii de bază, cum ar fi memoria, procesorul, viteza discului, lățimea de bandă a rețelei etc.

În mod ideal, configurația brokerului ar trebui să fie astfel încât toate elementele de infrastructură să fie folosite la capacitățile lor maxime. Cu toate acestea, în viața reală, această configurație este destul de complexă. Este mai probabil ca utilizatorii să configureze brokerii pentru a maximiza utilizarea a una sau două componente (disc, memorie sau procesor). În general, un broker arată performanțe maxime atunci când configurația sa permite ca cea mai lentă componentă să fie utilizată în cea mai mare măsură. În acest fel, ne putem face o idee aproximativă despre sarcina pe care o poate suporta un broker.

Teoretic, putem estima și numărul de brokeri necesari pentru a gestiona o anumită sarcină. Cu toate acestea, în practică există atât de multe opțiuni de configurare la diferite niveluri încât este foarte dificil (dacă nu imposibil) să evaluezi performanța potențială a unei anumite configurații. Cu alte cuvinte, este foarte dificil să planificați o configurație bazată pe o anumită performanță.

Pentru utilizatorii Supertubes, de obicei adoptăm următoarea abordare: începem cu o anumită configurație (infrastructură + setări), apoi măsurăm performanța acesteia, ajustam setările brokerului și repetăm ​​procesul din nou. Acest lucru se întâmplă până când cea mai lentă componentă a infrastructurii este utilizată pe deplin.

În acest fel, ne facem o idee mai clară despre câți brokeri are nevoie un cluster pentru a gestiona o anumită sarcină (numărul de brokeri depinde și de alți factori, cum ar fi numărul minim de replici a mesajelor pentru a asigura rezistența, numărul de partiții lideri etc.). În plus, obținem o perspectivă asupra componentelor infrastructurii care necesită scalare verticală.

Acest articol va vorbi despre pașii pe care îi luăm pentru a profita la maximum de cele mai lente componente din configurațiile inițiale și pentru a măsura debitul unui cluster Kafka. O configurație foarte rezistentă necesită cel puțin trei brokeri care rulează (min.insync.replicas=3), distribuite în trei zone diferite de accesibilitate. Pentru a configura, scala și monitoriza infrastructura Kubernetes, folosim propria noastră platformă de gestionare a containerelor pentru cloud-uri hibride - Conductă. Acceptă on-premise (bare metal, VMware) și cinci tipuri de cloud (Alibaba, AWS, Azure, Google, Oracle), precum și orice combinație a acestora.

Gânduri despre infrastructura și configurația clusterului Kafka

Pentru exemplele de mai jos, am ales AWS ca furnizor de cloud și EKS ca distribuție Kubernetes. O configurație similară poate fi implementată folosind PKE - Distributie Kubernetes de la Banzai Cloud, certificat CNCF.

disc

Amazon oferă diverse Tipuri de volum EBS. In nucleu gp2 и io1 există totuși unități SSD pentru a asigura un randament ridicat gp2 consumă credite acumulate (credite I/O), așa că am preferat tipul io1, care oferă un randament ridicat constant.

Tipuri de instanțe

Performanța lui Kafka depinde în mare măsură de memoria cache a paginii sistemului de operare, așa că avem nevoie de instanțe cu suficientă memorie pentru brokeri (JVM) și cache de pagină. Instanță c5.2xmare - un început bun, deoarece are 16 GB de memorie și optimizat pentru a lucra cu EBS. Dezavantajul său este că este capabil să ofere doar performanță maximă timp de cel mult 30 de minute la fiecare 24 de ore. Dacă volumul dvs. de lucru necesită performanțe de vârf pentru o perioadă mai lungă de timp, vă recomandăm să luați în considerare alte tipuri de instanțe. Exact asta am făcut, oprindu-ne la c5.4xmare. Oferă debit maxim în 593,75 Mbps. Debitul maxim al unui volum EBS io1 mai mare decât instanța c5.4xmare, deci cel mai lent element al infrastructurii este probabil să fie debitul I/O al acestui tip de instanță (pe care testele noastre de încărcare ar trebui să o confirme și ele).

rețea

Debitul rețelei trebuie să fie suficient de mare în comparație cu performanța instanței VM și a discului, altfel rețeaua devine un blocaj. În cazul nostru, interfața de rețea c5.4xmare acceptă viteze de până la 10 Gb/s, ceea ce este semnificativ mai mare decât debitul I/O al unei instanțe VM.

Implementarea brokerului

Brokerii ar trebui să fie implementați (programați în Kubernetes) în noduri dedicate pentru a evita concurența cu alte procese pentru resursele CPU, memorie, rețea și disc.

Versiunea Java

Alegerea logică este Java 11 deoarece este compatibil cu Docker în sensul că JVM-ul determină corect procesoarele și memoria disponibilă pentru containerul în care rulează brokerul. Știind că limitele CPU sunt importante, JVM-ul setează intern și transparent numărul de fire GC și fire JIT. Am folosit imaginea Kafka banzaicloud/kafka:2.13-2.4.0, care include versiunea Kafka 2.4.0 (Scala 2.13) pe Java 11.

Dacă doriți să aflați mai multe despre Java/JVM pe Kubernetes, consultați următoarele postări:

Setări de memorie broker

Există două aspecte cheie în configurarea memoriei brokerului: setările pentru JVM și pentru pod Kubernetes. Limita de memorie setată pentru un pod trebuie să fie mai mare decât dimensiunea maximă a heap-ului, astfel încât JVM-ul să aibă loc pentru metaspațiul Java care se află în propria memorie și pentru memoria cache a paginii sistemului de operare pe care Kafka o folosește în mod activ. În testele noastre am lansat brokeri Kafka cu parametri -Xmx4G -Xms2G, iar limita de memorie pentru pod a fost 10 Gi. Vă rugăm să rețineți că setările de memorie pentru JVM pot fi obținute automat folosind -XX:MaxRAMPercentage и -X:MinRAMPercentage, pe baza limitei de memorie pentru pod.

Setările procesorului brokerului

În general, puteți îmbunătăți performanța prin creșterea paralelismului prin creșterea numărului de fire utilizate de Kafka. Cu cât sunt mai multe procesoare disponibile pentru Kafka, cu atât mai bine. În testul nostru, am început cu o limită de 6 procesoare și treptat (prin iterații) am ridicat numărul acestora la 15. În plus, am setat num.network.threads=12 în setările brokerului pentru a crește numărul de fire care primesc date din rețea și le trimit. Descoperind imediat că brokerii adepți nu pot primi replici suficient de repede, aceștia au ridicat num.replica.fetchers la 4 pentru a crește viteza cu care brokerii adepți au replicat mesajele de la lideri.

Instrument de generare a încărcăturii

Trebuie să vă asigurați că generatorul de sarcină selectat nu epuizează capacitatea înainte ca clusterul Kafka (care este evaluat) să atingă sarcina maximă. Cu alte cuvinte, este necesar să se efectueze o evaluare preliminară a capacităților instrumentului de generare a sarcinii și, de asemenea, să se selecteze tipuri de instanțe pentru acesta cu un număr suficient de procesoare și memorie. În acest caz, instrumentul nostru va produce mai multă sarcină decât poate suporta clusterul Kafka. După multe experimente, ne-am hotărât pe trei exemplare c5.4xmare, fiecare dintre ele avea un generator în funcțiune.

Benchmarking

Măsurarea performanței este un proces iterativ care include următoarele etape:

  • crearea infrastructurii (cluster EKS, cluster Kafka, instrument de generare a încărcăturii, precum și Prometheus și Grafana);
  • generarea unei sarcini pentru o anumită perioadă pentru a filtra abaterile aleatoare ale indicatorilor de performanță colectați;
  • ajustarea infrastructurii și configurației brokerului pe baza indicatorilor de performanță observați;
  • repetarea procesului până la atingerea nivelului necesar de debit al clusterului Kafka. În același timp, trebuie să fie reproductibil în mod constant și să demonstreze variații minime în debit.

Următoarea secțiune descrie pașii care au fost efectuati în timpul procesului de evaluare comparativă a clusterului de testare.

Instrumente

Următoarele instrumente au fost folosite pentru a implementa rapid o configurație de bază, pentru a genera încărcări și pentru a măsura performanța:

  • Banzai Cloud Pipeline pentru organizarea unui cluster EKS de la Amazon c Prometeu (pentru a colecta valorile Kafka și a infrastructurii) și grafana (pentru a vizualiza aceste valori). Noi am profitat integrat в Conductă servicii care oferă monitorizare federată, colectare centralizată a jurnalelor, scanare a vulnerabilităților, recuperare în caz de dezastru, securitate la nivel de întreprindere și multe altele.
  • Sangrenel — un instrument pentru testarea încărcării unui cluster Kafka.
  • Tablouri de bord Grafana pentru vizualizarea valorilor și infrastructurii Kafka: Kubernetes Kafka, Exportator de noduri.
  • CLI Supertubes pentru cel mai simplu mod de a configura un cluster Kafka pe Kubernetes. Zookeeper, operatorul Kafka, Envoy și multe alte componente sunt instalate și configurate corespunzător pentru a rula un cluster Kafka gata de producție pe Kubernetes.
    • Pentru instalare supertuburi CLI utilizați instrucțiunile furnizate aici.

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

cluster EKS

Pregătiți un cluster EKS cu noduri de lucru dedicate c5.4xmare în diferite zone de disponibilitate pentru pod-uri cu brokeri Kafka, precum și noduri dedicate pentru generatorul de sarcină și infrastructura de monitorizare.

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

Odată ce clusterul EKS este activ și funcționează, activați-l integrat serviciu de monitorizare — ea îi va desfășura pe Prometheus și Grafana într-un cluster.

Componentele sistemului Kafka

Instalați componentele sistemului Kafka (Zookeeper, kafka-operator) în EKS folosind CLI supertubes:

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

cluster Kafka

În mod implicit, EKS utilizează volume de tip EBS gp2, deci trebuie să creați o clasă de stocare separată bazată pe volume io1 pentru clusterul Kafka:

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

Setați parametrul pentru brokeri min.insync.replicas=3 și implementați poduri de broker pe noduri în trei zone de disponibilitate diferite:

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

Subiecte

Am rulat trei instanțe generatoare de sarcină în paralel. Fiecare dintre ei scrie pe subiectul său, adică avem nevoie de trei subiecte în total:

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

Pentru fiecare subiect, factorul de replicare este 3 - valoarea minimă recomandată pentru sistemele de producție cu o mare disponibilitate.

Instrument de generare a încărcăturii

Am lansat trei copii ale generatorului de sarcină (fiecare a scris într-un subiect separat). Pentru podurile generatoare de încărcare, trebuie să setați afinitatea nodurilor astfel încât acestea să fie programate numai pe nodurile alocate pentru ele:

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

Câteva puncte de reținut:

  • Generatorul de încărcare generează mesaje cu lungimea de 512 octeți și le publică către Kafka în loturi de 500 de mesaje.
  • Folosind un argument -required-acks=all Publicarea este considerată de succes atunci când toate replicile sincronizate ale mesajului sunt primite și confirmate de către brokerii Kafka. Aceasta înseamnă că în benchmark am măsurat nu numai viteza liderilor care primesc mesaje, ci și adepții lor care reproduc mesajele. Scopul acestui test nu este de a evalua viteza de citire a consumatorilor (consumatori) mesajele primite recent care rămân încă în memoria cache a paginii OS și compararea acesteia cu viteza de citire a mesajelor stocate pe disc.
  • Generatorul de sarcină rulează 20 de lucrători în paralel (-workers=20). Fiecare lucrător conține 5 producători care împărtășesc conexiunea lucrătorului cu clusterul Kafka. Drept urmare, fiecare generator are 100 de producători și toți trimit mesaje către clusterul Kafka.

Monitorizarea stării de sănătate a clusterului

În timpul testării de încărcare a clusterului Kafka, i-am monitorizat, de asemenea, starea de sănătate pentru a ne asigura că nu există reporniri pod, replici nesincronizate și debit maxim cu fluctuații minime:

  • Generatorul de sarcină scrie statistici standard despre numărul de mesaje publicate și rata de eroare. Rata de eroare ar trebui să rămână aceeași 0,00%.
  • Controlul vitezei de croazieră, implementat de kafka-operator, oferă un tablou de bord unde putem monitoriza și starea clusterului. Pentru a vizualiza acest panou, faceți:
    supertubes cluster cruisecontrol show -n kafka --kubeconfig <path-to-eks-cluster-kubeconfig-file>
  • nivelul ISR (număr de replici „în sincronizare”) contracția și dilatarea sunt egale cu 0.

Rezultatele măsurătorilor

3 brokeri, dimensiunea mesajului - 512 octeți

Cu partițiile distribuite uniform între trei brokeri, am reușit să obținem performanță ~500 Mb/s (aproximativ 990 mii de mesaje pe secundă):

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Consumul de memorie al mașinii virtuale JVM nu a depășit 2 GB:

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Debitul discului a atins debitul maxim al nodului I/O în toate cele trei instanțe pe care rulau brokerii:

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Din datele privind utilizarea memoriei de către noduri, rezultă că stocarea în memoria tampon și stocarea în cache a sistemului a durat ~10-15 GB:

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

3 brokeri, dimensiunea mesajului - 100 octeți

Pe măsură ce dimensiunea mesajului scade, debitul scade cu aproximativ 15-20%: timpul petrecut procesând fiecare mesaj îl afectează. În plus, încărcarea procesorului aproape s-a dublat.

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Deoarece nodurile broker au încă nuclee neutilizate, performanța poate fi îmbunătățită prin schimbarea configurației Kafka. Aceasta nu este o sarcină ușoară, așa că pentru a crește debitul este mai bine să lucrați cu mesaje mai mari.

4 brokeri, dimensiunea mesajului - 512 octeți

Puteți crește cu ușurință performanța unui cluster Kafka prin simpla adăugare de noi brokeri și menținerea unui echilibru de partiții (acest lucru asigură că sarcina este distribuită uniform între brokeri). În cazul nostru, după adăugarea unui broker, debitul clusterului a crescut la ~580 Mb/s (~1,1 milioane de mesaje pe secundă). Creșterea s-a dovedit a fi mai mică decât se aștepta: acest lucru se explică în principal prin dezechilibrul partițiilor (nu toți brokerii lucrează la vârful capacităților lor).

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Consumul de memorie al mașinii JVM a rămas sub 2 GB:

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Munca brokerilor cu unități a fost afectată de dezechilibrul partițiilor:

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Determinați dimensiunea adecvată pentru un cluster Kafka în Kubernetes

Constatări

Abordarea iterativă prezentată mai sus poate fi extinsă pentru a acoperi scenarii mai complexe care implică sute de consumatori, recompartimentare, actualizări de rulare, reporniri pod etc. Toate acestea ne permit să evaluăm limitele capacităților clusterului Kafka în diferite condiții, să identificăm blocajele în funcționarea acestuia și să găsim modalități de a le combate.

Am proiectat Supertubes pentru a implementa rapid și ușor un cluster, pentru a-l configura, pentru a adăuga/elimina brokeri și subiecte, pentru a răspunde la alerte și pentru a ne asigura că, în general, Kafka funcționează corect pe Kubernetes. Scopul nostru este să vă ajutăm să vă concentrați asupra sarcinii principale („generați” și „consumați” mesaje Kafka) și să lăsați toată munca grea în seama Supertubes și operatorului Kafka.

Dacă sunteți interesat de tehnologiile Banzai Cloud și proiectele Open Source, abonați-vă la companie la adresa GitHub, LinkedIn sau Twitter.

PS de la traducator

Citește și pe blogul nostru:

Sursa: www.habr.com

Adauga un comentariu