Monitorea tu clúster de Kafka que se ejecuta en Kubernetes con el operador Strimzi implementando el recopilador de OpenTelemetry. El recopilador descubre automáticamente los pods del broker de Kafka y recopila métricas completas.
Instalación y configuración
Siga estos pasos para desplegar y configurar el OpenTelemetry Collector en su clúster de Kubernetes para descubrir y monitorear automáticamente sus brokers de Strimzi Kafka.
Antes de que empieces
Asegúrese de tener:
- Una cuenta de New Relic con un
- Clúster de Kubernetes con acceso kubectl
- Kafka desplegado a través del operador Strimzi
Configurar el clúster de Kafka para las métricas JMX de Kafka
Configure su clúster Strimzi Kafka para exponer las métricas JMX de Kafka mediante el Prometheus JMX Exporter. Esta configuración se desplegará como un ConfigMap y será referenciada por su clúster de Kafka.
Crear ConfigMap de métricas JMX
Cree un ConfigMap con patrones de JMX Exporter que definan qué métricas de Kafka recolectar. Guardar como kafka-jmx-metrics-config.yaml:
apiVersion: v1kind: ConfigMapmetadata: name: kafka-jmx-metrics namespace: newrelicdata: kafka-metrics-config.yml: | startDelaySeconds: 0 lowercaseOutputName: true lowercaseOutputLabelNames: true
rules: # Cluster-level controller metrics - pattern: 'kafka.controller<type=KafkaController, name=GlobalTopicCount><>Value' name: kafka_cluster_topic_count type: GAUGE
- pattern: 'kafka.controller<type=KafkaController, name=GlobalPartitionCount><>Value' name: kafka_cluster_partition_count type: GAUGE
- pattern: 'kafka.controller<type=KafkaController, name=FencedBrokerCount><>Value' name: kafka_broker_fenced_count type: GAUGE
- pattern: 'kafka.controller<type=KafkaController, name=PreferredReplicaImbalanceCount><>Value' name: kafka_partition_non_preferred_leader type: GAUGE
- pattern: 'kafka.controller<type=KafkaController, name=OfflinePartitionsCount><>Value' name: kafka_partition_offline type: GAUGE
- pattern: 'kafka.controller<type=KafkaController, name=ActiveControllerCount><>Value' name: kafka_controller_active_count type: GAUGE
# Broker-level replica metrics - pattern: 'kafka.server<type=ReplicaManager, name=UnderMinIsrPartitionCount><>Value' name: kafka_partition_under_min_isr type: GAUGE
- pattern: 'kafka.server<type=ReplicaManager, name=LeaderCount><>Value' name: kafka_broker_leader_count type: GAUGE
- pattern: 'kafka.server<type=ReplicaManager, name=PartitionCount><>Value' name: kafka_partition_count type: GAUGE
- pattern: 'kafka.server<type=ReplicaManager, name=UnderReplicatedPartitions><>Value' name: kafka_partition_under_replicated type: GAUGE
- pattern: 'kafka.server<type=ReplicaManager, name=IsrShrinksPerSec><>Count' name: kafka_isr_operation_count type: COUNTER labels: operation: "shrink"
- pattern: 'kafka.server<type=ReplicaManager, name=IsrExpandsPerSec><>Count' name: kafka_isr_operation_count type: COUNTER labels: operation: "expand"
- pattern: 'kafka.server<type=ReplicaFetcherManager, name=MaxLag, clientId=Replica><>Value' name: kafka_max_lag type: GAUGE
# Broker topic metrics (totals) - pattern: 'kafka.server<type=BrokerTopicMetrics, name=MessagesInPerSec><>Count' name: kafka_message_count type: COUNTER
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=TotalFetchRequestsPerSec><>Count' name: kafka_request_count type: COUNTER labels: type: "fetch"
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=TotalProduceRequestsPerSec><>Count' name: kafka_request_count type: COUNTER labels: type: "produce"
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=FailedFetchRequestsPerSec><>Count' name: kafka_request_failed type: COUNTER labels: type: "fetch"
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=FailedProduceRequestsPerSec><>Count' name: kafka_request_failed type: COUNTER labels: type: "produce"
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=BytesInPerSec><>Count' name: kafka_network_io type: COUNTER labels: direction: "in"
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=BytesOutPerSec><>Count' name: kafka_network_io type: COUNTER labels: direction: "out"
# Per-topic metrics (only appear after traffic flows) - pattern: 'kafka.server<type=BrokerTopicMetrics, name=MessagesInPerSec, topic=(.+)><>Count' name: kafka_prod_msg_count type: COUNTER labels: topic: "$1"
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=BytesInPerSec, topic=(.+)><>Count' name: kafka_topic_io type: COUNTER labels: topic: "$1" direction: "in"
- pattern: 'kafka.server<type=BrokerTopicMetrics, name=BytesOutPerSec, topic=(.+)><>Count' name: kafka_topic_io type: COUNTER labels: topic: "$1" direction: "out"
# Request metrics - pattern: 'kafka.network<type=RequestMetrics, name=TotalTimeMs, request=(Produce|FetchConsumer|FetchFollower)><>Count' name: kafka_request_time_total type: COUNTER labels: type: "$1"
- pattern: 'kafka.network<type=RequestMetrics, name=TotalTimeMs, request=(Produce|FetchConsumer|FetchFollower)><>50thPercentile' name: kafka_request_time_50p type: GAUGE labels: type: "$1"
- pattern: 'kafka.network<type=RequestMetrics, name=TotalTimeMs, request=(Produce|FetchConsumer|FetchFollower)><>99thPercentile' name: kafka_request_time_99p type: GAUGE labels: type: "$1"
- pattern: 'kafka.network<type=RequestMetrics, name=TotalTimeMs, request=(Produce|FetchConsumer|FetchFollower)><>Mean' name: kafka_request_time_avg type: GAUGE labels: type: "$1"
- pattern: 'kafka.network<type=RequestChannel, name=RequestQueueSize><>Value' name: kafka_request_queue type: GAUGE
- pattern: 'kafka.server<type=DelayedOperationPurgatory, name=PurgatorySize, delayedOperation=(.+)><>Value' name: kafka_purgatory_size type: GAUGE labels: type: "$1"
# Controller stats - pattern: 'kafka.controller<type=ControllerStats, name=LeaderElectionRateAndTimeMs><>Count' name: kafka_leader_election_rate type: COUNTER
- pattern: 'kafka.controller<type=ControllerStats, name=UncleanLeaderElectionsPerSec><>Count' name: kafka_unclean_election_rate type: COUNTER
# Log flush metrics - pattern: 'kafka.log<type=LogFlushStats, name=LogFlushRateAndTimeMs><>Count' name: kafka_logs_flush_count type: COUNTER
- pattern: 'kafka.log<type=LogFlushStats, name=LogFlushRateAndTimeMs><>50thPercentile' name: kafka_logs_flush_time_50p type: GAUGE
- pattern: 'kafka.log<type=LogFlushStats, name=LogFlushRateAndTimeMs><>99thPercentile' name: kafka_logs_flush_time_99p type: GAUGE
# JVM Garbage Collection - pattern: 'java.lang<name=(.+), type=GarbageCollector><>CollectionCount' name: jvm_gc_collections_count type: COUNTER labels: name: "$1"
- pattern: 'java.lang<name=(.+), type=GarbageCollector><>CollectionTime' name: jvm_gc_collections_elapsed type: COUNTER labels: name: "$1"
# JVM Memory - pattern: 'java.lang<type=Memory><HeapMemoryUsage>committed' name: jvm_memory_heap_committed type: GAUGE
- pattern: 'java.lang<type=Memory><HeapMemoryUsage>max' name: jvm_memory_heap_max type: GAUGE
- pattern: 'java.lang<type=Memory><HeapMemoryUsage>used' name: jvm_memory_heap_used type: GAUGE
# JVM Threading and System - pattern: 'java.lang<type=Threading><>ThreadCount' name: jvm_thread_count type: GAUGE
- pattern: 'java.lang<type=OperatingSystem><>SystemLoadAverage' name: jvm_system_cpu_load_1m type: GAUGE
- pattern: 'java.lang<type=OperatingSystem><>AvailableProcessors' name: jvm_cpu_count type: GAUGE
- pattern: 'java.lang<type=OperatingSystem><>ProcessCpuLoad' name: jvm_cpu_recent_utilization type: GAUGE
- pattern: 'java.lang<type=OperatingSystem><>SystemCpuLoad' name: jvm_system_cpu_utilization type: GAUGE
- pattern: 'java.lang<type=OperatingSystem><>OpenFileDescriptorCount' name: jvm_file_descriptor_count type: GAUGE
- pattern: 'java.lang<type=ClassLoading><>LoadedClassCount' name: jvm_class_count type: GAUGE
# JVM Memory Pool - pattern: 'java.lang<type=MemoryPool, name=(.+)><Usage>used' name: jvm_memory_pool_used type: GAUGE labels: name: "$1"
- pattern: 'java.lang<type=MemoryPool, name=(.+)><Usage>max' name: jvm_memory_pool_max type: GAUGE labels: name: "$1"
- pattern: 'java.lang<type=MemoryPool, name=(.+)><CollectionUsage>used' name: jvm_memory_pool_used_after_last_gc type: GAUGE labels: name: "$1"
# Broker uptime - pattern: 'java.lang<type=Runtime><>Uptime' name: kafka_broker_uptime type: GAUGESugerencia
Personalizar métricas: Este ConfigMap incluye métricas completas de brokers, temas, solicitudes, controladores y JVM de Kafka. Puede agregar o modificar patrones consultando los ejemplos de Prometheus JMX Exporter y la documentación de Kafka MBean. Consulte la documentación de reglas de JMX Exporter para configuraciones adicionales.
Importante
Requisito de espacio de nombres: El ConfigMap de métricas JMX y su clúster de Kafka deben estar en el mismo espacio de nombres. En esta guía, ambos se despliegan en el espacio de nombres newrelic.
Aplique el ConfigMap:
$kubectl apply -f kafka-jmx-metrics-config.yamlActualizar el clúster de Kafka para utilizar JMX Exporter
Actualice su recurso Strimzi Kafka para hacer referencia al ConfigMap de métricas:
apiVersion: kafka.strimzi.io/v1beta2kind: Kafkametadata: name: my-cluster namespace: newrelicspec: kafka: version: X.X.X metricsConfig: type: jmxPrometheusExporter valueFrom: configMapKeyRef: name: kafka-jmx-metrics key: kafka-metrics-config.yml # ...rest of your Kafka configurationAplicar los cambios. Strimzi realizará un reinicio escalonado de sus brokers de Kafka:
$kubectl apply -f kafka-cluster.yamlDespués de que se complete el reinicio gradual, cada broker de Kafka expondrá métricas de Prometheus en el puerto 9404.
Desplegar OpenTelemetry Collector
Despliegue el OpenTelemetry Collector para monitorear su clúster de Kafka. Seleccione su método de instalación preferido:
El método de instalación con Helm es el enfoque recomendado para desplegar OpenTelemetry Collector en Kubernetes.
Crear secreto de credenciales de New Relic
Crea un secreto de Kubernetes que contenga tu clave de licencia de New Relic y el endpoint OTLP. Selecciona el endpoint para tu región de New Relic:
Sugerencia
Para otras configuraciones de endpoints, consulte Configure su endpoint OTLP.
Cree values.yaml con la configuración del recopilador
Cree un archivo values.yaml que contenga la configuración completa del OpenTelemetry Collector. Tanto los recopiladores NRDOT como los de OpenTelemetry utilizan una configuración idéntica y proporcionan las mismas capacidades de monitoreo de Kafka. Seleccione su imagen de colector preferida:
Para opciones de configuración avanzadas, consulte estas páginas de documentación del receptor:
Documentación del receptor Prometheus - Opciones adicionales de configuración del receptor
Documentación del receptor de métricas de Kafka - Configuración adicional de métricas de Kafka
Instalar OpenTelemetry Collector con Helm
Agregue el repositorio de Helm e instale el OpenTelemetry Collector utilizando el archivo values.yaml:
bash$helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts$helm upgrade kafka-monitoring open-telemetry/opentelemetry-collector \>--install \>--namespace newrelic \>--create-namespace \>-f values.yamlVerifique el despliegue:
bash$# Check pod status$kubectl get pods -n newrelic -l app.kubernetes.io/name=opentelemetry-collector$$# View logs to verify metrics collection$kubectl logs -n newrelic -l app.kubernetes.io/name=opentelemetry-collector --tail=50Debería ver logs que indiquen un scraping exitoso de los brokers de Kafka en el puerto 9404.
El método de instalación de manifiesto proporciona control directo sobre los recursos de Kubernetes sin usar Helm.
Crear secreto de credenciales de New Relic
Crea un secreto de Kubernetes que contenga tu clave de licencia de New Relic y el endpoint OTLP. Selecciona el endpoint para tu región de New Relic:
Sugerencia
Para otras configuraciones de endpoints, consulte Configure su endpoint OTLP.
Crear archivos de manifiesto
Cree los archivos de manifiesto de Kubernetes para su recopilador preferido. Ambos colectores usan una configuración idéntica; solo la imagen difiere.
Elija su opción de colector y cree los tres archivos requeridos:
Para opciones de configuración avanzadas, consulte estas páginas de documentación del receptor:
Documentación del receptor Prometheus - Opciones adicionales de configuración del receptor
Documentación del receptor de métricas de Kafka - Configuración adicional de métricas de Kafka
Despliegue los manifiestos
Aplique los manifiestos de Kubernetes para desplegar el OpenTelemetry Collector:
bash$# Create namespace if it doesn't exist$kubectl create namespace newrelic --dry-run=client -o yaml | kubectl apply -f -$$# Apply RBAC configuration$kubectl apply -f collector-rbac.yaml$$# Apply ConfigMap$kubectl apply -f collector-configmap.yaml$$# Apply Deployment$kubectl apply -f collector-deployment.yamlVerifique el despliegue:
bash$# Check pod status$kubectl get pods -n newrelic -l app=otel-collector$$# View logs to verify metrics collection$kubectl logs -n newrelic -l app=otel-collector --tail=50Debería ver logs que indiquen un scraping exitoso de los brokers de Kafka en el puerto 9404.
(Opcional) Instrumentar aplicaciones productoras o consumidoras
Importante
Soporte de lenguajes: Las aplicaciones Java admiten la instrumentación del cliente Kafka lista para usar mediante el OpenTelemetry Java Agent.
Para recopilar telemetría a nivel de aplicación de sus aplicaciones productoras y consumidoras de Kafka, utilice el OpenTelemetry Java Agent.
Instrumente su aplicación Kafka
Use un contenedor de inicio para descargar el Agente Java de OpenTelemetry en tiempo de ejecución:
apiVersion: apps/v1kind: Deploymentmetadata: name: kafka-producer-appspec: template: spec: initContainers: - name: download-java-agent image: busybox:latest command: - sh - -c - | wget -O /otel-auto-instrumentation/opentelemetry-javaagent.jar \ https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar volumeMounts: - name: otel-auto-instrumentation mountPath: /otel-auto-instrumentation
containers: - name: app image: your-kafka-app:latest env: - name: JAVA_TOOL_OPTIONS value: >- -javaagent:/otel-auto-instrumentation/opentelemetry-javaagent.jar -Dotel.service.name=order-process-service -Dotel.resource.attributes=kafka.cluster.name=my-cluster -Dotel.exporter.otlp.endpoint=http://localhost:4317 -Dotel.exporter.otlp.protocol=grpc -Dotel.metrics.exporter=otlp -Dotel.traces.exporter=otlp -Dotel.logs.exporter=otlp -Dotel.instrumentation.kafka.experimental-span-attributes=true -Dotel.instrumentation.messaging.experimental.receive-telemetry.enabled=true -Dotel.instrumentation.kafka.producer-propagation.enabled=true -Dotel.instrumentation.kafka.enabled=true volumeMounts: - name: otel-auto-instrumentation mountPath: /otel-auto-instrumentation
volumes: - name: otel-auto-instrumentation emptyDir: {}Notas de configuración:
- Reemplace
order-process-servicecon un nombre único para su aplicación productora o consumidora - Reemplace
my-clustercon el mismo nombre de clúster utilizado en la configuración de su colector - El endpoint
http://localhost:4317asume que el colector se ejecuta como un sidecar en el mismo pod o que es accesible a través de localhost
Sugerencia
La configuración anterior envía telemetría a un OpenTelemetry Collector. Si necesita enviar telemetría al colector, impleméntelo como se describe en el Paso 3 con esta configuración:
El agente Java proporciona instrumentación de Kafka lista para usar sin cambios de código, capturando:
- Latencias de solicitud
- Métricas de rendimiento
- Tasas de error
- Rastreo distribuido
Para una configuración avanzada, consulte la documentación de instrumentación de Kafka.
Encuentra tus datos
Después de unos minutos, sus métricas de Kafka deberían aparecer en New Relic. Consulte Encuentre sus datos para obtener instrucciones detalladas sobre cómo explorar sus métricas de Kafka en diferentes vistas en la interfaz de usuario de New Relic.
También puede consultar sus datos con NRQL:
FROM Metric SELECT * WHERE kafka.cluster.name = 'my-kafka-cluster'Resolución de problemas
Próximos pasos
- Explora las métricas de Kafka - Consulta la referencia completa de métricas
- Crear dashboards personalizados - Construir visualizaciones para sus datos de Kafka
- Configurar alertas - Monitorea métricas críticas como el retraso del consumidor y las particiones subreplicadas