Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Nota. transl.: Neste artigo, Banzai Cloud comparte un exemplo de como se poden usar as súas ferramentas personalizadas para facilitar o uso de Kafka dentro de Kubernetes. As seguintes instrucións ilustran como pode determinar o tamaño óptimo da súa infraestrutura e configurar Kafka para acadar o rendemento necesario.

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Apache Kafka é unha plataforma de streaming distribuída para crear sistemas de transmisión en tempo real fiables, escalables e de alto rendemento. As súas impresionantes capacidades pódense ampliar usando Kubernetes. Para iso desenvolvemos Operador Kafka de código aberto e unha ferramenta chamada Supertubos. Permítenche executar Kafka en Kubernetes e utilizar as súas diversas funcións, como o axuste fino da configuración do corredor, a escala baseada en métricas con reequilibrio, a conciencia do rack, o "suave" (gracioso) lanzamento de actualizacións, etc.

Proba Supertubes no teu clúster:

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

Ou contactar documentación. Tamén podes ler sobre algunhas das capacidades de Kafka, cuxo traballo se automatiza mediante Supertubes e o operador Kafka. Xa escribimos sobre eles no blog:

Cando decida implantar un clúster de Kafka en Kubernetes, é probable que se enfronte ao reto de determinar o tamaño óptimo da infraestrutura subxacente e a necesidade de afinar a súa configuración de Kafka para cumprir os requisitos de rendemento. O rendemento máximo de cada corredor está determinado polo rendemento dos compoñentes da infraestrutura subxacente, como a memoria, o procesador, a velocidade do disco, o ancho de banda da rede, etc.

Idealmente, a configuración do corredor debería ser tal que todos os elementos da infraestrutura se utilicen ao máximo. Non obstante, na vida real esta configuración é bastante complexa. É máis probable que os usuarios configuren corredores para maximizar o uso dun ou dous compoñentes (disco, memoria ou procesador). En xeral, un corredor mostra o máximo rendemento cando a súa configuración permite que o compoñente máis lento se utilice ao máximo. Deste xeito, podemos facernos unha idea aproximada da carga que pode soportar un corredor.

Teoricamente, tamén podemos estimar o número de corretores necesarios para xestionar unha determinada carga. Non obstante, na práctica hai tantas opcións de configuración a diferentes niveis que é moi difícil (se non imposible) avaliar o rendemento potencial dunha configuración concreta. Noutras palabras, é moi difícil planificar unha configuración baseada nun determinado rendemento.

Para os usuarios de Supertubes, adoitamos adoptar o seguinte enfoque: comezamos con algunha configuración (infraestrutura + configuración), despois medimos o seu rendemento, axustamos a configuración do corredor e repetimos o proceso de novo. Isto ocorre ata que o compoñente máis lento da infraestrutura é totalmente utilizado.

Deste xeito, temos unha idea máis clara de cantos corredores necesita un clúster para xestionar unha determinada carga (o número de corretores tamén depende doutros factores, como o número mínimo de réplicas de mensaxes para garantir a resistencia, o número de particións). líderes, etc.). Ademais, obtemos información sobre os compoñentes da infraestrutura que requiren escalamento vertical.

Neste artigo falarase dos pasos que tomamos para sacar o máximo proveito dos compoñentes máis lentos nas configuracións iniciais e medir o rendemento dun clúster de Kafka. Unha configuración altamente resistente require polo menos tres corredores en execución (min.insync.replicas=3), distribuídas en tres zonas de accesibilidade diferentes. Para configurar, escalar e supervisar a infraestrutura de Kubernetes, usamos a nosa propia plataforma de xestión de contedores para nubes híbridas: Oleoduto. Admite on-premise (bare metal, VMware) e cinco tipos de nubes (Alibaba, AWS, Azure, Google, Oracle), así como calquera combinación delas.

Pensamentos sobre a infraestrutura e a configuración do clúster de Kafka

Para os exemplos seguintes, escollimos AWS como provedor de nube e EKS como distribución de Kubernetes. Pódese implementar unha configuración similar usando P.K.E. - Distribución Kubernetes de Banzai Cloud, certificada por CNCF.

disco

Amazon ofrece varios Tipos de volume EBS. No núcleo gp2 и io1 non obstante, hai unidades SSD para garantir un alto rendemento gp2 consume créditos acumulados (créditos de E/S), polo que preferimos o tipo io1, que ofrece un alto rendemento consistente.

Tipos de instancia

O rendemento de Kafka depende moito da caché de páxinas do sistema operativo, polo que necesitamos instancias con memoria suficiente para os intermediarios (JVM) e a caché de páxinas. Instancia c5.2xgrande - un bo comezo, xa que ten 16 GB de memoria e optimizado para traballar con EBS. A súa desvantaxe é que só é capaz de proporcionar o máximo rendemento durante non máis de 30 minutos cada 24 horas. Se a túa carga de traballo require un rendemento máximo durante un período de tempo máis longo, podes considerar outros tipos de instancias. Iso foi exactamente o que fixemos, parando c5.4xgrande. Ofrece o máximo rendemento 593,75 Mb/s. Rendemento máximo dun volume EBS io1 superior á instancia c5.4xgrande, polo que é probable que o elemento máis lento da infraestrutura sexa o rendemento de E/S deste tipo de instancia (que as nosas probas de carga tamén deberían confirmar).

Rede

O rendemento da rede debe ser o suficientemente grande en comparación co rendemento da instancia de VM e do disco, se non, a rede convértese nun pescozo de botella. No noso caso, a interface de rede c5.4xgrande admite velocidades de ata 10 Gb/s, o que é significativamente superior ao rendemento de E/S dunha instancia de VM.

Implementación do corredor

Os corredores deberían despregarse (programados en Kubernetes) en nós dedicados para evitar competir con outros procesos por recursos de CPU, memoria, rede e disco.

Versión de Java

A opción lóxica é Java 11 porque é compatible con Docker no sentido de que a JVM determina correctamente os procesadores e a memoria dispoñibles para o contedor no que se está a executar o corredor. Sabendo que os límites do procesador son importantes, a JVM establece de forma interna e transparente o número de fíos GC e fíos JIT. Usamos a imaxe de Kafka banzaicloud/kafka:2.13-2.4.0, que inclúe a versión de Kafka 2.4.0 (Scala 2.13) en Java 11.

Se desexa obter máis información sobre Java/JVM en Kubernetes, consulte as nosas seguintes publicacións:

Configuración da memoria do corredor

Hai dous aspectos fundamentais para configurar a memoria do corredor: a configuración para a JVM e para o pod Kubernetes. O límite de memoria establecido para un pod debe ser maior que o tamaño máximo do montón para que a JVM teña espazo para o metaespazo Java que reside na súa propia memoria e para a caché de páxinas do sistema operativo que Kafka utiliza activamente. Nas nosas probas lanzamos corretores Kafka con parámetros -Xmx4G -Xms2G, e o límite de memoria para o pod era 10 Gi. Teña en conta que a configuración de memoria para a JVM pódese obter automaticamente usando -XX:MaxRAMPercentage и -X:MinRAMPercentage, en función do límite de memoria para o pod.

Configuración do procesador do corredor

En xeral, pode mellorar o rendemento aumentando o paralelismo aumentando o número de fíos utilizados por Kafka. Cantos máis procesadores dispoña de Kafka, mellor. Na nosa proba, comezamos cun límite de 6 procesadores e aos poucos (a través de iteracións) subimos o seu número a 15. Ademais, establecemos num.network.threads=12 na configuración do corredor para aumentar o número de fíos que reciben datos da rede e os envían. Inmediatamente descubrindo que os corredores seguidores non podían recibir réplicas con suficiente rapidez, levantaron num.replica.fetchers a 4 para aumentar a velocidade coa que os corredores de seguidores replicaban as mensaxes dos líderes.

Ferramenta de xeración de carga

Debes asegurarte de que o xerador de carga seleccionado non se esgote antes de que o clúster de Kafka (que se está a comparar) alcance a súa carga máxima. Noutras palabras, é necesario realizar unha avaliación preliminar das capacidades da ferramenta de xeración de carga e tamén seleccionar tipos de instancia para ela cun número suficiente de procesadores e memoria. Neste caso, a nosa ferramenta producirá máis carga da que pode soportar o clúster de Kafka. Despois de moitos experimentos, decidimos tres copias c5.4xgrande, cada un dos cales tiña un xerador en funcionamento.

Benchmarking

A medición do rendemento é un proceso iterativo que inclúe as seguintes etapas:

  • creación de infraestruturas (clúster EKS, clúster Kafka, ferramenta de xeración de carga, así como Prometheus e Grafana);
  • xerando unha carga durante un período determinado para filtrar as desviacións aleatorias nos indicadores de rendemento recollidos;
  • axustar a infraestrutura e a configuración do corredor en función dos indicadores de rendemento observados;
  • repetindo o proceso ata acadar o nivel necesario de rendemento do clúster de Kafka. Ao mesmo tempo, debe ser constantemente reproducible e demostrar variacións mínimas no rendemento.

A seguinte sección describe os pasos que se realizaron durante o proceso de evaluación comparativa do clúster de probas.

Ferramentas

Utilizáronse as seguintes ferramentas para implementar rapidamente unha configuración de referencia, xerar cargas e medir o rendemento:

  • Banzai Cloud Pipeline para organizar un clúster EKS de Amazon c Prometeu (para recoller Kafka e métricas de infraestrutura) e grafana (para visualizar estas métricas). Aproveitamos integrado в Oleoduto servizos que proporcionan seguimento federado, recollida de rexistros centralizada, dixitalización de vulnerabilidades, recuperación ante desastres, seguridade de nivel empresarial e moito máis.
  • Sangrenel — unha ferramenta para probar a carga dun clúster de Kafka.
  • Paneis de Grafana para visualizar as métricas e infraestrutura de Kafka: Kubernetes Kafka, Exportador de nodos.
  • CLI de Supertubes para a forma máis sinxela de configurar un clúster de Kafka en Kubernetes. Zookeeper, operador de Kafka, Envoy e moitos outros compoñentes están instalados e configurados correctamente para executar un clúster Kafka listo para a produción en Kubernetes.
    • Para a instalación CLI de supertubos use as instrucións proporcionadas aquí.

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Clúster EKS

Prepare un clúster EKS con nodos de traballo dedicados c5.4xgrande en diferentes zonas de dispoñibilidade para pods con corretores de Kafka, así como nodos dedicados para o xerador de carga e a infraestrutura de monitorización.

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

Unha vez que o clúster EKS estea en funcionamento, active a súa integración servizo de vixilancia - desplegará a Prometheus e a Grafana nun clúster.

Compoñentes do sistema Kafka

Instale os compoñentes do sistema Kafka (Zookeeper, kafka-operator) en EKS usando supertubes CLI:

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

Clúster de Kafka

Por defecto, EKS usa volumes de tipo EBS gp2, polo que cómpre crear unha clase de almacenamento separada baseada nos volumes io1 para o cluster 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

Establece o parámetro para corretores min.insync.replicas=3 e implementar pods de corredor en nós en tres zonas de dispoñibilidade diferentes:

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

Temas

Executamos tres instancias do xerador de carga en paralelo. Cada un deles escribe sobre o seu propio tema, é dicir, necesitamos tres temas 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

Para cada tema, o factor de replicación é 3, o valor mínimo recomendado para sistemas de produción de alta dispoñibilidade.

Ferramenta de xeración de carga

Lanzamos tres copias do xerador de carga (cada unha escribiu nun tema separado). Para os pods xeradores de carga, cómpre establecer a afinidade de nodos para que estean programados só nos nodos asignados para eles:

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

Algúns puntos a destacar:

  • O xerador de carga xera mensaxes de 512 bytes de lonxitude e publícaas a Kafka en lotes de 500 mensaxes.
  • Usando un argumento -required-acks=all A publicación considérase exitosa cando todas as réplicas sincronizadas da mensaxe son recibidas e confirmadas polos corredores de Kafka. Isto significa que no benchmark non só medimos a velocidade dos líderes que reciben mensaxes, senón tamén os seus seguidores que replican as mensaxes. O obxectivo desta proba non é avaliar a velocidade de lectura do consumidor (consumidores) mensaxes recibidas recentemente que aínda permanecen na caché da páxina do SO e a súa comparación coa velocidade de lectura das mensaxes almacenadas no disco.
  • O xerador de carga fai funcionar 20 traballadores en paralelo (-workers=20). Cada traballador contén 5 produtores que comparten a conexión do traballador co clúster de Kafka. Como resultado, cada xerador ten 100 produtores, e todos envían mensaxes ao clúster de Kafka.

Seguimento da saúde do clúster

Durante a proba de carga do clúster de Kafka, tamén supervisamos o seu estado para asegurarnos de que non houbese reinicios de pod, réplicas sen sincronización e o máximo rendemento con flutuacións mínimas:

  • O xerador de carga escribe estatísticas estándar sobre o número de mensaxes publicadas e a taxa de erro. A taxa de erro debe seguir sendo a mesma 0,00%.
  • Control de cruceiro, despregado por kafka-operator, ofrece un panel onde tamén podemos supervisar o estado do clúster. Para ver este panel fai:
    supertubes cluster cruisecontrol show -n kafka --kubeconfig <path-to-eks-cluster-kubeconfig-file>
  • Nivel ISR (número de réplicas "sincronizadas") a contracción e a expansión son iguais a 0.

Resultados da medición

3 corredores, tamaño da mensaxe - 512 bytes

Con particións distribuídas uniformemente en tres corredores, puidemos acadar o rendemento ~500 Mb/s (aproximadamente 990 mil mensaxes por segundo):

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

O consumo de memoria da máquina virtual JVM non superou os 2 GB:

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

O rendemento do disco alcanzou o rendemento máximo do nodo de E/S nas tres instancias nas que se executaban os corredores:

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Dos datos sobre o uso da memoria polos nodos, despréndese que o almacenamento en búfer e caché do sistema tardaron entre 10 e 15 GB:

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

3 corredores, tamaño da mensaxe - 100 bytes

A medida que o tamaño da mensaxe diminúe, o rendemento cae aproximadamente entre un 15 e un 20 %: o tempo dedicado a procesar cada mensaxe inflúe nel. Ademais, a carga do procesador case se duplicou.

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Dado que os nodos do corredor aínda teñen núcleos sen usar, o rendemento pódese mellorar cambiando a configuración de Kafka. Non é unha tarefa sinxela, polo que para aumentar o rendemento é mellor traballar con mensaxes máis grandes.

4 corredores, tamaño da mensaxe - 512 bytes

Podes aumentar facilmente o rendemento dun clúster de Kafka simplemente engadindo novos corredores e mantendo un equilibrio de particións (isto garante que a carga se distribúa uniformemente entre os corredores). No noso caso, despois de engadir un corredor, o rendemento do clúster aumentou a ~580 Mb/s (~1,1 millóns de mensaxes por segundo). O crecemento resultou ser menor do esperado: isto explícase principalmente polo desequilibrio das particións (non todos os corredores traballan no cumio das súas capacidades).

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

O consumo de memoria da máquina JVM permaneceu por debaixo dos 2 GB:

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

O traballo dos corredores con unidades viuse afectado polo desequilibrio das particións:

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Determine o tamaño adecuado para un clúster de Kafka en Kubernetes

Descubrimentos

O enfoque iterativo presentado anteriormente pódese ampliar para cubrir escenarios máis complexos que involucren centos de consumidores, repartición, actualizacións continuas, reinicios de pod, etc. Todo isto permítenos avaliar os límites das capacidades do clúster de Kafka en diversas condicións, identificar colos de botella no seu funcionamento e atopar formas de combatelos.

Deseñamos Supertubes para implementar un clúster de xeito rápido e sinxelo, configuralo, engadir/eliminar corretores e temas, responder ás alertas e garantir que, en xeral, Kafka funcione correctamente en Kubernetes. O noso obxectivo é axudarche a concentrarte na tarefa principal ("xerar" e "consumir" mensaxes de Kafka) e deixar todo o traballo duro a Supertubes e ao operador de Kafka.

Se estás interesado en tecnoloxías Banzai Cloud e proxectos de código aberto, subscríbete á empresa en GitHub, LinkedIn ou chilro.

PS do tradutor

Lea tamén no noso blog:

Fonte: www.habr.com

Engadir un comentario