Gestion de Kafka dans Kubernetes avec Strimzi

Gestion de Kafka dans Kubernetes avec Strimzi

Vous appréciez notre travail......nous recrutons !

Ne ratez pas nos articles sur l'open source, le big data et les systèmes distribués, fréquence faible d’un email tous les deux mois.

Kubernetes n’est pas la première plateforme à laquelle on pense pour faire tourner des clusters Apache Kafka. En effet, la forte adhérence de Kafka au stockage pourrait être difficile à gérer par rapport à la manière de gérer le stockage dans Kubernetes. Les brokers d’un cluster Kafka sont uniques et stateful, comment gérer cela avec Kubernetes ?

Découvrons les bases du projet Strimzi, un operator Kafka pour Kubernetes créer et maintenu par Red Hat et voyons quels problèmes il peut nous aider à résoudre.

Nous ferons également une mise au point sur la manière dont nous pouvons connecter des outils Kafka aditionnels à un déploiement de Strimzi.

Enfin, nous comparerons Strimzi avec d’autres operators Kafka en fin d’article.

Strimzi

Strimzi logo

Strimzi est un Operator qui vise à réduire le coût technique du déploiement de clusters Apache Kafka des infrastructres cloud native.

Strimzi étend l’API Kubernetes et ajoute des ressources Kafka, dont entre autres :

  • Clusers Kafka
  • Topics Kafka
  • Utilisateurs Kafka
  • Instances Kafka MirrorMaker2
  • Instances Kafka Connect

Le project est actuellement incubé à l’état “Sandbox” au sein de la Cloud Native Computing Foundation.

Note : Le site de la CNCF définit un projet “sandbox” comme un “projet expérimental utilisant des technologies de pointes et non testé à l’échelle en production”.

Avec Strimzi, déployer un cluster Kakfa de 3 noeuds chiffrés avec TLS est aussi simple que d’appliquer le YAML suivant :

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    version: 3.2.3
    replicas: 3
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: true
    config:
      offsets.topic.replication.factor: 3
      transaction.state.log.replication.factor: 3
      transaction.state.log.min.isr: 2
      default.replication.factor: 3
      min.insync.replicas: 2
      inter.broker.protocol.version: "3.2"
    storage:
      type: jbod
      volumes:
        - id: 0
          type: persistent-claim
          size: 100Gi
          deleteClaim: false
        - id: 1
          type: persistent-claim
          size: 100Gi
          deleteClaim: false
  zookeeper:
    replicas: 3
    storage:
      type: persistent-claim
      size: 100Gi
      deleteClaim: false
  entityOperator:
    topicOperator: {}
    userOperator: {}

La ressource topic est définie de cette manière :

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: my-topic
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 1
  replicas: 1
  config:
    retention.ms: 7200000
    segment.bytes: 1073741824

Ces deux exemples viennent du dossier examples du code source de Strimzi. Il contient beaucoup d’autres examples qui couvrent l’ensemble des possibilités de Strimzi.

Sécurité

Une fonctionnalité particulièrement intéressante de Strimzi concerne la sécurité. Par défaut, la communication intra-broker est chiffrée avec TLS et celle entre les brokers et ZooKeeper est chiffrée et authentifiée avec mTLS.

Les clusters Apache ZooKeeper qui hébergent les métadonnées des instances Kafka ne sont pas exposées en dehors du cluster Kubernetes, ce qui améliore encore la sécurité des services.

Il n’est pas possible de surcharger ces configurations par défaut. On peut cependant accéder au ZooKeeper si besoin grâce à ce projet de scholzj.

Strimzi PodSets

Les StatefulSets permettent de gérer des applications statefuls distribuées nativement dans Kubernetes.

La documentation officielle décrit :

(Les StatefulSets) gèrent le déploiement et la mise à l’échelle d’un ensemble de Pods, et fournissent des garanties sur l’ordre et l’unicité de ces Pods.

Les StatefulSets sont natifs à Kubernetes mais présentent un certain nombre de limitations dont voici quelques exemples :

  • Le scaling up et down est linéaire. Par exemple avec un StatefulSet de 3 pods : pod-1, pod-2 et pod3, le scale up créera forcément pod-4 puis le scaling down supprimera forcément pod-4. Cela peut s’avérer problématique dans le cas où l’on souhaite éliminer un pod en particulier. Appliqué à Kafka, il peut arriver une situation dans laquelle un topic mal configuré rend un broker instable. Avec les StatefulSets, on ne peut pas supprimer ce broker en particulier et scaler sur un broker nouveau.
  • Tous les pods partagent les mêmes specs (CPU, Memoire, nombre de PVCs, etc.)

L’équipe de Strimzi a répondu à ces limitations en développant leur propre ressource : les StrimziPodSets, une foncionnalité disponible depuis Strimzi 0.29.0.

Voici quelques avatanges à utiliser les StrimziPodSets :

  • Le Scaling up et down est plus flexible
  • Configuration par broker
  • Permettra la spécialisation des brokers lorsque Kafka sans ZooKeeper sera disponible (KIP-500, voir ci-après)

L’inconvénient principal de l’utilisation des StrimziPodSets est que l’operator Strimzi devient critique.

Pour en savoir plus sur les StrimziPodSets, regardez la vidéo StrimziPodSets - What it is and why should you care ? de Jakub Scholz.

Déployement de Strimzi

La documentation “quickstart” de Strimzi est complète et fonctionnelle.

Nous allons maintenant voir comment ajouter certains services Kafka qui ne sont pas inclus dans Strimzi.

Une UI Kafka sur Strimzi

Strimzi facilite la vie des utiliateurs pour configurer et gérer des ressources. Nous souhaitions ici apporter quelque chose et montrer comment déployer un UI sur un cluster Kafka gérer par Strimzi.

Il y a plusieurs projets open source d’UI Kafka sur GitHub, parmi eux :

Partons sur Kafka UI qui a l’UI la plus propre (de notre point de vue).

Nous pouvons voir dans la documentation que ce projet fournit des images Docker officielles. Nous allons les utiliser et déployer une instance Kafka UI en tant que ressource deployment dans Kubernetes.

Le YAML suivant donne un example d’une Kakfa UI configuré sur un cluster Kafka Strimzi configuré avec SCRAM-SHA-512. L’authentification de l’UI se fait via ldaps sur une instance OpenLDAP.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-kafka-ui
  namespace: kafka
spec:
  selector:
    matchLabels:
      app: cluster-kafka-ui
  template:
    metadata:
      labels:
        app: cluster-kafka-ui
    spec:
      containers:
        - image: provectuslabs/kafka-ui:v0.4.0
          name: kafka-ui
          ports:
            - containerPort: 8080
          env:
            - name: KAFKA_CLUSTERS_0_NAME
              value: "cluster"
            - name: KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS
              value: "cluster-kafka-bootstrap:9092"
            - name: KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL
              value: SASL_PLAINTEXT
            - name: KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM
              value: SCRAM-SHA-512
            - name: KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG
              value: 'org.apache.kafka.common.security.scram.ScramLoginModule required username="admin" password="XSnBiq6pkFNp";'
            # LDAP auth
            - name: AUTH_TYPE
              value: LDAP
            - name: SPRING_LDAP_URLS
              value: ldaps://myldapinstance.company:636
            - name: SPRING_LDAP_DN_PATTERN
              value: uid={0},ou=People,dc=company
            - name: SPRING_LDAP_ADMINUSER
              value: uid=admin,ou=Apps,dc=company
            - name: SPRING_LDAP_ADMINPASSWORD
              value: Adm1nP@ssw0rd!
            # Custom truststore for ldaps
            - name: JAVA_OPTS
              value: "-Djdk.tls.client.cipherSuites=TLS_RSA_WITH_AES_128_GCM_SHA256 -Djavax.net.ssl.trustStore=/etc/kafka-ui/ssl/truststore.jks"
          volumeMounts:
            - name: truststore
              mountPath: /etc/kafka-ui/ssl
              readOnly: true
      volumes:
        - name: truststore
          secret:
            secretName: myldap-truststore

Note : En utilisant le listener interne PLAINTEXT sur le port 9092, nous n’avons pas à fournir une configuration KAFKA_CLUSTERS_0_PROPERTIES_SSL_TRUSTSTORE_LOCATION.

Avec cet exemple, les utilisateurs doivent s’authentifier via LDAP pour accéder à la Kafka UI. Une fois connecté, le compte configuré pour intéragir avec le cluster Kafka est défini dans KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG. Les RBAC ont été ajouté au projet récemment avec cette issue.

Schema Registry avec Strimzi

Nous avions un besoin fonctionnel de déployer une instance de Schema Registry pour nos clusters Kafka dans Kubernetes.

Bien que Strimzi permette de configurer des outils supplémentaires de l’écosystème Kafka tels que Kafka Connect ou MirrorMaker, il ne peut pas encore déployer de Schema Registry.

Pour résoudre ce problème, l’équipe du Rubin Observatory Science Quality and Reliability Engineering a publié le strimzi-registry-operator.

Les configurations que nous avons utilisés sont celles de la section example du README.

La seule issue que nous avons rencontré est que le l’operator n’est pas encore capable de déployer un Schema Registry sur un cluster Kafka sécurisé via SCRAM-SHA-512.

Quid de Kafka sans ZooKeeper ?

Après de nombreuses années de travail sur KIP-500, l’équipe de Apache Kafka a finalement annoncé que le mode KRaft mode (sans ZooKeeper) de Kafka était désormais production ready. L’annonce a été faite avec la sortie de Kafka 3.3.

L’équipe de développement de Strimzi a commencé à intégrer le mode KRaft depuis Strimzi 0.29.0 mais la feature est toujours experimentale.

Le principal contributeur de Strimi, Jakub Scholz, a fait le commentaire suivant sur ce sujet :

Je pense qu’il est un peu étrange de déclarer cela production ready pour les nouveaux clusters. Cela veut dire que nus devons maintenir 2 bases de code en parallèle avec des manières d’upgrader garanties etc. pour un long moment. Honnêtement, j’aurai aimé que l’on ai eu plus de progrès à cet instant et que nous soyons plus préparés pour la suppression de ZooKeeper. Mon avis étant que je ne serais pas du tout enclin à dire que c’est production ready de toute manière.

À partir de ces commentaires, on peut imaginer que Kafka sans ZooKeeper ne sera sûrement pas la configuration par défaut dans la prochaine release de Strimzi (0.34.0 à la publication de cet article) mais qu’elle le sera probablement dans l’avenir.

Quid du stockage ?

La partie stockage est souvent source de difficulté pour les clusters Kafka bare metal et Kafka n’est pas une exception.

La communauté s’accorde à dire que la meilleur solution pour provisionné du stockage persistant sur Kubernetes est avec Ceph via Rook bien que d’autres solutions existent comme Longhorn et OpenEBS pour la partie open source ou bien Portworx et Linstor qui sous licenses propriétaires.

La comparaison des briques de stockage pour clusters Kubernetes bare metal est un trop gros sujet pour être couvert dans cet article mais n’hésitez pas à consulter notre précédent article "" pour en savoir plus sur Rook.

Comparing storage engines for bare metal Kubernetes clusters is too big a topic to be included in this article but feel free to check out our previous article ”Stockage objet Ceph dans un cluster Kubernetes avec Rook” for more on Rook.

Nous avons tout de même eu la possibilité de comparer les performances entre un cluster Kafka de 3 brokers avec Strimzi/Rook par rapport à un cluster Kafka de 3 brokers sur la même machine mais avec un accès direct aux disques.

Voici les configurations et résultats de ce benchmark :

Configuration

Environnement Kubernetes :

  • Kafka Version 3.2.0 sur Kubernetes avec Strimzi
  • 3 brokers (un pod par noeud)
  • 6 RBD devices per broker (provisionné par la Storage Class Rook Ceph)
  • Xms java default (2g)
  • Xmx java default (29g)

Environnement Bare metal :

  • Kafka Version 3.2.0 en process JVM avec la release Apache
  • 3 brokers (une JVM par noeud)
  • 6 RBD devices per broker (JBOD avec filesystem ext4)
  • Xms java default (2g)
  • Xmx java default (29g)

Note : Ces benchmarks ont été lancés sur les mêmes machines (HP Gen 7 avec 192 Gb RAM et 6 x 2 TB disques) sous RHEL 7.9. Kubernetes était éteint lorsque la JVM Kafka tournait et inversement.

kafka-producer-perf-test \
--topic my-topic-benchmark \
--record-size 1000 \
--throughput -1 \
--producer.config /mnt/kafka.properties \
--num-records 50000000

Note : Le topic my-topic-benchmark est créé avec 100 paritions et 1 replica.

Résultats

Nous avons lancé le benchmark précédent 10 fois sur chaque environnement et fait une moyenne des résultats :

MetricJBOD bare metalCeph RBDPerformance difference
Records/sec7522365207- 13.3 %
Avg latency1.451.28+ 11.1 %

Les résultats sont intéressants : bien que les performances en écritures soit meilleur en JBOD, la latence est plus basse avec Ceph.

Alternatives à Strimzi

On peut citer deux principaux concurrents à Strimzi pour la gestion de Kafka sur Kubernetes :

Nous n’avons pas pu tester Koperator de manière exhaustive donc il serait injuste de le comparer avec Strimzi dans cet article.

Quand à l’operator Confluent, il apporte de nombreuses fonctionnalités dont ne dispose pas Strimzi. En voici quelques unes que nous avons trouvé intéressantes :

  • Intégration native Schema Registry
  • Intégration native ksqlDB
  • Support de l’authentication LDAP
  • UI (Confluent Control Center) disponible nativement pour les Admins et développeurs
  • Alerting
  • Tiered storage

Toutes ces fonctionnalités ont un coût : celui d’une license commerciale de Confluent. Notons que l’operator et Control Center peuvent être testés gratuitement pour une période de 30 jours.

Partagez cet article

Canada - Maroc - France

Nous sommes une équipe passionnée par l'Open Source, le Big Data et les technologies associées telles que le Cloud, le Data Engineering, la Data Science le DevOps…

Nous fournissons à nos clients un savoir faire reconnu sur la manière d'utiliser les technologies pour convertir leurs cas d'usage en projets exploités en production, sur la façon de réduire les coûts et d'accélérer les livraisons de nouvelles fonctionnalités.

Si vous appréciez la qualité de nos publications, nous vous invitons à nous contacter en vue de coopérer ensemble.

Support Ukrain