Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Nota. transl.: En aquest article, Banzai Cloud comparteix un exemple de com es poden utilitzar les seves eines personalitzades per fer que Kafka sigui més fàcil d'utilitzar a Kubernetes. Les instruccions següents il·lustren com podeu determinar la mida òptima de la vostra infraestructura i configurar Kafka per aconseguir el rendiment necessari.

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Apache Kafka és una plataforma de streaming distribuïda per crear sistemes de transmissió en temps real fiables, escalables i d'alt rendiment. Les seves impressionants capacitats es poden ampliar amb Kubernetes. Per això hem desenvolupat Operador Kafka de codi obert i una eina anomenada Supertubs. Us permeten executar Kafka a Kubernetes i utilitzar les seves diverses funcions, com ara l'ajustament de la configuració del corredor, l'escala basada en mètriques amb reequilibri, la consciència del bastidor, "suau" (agraciat) llançament d'actualitzacions, etc.

Proveu Supertubes al vostre clúster:

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

O contacteu documentació. També podeu llegir algunes de les capacitats de Kafka, el treball amb el qual s'automatitza mitjançant Supertubes i l'operador Kafka. Ja hem escrit sobre ells al blog:

Quan decidiu desplegar un clúster de Kafka a Kubernetes, probablement us trobareu amb el repte de determinar la mida òptima de la infraestructura subjacent i la necessitat d'ajustar la vostra configuració de Kafka per satisfer els requisits de rendiment. El rendiment màxim de cada corredor està determinat pel rendiment dels components de la infraestructura subjacent, com ara la memòria, el processador, la velocitat del disc, l'ample de banda de la xarxa, etc.

Idealment, la configuració del corredor hauria de ser tal que tots els elements de la infraestructura s'utilitzin al màxim. Tanmateix, a la vida real, aquesta configuració és força complexa. És més probable que els usuaris configuren corredors per maximitzar l'ús d'un o dos components (disc, memòria o processador). En termes generals, un corredor mostra el màxim rendiment quan la seva configuració permet utilitzar el component més lent al màxim. D'aquesta manera ens podem fer una idea aproximada de la càrrega que pot gestionar un corredor.

Teòricament, també podem estimar el nombre de corredors necessaris per gestionar una càrrega determinada. Tanmateix, a la pràctica hi ha tantes opcions de configuració a diferents nivells que és molt difícil (si no impossible) avaluar el rendiment potencial d'una configuració concreta. En altres paraules, és molt difícil planificar una configuració basada en un rendiment determinat.

Per als usuaris de Supertubes, normalment adoptem el següent enfocament: comencem amb una configuració (infraestructura + paràmetres), després mesurem el seu rendiment, ajustem la configuració del corredor i tornem a repetir el procés. Això passa fins que s'utilitza plenament el component més lent de la infraestructura.

D'aquesta manera, tenim una idea més clara de quants corredors necessita un clúster per gestionar una determinada càrrega (el nombre de corredors també depèn d'altres factors, com el nombre mínim de rèpliques de missatges per garantir la resiliència, el nombre de particions). líders, etc.). A més, obtenim informació sobre quins components d'infraestructura requereixen escala vertical.

Aquest article parlarà dels passos que fem per treure el màxim profit dels components més lents en les configuracions inicials i mesurar el rendiment d'un clúster Kafka. Una configuració altament resistent requereix almenys tres corredors en funcionament (min.insync.replicas=3), distribuïts en tres zones d'accessibilitat diferents. Per configurar, escalar i supervisar la infraestructura de Kubernetes, utilitzem la nostra pròpia plataforma de gestió de contenidors per a núvols híbrids: Canonada. Admet on-premise (bare metal, VMware) i cinc tipus de núvols (Alibaba, AWS, Azure, Google, Oracle), així com qualsevol combinació d'ells.

Pensaments sobre la infraestructura i la configuració del clúster de Kafka

Per als exemples següents, vam triar AWS com a proveïdor de núvol i EKS com a distribució de Kubernetes. Es pot implementar una configuració similar utilitzant P.K.E. - Distribució Kubernetes de Banzai Cloud, certificada per CNCF.

Conduir

Amazon ofereix diversos Tipus de volum EBS. Al nucli gp2 и io1 hi ha unitats SSD, però, per garantir un alt rendiment gp2 consumeix crèdits acumulats (crèdits d'E/S), així que hem preferit el tipus io1, que ofereix un alt rendiment constant.

Tipus d'instàncies

El rendiment de Kafka depèn molt de la memòria cau de la pàgina del sistema operatiu, de manera que necessitem instàncies amb prou memòria per als intermediaris (JVM) i la memòria cau de la pàgina. Instància c5.2xgran - un bon començament, ja que té 16 GB de memòria i optimitzat per treballar amb EBS. El seu inconvenient és que només és capaç de proporcionar el màxim rendiment durant no més de 30 minuts cada 24 hores. Si la vostra càrrega de treball requereix un rendiment màxim durant un període de temps més llarg, és possible que vulgueu considerar altres tipus d'instàncies. Això és exactament el que vam fer, aturant-nos c5.4xgran. Proporciona el màxim rendiment 593,75 Mb/s. Rendiment màxim d'un volum EBS io1 superior a la instància c5.4xgran, de manera que és probable que l'element més lent de la infraestructura sigui el rendiment d'E/S d'aquest tipus d'instància (que les nostres proves de càrrega també haurien de confirmar).

Xarxa

El rendiment de la xarxa ha de ser prou gran en comparació amb el rendiment de la instància de la màquina virtual i del disc, en cas contrari, la xarxa es convertirà en un coll d'ampolla. En el nostre cas, la interfície de xarxa c5.4xgran Admet velocitats de fins a 10 Gb/s, que és significativament superior al rendiment d'E/S d'una instància de VM.

Desplegament del corredor

Els intermediaris s'han de desplegar (programats a Kubernetes) a nodes dedicats per evitar competir amb altres processos per recursos de CPU, memòria, xarxa i disc.

Versió de Java

L'opció lògica és Java 11 perquè és compatible amb Docker en el sentit que la JVM determina correctament els processadors i la memòria disponibles per al contenidor en què s'executa el corredor. Sabent que els límits de la CPU són importants, la JVM estableix de manera interna i transparent el nombre de fils GC i fils JIT. Hem utilitzat la imatge de Kafka banzaicloud/kafka:2.13-2.4.0, que inclou la versió 2.4.0 de Kafka (Scala 2.13) a Java 11.

Si voleu obtenir més informació sobre Java/JVM a Kubernetes, consulteu les nostres publicacions següents:

Configuració de la memòria del corredor

Hi ha dos aspectes clau per configurar la memòria del corredor: la configuració per a la JVM i per al pod Kubernetes. El límit de memòria establert per a un pod ha de ser superior a la mida màxima de l'emmagatzematge dinàmic perquè la JVM tingui espai per al metaespai Java que resideix a la seva pròpia memòria i per a la memòria cau de pàgines del sistema operatiu que Kafka utilitza activament. A les nostres proves vam llançar corredors Kafka amb paràmetres -Xmx4G -Xms2G, i el límit de memòria per al pod era 10 Gi. Tingueu en compte que la configuració de memòria per a la JVM es pot obtenir automàticament mitjançant -XX:MaxRAMPercentage и -X:MinRAMPercentage, en funció del límit de memòria del pod.

Configuració del processador del corredor

En termes generals, podeu millorar el rendiment augmentant el paral·lelisme augmentant el nombre de fils utilitzats per Kafka. Com més processadors estigui disponible per a Kafka, millor. A la nostra prova, vam començar amb un límit de 6 processadors i a poc a poc (a través d'iteracions) vam augmentar el seu nombre fins a 15. A més, vam establir num.network.threads=12 a la configuració del corredor per augmentar el nombre de fils que reben dades de la xarxa i les envien. Immediatament descobrint que els corredors de seguidors no podien rebre rèpliques amb prou rapidesa, van plantejar num.replica.fetchers a 4 per augmentar la velocitat amb què els corredors de seguidors replicaven els missatges dels líders.

Eina de generació de càrrega

Hauríeu d'assegurar-vos que el generador de càrrega seleccionat no es quedi sense capacitat abans que el clúster de Kafka (que s'està fent un punt de referència) assoleixi la seva càrrega màxima. En altres paraules, cal dur a terme una avaluació preliminar de les capacitats de l'eina de generació de càrrega i també seleccionar tipus d'instàncies amb un nombre suficient de processadors i memòria. En aquest cas, la nostra eina produirà més càrrega de la que el clúster Kafka pot gestionar. Després de molts experiments, ens vam decidir per tres còpies c5.4xgran, cadascun dels quals tenia un generador en marxa.

Benchmarking

La mesura del rendiment és un procés iteratiu que inclou les etapes següents:

  • instal·lació d'infraestructures (clúster EKS, clúster Kafka, eina de generació de càrrega, així com Prometheus i Grafana);
  • generar una càrrega durant un període determinat per filtrar les desviacions aleatòries en els indicadors de rendiment recollits;
  • ajustar la infraestructura i la configuració del corredor en funció dels indicadors de rendiment observats;
  • repetint el procés fins que s'aconsegueixi el nivell requerit de rendiment del clúster de Kafka. Al mateix temps, ha de ser reproduïble constantment i demostrar variacions mínimes en el rendiment.

La següent secció descriu els passos que es van realitzar durant el procés d'avaluació comparativa del clúster de proves.

Instruments

Les eines següents es van utilitzar per desplegar ràpidament una configuració de referència, generar càrregues i mesurar el rendiment:

  • Banzai Cloud Pipeline per organitzar un clúster EKS d'Amazon c Prometeu (per recollir mètriques de Kafka i d'infraestructura) i Grafana (per visualitzar aquestes mètriques). Vam aprofitar integrat в Canonada serveis que proporcionen supervisió federada, recollida de registres centralitzada, exploració de vulnerabilitats, recuperació de desastres, seguretat de nivell empresarial i molt més.
  • Sangrenel — una eina per provar la càrrega d'un clúster de Kafka.
  • Taulers de control de Grafana per visualitzar les mètriques i la infraestructura de Kafka: Kubernetes Kafka, Exportador de nodes.
  • CLI de Supertubes per a la manera més senzilla de configurar un clúster Kafka a Kubernetes. Zookeeper, operador de Kafka, Envoy i molts altres components estan instal·lats i configurats correctament per executar un clúster Kafka preparat per a la producció a Kubernetes.
    • Per a la instal·lació CLI de supertubs utilitzeu les instruccions proporcionades aquí.

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Clúster EKS

Prepareu un clúster EKS amb nodes de treball dedicats c5.4xgran en diferents zones de disponibilitat per a pods amb corredors de Kafka, així com nodes dedicats per al generador de càrrega i la infraestructura de monitoratge.

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

Un cop el clúster EKS estigui en funcionament, habiliteu-lo integrat servei de vigilància - desplegarà Prometeu i Grafana en un clúster.

Components del sistema Kafka

Instal·leu els components del sistema Kafka (Zookeeper, kafka-operator) a EKS mitjançant la CLI de supertubes:

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

Clúster de Kafka

Per defecte, EKS utilitza volums de tipus EBS gp2, per tant, heu de crear una classe d'emmagatzematge independent basada en els volums io1 per al clúster de 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

Establiu el paràmetre per als corredors min.insync.replicas=3 i implementeu pods de corredor als nodes de tres zones de disponibilitat diferents:

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

Temes

Vam executar tres instàncies del generador de càrrega en paral·lel. Cadascun d'ells escriu sobre el seu tema, és a dir, necessitem tres temes en 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

Per a cada tema, el factor de replicació és 3, el valor mínim recomanat per als sistemes de producció d'alta disponibilitat.

Eina de generació de càrrega

Vam llançar tres còpies del generador de càrrega (cadascun va escriure en un tema independent). Per als pods del generador de càrrega, heu d'establir l'afinitat dels nodes perquè només es programin als nodes assignats per a ells:

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

Alguns punts a tenir en compte:

  • El generador de càrrega genera missatges de 512 bytes de longitud i els publica a Kafka en lots de 500 missatges.
  • Utilitzant un argument -required-acks=all La publicació es considera reeixida quan totes les rèpliques sincronitzades del missatge són rebudes i confirmades pels corredors de Kafka. Això vol dir que en el benchmark vam mesurar no només la velocitat dels líders que reben missatges, sinó també els seus seguidors que replicaven missatges. L'objectiu d'aquesta prova no és avaluar la velocitat de lectura del consumidor (consumidors) missatges rebuts recentment que encara romanen a la memòria cau de la pàgina del sistema operatiu i la seva comparació amb la velocitat de lectura dels missatges emmagatzemats al disc.
  • El generador de càrrega fa funcionar 20 treballadors en paral·lel (-workers=20). Cada treballador conté 5 productors que comparteixen la connexió del treballador amb el clúster de Kafka. Com a resultat, cada generador té 100 productors, i tots envien missatges al clúster de Kafka.

Supervisió de la salut del clúster

Durant les proves de càrrega del clúster de Kafka, també vam supervisar el seu estat per assegurar-nos que no hi havia reinicis de pod, rèpliques fora de sincronització i rendiment màxim amb fluctuacions mínimes:

  • El generador de càrrega escriu estadístiques estàndard sobre el nombre de missatges publicats i la taxa d'error. La taxa d'error hauria de romandre igual 0,00%.
  • Control de creuer, desplegat per kafka-operator, proporciona un tauler on també podem supervisar l'estat del clúster. Per veure aquest panell, feu el següent:
    supertubes cluster cruisecontrol show -n kafka --kubeconfig <path-to-eks-cluster-kubeconfig-file>
  • Nivell ISR (nombre de rèpliques "sincronitzades") la contracció i l'expansió són iguals a 0.

Resultats de la mesura

3 corredors, mida del missatge - 512 bytes

Amb les particions distribuïdes uniformement entre tres corredors, vam poder aconseguir el rendiment ~500 Mb/s (aproximadament 990 mil missatges per segon):

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

El consum de memòria de la màquina virtual JVM no superava els 2 GB:

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

El rendiment del disc va assolir el rendiment màxim del node d'E/S en les tres instàncies en què estaven executant els corredors:

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

De les dades sobre l'ús de la memòria per part dels nodes, es desprèn que l'emmagatzematge i la memòria cau del sistema van trigar entre 10 i 15 GB:

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

3 corredors, mida del missatge - 100 bytes

A mesura que la mida del missatge disminueix, el rendiment es redueix aproximadament entre un 15 i un 20%: el temps dedicat a processar cada missatge l'afecta. A més, la càrrega del processador gairebé s'ha duplicat.

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Com que els nodes del corredor encara tenen nuclis no utilitzats, el rendiment es pot millorar canviant la configuració de Kafka. Aquesta no és una tasca fàcil, així que per augmentar el rendiment és millor treballar amb missatges més grans.

4 corredors, mida del missatge - 512 bytes

Podeu augmentar fàcilment el rendiment d'un clúster de Kafka simplement afegint nous corredors i mantenint un equilibri de particions (això garanteix que la càrrega es distribueixi uniformement entre els intermediaris). En el nostre cas, després d'afegir un corredor, el rendiment del clúster va augmentar a ~580 Mb/s (~1,1 milions de missatges per segon). El creixement va resultar ser inferior a l'esperat: això s'explica principalment pel desequilibri de les particions (no tots els corredors treballen al màxim de les seves capacitats).

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

El consum de memòria de la màquina JVM es va mantenir per sota dels 2 GB:

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

El treball dels corredors amb unitats es va veure afectat pel desequilibri de les particions:

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Determineu la mida adequada per a un clúster de Kafka a Kubernetes

Troballes

L'enfocament iteratiu que s'ha presentat anteriorment es pot ampliar per cobrir escenaris més complexos que involucren centenars de consumidors, reparticions, actualitzacions continuades, reinicis de pods, etc. Tot això ens permet avaluar els límits de les capacitats del clúster Kafka en diverses condicions, identificar colls d'ampolla en el seu funcionament i trobar maneres de combatre'ls.

Hem dissenyat Supertubes per desplegar un clúster de manera ràpida i senzilla, configurar-lo, afegir/eliminar intermediaris i temes, respondre a les alertes i garantir que Kafka en general funcioni correctament a Kubernetes. El nostre objectiu és ajudar-vos a concentrar-vos en la tasca principal (“generar” i “consumir” missatges de Kafka) i deixar tota la feina a Supertubes i a l'operador de Kafka.

Si esteu interessats en les tecnologies Banzai Cloud i els projectes de codi obert, subscriviu-vos a l'empresa a GitHub, LinkedIn o Twitter.

PS del traductor

Llegeix també al nostre blog:

Font: www.habr.com

Afegeix comentari