Soporte de registro de TIBCO BW ECS

Soporte de registro de TIBCO BW ECS

El soporte de registro de TIBCO BW ECS se está convirtiendo en una característica demandada debido al uso creciente del Esquema Común de Elastic para la solución de agregación de registros basada en la pila de Elastic (anteriormente conocida como pila ELK)

Ya hemos comentado mucho sobre la importancia de las soluciones de agregación de registros y sus beneficios, especialmente al discutir la arquitectura de contenedores. Debido a eso, hoy nos centraremos en cómo podemos adaptar nuestras aplicaciones BW para soportar este nuevo formato de registro.

Porque lo primero que necesitamos saber es la siguiente afirmación: Sí, esto se puede hacer. Y se puede hacer independientemente de su modelo de implementación. Por lo tanto, la solución proporcionada aquí funciona tanto para soluciones locales como para implementaciones en contenedores utilizando BWCE.

Antecedentes del Registro de TIBCO BW

TIBCO BusinessWorks (contenedor o no) se basa en sus capacidades de registro en la biblioteca logback, y esta biblioteca se configura utilizando un archivo llamado logback.xml que podría tener la configuración que necesita, como puede ver en la imagen a continuación:

BW ECS Logging: Ejemplo de configuración predeterminada de Logback.xml

Logback es una biblioteca bien conocida para desarrollos basados en Java y tiene una arquitectura basada en una solución central y complementos que extienden sus capacidades actuales. Es este enfoque de complemento el que vamos a utilizar para soportar ECS.

Incluso en la documentación oficial de ECS se cubre la configuración para habilitar esta configuración de registro cuando se utiliza la solución Logback, como puede ver en la imagen a continuación y en este enlace oficial:

BW ECS Logging: Información de Dependencia de ECS Java

En nuestro caso, no necesitamos agregar la dependencia en ningún lugar, sino simplemente descargar la dependencia, ya que necesitaremos incluirla en los paquetes OSGI existentes para la instalación de TIBCO BW. Solo necesitaremos dos archivos que son los siguientes:

  • ecs-logging-core-1.5.0.jar
  • logback-ecs-encoder-1.5.0.jar

En el momento de escribir este artículo, las versiones actuales son 1.5.0 para cada uno de ellos, pero manténgase atento para asegurarse de que está utilizando una versión reciente de este software para evitar problemas con el soporte y las vulnerabilidades.

Una vez que tengamos estas bibliotecas, necesitamos agregarlas a la instalación del sistema BW, y necesitamos hacerlo de manera diferente si estamos utilizando una instalación local de TIBCO o una instalación base de TIBCO BW. Para ser honesto, las cosas que necesitamos hacer son las mismas; el proceso de hacerlo es diferente.

Porque, al final, lo que necesitamos hacer es solo una tarea simple. Incluir estos archivos JAR como parte del paquete OSGI actual de logback que carga TIBCO BW. Así que, veamos cómo podemos hacer eso y comenzar con una instalación local. Usaremos la versión TIBCO BWCE 2.8.2 como ejemplo, pero se requerirán pasos similares para otras versiones.

La instalación local es la forma más fácil de hacerlo, pero solo porque tiene menos pasos que cuando lo hacemos en una imagen base de TIBCO BWCE. Así que, en este caso, iremos a la siguiente ubicación: <TIBCO_HOME>/bwce/2.8/system/shared/com.tibco.tpcl.logback_1.2.1600.002/

  • Colocaremos los JARs descargados en esa carpeta
BW ECS Logging: Ubicación del JAR
  • Abriremos el META-INF/MANIFEST.MF y haremos las siguientes modificaciones:
    • Agregar esos JARs a la sección Bundle-Classpath:
BW ECS Logging: Cambios en Bundle-Classpath
  • Incluir el siguiente paquete (co.elastic.logging.logback) como parte de los paquetes exportados agregándolo a la sección Exported-package:
BW ECS Logging: Cambios en Export-Package

Una vez hecho esto, nuestra instalación de TIBCO BW soporta el formato ECS. y solo necesitamos configurar el logback.xml para usarlo, y podemos hacerlo confiando en la documentación oficial en la página de ECS. Necesitamos incluir el siguiente codificador, como se muestra a continuación:

 <encoder class="co.elastic.logging.logback.EcsEncoder">
    <serviceName>mi-aplicación</serviceName>
    <serviceVersion>mi-versión-de-aplicación</serviceVersion>
    <serviceEnvironment>mi-entorno-de-aplicación</serviceEnvironment>
    <serviceNodeName>mi-nodo-de-clúster-de-aplicación</serviceNodeName>
</encoder>

Por ejemplo, si modificamos el archivo de configuración predeterminado logback.xml con esta información, tendremos algo como esto:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
  
  <!-- *=============================================================* -->
  <!-- *  APPENDER: Console Appender                                 * -->
  <!-- *=============================================================* -->  
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="co.elastic.logging.logback.EcsEncoder">
      <serviceName>a</serviceName>
      <serviceVersion>b</serviceVersion>
      <serviceEnvironment>c</serviceEnvironment>
      <serviceNodeName>d</serviceNodeName>
  </encoder>
  </appender>



  <!-- *=============================================================* -->
  <!-- * LOGGER: Thor Framework loggers                              * -->
  <!-- *=============================================================* -->
  <logger name="com.tibco.thor.frwk">
    <level value="INFO"/>
  </logger>
  
  
  
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Framework loggers                     * -->
  <!-- *=============================================================* -->
  <logger name="com.tibco.bw.frwk">
    <level value="WARN"/>
  </logger>  
  
  <logger name="com.tibco.bw.frwk.engine">
    <level value="INFO"/>
  </logger>   
  
  
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Engine loggers                        * -->
  <!-- *=============================================================* --> 
  <logger name="com.tibco.bw.core">
    <level value="WARN"/>
  </logger>
  
  <logger name="com.tibco.bx">
    <level value="ERROR"/>
  </logger>

  <logger name="com.tibco.pvm">
    <level value="ERROR"/>
  </logger>
  
  <logger name="configuration.management.logger">
    <level value="INFO"/>
  </logger>
  
  
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Palette and Activity loggers          * -->
  <!-- *=============================================================* -->
  
  <!-- Default Log activity logger -->
  <logger name="com.tibco.bw.palette.generalactivities.Log">
    <level value="DEBUG"/>
  </logger>
  
  <logger name="com.tibco.bw.palette">
    <level value="ERROR"/>
  </logger>

  
  
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Binding loggers                       * -->
  <!-- *=============================================================* -->
  
  <!-- SOAP Binding logger -->
  <logger name="com.tibco.bw.binding.soap">
    <level value="ERROR"/>
  </logger>
  
  <!-- REST Binding logger -->
  <logger name="com.tibco.bw.binding.rest">
    <level value="ERROR"/>
  </logger>
  
  
  
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Shared Resource loggers               * -->
  <!-- *=============================================================* --> 
  <logger name="com.tibco.bw.sharedresource">
    <level value="ERROR"/>
  </logger>
  
  
   
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Schema Cache loggers                  * -->
  <!-- *=============================================================* -->
  <logger name="com.tibco.bw.cache.runtime.xsd">
    <level value="ERROR"/>
  </logger> 
  
  <logger name="com.tibco.bw.cache.runtime.wsdl">
    <level value="ERROR"/>
  </logger> 
  
    
  
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Governance loggers                    * -->
  <!-- *=============================================================* -->  
  <!-- Governance: Policy Director logger1 --> 
  <logger name="com.tibco.governance">
    <level value="ERROR"/>
  </logger>
   
  <logger name="com.tibco.amx.governance">
    <level value="WARN"/>
  </logger>
   
  <!-- Governance: Policy Director logger2 -->
  <logger name="com.tibco.governance.pa.action.runtime.PolicyProperties">
    <level value="ERROR"/>
  </logger>
  
  <!-- Governance: SPM logger1 -->
  <logger name="com.tibco.governance.spm">
    <level value="ERROR"/>
  </logger>
  
  <!-- Governance: SPM logger2 -->
  <logger name="rta.client">
    <level value="ERROR"/>
  </logger>
  
  
    
  <!-- *=============================================================* -->
  <!-- * LOGGER: BusinessWorks Miscellaneous Loggers                 * -->
  <!-- *=============================================================* --> 
  <logger name="com.tibco.bw.platformservices">
    <level value="INFO"/>
  </logger>
  
  <logger name="com.tibco.bw.core.runtime.statistics">
    <level value="ERROR"/>
  </logger>
  

  
  <!-- *=============================================================* -->
  <!-- * LOGGER: Other loggers                                       * -->
  <!-- *=============================================================* -->  
  <logger name="org.apache.axis2">
    <level value="ERROR"/>
  </logger>

  <logger name="org.eclipse">
    <level value="ERROR"/>
  </logger>
  
  <logger name="org.quartz">
    <level value="ERROR"/>
  </logger>
  
  <logger name="org.apache.commons.httpclient.util.IdleConnectionHandler">
    <level value="ERROR"/>
  </logger>
  
  
  
  <!-- *=============================================================* -->
  <!-- * LOGGER: User loggers.  User's custom loggers should be      * -->
  <!-- *         configured in this section.                         * -->
  <!-- *=============================================================* -->

  <!-- *=============================================================* -->
  <!-- * ROOT                                                        * -->
  <!-- *=============================================================* --> 
  <root level="ERROR">
   <appender-ref ref="STDOUT" />
  </root>
  
</configuration>

También puede hacer configuraciones más personalizadas basadas en la información disponible en la página de configuración del codificador ECS aquí.

¿Cómo habilitar el soporte de registro de TIBCO BW ECS?

Para BWCE, los pasos son similares, pero debemos tener en cuenta que todos los componentes de tiempo de ejecución están empaquetados dentro del base-runtime-version.zip que descargamos de nuestro sitio de eDelivery de TIBCO, por lo que necesitaremos usar una herramienta para abrir ese ZIP y hacer las siguientes modificaciones:

  • Colocaremos los JARs descargados en esa carpeta /tibco.home/bwce/2.8/system/shared/com.tibco.tpcl.logback_1.2.1600.004
BW ECS Logging: Ubicación del JAR
  • Abriremos el META-INF/MANIFEST.MF y haremos las siguientes modificaciones:
    • Agregar esos JARs a la sección Bundle-Classpath:
BW ECS Logging: Cambios en Bundle-Classpath
  • Incluir el siguiente paquete (co.elastic.logging.logback) como parte de los paquetes exportados agregándolo a la sección Exported-package:
BW ECS Logging: Cambios en Export-package
  • Además, necesitaremos modificar el bwappnode en la ubicación /tibco.home/bwce/2.8/bin para agregar los archivos JAR también al classpath que la imagen base de BWCE usa para ejecutar y asegurar que esto se esté cargando:
BW ECS Logging: cambio en bwappnode

Ahora podemos construir nuestra imagen base de BWCE como de costumbre y modificar el logback.xml como se explicó anteriormente. Aquí puede ver una aplicación de ejemplo utilizando esta configuración:

{"@timestamp":"2023-08-28T12:49:08.524Z","log.level": "INFO","message":"TIBCO BusinessWorks version 2.8.2, build V17, 2023-05-19","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"main","log.logger":"com.tibco.thor.frwk"}

<>@BWEclipseAppNode> {"@timestamp":"2023-08-28T12:49:25.435Z","log.level": "INFO","message":"Started by BusinessStudio.","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"main","log.logger":"com.tibco.thor.frwk.Deployer"}
{"@timestamp":"2023-08-28T12:49:32.795Z","log.level": "INFO","message":"TIBCO-BW-FRWK-300002: BW Engine [Main] started successfully.","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"main","log.logger":"com.tibco.bw.frwk.engine.BWEngine"}
{"@timestamp":"2023-08-28T12:49:34.338Z","log.level": "INFO","message":"TIBCO-THOR-FRWK-300001: Started OSGi Framework of AppNode [BWEclipseAppNode] in AppSpace [BWEclipseAppSpace] of Domain [BWEclipseDomain]","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"Framework Event Dispatcher: Equinox Container: 1395256a-27a2-4e91-b774-310e85b0b87c","log.logger":"com.tibco.thor.frwk.Deployer"}
{"@timestamp":"2023-08-28T12:49:34.456Z","log.level": "INFO","message":"TIBCO-THOR-FRWK-300018: Deploying BW Application [t3:1.0].","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"Framework Event Dispatcher: Equinox Container: 1395256a-27a2-4e91-b774-310e85b0b87c","log.logger":"com.tibco.thor.frwk.Application"}
{"@timestamp":"2023-08-28T12:49:34.524Z","log.level": "INFO","message":"TIBCO-THOR-FRWK-300021: All Application dependencies are resolved for Application [t3:1.0]","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"Framework Event Dispatcher: Equinox Container: 1395256a-27a2-4e91-b774-310e85b0b87c","log.logger":"com.tibco.thor.frwk.Application"}
{"@timestamp":"2023-08-28T12:49:34.541Z","log.level": "INFO","message":"Started by BusinessStudio, ignoring .enabled settings.","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"Framework Event Dispatcher: Equinox Container: 1395256a-27a2-4e91-b774-310e85b0b87c","log.logger":"com.tibco.thor.frwk.Application"}
{"@timestamp":"2023-08-28T12:49:35.842Z","log.level": "INFO","message":"TIBCO-THOR-FRWK-300006: Started BW Application [t3:1.0]","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"EventAdminThread #1","log.logger":"com.tibco.thor.frwk.Application"}
{"@timestamp":"2023-08-28T12:49:35.954Z","log.level": "INFO","message":"aaaaaaa
","ecs.version": "1.2.0","service.name":"a","service.version":"b","service.environment":"c","service.node.name":"d","event.dataset":"a","process.thread.name":"bwEngThread:In-Memory Process Worker-1","log.logger":"com.tibco.bw.palette.generalactivities.Log.t3.module.Log"}
gosh: stopping shell

Aumentar los registros HTTP en TIBCO BusinessWorks en 5 minutos

Aumentar los registros HTTP en TIBCO BusinessWorks en 5 minutos

Aumentar los registros HTTP en TIBCO BusinessWorks cuando estás depurando o solucionando problemas en una integración basada en HTTP que podría estar relacionada con un servicio REST o SOAP es una de las cosas más utilizadas y útiles que puedes hacer al desarrollar con TIBCO BusinessWorks.

El propósito principal de aumentar los registros HTTP es obtener un conocimiento completo sobre qué información estás enviando y qué comunicación estás recibiendo de tu comunicador asociado para ayudar a entender un error o comportamiento inesperado.

¿Cuáles son los casos de uso principales para aumentar los registros HTTP?

Al final, todos los diferentes casos de uso son variaciones del caso de uso principal: “Obtener conocimiento completo sobre la comunicación de intercambio HTTP entre ambas partes.” Aún así, algunos más detallados se pueden listar a continuación:

  • Entender por qué un servidor backend está rechazando una llamada que podría estar relacionada con Autenticación o Autorización, y necesitas ver la respuesta detallada del servidor backend.
  • Verificar el valor de cada Encabezado HTTP que estás enviando y que podría afectar la compresión de la comunicación o el tipo de contenido aceptado.
  • Ver por qué estás rechazando una llamada de un consumidor

Dividiendo la comunicación según la fuente

Lo más importante a entender es que los registros usualmente dependen de la biblioteca que estás usando, y no es la misma biblioteca utilizada para exponer un servidor basado en HTTP que la biblioteca que usas para consumir un servicio basado en HTTP como REST o un servicio SOAP.

Comenzando por lo que expones, esto es lo más fácil porque esto será definido por los recursos del Conector HTTP que estás usando, como puedes ver en la imagen a continuación:

Conector de Recursos Compartidos HTTP en BW

Todos los Recursos del Conector HTTP que puedes usar para exponer servicios REST y SOAP están basados en la implementación del Servicio Jetty, y eso significa que los registradores que necesitas cambiar su configuración están relacionados con el servidor Jetty en sí.

Más complejos, en teoría, son los relacionados con la comunicación del cliente cuando nuestra aplicación TIBCO BusinessWorks consume un servicio basado en HTTP proporcionado por un backend porque cada una de estas comunicaciones tiene sus propios Recursos Compartidos del Cliente HTTP. La configuración de cada uno de ellos será diferente porque una de las configuraciones que podemos obtener aquí es la Biblioteca de Implementación, y eso tendrá un efecto directo en la forma de cambiar la configuración del registro:

Recurso del Cliente HTTP en BW que muestra las diferentes bibliotecas de implementación para detectar el registrador para Aumentar los Registros HTTP en TIBCO BusinessWorks

Tienes tres opciones cuando defines un Recurso del Cliente HTTP, como puedes ver en la imagen anterior:

  • Apache HttpComponents: El predeterminado que soporta servicios HTTP1, SOAP y REST.
  • Cliente HTTP Jetty: Este cliente solo soporta flujos HTTP como HTTP1 y HTTP2, y sería la opción principal cuando estás trabajando con flujos HTTP2.
  • Apache Commons: Similar al primero, pero actualmente está obsoleto, y para ser honesto, si tienes algún componente cliente usando esta configuración, deberías cambiarlo cuando puedas a Apache HttpComponents.

Entonces, si estamos consumiendo un servicio SOAP y REST, está claro que estaremos usando la biblioteca de implementación Apache HttpComponents, y eso nos dará el registrador que necesitamos usar.

Porque para Apache HttpComponents, podemos confiar en el siguiente registrador: “org.apache.http” y en caso de que queramos extender el lado del servidor, o estemos usando el cliente HTTP Jetty, podemos usar este: “org.eclipse.jetty.http”

Debemos ser conscientes de que no podemos extenderlo solo para un único recurso de Cliente HTTP porque la configuración se basará en la Biblioteca de Implementación, así que en caso de que establezcamos el nivel DEBUG para la biblioteca Apache HttpComponents, afectará a todos los Recursos Compartidos que usen esta Biblioteca de Implementación, y necesitarás diferenciar basado en los datos dentro del registro, por lo que eso será parte de tu análisis de datos.

¿Cómo configurar los Registros HTTP en TIBCO BusinessWorks?

Ahora que tenemos los registradores, debemos configurarlo a un nivel DEBUG (o TRACE). Necesitamos saber cómo hacerlo, y tenemos varias opciones dependiendo de cómo nos gustaría hacerlo y qué acceso tenemos. El alcance de este artículo es TIBCO BusinessWorks Container Edition, pero puedes extrapolar fácilmente parte de este conocimiento a una instalación de TIBCO BusinessWorks en las instalaciones.

TIBCO BusinessWorks (contenedor o no) se basa en sus capacidades de registro en la biblioteca log back, y esta biblioteca se configura usando un archivo llamado logback.xml que podría tener la configuración que necesitas, como puedes ver en la imagen a continuación:

configuración de logback.xml con la estructura predeterminada en TIBCO BW

Entonces, si queremos agregar una nueva configuración de registro, necesitamos agregar un nuevo elemento logger al archivo con la siguiente estructura:

  <logger name="%LOGGER_QUE_QUEREMOS_VER">
    <level value="%NIVEL_QUE_QUEREMOS_VER%"/>
  </logger>    

Entonces, el registrador fue preciso basado en la sección anterior, y el nivel dependerá de cuánta información quieras ver. Los niveles de registro son los siguientes: ERROR, WARN, INFO, DEBUG, TRACE. DEBUG y TRACE son los que muestran más información.

En nuestro caso, DEBUG debería ser suficiente para obtener la Solicitud HTTP completa y la Respuesta HTTP, pero también puedes aplicarlo a otras cosas donde podrías necesitar un nivel de registro diferente.

Ahora necesitas agregar eso al archivo logback.xml, y para hacerlo, tienes varias opciones, como se comentó:

  • Puedes encontrar el logback.xml dentro del contenedor BWCE (o la carpeta de configuración de AppNode) y modificar su contenido. La ubicación predeterminada de este archivo es esta: /tmp/tibco.home/bwce/<VERSION>/config/logback.xml Para hacer esto, necesitarás tener acceso para hacer un kubectl exec en el contenedor bwce, y si haces el cambio, el cambio será temporal y se perderá en el próximo reinicio. Eso podría ser algo bueno o malo, dependiendo de tu objetivo.
  • Si quieres que sea permanente o no tienes acceso al contenedor, tienes dos opciones. La primera es incluir una copia personalizada del logback.xml en la carpeta /resources/custom-logback/ en la imagen base de BWCE y establecer la variable de entorno CUSTOM_LOGBACK a valor TRUE, y eso sobrescribirá la configuración predeterminada de logback.xml con el contenido de este archivo. Como se comentó, esto será “permanente” y se aplicará desde el primer despliegue de la aplicación con esta configuración. Puedes encontrar más información en la documentación oficial aquí.
  • También hay una adicional desde BWCE 2.7.0 y superior que te permite cambiar el contenido de logback.xml sin una nueva copia o cambiar la imagen base, y eso se basa en el uso de la propiedad de entorno BW_LOGGER_OVERRIDES con el contenido de la siguiente manera (logger=value) así que en nuestro caso sería algo como esto org.apache.http=DEBUG y en el próximo despliegue obtendrás esta configuración. Similar a la anterior, esto será permanente pero no requiere agregar un archivo a la imagen base para ser alcanzable.

Entonces, como puedes ver, tienes diferentes opciones dependiendo de tus necesidades y niveles de acceso.

Conclusión

En conclusión, mejorar los registros HTTP dentro de TIBCO BusinessWorks durante la depuración y solución de problemas es una estrategia vital. Elevar los niveles de registro proporciona una comprensión completa del intercambio de información, ayudando en el análisis de errores y comportamientos inesperados. Ya sea discerniendo las causas de rechazo del backend, examinando los efectos de los encabezados HTTP, o aislando rechazos de llamadas de consumidores, los registros amplificados iluminan escenarios de integración complejos. Las adaptaciones varían según el uso de la biblioteca, abarcando la exposición del servidor y el consumo de servicios. La configuración a través de la biblioteca logback implica ajustes personalizados de registrador y nivel. Esta práctica empodera a los desarrolladores para desentrañar las complejidades de la integración de manera eficiente, asegurando interacciones robustas y fluidas basadas en HTTP a través de sistemas.

Operador de Registro de BanzaiCloud en Kubernetes Simplificado en 5 minutos

Operador de Registro de BanzaiCloud en Kubernetes Simplificado en 5 minutos

En el artículo anterior, describimos qué capacidad proporciona BanzaiCloud Logging Operator y sus características principales. Así que hoy vamos a ver cómo podemos implementarlo.

Lo primero que necesitamos hacer es instalar el operador en sí, y para hacerlo, tenemos un chart de helm a nuestra disposición, así que lo único que necesitaremos hacer son los siguientes comandos:

 helm repo add banzaicloud-stable https://kubernetes-charts.banzaicloud.com
helm upgrade --install --wait --create-namespace --namespace logging logging-operator banzaicloud-stable/logging-operator

Eso creará un namespace de logging (en caso de que aún no lo tengas), y desplegará los componentes del operador en sí, como puedes ver en la imagen a continuación:

Operador de Registro de BanzaiCloud en Kubernetes Simplificado en 5 minutos
BanzaiCloud Logging Operator instalado usando HelmChart

Así que, ahora podemos empezar a crear los recursos que necesitamos usando el CRD que comentamos en el artículo anterior, pero para hacer un resumen. Estos son los que tenemos a nuestra disposición:

  • logging – El recurso de logging define la infraestructura de logging para tu clúster que recoge y transporta tus mensajes de log. También contiene configuraciones para Fluentd y Fluent-bit.
  • output / clusteroutput – Define una Salida para un flujo de logging, donde se envían los mensajes de log. output será basado en namespace, y clusteroutput será basado en clúster.
  • flow / clusterflow – Define un flujo de logging usando filtros y salidas. El flujo dirige los mensajes de log seleccionados a las salidas especificadas. flow será basado en namespace, y clusterflows serán basados en clúster.

Así que, primero que nada, vamos a definir nuestro escenario. No quiero hacer algo complejo; deseo que todos los logs que mis cargas de trabajo generen, sin importar en qué namespace estén, sean enviados a una instancia de Grafana Loki que también he instalado en ese clúster de Kubernetes en un endpoint específico usando la configuración Simple Scalable para Grafana Loki.

Así que, comencemos con los componentes que necesitamos. Primero, necesitamos un objeto de Logging para definir mi infraestructura de Logging, y lo crearé con el siguiente comando.

kubectl -n logging apply -f - <<"EOF"
apiVersion: logging.banzaicloud.io/v1beta1
kind: Logging
metadata:
  name: default-logging-simple
spec:
  fluentd: {}
  fluentbit: {}
  controlNamespace: logging
EOF

Mantendremos la configuración predeterminada para fluentd y fluent-bit solo por el bien del ejemplo, y más adelante en próximos artículos, podemos hablar sobre un diseño específico, pero eso es todo.

Una vez que el CRD se procese, los componentes aparecerán en tu namespace de logging. En mi caso, que estoy usando un clúster de 3 nodos, veré 3 instancias de fluent-bit desplegadas como un DaemonSet y un solo ejemplo de fluentd, como puedes ver en la imagen a continuación:

Operador de Registro de BanzaiCloud en Kubernetes Simplificado en 5 minutos
Configuración de BanzaiCloud Logging Operator después de aplicar el CRD de Logging

Así que, ahora necesitamos definir la comunicación con Loki, y como me gustaría usar esto para cualquier namespace que pueda tener en mi clúster, usaré la opción ClusterOutput en lugar de la normal Output que está basada en namespace. Y para hacer eso, usaremos el siguiente comando (por favor asegúrate de que el endpoint sea el correcto; en nuestro caso, este es loki-gateway.default ya que está ejecutándose dentro del clúster de Kubernetes:

kubectl -n logging apply -f - <<"EOF"
apiVersion: logging.banzaicloud.io/v1beta1
kind: ClusterOutput
metadata:
 name: loki-output
spec:
 loki:
   url: http://loki-gateway.default
   configure_kubernetes_labels: true
   buffer:
     timekey: 1m
     timekey_wait: 30s
     timekey_use_utc: true
EOF

Y prácticamente tenemos todo; solo necesitamos un flujo para comunicar nuestra configuración de Logging al ClusterOutput que acabamos de crear. Y nuevamente, iremos con el ClusterFlow porque nos gustaría definir esto a nivel de Clúster y no de manera basada en namespace. Así que usaremos el siguiente comando:

 kubectl -n logging  apply -f - <<"EOF"
apiVersion: logging.banzaicloud.io/v1beta1
kind: ClusterFlow
metadata:
  name: loki-flow
spec:
  filters:
    - tag_normaliser: {}
  match:
    - select: {}
  globalOutputRefs:
    - loki-output
EOF

Y después de un tiempo para recargar la configuración (1-2 minutos más o menos), comenzarás a ver en los rastros de Loki algo como esto:

Operador de Registro de BanzaiCloud en Kubernetes Simplificado en 5 minutos
Grafana mostrando los logs enviados por el BanzaiCloud Logging Operator

Y eso indica que ya estamos recibiendo el envío de logs de los diferentes componentes, principalmente el elemento fluentd que configuramos en este caso. Pero creo que es mejor verlo gráficamente con Grafana:

Operador de Registro de BanzaiCloud en Kubernetes Simplificado en 5 minutos
Grafana mostrando los logs enviados por el BanzaiCloud Logging Operator

¡Y eso es todo! Y cambiar nuestra configuración de logging es tan simple como cambiar el componente CRD que definimos, aplicando coincidencias y filtros, o enviándolo a un nuevo lugar. De manera sencilla, tenemos esto completamente gestionado.

📚 Want to dive deeper into Kubernetes? This article is part of our comprehensive Kubernetes Architecture Patterns guide, where you’ll find all fundamental and advanced concepts explained step by step.

Potencia la agregación de registros en Kubernetes con BanzaiCloud Logging Operator

Potencia la agregación de registros en Kubernetes con BanzaiCloud Logging Operator
Potenciar la Agregación de Logs en Kubernetes con BanzaiCloud Logging Operator
Potenciar la Agregación de Logs en Kubernetes con BanzaiCloud Logging Operator (Foto por Markus Spiske en Unsplash)

Ya hemos hablado sobre la importancia de la Agregación de Logs en Kubernetes y por qué el cambio en el comportamiento de los componentes lo convierte en un requisito obligatorio para cualquier nueva arquitectura que implementemos hoy.

Para resolver esa parte, tenemos muchas pilas diferentes de las que probablemente hayas oído hablar. Por ejemplo, si seguimos el camino tradicional de Elasticsearch, tendremos la pila ELK pura de Elasticsearch, Logstash y Kibana. Ahora esta pila se ha ampliado con los diferentes «Beats» (FileBeat, NetworkBeat, …) que proporcionan un reenviador de logs ligero para ser añadido a la tarea.

Además, puedes cambiar Logstash por un componente de CNCF como Fluentd del que probablemente hayas oído hablar, y en ese caso, estamos hablando de una pila EFK siguiendo el mismo principio. Y también, tener la vista de Grafana Labs usando promtail, Grafana Loki, y Grafana para paneles de control siguiendo una perspectiva diferente.

Luego puedes cambiar y modificar cualquier componente por el de tu preferencia, pero al final, tendrás tres tipos diferentes de componentes:

  • Reenviador: Componente que escuchará todas las entradas de logs, principalmente la salida stdout/stderr de tus contenedores, y lo enviará a un componente central.
  • Agregador: Componente que recibirá todos los rastros del reenviador, y tendrá algunas reglas para filtrar algunos de los eventos, formatear y enriquecer los recibidos antes de enviarlos al almacenamiento central.
  • Almacenamiento: Componente que recibirá los rastros finales para ser almacenados y recuperados por los diferentes clientes.

Para simplificar la gestión de eso en Kubernetes, tenemos un gran Operador de Kubernetes llamado BanzaiCloud Logging Operator que intenta seguir ese enfoque de manera declarativa / política. Así que veamos cómo funciona, y para explicarlo mejor, usaré su diagrama central de su sitio web:

Potencia la agregación de registros en Kubernetes con BanzaiCloud Logging Operator
Arquitectura de BanzaiCloud Logging Operator

Este operador utiliza las mismas tecnologías de las que estábamos hablando. Cubre principalmente los dos primeros pasos: Reenvío y Agregación y la configuración para ser enviada a un Almacenamiento Central de tu elección. Para hacer eso, trabaja con las siguientes tecnologías, todas ellas parte del Paisaje CNCF:

  • Fluent-bit actuará como un reenviador desplegado en modo DaemonSet para recopilar todos los logs que hayas configurado.
  • Fluentd actuará como un agregador definiendo los flujos y reglas de tu elección para adaptar el flujo de rastros que estás recibiendo y enviando a la salida de tu elección.

Y como este es un Operador de Kubernetes, esto funciona de manera declarativa. Definiremos un conjunto de objetos que definirán nuestras políticas de registro. Tenemos los siguientes componentes:

  • logging – El recurso de logging define la infraestructura de registro para tu clúster que recopila y transporta tus mensajes de log. También contiene configuraciones para Fluentd y Fluent-bit.
  • output / clusteroutput – Define una Salida para un flujo de registro, donde se envían los mensajes de log. output será basado en el espacio de nombres, y clusteroutput será basado en el clúster.
  • flow / clusterflow – Define un flujo de registro usando filtros y salidas. El flujo dirige los mensajes de log seleccionados a las salidas especificadas. flow será basado en el espacio de nombres, y clusterflows será basado en el clúster.

En la imagen a continuación, verás cómo estos objetos están «interactuando» para definir tu arquitectura de registro deseada:

Potencia la agregación de registros en Kubernetes con BanzaiCloud Logging Operator
Relación CRD de BanzaiCloud Logging Operator

Y aparte del modo de política, también incluye muchas características geniales como:

  • Aislamiento de espacio de nombres
  • Selectores de etiquetas nativos de Kubernetes
  • Comunicación segura (TLS)
  • Validación de configuración
  • Soporte para múltiples flujos (multiplicar logs para diferentes transformaciones)
  • Soporte para múltiples salidas (almacenar los mismos logs en múltiples almacenamientos: S3, GCS, ES, Loki, y más…)
  • Soporte para múltiples sistemas de registro (múltiples despliegues de Fluentd, Fluent Bit en el mismo clúster)

En próximos artículos hablaremos sobre cómo podemos implementar esto para que puedas ver todos los beneficios que este enfoque basado en CRD y políticas puede proporcionar a tu arquitectura.

📚 Want to dive deeper into Kubernetes? This article is part of our comprehensive Kubernetes Architecture Patterns guide, where you’ll find all fundamental and advanced concepts explained step by step.

Grafana Loki y MinIO: ¡Una combinación perfecta!

Grafana Loki y MinIO: ¡Una combinación perfecta!

Grafana Loki se está convirtiendo en uno de los estándares de facto para la agregación de logs en cargas de trabajo de Kubernetes hoy en día, y hoy vamos a mostrar cómo podemos usar juntos Grafana Loki y MinIO. Ya hemos cubierto en varias ocasiones las capacidades de Grafana Loki que han surgido como la principal alternativa al liderazgo de Elasticsearch en los últimos 5-10 años para la agregación de logs.

Con un enfoque diferente, más ligero, más nativo de la nube, más enfocado en las cosas buenas que Prometheus ha proporcionado pero para logs y con el patrocinio de una gran empresa como Grafana Labs con las herramientas de paneles como líder de un stack de herramientas cada día más enorme en el mundo de la observabilidad.

Y también, ya hemos cubierto MinIO como un almacén de objetos que se puede implementar en cualquier lugar. Es como tener tu servicio S3 en cualquier nube que te guste o en las instalaciones. Así que hoy, vamos a ver cómo ambos pueden trabajar juntos.

Grafana Loki principalmente admite tres modelos de despliegue: monolítico, simple-escalable y distribuido. Prácticamente todo excepto el monolítico tiene el requisito de tener una solución de Almacenamiento de Objetos para poder trabajar en un modo escalable distribuido. Entonces, si tienes tu implementación en AWS, ya estás cubierto con S3. Además, Grafana Loki admite la mayoría de las soluciones de Almacenamiento de Objetos para el ecosistema en la nube de los principales proveedores. Aún así, el problema surge cuando deseas confiar en Grafana Loki para una instalación en la nube privada o en las instalaciones.

En ese caso, es donde podemos confiar en MinIO. Para ser honesto, puedes usar MinIO también en el mundo de la nube para tener una solución más flexible y transparente y evitar cualquier dependencia con un proveedor de nube. Aún así, para las instalaciones, su uso se ha vuelto obligatorio. Una de las grandes características de MinIO es que implementa la API de S3, por lo que prácticamente cualquier cosa que admita S3 funcionará con MinIO.

En este caso, solo necesito adaptar algunos valores en el gráfico de helm de Loki en el modo simple-distribuido como se muestra a continuación:

 loki:
  storage:
    s3:
      s3: null
      endpoint: http://minio.minio:9000
      region: null
      secretAccessKey: XXXXXXXXXXX
      accessKeyId: XXXXXXXXXX
      s3ForcePathStyle: true
      insecure: true

Simplemente estamos apuntando al endpoint de nuestro inquilino de MinIO, en nuestro caso, también implementado en Kubernetes en el puerto 9000. También estamos proporcionando las credenciales para conectar y finalmente mostrando que necesita s3ForcePathSyle: true es necesario para que el endpoint se transforme a minio.minio:9000/bucket en lugar de bucket.minio.minio:9000, por lo que funcionará mejor en un ecosistema de Kubernetes.

Y eso es prácticamente todo; tan pronto como lo inicies, comenzarás a ver que los buckets comienzan a poblarse como lo harían en caso de que estuvieras usando S3, como puedes ver en la imagen a continuación:

MinIO mostrando buckets y objetos de la configuración de Loki
MinIO mostrando buckets y objetos de la configuración de Loki

Ya cubrimos los modelos de implementación de MinIO. Como se muestra aquí, puedes usar su gráfico de helm o el operador de MinIO. Pero, la integración con Loki es aún mejor porque los gráficos de helm de Loki ya incluyen MinIO como un sub-gráfico para que puedas implementar MinIO como parte de tu implementación de Loki basado en la configuración que encontrarás en el values.yml como se muestra a continuación:

 # -------------------------------------
# Configuración para el gráfico hijo `minio`
# -------------------------------------
minio:
  enabled: false
  accessKey: enterprise-logs
  secretKey: supersecret
  buckets:
    - name: chunks
      policy: none
      purge: false
    - name: ruler
      policy: none
      purge: false
    - name: admin
      policy: none
      purge: false
  persistence:
    size: 5Gi
  resources:
    requests:
      cpu: 100m
      memory: 128Mi

¡Así que con un solo comando, puedes tener ambas plataformas implementadas y configuradas automáticamente! Espero que esto sea tan útil para ti como lo fue para mí cuando descubrí e hice este proceso.

📚 Want to dive deeper into Kubernetes? This article is part of our comprehensive Kubernetes Architecture Patterns guide, where you’ll find all fundamental and advanced concepts explained step by step.

Tres razones por las que necesitas una arquitectura de agregación de registros hoy

Tres razones por las que necesitas una arquitectura de agregación de registros hoy

La agregación de registros ya no es una mercancía, sino un componente crítico en plataformas basadas en contenedores

La gestión de registros no parece un tema muy fantástico. No es el tema que ves y dices: “¡Oh! ¡Increíble! Esto es con lo que he soñado toda mi vida”. No, soy consciente de que esto no es muy atractivo, pero eso no lo hace menos crítico que otras capacidades que tu arquitectura necesita tener.

Desde el principio de los tiempos, hemos usado archivos de registro como la única fuente de datos confiable cuando se trataba de solucionar problemas de tus aplicaciones o saber qué falló en tu implementación o cualquier otra acción relacionada con una computadora.

El procedimiento era fácil:

  • Lanzar “algo”
  • “Algo” falló.
  • Revisar los registros
  • Cambiar algo
  • Repetir

Y lo hemos estado haciendo de esa manera durante mucho, mucho tiempo. Incluso con otros enfoques más robustos de manejo y gestión de errores como el Sistema de Auditoría, también volvemos a los registros cuando necesitamos obtener el detalle minucioso sobre el error. Buscar una traza de pila allí, más detalle sobre el error que se insertó en el Sistema de Auditoría o más datos que solo el código de error y la descripción que proporcionó una API REST.

Los sistemas comenzaron a crecer, la arquitectura se volvió más complicada, pero incluso con eso, terminamos con el mismo método una y otra vez. Estás al tanto de arquitecturas de agregación de registros como la pila ELK o soluciones comerciales como Splunk o incluso ofertas SaaS como Loggly, pero simplemente piensas que no son para ti.

Son caras de comprar o caras de configurar, y conoces muy bien tu ecosistema, y es más fácil simplemente entrar en una máquina y seguir el archivo de registro. Probablemente también tengas tu caja de herramientas de scripts para hacer esto tan rápido como cualquiera puede abrir Kibana e intentar buscar algo como el ID de instancia allí para ver el error de una transacción específica.

Ok, necesito decirte algo: Es hora de cambiar, y te voy a explicar por qué.

Las cosas están cambiando, y TI y todos los nuevos paradigmas se basan en algunos fundamentos comunes:

  • Vas a tener más componentes que van a funcionar aislados con sus archivos de registro y datos.
  • Las implementaciones serán más regulares en tu entorno de producción, y eso significa que las cosas van a estar mal más a menudo (de una manera controlada, pero más a menudo)
  • Las tecnologías van a coexistir, por lo que los registros van a ser muy diferentes en términos de patrones y diseños, y necesitas estar preparado para eso.

Así que, discutamos estos tres argumentos que espero te hagan pensar de una manera diferente sobre las arquitecturas y enfoques de Gestión de Registros.

1.- Tu enfoque simplemente no escalable

Tu enfoque es excelente para sistemas tradicionales. ¿Cuántas máquinas gestionas? ¿30? ¿50? ¿100? Y puedes hacerlo bastante bien. Imagina ahora una plataforma basada en contenedores para una empresa típica. Creo que un número promedio podría ser alrededor de 1000 contenedores solo para propósitos comerciales, sin hablar de arquitectura o servicios básicos. ¿Eres capaz de estar listo para ir contenedor por contenedor para verificar 1000 flujos de registros para conocer el error?

Incluso si eso es posible, ¿vas a ser el cuello de botella para el crecimiento de tu empresa? ¿Cuántos registros de contenedores puedes seguir? ¿2000? Como decía al principio, eso simplemente no es escalable.

2.- Los registros no están allí para siempre

Y ahora, lees el primer tema y probablemente solo estás diciendo a la pantalla que estás usando para leer esto. ¡Vamos! Ya sé que los registros no están allí, se están rotando, se pierden, y así sucesivamente.

Sí, eso es cierto, esto es aún más importante en el enfoque nativo de la nube. Con plataformas basadas en contenedores, los registros son efímeros, y además, si seguimos el manifiesto de la aplicación de 12 factores, no hay archivo con el registro. Todas las trazas de registro deben imprimirse en la salida estándar, y eso es todo.

¿Y dónde se eliminan los registros? Cuando el contenedor falla… ¿y cuáles son los registros que más necesitas? Los que han fallado.

Así que, si no haces nada, las trazas de registro que más necesitas son las que vas a perder.

3.- Necesitas poder predecir cuándo las cosas van a fallar

Pero los registros no solo son válidos cuando algo sale mal, son adecuados para detectar cuándo algo va a estar mal, sino para predecir cuándo las cosas van a fallar. Y necesitas poder agregar esos datos para poder generar información y conocimientos a partir de ellos. Para poder ejecutar modelos de ML para detectar si algo va como se espera o si algo diferente está sucediendo que podría llevar a algún problema antes de que ocurra.

Resumen

Espero que estos argumentos te hayan hecho pensar que incluso para tu empresa de pequeño tamaño o incluso para tu sistema, necesitas poder configurar una técnica de Agregación de Registros ahora y no esperar a otro momento cuando probablemente sea demasiado tarde.