Acceso externo de Apache Kafka en OpenShift

2 de julio de 2020

Los contenedores son una solución al problema de cómo hacer que el software funcione cuando se traslada de un entorno informático a otro. Especialmente con Docker, como solución de contenedor, comenzó una nueva tendencia de DevOps. Nosotros, como ingenieros de software, aprovechamos esta tecnología para enviar nuestro software a cualquier entorno.

Con la tecnología de contenedores, Kubernetes (K8S) se convirtió en el estándar de facto de la industria para la orquestación de contenedores. K8S es un sistema de código abierto para automatizar el despliegue, el escalado y la gestión de aplicaciones en contenedores. RedHat ha remodelado OpenShift con una solución empresarial de K8S, OpenShift Container Platform. OpenShift es una plataforma de contenedores que ejecuta su software sobre el K8S y otros conceptos adicionales.

Muchas de nuestras arquitecturas de software dependen de Apache Kafka. Apache Kafka es un sistema de mensajería distribuida. ¿Cómo instalamos Kafka en OpenShift? Si está en OpenShift, ¿cómo accedemos a los datos? La respuesta a estas preguntas es Strimzi.

Strimzi es un proyecto Open Source que ofrece imágenes de contenedores y operadores para ejecutar Apache Kafka en Kubernetes y Red Hat OpenShift.

Motivación

¿Para quién es ese artículo?

Este artículo explicará cómo Strimzi hace accesible a Kafka a los clientes fuera de Kubernetes. Desplegaremos un clúster de Kafka con el Operador de Strimzi en minishift (OKD/OpenShift). En este artículo se explica un ejemplo del funcionamiento de Strimzi.

¿Qué conocimientos básicos se necesitan para entender este artículo?

No es necesario tener todos los conocimientos necesarios, pero ayuda enormemente si tienes conocimientos de

Lo que aprenderás en este artículo:

Créditos

Este artículo se basa en el trabajo de Accessing Apache Kafka in Strimzi: Part 1 y Accessing Apache Kafka in Strimzi: Part 3.

Diferenciación

Apache Kafka (Open Source) de Confluent Confluent Platform es una oferta empresarial para Apache Kafkai.SStrimzi lleva Apache Kafka a Kubernetes y OpenShift.

Beneficios de Kafka en Kubernetes

Apache Kafka es una infraestructura de datos esencial. Kafka, como sistema distribuido, promete una alta disponibilidad y la disociación de las dependencias del sistema. Los productores (proveedores de datos) y los consumidores pueden procesar los datos a su propia velocidad. Por lo tanto, Kafka está instalado y desplegado en varias máquinas.

Kubernetes es un sistema de despliegue de aplicaciones, que puede ahorrar dinero porque requiere menos personal informático para su gestión. Además de ello, hace que sus aplicaciones sean mucho más portables, por lo que puede moverlas más fácilmente entre diferentes nubes y entornos internos. La clave es la automatización, el precio que hay que pagar es la complejidad y la formación de tus DevOps Engineers.

Tener Kafka en Kubernetes, permite a Kubernetes desplegar Kafka en los recursos disponibles con la garantía de que el cluster de Kafka nunca se enfrentará a una interrupción o a un tiempo de inactividad.

¿Necesito Kafka en K8S? Depende del escenario y del entorno. Si no tienes ninguna experiencia con Apache Kafka, lo primero seria conocer y aprender el producto antes de operarlo en K8S.

El entorno

Para entender nuestro ejemplo, proporcionamos los detalles del entorno para este artículo:

Usamos un sistema Linux system para la demostración.

Minishift

Minishift es una herramienta que ayuda a ejecutar OpenShift localmente ejecutando un clúster OpenShift de un solo nodo dentro de un VM. Para obtener más información sobre la instalación, consulta la página del producto product page. Es una solución robusta para probar los conceptos de OpenShift.

Lanzamos minishift con un comando en un terminal Linux:

minishift start

El resultado debería ser así : minishift start

Para empezar, tenemos que añadir el cliente de OC al PATH.

Simplemente ejecuta este comando.

eval $(minishift oc-env)

Consulta la versión OpenShift/OKD para comprobar si el cliente oc funciona.

oc version
oc v3.11.0+0cbc58b
kubernetes v1.11.0+d4cacc0
features: Basic-Auth GSSAPI Kerberos SPNEGO

Server https://192.168.42.24:8443
kubernetes v1.11.0+d4cacc0

Ahora tenemos nuestra infraestructura funcionando. OpenShift es un producto ofrecido por RedHat basado en el proyecto Opensource Kubernetes. La distribución de la comunidad de Kubernetes que impulsa a Red Hat OpenShift es OKD.

Instalación de Strimzi

Ahora vemos cómo instalamos el Operador Strimzi en minishift.

Login como admin en minishift.

oc login -u system:admin
Logged into "https://192.168.42.24:8443" as "system:admin" using existing credentials.

You have access to the following projects and can switch between them with 'oc project <projectname>':

  * default
    kube-dns
    kube-proxy
    kube-public
    kube-system
    openshift
    openshift-apiserver
    openshift-controller-manager
    openshift-core-operators
    openshift-infra
    openshift-node
    openshift-service-cert-signer
    openshift-web-console

Using project "default".

Crea un nuevo proyecto con el nombre de streaming.

oc new-project streaming
Now using project "streaming" on server "https://192.168.42.24:8443".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git

to build a new example application in Ruby.

Instala el operador Strimzi (la opción de espacio de nombres no es necesaria pero para completarlo lo declaramos).

oc apply -f 'https://strimzi.io/install/latest?namespace=streaming' -n streaming

Output de minishift:

customresourcedefinition.apiextensions.k8s.io/kafkas.kafka.strimzi.io created
rolebinding.rbac.authorization.k8s.io/strimzi-cluster-operator-entity-operator-delegation created
clusterrolebinding.rbac.authorization.k8s.io/strimzi-cluster-operator created
rolebinding.rbac.authorization.k8s.io/strimzi-cluster-operator-topic-operator-delegation created
customresourcedefinition.apiextensions.k8s.io/kafkausers.kafka.strimzi.io created
customresourcedefinition.apiextensions.k8s.io/kafkarebalances.kafka.strimzi.io created
customresourcedefinition.apiextensions.k8s.io/kafkamirrormaker2s.kafka.strimzi.io created
clusterrole.rbac.authorization.k8s.io/strimzi-entity-operator created
clusterrole.rbac.authorization.k8s.io/strimzi-cluster-operator-global created
clusterrolebinding.rbac.authorization.k8s.io/strimzi-cluster-operator-kafka-broker-delegation created
rolebinding.rbac.authorization.k8s.io/strimzi-cluster-operator created
clusterrole.rbac.authorization.k8s.io/strimzi-cluster-operator-namespaced created
clusterrole.rbac.authorization.k8s.io/strimzi-topic-operator created
serviceaccount/strimzi-cluster-operator created
clusterrole.rbac.authorization.k8s.io/strimzi-kafka-broker created
customresourcedefinition.apiextensions.k8s.io/kafkatopics.kafka.strimzi.io created
customresourcedefinition.apiextensions.k8s.io/kafkabridges.kafka.strimzi.io created
deployment.apps/strimzi-cluster-operator created
customresourcedefinition.apiextensions.k8s.io/kafkaconnectors.kafka.strimzi.io created
customresourcedefinition.apiextensions.k8s.io/kafkaconnects2is.kafka.strimzi.io created
customresourcedefinition.apiextensions.k8s.io/kafkaconnects.kafka.strimzi.io created
customresourcedefinition.apiextensions.k8s.io/kafkamirrormakers.kafka.strimzi.io created

Si no puedes acceder a la página de Strimzi, añade un proxy o écahale un vistazo a GitHub Repo.

El concepto de operador

Los operadores son extensiones de software que utilizan recursos personalizados para gestionar las aplicaciones y sus componentes. Como ves en el resultado de la instalación anterior, Strimzi crea recursos personalizados.

El patrón "Operator" trata de capturar la esencia de un operador humano que gestiona un conjunto de servicios Los operadores humanos que se ocupan de aplicaciones y servicios específicos tienen un profundo conocimiento de cómo debe comportarse el sistema, hcómo desplegarlo y cómo reaccionar si hay problemas.

Un Operador es esencialmente un controlador personalizado. El Operador Strimzi tiene un profundo conocimiento de los clusters de Apache Kafka.

Un Operador observa estos tipos de recursos personalizados y es notificado de su presencia o modificación. Con el recurso personalizado kafkas.kafka.strimzi.io se describe el clúster Kafka y el operador Strimzi despliega el clúster Kafka de forma automatizada.

El recurso Kafka

Cuando el operador recibe esta notificación, comenzará a ejecutar un bucle para asegurarse de que todos los objetos necesarios para el servicio de aplicación están realmente disponibles y configurados en la especificación del objeto por el usuario

Tomamos de Strimzi el ejemplo de una especificación de un clúster de Kafka y creamos uno personalizado para nuestro escenario de prueba.

curl -s https://strimzi.io/examples/latest/kafka/kafka-persistent-single.yaml \
 | sed 's/name: .*/name: logs/' \
 | sed 's/size: .*/size: 100Mi/' \
 | cat 

El comando de arriba toma el archivo de ejemplo y reemplaza el nombre del clúster a los registros y sólo solicitamos 100 MegaBytes en lugar de 1 GigaByte para nuestro escenario de prueba. En la termnial verás lo siguiente:

apiVersion: kafka.strimzi.io/v1beta1
kind: Kafka
metadata:
  name: logs
spec:
  kafka:
    version: 2.5.0
    replicas: 1
    listeners:
      plain: {}
      tls: {}
    config:
      offsets.topic.replication.factor: 1
      transaction.state.log.replication.factor: 1
      transaction.state.log.min.isr: 1
      log.message.format.version: "2.5"
    storage:
      type: jbod
      volumes:
      - id: 0
        type: persistent-claim
        size: 100Mi
        deleteClaim: false
  zookeeper:
    replicas: 1
    storage:
      type: persistent-claim
      size: 100Mi
      deleteClaim: false
  entityOperator:
    topicOperator: {}
    userOperator: {}

Tenemos una descripción suficiente del clúster de Kafka.

Ahora que tenemos la descripción de nuestro clúster deseado, lo desplegamos en el espacio que hemos creado en minishift con el nombre streaming.

curl -s https://strimzi.io/examples/latest/kafka/kafka-persistent-single.yaml \
 | sed 's/name: .*/name: logs/' \
 | sed 's/size: .*/size: 100Mi/' \
 | oc -n streaming apply -f -

minishift responderá:

kafka.kafka.strimzi.io/logs created

El Operador Strimzi en acción

El operador de Strimzi crea todos los objetos necesarios para cumplir la descripción. El operador mismo está en un pod. Mostrando los logs del operador, se ve lo que está haciendo Strimzi.

oc logs -f strimzi-cluster-operator-bf978cf5c-rc5l2
+ shift
+ export MALLOC_ARENA_MAX=2
+ MALLOC_ARENA_MAX=2
+ JAVA_OPTS=' -Dvertx.cacheDirBase=/tmp -Djava.security.egd=file:/dev/./urandom'
++ get_gc_opts
++ '[' '' == true ']'
++ echo ''
+ JAVA_OPTS=' -Dvertx.cacheDirBase=/tmp -Djava.security.egd=file:/dev/./urandom '
+ exec /usr/bin/tini -w -e 143 -- java -Dvertx.cacheDirBase=/tmp -Djava.security.egd=file:/dev/./urandom -classpath lib/io.strimzi.cluster-operator-0.18.0.jar:lib/io.prometheus.simpleclient_common-0.7.0.jar:lib/io.strimzi.kafka-oauth-client-0.5.0.jar:lib/io.netty.netty-handler-4.1.45.Final.jar:lib/io.netty.netty-codec-http-4.1.45.Final.jar:lib/org.quartz-scheduler.quartz-2.2.1.jar:lib/org.bouncycastle.bcprov-jdk15on-1.60.jar:lib/com.squareup.okio.okio-1.15.0.jar:lib/org.keycloak.keycloak-core-10.0.0.jar:lib/io.netty.netty-buffer-4.1.45.Final.jar:lib/org.yaml.snakeyaml-1.24.jar:lib/io.fabric8.openshift-client-4.6.4.jar:lib/io.netty.netty-common-4.1.45.Final.jar:lib/org.apache.logging.log4j.log4j-api-2.13.0.jar:lib/org.xerial.snappy.snappy-java-1.1.7.3.jar:lib/org.hdrhistogram.HdrHistogram-2.1.11.jar:lib/io.prometheus.simpleclient-0.7.0.jar:lib/com.sun.activation.jakarta.activation-1.2.1.jar:lib/org.apache.yetus.audience-annotations-0.5.0.jar:lib/com.fasterxml.jackson.dataformat.jackson-dataformat-yaml-2.10.2.jar:lib/io.micrometer.micrometer-core-1.3.1.jar:lib/io.netty.netty-codec-4.1.45.Final.jar:lib/org.keycloak.keycloak-common-10.0.0.jar:lib/jakarta.activation.jakarta.activation-api-1.2.1.jar:lib/io.vertx.vertx-core-3.8.5.jar:lib/io.strimzi.certificate-manager-0.18.0.jar:lib/io.strimzi.kafka-oauth-common-0.5.0.jar:lib/io.strimzi.kafka-oauth-server-0.5.0.jar:lib/io.netty.netty-codec-dns-4.1.45.Final.jar:lib/io.fabric8.kubernetes-model-4.6.4.jar:lib/io.netty.netty-codec-socks-4.1.45.Final.jar:lib/com.github.mifmif.generex-1.0.2.jar:lib/io.netty.netty-resolver-4.1.45.Final.jar:lib/com.github.luben.zstd-jni-1.4.4-7.jar:lib/io.netty.netty-handler-proxy-4.1.45.Final.jar:lib/com.squareup.okhttp3.logging-interceptor-3.12.6.jar:lib/io.strimzi.operator-common-0.18.0.jar:lib/org.bouncycastle.bcpkix-jdk15on-1.62.jar:lib/org.lz4.lz4-java-1.7.1.jar:lib/io.netty.netty-transport-native-epoll-4.1.45.Final-linux-x86_64.jar:lib/io.netty.netty-transport-native-unix-common-4.1.45.Final.jar:lib/dk.brics.automaton.automaton-1.11-8.jar:lib/io.vertx.vertx-micrometer-metrics-3.8.5.jar:lib/org.apache.kafka.kafka-clients-2.5.0.jar:lib/com.fasterxml.jackson.core.jackson-core-2.10.2.jar:lib/org.apache.zookeeper.zookeeper-jute-3.5.7.jar:lib/io.netty.netty-transport-4.1.45.Final.jar:lib/io.netty.netty-transport-native-epoll-4.1.45.Final.jar:lib/jakarta.xml.bind.jakarta.xml.bind-api-2.3.2.jar:lib/org.apache.logging.log4j.log4j-slf4j-impl-2.13.0.jar:lib/com.fasterxml.jackson.core.jackson-annotations-2.10.2.jar:lib/io.fabric8.zjsonpatch-0.3.0.jar:lib/org.apache.zookeeper.zookeeper-3.5.7.jar:lib/io.strimzi.api-0.18.0.jar:lib/io.fabric8.kubernetes-client-4.6.4.jar:lib/com.fasterxml.jackson.module.jackson-module-jaxb-annotations-2.10.2.jar:lib/com.squareup.okhttp3.okhttp-3.12.6.jar:lib/io.netty.netty-codec-http2-4.1.45.Final.jar:lib/io.strimzi.config-model-0.18.0.jar:lib/org.apache.logging.log4j.log4j-core-2.13.0.jar:lib/io.fabric8.kubernetes-model-common-4.6.4.jar:lib/com.fasterxml.jackson.core.jackson-databind-2.10.2.jar:lib/io.strimzi.crd-annotations-0.18.0.jar:lib/io.netty.netty-resolver-dns-4.1.45.Final.jar:lib/org.slf4j.slf4j-api-1.7.25.jar:lib/org.latencyutils.LatencyUtils-2.0.3.jar:lib/io.micrometer.micrometer-registry-prometheus-1.3.1.jar io.strimzi.operator.cluster.Main
2020-05-27 11:09:16 INFO  Main:60 - ClusterOperator 0.18.0 is starting
2020-05-27 11:09:20 INFO  Main:85 - Environment facts gathered: ClusterOperatorConfig(KubernetesVersion=1.11,OpenShiftRoutes=true,OpenShiftBuilds=true,OpenShiftImageStreams=true,OpenShiftDeploymentConfigs=true)
2020-05-27 11:09:20 INFO  Util:237 - Using config:
   PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
   STRIMZI_DEFAULT_KAFKA_BRIDGE_IMAGE: strimzi/kafka-bridge:0.16.0
   TINI_SHA256: 12d20136605531b09a2c2dac02ccee85e1b874eb322ef6baf7561cd93f93c855
   STRIMZI_KAFKA_MIRROR_MAKER_IMAGES: 2.4.0=strimzi/kafka:0.18.0-kafka-2.4.0
2.4.1=strimzi/kafka:0.18.0-kafka-2.4.1
2.5.0=strimzi/kafka:0.18.0-kafka-2.5.0
   KUBERNETES_PORT: tcp://172.30.0.1:443
   STRIMZI_DEFAULT_TOPIC_OPERATOR_IMAGE: strimzi/operator:0.18.0
   STRIMZI_FULL_RECONCILIATION_INTERVAL_MS: 120000
   KUBERNETES_SERVICE_HOST: 172.30.0.1
   JAVA_CLASSPATH: lib/io.strimzi.cluster-operator-0.18.0.jar:lib/io.prometheus.simpleclient_common-0.7.0.jar:lib/io.strimzi.kafka-oauth-client-0.5.0.jar:lib/io.netty.netty-handler-4.1.45.Final.jar:lib/io.netty.netty-codec-http-4.1.45.Final.jar:lib/org.quartz-scheduler.quartz-2.2.1.jar:lib/org.bouncycastle.bcprov-jdk15on-1.60.jar:lib/com.squareup.okio.okio-1.15.0.jar:lib/org.keycloak.keycloak-core-10.0.0.jar:lib/io.netty.netty-buffer-4.1.45.Final.jar:lib/org.yaml.snakeyaml-1.24.jar:lib/io.fabric8.openshift-client-4.6.4.jar:lib/io.netty.netty-common-4.1.45.Final.jar:lib/org.apache.logging.log4j.log4j-api-2.13.0.jar:lib/org.xerial.snappy.snappy-java-1.1.7.3.jar:lib/org.hdrhistogram.HdrHistogram-2.1.11.jar:lib/io.prometheus.simpleclient-0.7.0.jar:lib/com.sun.activation.jakarta.activation-1.2.1.jar:lib/org.apache.yetus.audience-annotations-0.5.0.jar:lib/com.fasterxml.jackson.dataformat.jackson-dataformat-yaml-2.10.2.jar:lib/io.micrometer.micrometer-core-1.3.1.jar:lib/io.netty.netty-codec-4.1.45.Final.jar:lib/org.keycloak.keycloak-common-10.0.0.jar:lib/jakarta.activation.jakarta.activation-api-1.2.1.jar:lib/io.vertx.vertx-core-3.8.5.jar:lib/io.strimzi.certificate-manager-0.18.0.jar:lib/io.strimzi.kafka-oauth-common-0.5.0.jar:lib/io.strimzi.kafka-oauth-server-0.5.0.jar:lib/io.netty.netty-codec-dns-4.1.45.Final.jar:lib/io.fabric8.kubernetes-model-4.6.4.jar:lib/io.netty.netty-codec-socks-4.1.45.Final.jar:lib/com.github.mifmif.generex-1.0.2.jar:lib/io.netty.netty-resolver-4.1.45.Final.jar:lib/com.github.luben.zstd-jni-1.4.4-7.jar:lib/io.netty.netty-handler-proxy-4.1.45.Final.jar:lib/com.squareup.okhttp3.logging-interceptor-3.12.6.jar:lib/io.strimzi.operator-common-0.18.0.jar:lib/org.bouncycastle.bcpkix-jdk15on-1.62.jar:lib/org.lz4.lz4-java-1.7.1.jar:lib/io.netty.netty-transport-native-epoll-4.1.45.Final-linux-x86_64.jar:lib/io.netty.netty-transport-native-unix-common-4.1.45.Final.jar:lib/dk.brics.automaton.automaton-1.11-8.jar:lib/io.vertx.vertx-micrometer-metrics-3.8.5.jar:lib/org.apache.kafka.kafka-clients-2.5.0.jar:lib/com.fasterxml.jackson.core.jackson-core-2.10.2.jar:lib/org.apache.zookeeper.zookeeper-jute-3.5.7.jar:lib/io.netty.netty-transport-4.1.45.Final.jar:lib/io.netty.netty-transport-native-epoll-4.1.45.Final.jar:lib/jakarta.xml.bind.jakarta.xml.bind-api-2.3.2.jar:lib/org.apache.logging.log4j.log4j-slf4j-impl-2.13.0.jar:lib/com.fasterxml.jackson.core.jackson-annotations-2.10.2.jar:lib/io.fabric8.zjsonpatch-0.3.0.jar:lib/org.apache.zookeeper.zookeeper-3.5.7.jar:lib/io.strimzi.api-0.18.0.jar:lib/io.fabric8.kubernetes-client-4.6.4.jar:lib/com.fasterxml.jackson.module.jackson-module-jaxb-annotations-2.10.2.jar:lib/com.squareup.okhttp3.okhttp-3.12.6.jar:lib/io.netty.netty-codec-http2-4.1.45.Final.jar:lib/io.strimzi.config-model-0.18.0.jar:lib/org.apache.logging.log4j.log4j-core-2.13.0.jar:lib/io.fabric8.kubernetes-model-common-4.6.4.jar:lib/com.fasterxml.jackson.core.jackson-databind-2.10.2.jar:lib/io.strimzi.crd-annotations-0.18.0.jar:lib/io.netty.netty-resolver-dns-4.1.45.Final.jar:lib/org.slf4j.slf4j-api-1.7.25.jar:lib/org.latencyutils.LatencyUtils-2.0.3.jar:lib/io.micrometer.micrometer-registry-prometheus-1.3.1.jar
   STRIMZI_KAFKA_CONNECT_S2I_IMAGES: 2.4.0=strimzi/kafka:0.18.0-kafka-2.4.0
2.4.1=strimzi/kafka:0.18.0-kafka-2.4.1
2.5.0=strimzi/kafka:0.18.0-kafka-2.5.0
   STRIMZI_DEFAULT_TLS_SIDECAR_KAFKA_IMAGE: strimzi/kafka:0.18.0-kafka-2.5.0
   TINI_VERSION: v0.18.0
   STRIMZI_HOME: /opt/strimzi
   STRIMZI_DEFAULT_TLS_SIDECAR_CRUISE_CONTROL_IMAGE: strimzi/kafka:0.18.0-kafka-2.5.0
   PWD: /opt/strimzi
   STRIMZI_DEFAULT_CRUISE_CONTROL_IMAGE: strimzi/kafka:0.18.0-kafka-2.5.0
   KUBERNETES_PORT_443_TCP: tcp://172.30.0.1:443
   STRIMZI_OPERATION_TIMEOUT_MS: 300000
   JAVA_MAIN: io.strimzi.operator.cluster.Main
   KUBERNETES_PORT_443_TCP_ADDR: 172.30.0.1
   STRIMZI_VERSION: 0.18.0
   STRIMZI_DEFAULT_JMXTRANS_IMAGE: strimzi/jmxtrans:0.18.0
   STRIMZI_NAMESPACE: streaming
   STRIMZI_KAFKA_MIRROR_MAKER_2_IMAGES: 2.4.0=strimzi/kafka:0.18.0-kafka-2.4.0
2.4.1=strimzi/kafka:0.18.0-kafka-2.4.1
2.5.0=strimzi/kafka:0.18.0-kafka-2.5.0
   KUBERNETES_PORT_443_TCP_PROTO: tcp
   STRIMZI_DEFAULT_USER_OPERATOR_IMAGE: strimzi/operator:0.18.0
   KUBERNETES_SERVICE_PORT: 443
   STRIMZI_DEFAULT_KAFKA_EXPORTER_IMAGE: strimzi/kafka:0.18.0-kafka-2.5.0
   STRIMZI_DEFAULT_KAFKA_INIT_IMAGE: strimzi/operator:0.18.0
   STRIMZI_LOG_LEVEL: INFO
   HOSTNAME: strimzi-cluster-operator-bf978cf5c-rc5l2
   STRIMZI_KAFKA_CONNECT_IMAGES: 2.4.0=strimzi/kafka:0.18.0-kafka-2.4.0
2.4.1=strimzi/kafka:0.18.0-kafka-2.4.1
2.5.0=strimzi/kafka:0.18.0-kafka-2.5.0
   STRIMZI_KAFKA_IMAGES: 2.4.0=strimzi/kafka:0.18.0-kafka-2.4.0
2.4.1=strimzi/kafka:0.18.0-kafka-2.4.1
2.5.0=strimzi/kafka:0.18.0-kafka-2.5.0
   KUBERNETES_PORT_443_TCP_PORT: 443
   STRIMZI_DEFAULT_TLS_SIDECAR_ENTITY_OPERATOR_IMAGE: strimzi/kafka:0.18.0-kafka-2.5.0
   KUBERNETES_SERVICE_PORT_HTTPS: 443
   SHLVL: 0
   HOME: /
   MALLOC_ARENA_MAX: 2
2020-05-27 11:09:20 INFO  ClusterOperator:87 - Creating ClusterOperator for namespace streaming
2020-05-27 11:09:20 INFO  ClusterOperator:105 - Starting ClusterOperator for namespace streaming
2020-05-27 11:09:21 INFO  ClusterOperator:119 - Opened watch for Kafka operator
2020-05-27 11:09:21 INFO  ClusterOperator:119 - Opened watch for KafkaMirrorMaker operator
2020-05-27 11:09:21 INFO  ClusterOperator:119 - Opened watch for KafkaConnect operator
2020-05-27 11:09:21 INFO  ClusterOperator:119 - Opened watch for KafkaBridge operator
2020-05-27 11:09:21 INFO  ClusterOperator:119 - Opened watch for KafkaMirrorMaker2 operator
2020-05-27 11:09:21 INFO  ClusterOperator:119 - Opened watch for KafkaConnectS2I operator
2020-05-27 11:09:21 INFO  ClusterOperator:130 - Setting up periodic reconciliation for namespace streaming
2020-05-27 11:09:22 INFO  ClusterOperator:192 - ClusterOperator is now ready (health server listening on 8080)
2020-05-27 11:09:22 INFO  Main:159 - Cluster Operator verticle started in namespace streaming
2020-05-27 11:11:21 INFO  ClusterOperator:132 - Triggering periodic reconciliation for namespace streaming...
2020-05-27 11:11:21 WARN  VersionUsageUtils:60 - The client is using resource type 'kafkas' with unstable version 'v1beta1'
2020-05-27 11:11:22 WARN  VersionUsageUtils:60 - The client is using resource type 'kafkamirrormakers' with unstable version 'v1beta1'
2020-05-27 11:11:22 WARN  VersionUsageUtils:60 - The client is using resource type 'kafkaconnects' with unstable version 'v1beta1'
2020-05-27 11:11:22 WARN  VersionUsageUtils:60 - The client is using resource type 'kafkamirrormaker2s' with unstable version 'v1alpha1'
2020-05-27 11:11:22 WARN  VersionUsageUtils:60 - The client is using resource type 'kafkabridges' with unstable version 'v1alpha1'
2020-05-27 11:11:22 WARN  VersionUsageUtils:60 - The client is using resource type 'kafkarebalances' with unstable version 'v1alpha1'
2020-05-27 11:11:22 WARN  VersionUsageUtils:60 - The client is using resource type 'kafkaconnects2is' with unstable version 'v1beta1'
2020-05-27 11:12:27 INFO  OperatorWatcher:40 - Reconciliation #0(watch) Kafka(streaming/logs): Kafka logs in namespace streaming was ADDED
2020-05-27 11:12:27 INFO  AbstractOperator:173 - Reconciliation #0(watch) Kafka(streaming/logs): Kafka logs should be created or updated
2020-05-27 11:12:28 INFO  OperatorWatcher:40 - Reconciliation #1(watch) Kafka(streaming/logs): Kafka logs in namespace streaming was MODIFIED
2020-05-27 11:12:31 WARN  VersionUsageUtils:60 - The client is using resource type 'poddisruptionbudgets' with unstable version 'v1beta1'
2020-05-27 11:12:38 WARN  AbstractOperator:247 - Reconciliation #1(watch) Kafka(streaming/logs): Failed to acquire lock lock::streaming::Kafka::logs within 10000ms.
2020-05-27 11:13:21 INFO  ClusterOperator:132 - Triggering periodic reconciliation for namespace streaming...
2020-05-27 11:13:31 WARN  AbstractOperator:247 - Reconciliation #2(timer) Kafka(streaming/logs): Failed to acquire lock lock::streaming::Kafka::logs within 10000ms.
2020-05-27 11:14:20 INFO  OperatorWatcher:40 - Reconciliation #3(watch) Kafka(streaming/logs): Kafka logs in namespace streaming was MODIFIED
2020-05-27 11:14:20 INFO  AbstractOperator:318 - Reconciliation #0(watch) Kafka(streaming/logs): reconciled
2020-05-27 11:14:20 INFO  AbstractOperator:173 - Reconciliation #3(watch) Kafka(streaming/logs): Kafka logs should be created or updated
2020-05-27 11:14:23 INFO  AbstractOperator:318 - Reconciliation #3(watch) Kafka(streaming/logs): reconciled

Después de que el operador haya ejecutad sus funciones, tienes el clúster a tu disposición. Para comprobar los recursos de Kafka en Minishift:

 ~  oc get kafka
NAME         DESIRED KAFKA REPLICAS   DESIRED ZK REPLICAS
logs         1                        1

Si eliminas Kafka, Strimzi eliminará todos los objetos dependientes por ti. Esto es muy importante, porque si eliminas objetos individuales como un conjunto de estado de Apache ZooKeeper, Strimzi lo reconciliará y lo creará de nuevo automáticamente. La única forma de eliminar todos los recursos creados es eliminar Kafka

No lo hagas todavía, si quieres seguir el ejemplo:

 ~  oc delete kafka logs
kafka.kafka.strimzi.io "logs" deleted

Stateful Sets

Strimzi crea conjuntos de stateful sets para nuestro Kafka. ¿Qué es un statefulset?

Statefulset es objeto de la API usado para gestionar aplicaciones stateful que controla el despliegue y el escalado de un conjunto de Pods y proporciona garantías sobre el orden y la singularidad de estos Pods. Un broker Kafka y un nodo ZooKeeper deben ser únicos. Esto es obligatorio para los clústeres que tienen como objetivo la alta disponibilidad.

El nombre del clúster de Kafka es el prefijo para los siguientes statefulsets.

oc get statefulset
NAME             DESIRED   CURRENT   AGE
logs-kafka       1         1         15m
logs-zookeeper   1         1         16m

Despliegues

El operador Strimzi también despliega operadores por sí mismo.

~  oc get deployment
NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
logs-entity-operator       1         1         1            1           15m
strimzi-cluster-operator   1         1         1            1           56m

En este caso, es el operador Entity Operator.

Operators

El Operator Entitiy se consiste en Topic Operator y User Operator.

Estos operadores escuchan los recursos personalizados. En el caso de Topic Operator, se trata de KafkaTopic. Creamos un topic de Kafka.

cat mimacom-topic.yml:

apiVersion: kafka.strimzi.io/v1beta1
kind: KafkaTopic
metadata:
  name: spring-boot
  labels:
    strimzi.io/cluster: logs
spec:
  partitions: 1
  replicas: 1

Como es un nodo único, usamos una partición y una réplica. Creamos el KafkaTopic

oc apply -f mimacom-topic.yml
kafkatopic.kafka.strimzi.io/spring-boot created

List topic (the OpenShift/Strimzi way)

oc get kafkatopic                  
NAME          PARTITIONS   REPLICATION FACTOR
spring-boot   1            1

Los topics de Kafka se gestionan de forma diferente en OpenShift y Kubernetes. En una instalación nativa de Kafka, usarás el kafka-topics.sh para crear un topic, o si la función de auto-creación está activada, Kafka crea el topic por sí mismo. Estos topics no serán visibles para Strimzi, por lo que usar el operador de entidad es vital para gestionar los topics de Kafka en OpenShift!

Networking

Strimzi crea estas rutas y expone el cluster al exterior

oc get routes
NAME                   HOST/PORT                                             PATH      SERVICES                        PORT      TERMINATION   WILDCARD
logs-kafka-0           logs-kafka-0-streaming.192.168.42.24.nip.io                     logs-kafka-0                    9094      passthrough   None
logs-kafka-bootstrap   logs-kafka-bootstrap-streaming.192.168.42.24.nip.io             logs-kafka-external-bootstrap   9094      passthrough   None

Otros Objetos

Si quieres ver todos los recursos que Strimzi ha creado, haz una lista de todos los objetos..

oc get all
NAME                                           READY     STATUS    RESTARTS   AGE
pod/logs-entity-operator-c8ff8696f-8x6vk       3/3       Running   0          43m
pod/logs-kafka-0                               2/2       Running   0          43m
pod/logs-zookeeper-0                           1/1       Running   0          44m
pod/strimzi-cluster-operator-bf978cf5c-rc5l2   1/1       Running   0          2h

NAME                                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/logs-kafka-0                    ClusterIP   172.30.204.40   <none>        9094/TCP                     43m
service/logs-kafka-bootstrap            ClusterIP   172.30.99.158   <none>        9091/TCP,9092/TCP,9093/TCP   43m
service/logs-kafka-brokers              ClusterIP   None            <none>        9091/TCP,9092/TCP,9093/TCP   43m
service/logs-kafka-external-bootstrap   ClusterIP   172.30.39.229   <none>        9094/TCP                     43m
service/logs-zookeeper-client           ClusterIP   172.30.142.59   <none>        2181/TCP                     44m
service/logs-zookeeper-nodes            ClusterIP   None            <none>        2181/TCP,2888/TCP,3888/TCP   44m

NAME                                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/logs-entity-operator       1         1         1            1           43m
deployment.apps/strimzi-cluster-operator   1         1         1            1           2h

NAME                                                 DESIRED   CURRENT   READY     AGE
replicaset.apps/logs-entity-operator-c8ff8696f       1         1         1         43m
replicaset.apps/strimzi-cluster-operator-bf978cf5c   1         1         1         2h

NAME                              DESIRED   CURRENT   AGE
statefulset.apps/logs-kafka       1         1         43m
statefulset.apps/logs-zookeeper   1         1         44m

NAME                                            HOST/PORT                                             PATH      SERVICES                        PORT      TERMINATION   WILDCARD
route.route.openshift.io/logs-kafka-0           logs-kafka-0-streaming.192.168.42.24.nip.io                     logs-kafka-0                    9094      passthrough   None
route.route.openshift.io/logs-kafka-bootstrap   logs-kafka-bootstrap-streaming.192.168.42.24.nip.io             logs-kafka-external-bootstrap   9094      passthrough   None

Usar Kafka en OpenShift

Utilizamos algunos datos de prueba para el time tracking. Estos datos se generan de forma aleatoria.

[{
  "id": 1,
  "first_name": "Redd",
  "last_name": "Ulyat",
  "email": "rulyat0@ft.com",
  "gender": "Male",
  "start": "18:06",
  "end": "17:50",
  "customer": "Feedspan"
}, {
  "id": 2,
  "first_name": "Suzann",
  "last_name": "Andryushchenko",
  "email": "sandryushchenko1@cyberchimps.com",
  "gender": "Female",
  "start": "12:14",
  "end": "20:53",
  "customer": "Skyndu"
}, {
  "id": 3,
  "first_name": "Sunny",
  "last_name": "Statter",
  "email": "sstatter2@purevolume.com",
  "gender": "Male",
  "start": "9:46",
  "end": "14:29",
  "customer": "Pixope"
}, {
  "id": 4,
  "first_name": "Glori",
  "last_name": "Cumberpatch",
  "email": "gcumberpatch3@dedecms.com",
  "gender": "Female",
  "start": "18:13",
  "end": "11:29",
  "customer": "Agimba"
}, {
  "id": 5,
  "first_name": "Ashlee",
  "last_name": "Fynan",
  "email": "afynan4@uiuc.edu",
  "gender": "Female",
  "start": "10:01",
  "end": "1:53",
  "customer": "Gigabox"
}, {
  "id": 6,
  "first_name": "Darin",
  "last_name": "Gulc",
  "email": "dgulc5@ihg.com",
  "gender": "Male",
  "start": "9:43",
  "end": "5:10",
  "customer": "Rhyloo"
}, {
  "id": 7,
  "first_name": "Brodie",
  "last_name": "Casari",
  "email": "bcasari6@mashable.com",
  "gender": "Male",
  "start": "5:22",
  "end": "12:00",
  "customer": "Eamia"
}, {
  "id": 8,
  "first_name": "Morty",
  "last_name": "Currington",
  "email": "mcurrington7@usa.gov",
  "gender": "Male",
  "start": "21:22",
  "end": "17:01",
  "customer": "Quatz"
}, {
  "id": 9,
  "first_name": "Jacobo",
  "last_name": "Lanmeid",
  "email": "jlanmeid8@illinois.edu",
  "gender": "Male",
  "start": "18:10",
  "end": "18:39",
  "customer": "Buzzster"
}, {
  "id": 10,
  "first_name": "Ilario",
  "last_name": "Embra",
  "email": "iembra9@ca.gov",
  "gender": "Male",
  "start": "13:51",
  "end": "18:54",
  "customer": "Oyondu"
}]

Produciendo datos

Ponemos en marcha un pod con un contenedor para la producción de datos. El contenedor se limpiará cuando termine. Haz esto en tu terminal Linux.

oc -n streaming run kafka-producer -ti --image=strimzi/kafka:0.18.0-kafka-2.5.0 \
--rm=true --restart=Never -- bin/kafka-console-producer.sh \
--broker-list logs-kafka-bootstrap:9092 --topic time-tracking

Pega los datos de prueba de minishift. CTRL + C cierra el productor.

If you don't see a command prompt, try pressing enter.
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
>[{"id":1,"first_name":"Redd","last_name":"Ulyat","email":"rulyat0@ft.com","gender":"Male","start":"18:06","end":"17:50","customer":"Feedspan"},{"id":2,"first_name":"Suzann","last_name":"Andryushchenko","email":"sandryushchenko1@cyberchimps.com","gender":"Female","start":"12:14","end":"20:53","customer":"Skyndu"},{"id":3,"first_name":"Sunny","last_name":"Statter","email":"sstatter2@purevolume.com","gender":"Male","start":"9:46","end":"14:29","customer":"Pixope"},{"id":4,"first_name":"Glori","last_name":"Cumberpatch","email":"gcumberpatch3@dedecms.com","gender":"Female","start":"18:13","end":"11:29","customer":"Agimba"},{"id":5,"first_name":"Ashlee","last_name":"Fynan","email":"afynan4@uiuc.edu","gender":"Female","start":"10:01","end":"1:53","customer":"Gigabox"},{"id":6,"first_name":"Darin","last_name":"Gulc","email":"dgulc5@ihg.com","gender":"Male","start":"9:43","end":"5:10","customer":"Rhyloo"},{"id":7,"first_name":"Brodie","last_name":"Casari","email":"bcasari6@mashable.com","gender":"Male","start":"5:22","end":"12:00","customer":"Eamia"},{"id":8,"first_name":"Morty","last_name":"Currington","email":"mcurrington7@usa.gov","gender":"Male","start":"21:22","end":"17:01","customer":"Quatz"},{"id":9,"first_name":"Jacobo","last_name":"Lanmeid","email":"jlanmeid8@illinois.edu","gender":"Male","start":"18:10","end":"18:39","customer":"Buzzster"},{"id":10,"first_name":"Ilario","last_name":"Embra","email":"iembra9@ca.gov","gender":"Male","start":"13:51","end":"18:54","customer":"Oyondu"}]
[2020-05-27 14:40:37,082] WARN [Producer clientId=console-producer] Error while fetching metadata with correlation id 11 : {time-tracking=LEADER_NOT_AVAILABLE} (org.apache.kafka.clients.NetworkClient)
[2020-05-27 14:40:37,195] WARN [Producer clientId=console-producer] Error while fetching metadata with correlation id 12 : {time-tracking=LEADER_NOT_AVAILABLE} (org.apache.kafka.clients.NetworkClient)
>^Cpod "kafka-producer" deleted
pod streaming/kafka-producer terminated (Error)

El contenedor podría comunicarse dentro del espacio de nombres con el grupo Kafka a través de los registros de nombres de logs-kafka-bootstrap en el puerto 9092.

Consumiendo datos

El consumo de datos sigue el mismo principio. Para obtener los datos desde el principio, pasa la opción --from-beginning.

oc -n streaming run kafka-consumer -ti --image=strimzi/kafka:0.18.0-kafka-2.5.0 \
--rm=true --restart=Never -- bin/kafka-console-consumer.sh \
--bootstrap-server logs-kafka-bootstrap:9092 --topic time-tracking --from-beginning

Recibirás este output. CTRL + C cierra la aplicación.

If you don't see a command prompt, try pressing enter.
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
[{"id":1,"first_name":"Redd","last_name":"Ulyat","email":"rulyat0@ft.com","gender":"Male","start":"18:06","end":"17:50","customer":"Feedspan"},{"id":2,"first_name":"Suzann","last_name":"Andryushchenko","email":"sandryushchenko1@cyberchimps.com","gender":"Female","start":"12:14","end":"20:53","customer":"Skyndu"},{"id":3,"first_name":"Sunny","last_name":"Statter","email":"sstatter2@purevolume.com","gender":"Male","start":"9:46","end":"14:29","customer":"Pixope"},{"id":4,"first_name":"Glori","last_name":"Cumberpatch","email":"gcumberpatch3@dedecms.com","gender":"Female","start":"18:13","end":"11:29","customer":"Agimba"},{"id":5,"first_name":"Ashlee","last_name":"Fynan","email":"afynan4@uiuc.edu","gender":"Female","start":"10:01","end":"1:53","customer":"Gigabox"},{"id":6,"first_name":"Darin","last_name":"Gulc","email":"dgulc5@ihg.com","gender":"Male","start":"9:43","end":"5:10","customer":"Rhyloo"},{"id":7,"first_name":"Brodie","last_name":"Casari","email":"bcasari6@mashable.com","gender":"Male","start":"5:22","end":"12:00","customer":"Eamia"},{"id":8,"first_name":"Morty","last_name":"Currington","email":"mcurrington7@usa.gov","gender":"Male","start":"21:22","end":"17:01","customer":"Quatz"},{"id":9,"first_name":"Jacobo","last_name":"Lanmeid","email":"jlanmeid8@illinois.edu","gender":"Male","start":"18:10","end":"18:39","customer":"Buzzster"},{"id":10,"first_name":"Ilario","last_name":"Embra","email":"iembra9@ca.gov","gender":"Male","start":"13:51","end":"18:54","customer":"Oyondu"}]

^CProcessed a total of 2 messages
pod "kafka-consumer" deleted
pod streaming/kafka-consumer terminated (Error)

Acceso externo de Kafka

Para acceder al clúster desde una instalación local de Kafka, tenemos que conseguir un certificado ya que la ruta está cifrada por HTTPS. Este es otro punto fuerte de Strimzi - viene sin necesidad de que lo hagamos nosotros.

Para la demostración, usamos un cliente antiguo de la versión 2.4.1 diferente a la versión desplegada 2.5.0.

Mostrar todos los secretos y listar las autoridades de certificación (ca).

oc get secrets | grep ca-cert
logs-clients-ca-cert                       Opaque                                3         1h
logs-cluster-ca-cert                       Opaque                                3         1h

Sólo estamos interesados en el clúster de ca. Para verlo, utiliza este comando. Se redacta el output sensible.

oc get secret logs-cluster-ca-cert -o yaml
apiVersion: v1
data:
  ca.crt: LS0tLS1...
  ca.p12: MIIEVgI...
  ca.password: xxxx
kind: Secret
metadata:
  annotations:
    strimzi.io/ca-cert-generation: "0"
  creationTimestamp: 2020-05-27T12:55:29Z
  labels:
    app.kubernetes.io/instance: logs
    app.kubernetes.io/managed-by: strimzi-cluster-operator
    app.kubernetes.io/name: strimzi
    app.kubernetes.io/part-of: strimzi-logs
    strimzi.io/cluster: logs
    strimzi.io/kind: Kafka
    strimzi.io/name: strimzi
  name: logs-cluster-ca-cert
  namespace: streaming
  ownerReferences:
  - apiVersion: kafka.strimzi.io/v1beta1
    blockOwnerDeletion: false
    controller: false
    kind: Kafka
    name: logs
    uid: 5783c877-a019-11ea-9be2-525400a45a70
  resourceVersion: "147848"
  selfLink: /api/v1/namespaces/streaming/secrets/logs-cluster-ca-cert
  uid: 57fa7398-a019-11ea-9be2-525400a45a70
type: Opaque

Expórtalo al truststore de Java recién creado.

oc extract secret/logs-cluster-ca-cert --keys=ca.crt --to=- > ca.crt
keytool -import -trustcacerts -alias root -file ca.crt -keystore truststore.jks -storepass password -noprompt
# ca.crt
Certificate was added to keystore

Consumiendo datos

Ve a tu instalación local de Kafka y pasa la información obligatoria. Usamos la dirección de bootstrap logs-kafka-bootstrap-streaming.192.168.42.24.nip.io para acceder al clúster de Kafka.

bin/kafka-console-consumer.sh \
--bootstrap-server logs-kafka-bootstrap-streaming.192.168.42.24.nip.io:443 \
--consumer-property security.protocol=SSL \
--consumer-property ssl.truststore.password=password \
--consumer-property ssl.truststore.location=/home/tan/truststore.jks \
--topic time-tracking --from-beginning 

Output del cliente:

[{"id":1,"first_name":"Redd","last_name":"Ulyat","email":"rulyat0@ft.com","gender":"Male","start":"18:06","end":"17:50","customer":"Feedspan"},{"id":2,"first_name":"Suzann","last_name":"Andryushchenko","email":"sandryushchenko1@cyberchimps.com","gender":"Female","start":"12:14","end":"20:53","customer":"Skyndu"},{"id":3,"first_name":"Sunny","last_name":"Statter","email":"sstatter2@purevolume.com","gender":"Male","start":"9:46","end":"14:29","customer":"Pixope"},{"id":4,"first_name":"Glori","last_name":"Cumberpatch","email":"gcumberpatch3@dedecms.com","gender":"Female","start":"18:13","end":"11:29","customer":"Agimba"},{"id":5,"first_name":"Ashlee","last_name":"Fynan","email":"afynan4@uiuc.edu","gender":"Female","start":"10:01","end":"1:53","customer":"Gigabox"},{"id":6,"first_name":"Darin","last_name":"Gulc","email":"dgulc5@ihg.com","gender":"Male","start":"9:43","end":"5:10","customer":"Rhyloo"},{"id":7,"first_name":"Brodie","last_name":"Casari","email":"bcasari6@mashable.com","gender":"Male","start":"5:22","end":"12:00","customer":"Eamia"},{"id":8,"first_name":"Morty","last_name":"Currington","email":"mcurrington7@usa.gov","gender":"Male","start":"21:22","end":"17:01","customer":"Quatz"},{"id":9,"first_name":"Jacobo","last_name":"Lanmeid","email":"jlanmeid8@illinois.edu","gender":"Male","start":"18:10","end":"18:39","customer":"Buzzster"},{"id":10,"first_name":"Ilario","last_name":"Embra","email":"iembra9@ca.gov","gender":"Male","start":"13:51","end":"18:54","customer":"Oyondu"}]

^CProcessed a total of 2 messages

La producción de datos sigue el mismo principio. Se pueden pasar todas las propiedades o crear consumer.properties o producer.properties para su respectivo uso. Lo demostramos en la siguiente sección.

Listado de topics

Como has leído, los handling topics deben ir sobre el operador de la entidad. El topic de ejemplo creado de time-tracking no aparece en OpenShift. Puedes usar kafka-topics.sh para ver los topics desde fuera. Necesitamos crear un archivo de propiedades para el cliente con la configuración para la comunicación encriptada.

Crea properties.file

 ~/test/kafka_2.11-2.4.1  echo security.protocol=SSL >> strimzi-minishift.properties
 ~/test/kafka_2.11-2.4.1  echo ssl.truststore.password=password >> strimzi-minishift.properties
 ~/test/kafka_2.11-2.4.1  echo ssl.truststore.location=/home/tan/truststore.jks >> strimzi-minishift.properties

Lista todos los topics

bin/kafka-topics.sh --bootstrap-server logs-kafka-bootstrap-streaming.192.168.42.24.nip.io:443 \
--list --command-config ./strimzi-minishift.properties

Output

 ~/test/kafka_2.11-2.4.1  bin/kafka-topics.sh --bootstrap-server logs-kafka-bootstrap-streaming.192.168.42.24.nip.io:443 --list --command-config ./strimzi-minishift.properties                                                                             
__consumer_offsets
spring-boot
time-tracking

Resumen

En este artículo, has aprendido lo básico sobre el uso de Strimzi para desplegar Apache Kafka en Kubernetes y OpenShift. El acceso externo era un deseo crucial para nosotros, y Strimzi viene con soluciones robustas. Puedes probar este ejemplo por tu mismo. Todo lo que necesitas es instalar minishift y Apache Kafka en su entorno Linux.

Sobre el autor: Vinh Nguyên

Le encanta programar y hacer excursiones, pero, sobre todo, beber cafe solo. Tiene predilección por Apache Kafka, Elasticsearch, el desarrollo en Java y la música de los 80

Comments
Únete a nosotros