¿Cómo conocer las publicaciones más grandes en Medium para compartir tus artículos?

¿Cómo conocer las publicaciones más grandes en Medium para compartir tus artículos?

Sigue estos consejos para seleccionar la publicación adecuada para tu artículo y asegurarte de garantizar el mejor impacto.

Cuando estamos escribiendo un artículo en Medium y nos gustaría compartirlo con nuestra audiencia, todos sabemos que usar una Publicación es la mejor manera de hacerlo. Una Publicación es como un sitio de medios o una revista tradicional que aloja artículos sobre un tema y los comparte con sus suscriptores. Cuanto más grande sea la publicación, más personas serán notificadas de que tu artículo está disponible, y mejor será la oportunidad de que tus artículos se muestren en la página de inicio de los usuarios de Medium. Así que seleccionar la publicación adecuada es crucial en este proceso.

Encuentra los seguidores de cualquier publicación.

Lo primero que necesitamos hacer para conocer el número de seguidores de cada publicación es seleccionar la publicación que nos gustaría verificar. Por ejemplo, voy a usar una de las principales, que es The Innovation. Si vas a su página principal: https://medium.com/the-innovation

No verás el número de seguidores directamente en su barra de menú como se muestra en la imagen a continuación:

¿Cómo conocer las publicaciones más grandes en Medium para compartir tus artículos?
Página principal de la publicación The Innovation en Medium

Algunas otras publicaciones pueden mostrar su número de seguidores en el menú de la barra superior, pero esto no sucede para todas las publicaciones. Pero aún tienes la opción de conocer el número de seguidores de cada publicación haciendo este pequeño truco. Si tienes la URL principal de una publicación, si agregas /latest a esa URL, estarás en una página que siempre muestra el mismo diseño para todas las publicaciones, y como parte de ese diseño, encontrarás en la barra lateral derecha el número de seguidores:

¿Cómo conocer las publicaciones más grandes en Medium para compartir tus artículos?
La página más reciente de la publicación The Innovation mostrando el número de seguidores

Así que, ahora puedes verificar el número de seguidores de cada publicación disponible en Medium, y también te ayudará a saber cuánto tiempo ha pasado desde que se publicó su última entrada. Si la publicación no está publicando nada nuevo, tu historia nunca llegará a todos los seguidores que tiene, así que también verifica la fecha de la última entrada disponible en la misma página.

Encuentra las publicaciones más grandes de hoy.

Ahora sabemos cómo conocer el número de seguidores de cada publicación, pero eso requiere verificar publicación por publicación para obtener ese número, y esto es tedioso. Pero aún peor, necesitamos conocer la publicación que nos gustaría verificar, y no creo que nadie en el espacio de Medium conozca todas las publicaciones para asegurarse de haber verificado todas las relevantes. Entonces, ¿cómo podemos hacer eso más rápido y mejor? Fácil. Aquí está el truco mágico que estabas esperando.

Simplemente ve a esta URL: https://medium.com/search/publications?q=*. Esta URL va a enviar todas las publicaciones (* actúa como un comodín que dice «todo»), por lo que se mostrarán todas las publicaciones, y se ordenarán según el número de editores, como puedes ver aquí:

¿Cómo conocer las publicaciones más grandes en Medium para compartir tus artículos?
Resultados de búsqueda de publicaciones ordenados por Seguidores

Para mostrar el número de seguidores, tomo los primeros 20 y hago el truco del primer paso para obtener la siguiente tabla:

¿Cómo conocer las publicaciones más grandes en Medium para compartir tus artículos?
Las 14 principales publicaciones en Medium ordenadas por el número de seguidores que tienen

Encuentra la adecuada para ti

Ahora que tenemos todos los datos en nuestras manos, solo necesitamos seleccionar la adecuada para el artículo que nos gustaría enviar, basado en el tema que estamos cubriendo y la perspectiva y estilo que usamos para generar nuestra historia. Es muy recomendable mirar las pautas del creador que tiene cada publicación para adaptar el contenido a lo que se espera de la audiencia de la publicación. De esa manera, maximizamos nuestro éxito con la audiencia.

Principios SOA que sobrevivieron en la arquitectura nativa de la nube

Principios SOA que sobrevivieron en la arquitectura nativa de la nube

El mundo del desarrollo ha cambiado mucho, pero eso no significa que todas las cosas no sean válidas. Aprende qué principios debes tener en cuenta.

El mundo cambia rápido, y en TI, cambia aún más rápido. Todos sabemos eso, lo que generalmente significa que necesitamos enfrentar nuevos desafíos y encontrar nuevas soluciones. Ejemplos de ese enfoque son las tendencias que hemos visto en los últimos años: Contenedores, DevSecOps, Microservicios, GitOps, Service Mesh…

Pero al mismo tiempo, sabemos que TI es un ciclo en términos de que los desafíos que enfrentamos hoy son diferentes evoluciones de desafíos que se han abordado en el pasado. El objetivo principal es evitar reinventar la rueda y evitar cometer los mismos errores que las personas antes que nosotros.

Por lo tanto, creo que vale la pena revisar los principios que las Arquitecturas Orientadas a Servicios (SOA) nos proporcionaron en las últimas décadas y ver cuáles son relevantes hoy en día.

Definición de Principios

Utilizaré los principios del libro de Thomas Erl SOA Principles of Service Design y las definiciones que podemos encontrar en el artículo de Wikipedia:

1.- Abstracción de Servicio

Principio de diseño que se aplica dentro del paradigma de diseño orientado a servicios para que la información publicada en un contrato de servicio se limite a lo que se requiere para utilizar efectivamente el servicio.

El objetivo principal detrás de estos principios es que un consumidor de servicios no debe ser consciente del componente particular. La principal ventaja de ese enfoque es que necesitamos cambiar el proveedor de servicios actual. Podemos hacerlo sin afectar a esos consumidores. Esto sigue siendo totalmente relevante hoy en día por diferentes razones:

  • Comunicación de servicio a servicio: Los Service Meshes y proyectos similares proporcionan capacidades de registro y descubrimiento de servicios basadas en los mismos principios para evitar conocer el pod que proporciona la funcionalidad.
  • Modo de protección SaaS habilitado: Algunos sistemas backend todavía están aquí para quedarse, incluso si tienen formas más modernas de configurarse como plataformas SaaS. Esa flexibilidad también proporciona una manera más fácil de alejarse o cambiar la aplicación SaaS que proporciona la funcionalidad. Pero toda esa flexibilidad no es real si tienes esa aplicación SaaS totalmente acoplada con el resto de los microservicios y la aplicación nativa de la nube en tu espacio.

2.- Autonomía del Servicio

Principio de diseño que se aplica dentro del paradigma de diseño orientado a servicios, para proporcionar servicios con mayor independencia de sus entornos de ejecución.

Todos conocemos la importancia del aislamiento de servicios que los patrones de desarrollo nativos de la nube proporcionan basados en las capacidades de los contenedores para proporcionar independencia entre entornos de ejecución.

Cada servicio debe tener su propio contexto de ejecución aislado tanto como sea posible del contexto de ejecución de los otros servicios para evitar cualquier interferencia entre ellos.

Por lo tanto, eso sigue siendo relevante hoy en día, pero alentado por los paradigmas actuales como la nueva forma normal de hacer las cosas debido a los beneficios mostrados.

3.- Ausencia de Estado del Servicio

Principio de diseño que se aplica dentro del paradigma de diseño orientado a servicios, para diseñar servicios escalables separándolos de sus datos de estado siempre que sea posible.

Los microservicios sin estado no mantienen su propio estado dentro de los servicios a través de las llamadas. Los servicios reciben una solicitud, la manejan y responden al cliente que solicita esa información. Si es necesario almacenar alguna información de estado, esto debe hacerse externamente a los microservicios utilizando un almacén de datos externo como una base de datos relacional, una base de datos NoSQL o cualquier otra forma de almacenar información fuera del microservicio.

4.- Composibilidad del Servicio

Diseño de servicios que pueden ser reutilizados en múltiples soluciones que están compuestas por servicios compuestos. La capacidad de recomponer el servicio es idealmente independiente del tamaño y la complejidad de la composición del servicio.

Todos sabemos que la reutilización no es uno de los principios detrás de los microservicios porque argumentan que la reutilización va en contra de la agilidad; cuando tenemos un servicio compartido entre muchas partes, no tenemos una manera fácil de evolucionarlo.

Pero esto se trata más de aprovechar los servicios existentes para crear nuevos que son el mismo enfoque que seguimos con el paradigma de Orquestación y Coreografía de API y la agilidad que proporciona aprovechar los existentes para crear servicios compuestos que cumplan con los objetivos de innovación del negocio.

Resumen

Los paradigmas de desarrollo de aplicaciones nativas de la nube son una evolución suave de los principios existentes. Debemos aprovechar los que aún son relevantes y proporcionar una visión actualizada de ellos y actualizar los que se necesiten.

Al final, en esta industria, lo que hacemos cada día es dar un nuevo paso en el largo viaje que es la historia de la industria, y aprovechamos todo el trabajo que se ha hecho en el pasado, y aprendemos de ello.

#TIBFAQS 2022! ¡La solución a tus preguntas basadas en el desarrollo de TIBCO!

#TIBFAQS 2022! ¡La solución a tus preguntas basadas en el desarrollo de TIBCO!

Mejora tu conocimiento sobre la tecnología TIBCO y también resuelve los problemas que enfrentas en tus tareas diarias de desarrollo

Presentando #TIBFAQS: La Solución a Tus Preguntas Basadas en el Desarrollo de TIBCO
Presentando TIBFAQs por Alex Vazquez

¡TIBFAQS está aquí! Este nuevo año me gustaría comenzar varias iniciativas, y espero que puedas acompañarme durante este viaje. Como sabrás, soy un Arquitecto de TIBCO, así que en mis actividades diarias recibo muchas preguntas e inquietudes sobre cómo hacer diferentes cosas con la tecnología TIBCO, desde TIBCO BusinessWorks hasta TIBCO EMS o TIBCO Spotfire.

He notado que algunas de estas preguntas son similares de un cliente a otro, así que me gustaría usar esta plataforma para compartir todo este conocimiento para beneficiarnos en nuestras actividades diarias y usar la tecnología de la manera más eficiente.

1.- ¿Cómo va a funcionar esto?

Utilizaré algunos de los temas comunes que conozco en términos de preguntas de desarrollo de TIBCO y crearé un artículo periódico cubriéndolo con detalle y con una aplicación de muestra que muestre el problema y la solución. Todo el código estará disponible en mi repositorio de GitHub para que lo uses como referencia.

https://github.com/alexandrev

2.- ¿Puedo enviarte mis preguntas?

¡Sí, claro! ¡Eso sería increíble! Como dije, me gustaría crear una comunidad participativa alrededor de estas publicaciones para que todos podamos beneficiarnos de ello. Así que me gustaría ver tus preguntas y para enviármelas puedes hacerlo de las siguientes maneras:

  • Twitter: Puedes enviarme una mención a @alexandrev en Twitter o un DM o incluso solo usando el hashtag #TIBFAQs que estaré monitoreando.
  • Email: Puedes enviarme un correo electrónico a alexandre.vazquez en gmail.com con tu pregunta.
  • Instagram: Puedes enviarme un DM en Instagram a @alexandrev

3.- ¿Dónde va a comenzar esto?

Esto comenzará a finales de enero. La idea es tener al menos un artículo con una periodicidad quincenal, pero eso dependerá mucho del compromiso con esta iniciativa. Cuanto más compartas y hables sobre esta iniciativa con tus compañeros, y cuantas más preguntas me envíes, más artículos crearé.

4.- ¿Qué sigue?

Desde hoy puedes comenzar a enviar tus preguntas y compartir tus comentarios sobre esta iniciativa, y puedes seguir este blog para esperar los artículos que vendrán. ¡Hagámoslo juntos!

#TIBFAQS 2022! ¡La solución a tus preguntas basadas en el desarrollo de TIBCO!
Foto por Brett Jordan en Unsplash

Para una visión completa del ecosistema TIBCO, consulta nuestra Guía de la plataforma de integración TIBCO.

CICD Docker: Las 3 principales razones para usar contenedores en tu pipeline de DevSecOps

CICD Docker: Las 3 principales razones para usar contenedores en tu pipeline de DevSecOps

Mejora el rendimiento y la productividad de tu canalización DevSecOps usando contenedores.

CICD Docker significa el enfoque que la mayoría de las empresas están utilizando para introducir contenedores también en la fase de construcción y pre-despliegue para implementar una parte de la canalización CICD. Veamos por qué.

DevSecOps es la nueva norma para despliegues a gran escala en grandes empresas para cumplir con el ritmo requerido en los negocios digitales hoy en día. Estos procesos se orquestan utilizando una herramienta de orquestación CICD que actúa como el cerebro de este proceso. Las herramientas habituales para hacer este trabajo son Jenkins, Bamboo, AzureDevOps, GitLab, GitHub.

En el enfoque tradicional, tenemos diferentes servidores de trabajo realizando etapas del proceso DevOps: Código, Construcción, Prueba, Despliegue, y para cada uno de ellos, necesitamos diferentes tipos de herramientas y utilidades para hacer el trabajo. Por ejemplo, para obtener el código, podemos necesitar un git instalado. Para hacer la construcción, podemos confiar en maven o Gradle, y para probar, podemos usar SonarQube, etc.

CICD Docker: 3 Razones para usar Contenedores en tu canalización DevSecOps
Estructura de CICD Docker y la relación entre Orquestador y Trabajadores

Entonces, al final, necesitamos un conjunto de herramientas para desempeñarnos con éxito, y eso también requiere algo de gestión. En los nuevos días, con el auge del desarrollo nativo en la nube y el enfoque de contenedores en la industria, esto también está afectando la forma en que desarrollas tus canalizaciones para introducir contenedores como parte de la etapa.

En la mayoría de los Orquestadores CI, puedes definir una imagen de contenedor para ejecutar como cualquier paso de tu proceso DevSecOps, y déjame decirte que es genial si lo haces porque esto te proporcionará muchos de los beneficios de los que necesitas estar consciente.

1.- Solución mucho más escalable 

Uno de los problemas cuando usas un orquestador como el elemento principal en tu empresa, y que está siendo utilizado por muchas tecnologías diferentes que pueden ser de código abierto, propietario, basado en código, desarrollo visual, etc., significa que necesitas gestionar muchas cosas e instalar el software en los trabajadores.

Usualmente, lo que haces es que defines algunos trabajadores para hacer la construcción de algunos artefactos, como la imagen mostrada a continuación:

CICD Docker: Las 3 principales razones para usar contenedores en tu pipeline de DevSecOps
Distribución de trabajadores basada en sus propias capacidades

Eso es genial porque permite la segmentación del proceso de construcción y no requiere que todo el software esté instalado en todas las máquinas, incluso cuando pueden ser incompatibles.

Pero, ¿qué pasa si necesitamos desplegar muchas aplicaciones de uno de los tipos que tenemos en la imagen a continuación, como aplicaciones de TIBCO BusinessWorks? Que estarás limitado según el número de trabajadores que tengan el software instalado para construirlo y desplegarlo.

Con un enfoque basado en contenedores, tendrás todos los trabajadores disponibles porque no se necesita software, solo necesitas extraer la imagen de docker, y eso es todo, así que solo estás limitado por la infraestructura que usas, y si adoptas una plataforma en la nube como parte del proceso de construcción, estas limitaciones simplemente se eliminan. Tu tiempo de comercialización y ritmo de despliegue mejoran.

2.- Fácil de mantener y extender

Si eliminas la necesidad de instalar y gestionar los trabajadores porque se activan cuando los necesitas y se eliminan cuando no son necesarios y todo lo que necesitas hacer es crear una imagen de contenedor que haga el trabajo, el tiempo y el esfuerzo que los equipos necesitan gastar en mantener y extender la solución disminuirán considerablemente.

También la eliminación de cualquier proceso de actualización para los componentes involucrados en los pasos ya que siguen el proceso habitual de imagen de contenedor.

3.- Evitar el bloqueo del Orquestador

Como confiamos en los contenedores para hacer la mayor parte del trabajo, el trabajo que necesitamos hacer para movernos de una solución DevOps a otra es pequeño, y eso nos da el control para elegir en cualquier momento si la solución que estamos usando es la mejor para nuestro caso de uso y contexto o necesitamos movernos a otra más optimizada sin el problema de justificar grandes inversiones para hacer ese trabajo.

Recuperas el control, y también puedes incluso ir a un enfoque de multi-orquestador si es necesario, como usar la mejor solución para cada caso de uso y obtener todos los beneficios de cada uno de ellos al mismo tiempo sin necesidad de luchar contra cada uno de ellos.

Resumen

Todos los beneficios que todos conocemos de los paradigmas de desarrollo nativo en la nube y los contenedores son relevantes para el desarrollo de aplicaciones y otros procesos que usamos en nuestra organización, siendo uno de esos tu canalización y procesos DevSecOps. Comienza hoy haciendo ese viaje para obtener todas esas ventajas en el proceso de construcción y no esperes hasta que sea demasiado tarde. Disfruta tu día. Disfruta tu vida.

📚 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.

Escalado automático de Kubernetes: Aprende a escalar tus implementaciones de Kubernetes de manera dinámica

Escalado automático de Kubernetes: Aprende a escalar tus implementaciones de Kubernetes de manera dinámica

Descubre las diferentes opciones para escalar tu plataforma según la carga de tráfico que recibas

Cuando hablamos de Kubernetes, siempre estamos hablando de las opciones de flexibilidad que proporciona. Normalmente, uno de los temas que surgen en la discusión son las opciones de elasticidad que vienen con la plataforma, especialmente cuando se trabaja con un proveedor de nube pública. Pero, ¿cómo podemos implementarlo realmente?

Antes de comenzar a mostrar cómo escalar nuestra plataforma Kubernetes, necesitamos hacer un breve repaso de las opciones que están disponibles para nosotros:

  • Cluster Autoscaler: Cuando la carga de toda la infraestructura alcanza su pico, podemos mejorarla creando nuevos nodos de trabajo para alojar más instancias de servicio.
  • Horizontal Pod Autoscaling: Cuando la carga para un pod específico o conjunto de pods alcanza su pico, desplegamos una nueva instancia para asegurar que podemos tener la disponibilidad global que necesitamos.

Veamos cómo podemos implementar esto usando uno de los servicios gestionados de Kubernetes más populares, los Servicios de Kubernetes Elásticos (EKS) de Amazon.


Configuración

Lo primero que vamos a hacer es crear un clúster con un solo nodo de trabajo para demostrar fácilmente el comportamiento de escalabilidad. Y para hacerlo, vamos a usar la herramienta de línea de comandos eksctl para gestionar fácilmente un clúster EKS.

Para poder crear el clúster, lo haremos con el siguiente comando:

eksctl create cluster --name=eks-scalability --nodes=1 --region=eu-west-2 --node-type=m5.large --version 1.17 --managed --asg-access

Después de unos minutos, tendremos nuestro propio clúster de Kubernetes con un solo nodo para desplegar aplicaciones sobre él.

Ahora vamos a crear una aplicación de muestra para generar carga. Vamos a usar TIBCO BusinessWorks Application Container Edition para generar una aplicación simple. Será una API REST que ejecutará un bucle de 100,000 iteraciones actuando como un contador y devolverá un resultado.

Aplicación de muestra de BusinessWorks para mostrar las opciones de escalabilidad
Aplicación de muestra de BusinessWorks para mostrar las opciones de escalabilidad

Y utilizaremos los recursos disponibles en este repositorio de GitHub:

Construiremos la imagen del contenedor y la subiremos a un registro de contenedores. En mi caso, voy a usar mi instancia de Amazon ECR para hacerlo, y usaré los siguientes comandos:

docker build -t testeks:1.0 .
docker tag testeks:1.0 938784100097.dkr.ecr.eu-west-2.amazonaws.com/testeks:1.0
docker push 938784100097.dkr.ecr.eu-west-2.amazonaws.com/testeks:1.0

Y una vez que la imagen esté subida al registro, desplegaremos la aplicación sobre el clúster de Kubernetes usando este comando:

kubectl apply -f .testeks.yaml

Después de eso, tendremos nuestra aplicación desplegada allí, como puedes ver en la imagen a continuación:

Imagen desplegada en el clúster de Kubernetes
Imagen desplegada en el clúster de Kubernetes

Entonces, ahora podemos probar la aplicación. Para hacerlo, haré que el puerto 8080 esté disponible usando un comando de reenvío de puerto como este:

kubectl port-forward pod/testeks-v1-869948fbb-j5jh7 8080:8080

Con eso, puedo ver y probar la aplicación de muestra usando el navegador, como se muestra a continuación:

Probador de Swagger UI para la aplicación de muestra de Kubernetes
Probador de Swagger UI para la aplicación de muestra de Kubernetes

Escalado automático de pods horizontales

Ahora, necesitamos comenzar a definir las reglas de escalado automático, y comenzaremos con la regla de Escalado Automático de Pods Horizontales (HPA). Necesitaremos elegir el recurso que nos gustaría usar para escalar nuestro pod. En esta prueba, usaré la utilización de CPU para hacerlo, y usaré el siguiente comando:

kubectl autoscale deployment testeks-v1 --min=1 --max=5 --cpu-percent=80

Ese comando escalará el conjunto de réplicas testeks de una (1) instancia a cinco (5) instancias cuando el porcentaje de utilización de CPU sea superior al 80%.

Si ahora verificamos el estado de los componentes, obtendremos algo similar a la imagen a continuación:

Definición de regla HPA para la aplicación usando la utilización de CPU como la métrica clave
Definición de regla HPA para la aplicación usando la utilización de CPU como la métrica clave

Si verificamos la columna TARGETS, veremos este valor: <unknown>/80%. Eso significa que el 80% es el objetivo para activar las nuevas instancias y el uso actual es <unknown>.

No tenemos nada desplegado en el clúster para obtener las métricas de cada uno de los pods. Para resolver eso, necesitamos desplegar el Servidor de Métricas. Para hacerlo, seguiremos la documentación de Amazon AWS:

Entonces, ejecutando el siguiente comando, tendremos el Servidor de Métricas instalado.

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml

Y después de hacer eso, si verificamos nuevamente, podemos ver que el uso actual ha reemplazado el <unknown>:

Utilización actual de recursos después de instalar el servidor de métricas en el clúster de Kubernetes
Utilización actual de recursos después de instalar el Servidor de Métricas en el clúster de Kubernetes

Si eso funciona, voy a comenzar a enviar solicitudes usando una Prueba de Carga dentro del clúster. Usaré la aplicación de muestra definida a continuación:

Para desplegar, usaremos un archivo YAML con el siguiente contenido:

https://gist.github.com/BetterProgramming/53181f3aa7bee7b7e3adda7c4ed8ca40#file-deploy-yaml

Y lo desplegaremos usando el siguiente comando:

kubectl apply -f tester.yaml

Después de hacer eso, veremos que la utilización actual está aumentando. Después de unos segundos, comenzará a girar nuevas instancias hasta que alcance el número máximo de pods definido en la regla HPA.

Aumento de pods cuando la carga excede el objetivo definido en pasos anteriores.
Aumento de pods cuando la carga excede el objetivo definido en pasos anteriores.

Luego, tan pronto como la carga también disminuya, el número de instancias será eliminado.

Los pods se eliminan tan pronto como la carga disminuye.
Los pods se eliminan tan pronto como la carga disminuye.

Escalado automático de clústeres

Ahora, necesitamos ver cómo podemos implementar el Escalador Automático de Clústeres usando EKS. Usaremos la información que proporciona Amazon:

https://github.com/alexandrev/testeks

El primer paso es desplegar el escalado automático del clúster, y lo haremos usando el siguiente comando:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml

Luego ejecutaremos este comando:

kubectl -n kube-system annotate deployment.apps/cluster-autoscaler cluster-autoscaler.kubernetes.io/safe-to-evict=”false”

Y editaremos el despliegue para proporcionar el nombre actual del clúster que estamos gestionando. Para hacer eso, ejecutaremos el siguiente comando:

kubectl -n kube-system edit deployment.apps/cluster-autoscaler

Cuando tu editor de texto predeterminado se abra con el contenido del texto, necesitas hacer los siguientes cambios:

  • Establece el nombre de tu clúster en el marcador de posición disponible.
  • Agrega estas propiedades adicionales:
- --balance-similar-node-groups
- --skip-nodes-with-system-pods=false
Ediciones de despliegue necesarias para configurar el Escalador Automático de Clústeres
Ediciones de despliegue necesarias para configurar el Escalador Automático de Clústeres

Ahora necesitamos ejecutar el siguiente comando:

kubectl -n kube-system set image deployment.apps/cluster-autoscaler cluster-autoscaler=eu.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler:v1.17.4

Lo único que queda es definir la política de AutoScaling. Para hacerlo, usaremos el portal de Servicios de AWS:

  • Ingresa a la página de servicio EC en la región en la que hemos desplegado el clúster.
  • Selecciona las opciones de Grupo de Auto Scaling.
  • Selecciona el Grupo de Auto Scaling que se ha creado como parte del proceso de creación del clúster EKS.
  • Ve a la pestaña de Escalado Automático y haz clic en el botón Agregar Política disponible.
Opción de política de escalado automático en la consola de servicio EC2
Opción de política de escalado automático en la consola de servicio EC2

Luego deberíamos definir la política. Usaremos la utilización promedio de CPU como la métrica y estableceremos el valor objetivo en 50%:

Diálogo de creación de política de escalado automático
Diálogo de creación de política de escalado automático

Para validar el comportamiento, generaremos carga usando el probador como lo hicimos en la prueba anterior y validaremos la carga del nodo usando el siguiente comando:

kubectl top nodes
Salida de muestra de kubectl top nodes
Salida de muestra de kubectl top nodes

Ahora desplegamos el probador nuevamente. Como ya lo tenemos desplegado en este clúster, necesitamos eliminarlo primero para desplegarlo nuevamente:

kubectl delete -f .tester.yaml
kubectl apply -f .tester.yaml

Tan pronto como comience la carga, se crearán nuevos nodos, como se muestra en la imagen a continuación:

Salida de muestra de kubectl top nodes
kubectl top nodes mostrando cómo los nodos han sido escalados hacia arriba

Después de que la carga termine, volvemos a la situación anterior:

kubectl top nodes mostrando cómo los nodos han sido escalados hacia abajo
kubectl top nodes mostrando cómo los nodos han sido escalados hacia abajo

Resumen

En este artículo, hemos mostrado cómo podemos escalar un clúster de Kubernetes de manera dinámica tanto a nivel de nodo de trabajo usando la capacidad de Escalador Automático de Clústeres como a nivel de pod usando el Escalador Automático de Pods Horizontales. Eso nos da todas las opciones necesarias para crear un entorno verdaderamente elástico y flexible capaz de adaptarse a las necesidades de cada momento con el enfoque más eficiente.

📚 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.

Distribuciones de Kubernetes: ¿Qué son y cuáles son los 5 mejores jugadores disponibles?

Distribuciones de Kubernetes: ¿Qué son y cuáles son los 5 mejores jugadores disponibles?

Aprende qué son las Distribuciones de Kubernetes, por qué te importa a ti y quiénes son los mejores jugadores disponibles en el mercado hoy en día

Introducción

Uno de los mayores anuncios de las últimas sesiones de AWS re:Invent 2020 fue el lanzamiento de EKS-D de Amazon. EKS-D es su Distribución de Kubernetes de código abierto que ahora está disponible para que todos la usen en su proveedor de nube o incluso en sus instalaciones.

Está basado en hallazgos anteriores y en todo el proceso que Amazon ha llevado a cabo en la gestión de su plataforma gestionada de Kubernetes, Amazon EKS.

Estos anuncios han hecho que muchas personas se pregunten: “OK, conozco Kubernetes, pero ¿qué es una distribución de Kubernetes? ¿Y por qué debería importarme?”

Así que intentaré responder eso con el conocimiento que tengo, y siempre trato de usar el mismo enfoque: una comparación del modelo de Kubernetes versus Linux.

Kubernetes es un proyecto de código abierto, como sabes, iniciado por Google y ahora gestionado por la comunidad y la Cloud Native Computing Foundation (CNCF), y puedes encontrar todo el código disponible aquí:

Pero seamos honestos: No muchos de nosotros estamos descargando ese repositorio e intentando compilarlo para proporcionar un clúster. No es así como solemos trabajar. Si sigues el camino del código — descargándolo, construyéndolo, etc. — esto generalmente se llama vanilla Kubernetes.

Si comenzamos con la comparación con Linux, es la misma situación que tenemos con el kernel de Linux que la mayoría de las distribuciones de Linux envían, pero esto ya está compilado y disponible con un montón de otras herramientas que trabajan juntas a través del enfoque habitual.

Así que eso es lo que es una distribución de Kubernetes. Construyen Kubernetes. Proporcionan otras herramientas y componentes para mejorar o proporcionar más características y para centrarse en aspectos adicionales como un enfoque en la seguridad, un enfoque en DevOps, u otro enfoque. Otro concepto que generalmente se plantea es la pureza de la distribución, y tratamos de hablar sobre una distribución que sea pura.

Llamamos a una distribución pura cuando está construyendo Kubernetes, y eso es todo. Deja todo lo demás a los desarrolladores o usuarios para decidir qué quieren usar encima de ella.


¿Cuáles son los Componentes Principales que se Incluyen en una Distribución de Kubernetes?

Los componentes principales que pueden diferir cuando hablamos de una distribución de Kubernetes son los siguientes:

Tiempo de ejecución de contenedores y registros

Todos sabemos que hay más de un tiempo de ejecución de contenedores, e incluso si no estabas al tanto de eso, probablemente hayas leído todos los artículos sobre la eliminación del soporte de Docker en Kubernetes v1.20, como puedes leer en este increíble artículo de Edgar Rodriguez.

En este momento, parece que todos los tiempos de ejecución deberían soportar la existente Interfaz de Tiempo de Ejecución de Contenedores, y tiempos de ejecución como CRI-O, Containerd, o Kata parecen ser las opciones predeterminadas ahora.

Redes

Otro tema que a menudo difiere cuando hablamos de distribuciones de Kubernetes es cómo gestionan su red, y este es uno de los aspectos más críticos de toda la plataforma.

Como tenemos con el tiempo de ejecución de contenedores, existe una especificación estándar para cubrir ese tema, y esa es la Interfaz de Red de Contenedores (CNI). Existen varios proyectos sobre este tema, como Flannel, Calico, Canal, y Wave. Además, algunas plataformas proporcionan su propio componente, como el operador Openshift SDN.

Almacenamiento

Cómo manejar el almacenamiento en Kubernetes también es muy importante, especialmente a medida que adoptamos este modelo en implementaciones que requieren modelos con estado. Diferentes plataformas pueden soportar diferentes opciones de almacenamiento, como sistemas de archivos, etc.


¿Quiénes son los Mejores Jugadores?

Lo primero que debemos tener en cuenta es que hay un gran número de distribuciones de Kubernetes por ahí.

Contaremos las que tienen una certificación CNCF, y puedes echar un vistazo a todas ellas aquí. En el momento de escribir este artículo, estamos hablando de 72 distribuciones certificadas.

Logos de las diversas distribuciones certificadas por CNCF.
Imagen a través de la Cloud Native Computing Foundation

Estos son los que me gustaría destacar hoy:

Red Hat OpenShift

Logo de Red Hat OpenShift.

La plataforma Red Hat OpenShift podría ser una de las plataformas más utilizadas, especialmente en un entorno de nube privada. Podría incluir la mayoría de los servicios de Red Hat en cuanto a almacenamiento, como GlusterFS y redes con OpenShift DNS. Tiene OKD como el proyecto de código abierto que respalda y contribuye a la plataforma OpenShift. Consulta este artículo para ver cómo configurar Openshift localmente para probarlo

Mirantis

Logo de Mirantis

La antigua empresa Docker que ha sido adquirida por Mirantis es otra de las opciones habituales cuando hablamos de plataformas soportadas.

VMware Tanzu

Logo de VMware Tanzu

VMware Tanzu, también proveniente de la adquisición de Pivotal por parte de VMware, es una plataforma de Kubernetes.

Canonical

Logo de Canonical

Canonical (código abierto) es una plataforma de la empresa que desarrolla y mantiene Ubuntu. Es otra de las opciones importantes aquí y proporciona una variedad de opciones, centrándose no solo en el modo central común sino también en implementaciones de Kubernetes en el borde con proyectos como MicroK8S y más opciones.

Rancher

Logo de Rancher

Rancher (código abierto) es otro de los grandes jugadores, centrándose en seguir y extender los estándares de CNCF y también ofreciendo un gran impulso para la implementación en el borde con K3S. También ofrece actualizaciones automáticas.


Resumen

Así que, como puedes ver, el número de opciones disponibles es enorme. Todas difieren, por lo que es importante tomarse su tiempo cuando se decide la plataforma objetivo basada en sus criterios para su proyecto o su empresa.

Y eso sin cubrir las plataformas gestionadas disponibles que se están convirtiendo en una de las opciones más preferidas para las empresas para que puedan obtener toda la flexibilidad de Kubernetes sin necesidad de manejar la complejidad de gestionar una plataforma de Kubernetes por sí mismos. Pero ese es un tema para otro artículo — esperemos que pronto.

Este artículo al menos te ha proporcionado más claridad sobre qué es una distribución de Kubernetes, las principales diferencias entre ellas, y un vistazo rápido a algunos de los actores clave en este espectro. Disfruta tu día, y disfruta tu vida.

📚 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.

La diferencia visual podría ser la pieza que falta en el desarrollo de bajo código

La diferencia visual podría ser la pieza que falta en el desarrollo de bajo código

Ayudándote a sobresalir usando low code en equipos distribuidos y programación paralela

La mayoría de las empresas están explorando el desarrollo low-code/no-code ahora que lo más importante es lograr agilidad en los artefactos tecnológicos desde diferentes perspectivas (desarrollo, implementación y operación).

Los beneficios de esta forma de trabajar hacen que sea casi una decisión obvia para la mayoría de las empresas. Ya los cubrimos en un artículo anterior. Échale un vistazo si aún no lo has leído.

Pero sabemos que todas las cosas nuevas vienen con sus propios desafíos que necesitamos abordar y dominar para liberar todos los beneficios que estos nuevos paradigmas o tecnologías están proporcionando. Al igual que con la arquitectura nativa de la nube, necesitamos ser capaces de adaptarnos.

A veces no es la cultura lo que necesitamos cambiar. A veces la tecnología y las herramientas también necesitan evolucionar para abordar esos desafíos y ayudarnos en ese viaje. Y así es como Visual Diff cobró vida.

Cuando desarrollas usando un enfoque low-code, todo el proceso de desarrollo es más fácil. Necesitas combinar diferentes bloques que realizan la lógica que necesitas, y todo es más simple que un montón de líneas de código.

Ejemplo de desarrollo low-code
Enfoque de desarrollo low-code usando TIBCO BusinessWorks.

Pero también necesitamos gestionar todos estos artefactos en un repositorio donde todos ellos están enfocados en el desarrollo de código fuente. Eso significa que cuando trabajas con esas herramientas al final, no estás trabajando con un “enfoque low-code” sino más bien con un enfoque de código fuente. Cosas como fusionar diferentes ramas y mirar el historial de versiones para conocer los cambios son complejas.

Y son complejas porque son realizadas por el propio repositorio, que está enfocado en los cambios de archivos y el código fuente que cambia. Pero uno de los grandes beneficios del desarrollo low-code es que el desarrollador no necesita estar al tanto del código fuente generado como parte de la actividad visual, más rápida. Entonces, ¿cómo podemos resolver eso? ¿Qué podemos usar para resolver eso?

Las tecnologías low-code necesitan avanzar para tomar la delantera aquí. Por ejemplo, esto es lo que TIBCO BusinessWorks ha hecho con el lanzamiento de su capacidad Visual Diff.

Entonces, todavía tienes tu integración con tu repositorio de código fuente. Puedes hacer todos los procesos y actividades que usualmente necesitas hacer en este tipo de desarrollo distribuido paralelo. Aún así, también puedes ver todas esas actividades desde una perspectiva “low-code”.

Eso significa que cuando estoy echando un vistazo al historial de versiones, puedo ver los artefactos visuales que han sido modificados. Las actividades añadidas o eliminadas se muestran allí de una manera significativa para el desarrollo low-code. Eso cierra el ciclo sobre cómo los desarrollos low-code pueden aprovechar todas las ventajas de los repositorios de código fuente modernos y sus flujos (GitFlow, GitHub Flow, One Flow, etc.) así como las ventajas de la perspectiva low-code.

Digamos que hay dos opciones con las que puedes ver cómo ha cambiado una aplicación. Una es el enfoque tradicional y la otra usa el Visual Diff:

Visual Diff de tus procesos
Opción A: Visual Diff de tus procesos
Mismos procesos pero con un enfoque de Comparación de Texto
Opción B: Mismos procesos pero con un enfoque de Comparación de Texto

Entonces, basándonos en esta evidencia, ¿qué crees que es más fácil de entender? Incluso si eres un verdadero programador como yo, no podemos negar la facilidad y los beneficios del enfoque low-code para el desarrollo masivo y estándar en el mundo empresarial.


Resumen

No importa qué tan rápido estemos desarrollando con todos los aceleradores y marcos que tenemos, una aplicación low-code bien definida será más rápida que cualquiera de nosotros. Es la misma batalla que tuvimos en el pasado con las Interfaces Gráficas o el control del ratón frente al teclado.

Aceptamos que hay una preferencia personal para elegir una u otra, pero cuando necesitamos decidir qué es más efectivo y necesitamos basarnos en los hechos, no podemos ser ciegos a lo que está frente a nosotros.

Espero que hayas disfrutado este artículo. ¡Que tengas un buen día!

Lens podría ser la herramienta que te faltaba para dominar el desarrollo y la gestión basados en Kubernetes

Lens podría ser la herramienta que te faltaba para dominar el desarrollo y la gestión basados en Kubernetes

Encuentra la mejor manera de gestionar tu clúster de desarrollo de Kubernetes

Necesito comenzar este artículo admitiendo que soy un defensor de las Interfaces Gráficas de Usuario y de todo lo que proporciona una forma de acelerar la manera en que hacemos las cosas y ser más productivos. Así que cuando hablamos de cómo gestionar nuestro clúster de Kubernetes principalmente con fines de desarrollo, puedes imaginar que soy una de esas personas que prueba cualquier herramienta disponible para hacer ese viaje más fácil. Aquellos que han comenzado a usar Portainer para gestionar su motor Docker local o son fanáticos del nuevo panel en Docker para Windows/Mac. Pero eso está lejos de la realidad. En términos de gestión de Kubernetes, me acostumbré a escribir todos los comandos para verificar los pods, los registros, el estado del clúster para hacer los reenvíos de puertos, etc. Cualquier tarea que realizaba era con una terminal, y sentía que era lo correcto. Ni siquiera usaba un panel de Kubernetes para tener una página web para mi entorno de Kubernetes. Todo eso cambió la semana pasada cuando me encontré con un colega que me mostró lo que Lens podía hacer. Lens es una historia totalmente diferente. No lo estoy alabando porque me paguen por hacerlo. Este es un proyecto de código abierto que puedes encontrar en GitHub. ¡Pero la forma en que hace el trabajo es simplemente increíble!
Imagen de Lens mostrando el estado de un clúster de Kubernetes
Imagen de Lens mostrando el estado de un clúster de Kubernetes — Captura de pantalla por el autor.
Lo primero que me gustaría mencionar sobre Lens es que tiene soporte multi-contexto, por lo que puedes tener todos los diferentes contextos de Kubernetes disponibles para cambiar siguiendo un enfoque similar al de Slack cuando cambiamos de diferentes espacios de trabajo. Simplemente lee tu archivo .kube/config y hace que todos esos contextos estén disponibles para que te conectes al que desees.
Selección de contexto de Kubernetes en Lens
Selección de contexto de Kubernetes en Lens
Una vez que nos hemos conectado a uno de estos clústeres, tenemos diferentes opciones para ver su estado, pero la primera es verificar las Cargas de Trabajo usando la opción de Vista General:
Vista General de Cargas de Trabajo en Lens
Vista General de Cargas de Trabajo en Lens
Luego, puedes profundizar en cualquier pod u objeto diferente dentro de Kubernetes para verificar su estado y al mismo tiempo realizar las acciones principales que usualmente haces cuando tratas con un pod, como verificar los registros, ejecutar una terminal en uno de los contenedores que pertenecen a ese pod, o incluso editar el YAML para ese pod.
Opciones de pod dentro de Lens
Opciones de pod dentro de Lens
Pero Lens va más allá de las tareas habituales de Kubernetes porque también tiene una integración con Helm, por lo que puedes verificar las versiones que tienes allí, la versión del estado, y así sucesivamente:
Opción de integración de Helm en Lens
Opción de integración de Helm en Lens
La experiencia de gestionar todo se siente perfecta. También eres más productivo. Incluso aquellos que aman la CLI y las terminales deben admitir que para realizar tareas regulares, el enfoque Gráfico y el ratón son más rápidos que el teclado — incluso para los defensores del teclado mecánico como yo. Así que te animo a descargar Lens y comenzar a usarlo ahora mismo. Para hacerlo, ve a su página web principal y descárgalo: ¡Gracias por leer!

📚 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.

Procesamiento de XML con Shell: Cómo actualizar un valor en un archivo XML en 5 minutos

Procesamiento de XML con Shell: Cómo actualizar un valor en un archivo XML en 5 minutos

Aprende a usar xmlstarlet para actualizar valores en archivos XML y manejar cargas XML complejas de manera eficiente en tus scripts de shell

Si trabajas en TI o incluso si consideras TI como uno de tus principales pasatiempos, has escrito un script de shell en algún momento. Si también trabajas en el lado operativo del negocio, esta puede ser tu tarea diaria. Crear, mantener o actualizar el proceso existente.

Hoy en día, es más común interactuar con sistemas externos que utilizan cargas en archivos XML o incluso archivos de configuración escritos en este formato.

El script de shell nativo no proporciona una manera fácil de hacer eso ni bibliotecas de soporte para manejarlo como podemos en lenguajes de programación modernos como Python, Java o Go. Así que, probablemente te has encontrado escribiendo código para analizar este tipo de carga. Pero esta no es la única manera de hacerlo, y podemos (¡y debemos!) aprovechar las utilidades existentes para hacer este trabajo por nosotros.

xmlstarlet

No pude encontrar una mejor manera de explicar lo que hace xmlstarlet que la definición que los propietarios hacen en su repositorio de código fuente:

XMLStarlet es un conjunto de herramientas XML de línea de comandos que se puede usar para transformar,
consultar, validar y editar documentos y archivos XML usando un conjunto simple de comandos de shell
de manera similar a como se hace para archivos de texto plano usando grep/sed/awk/
tr/diff/patch.

Así que, xmlstarlet proporciona todo el poder para hacer cualquier cosa que puedas imaginar al tratar con XML de manera similar a como si fueran archivos de texto plano.

Instalación

El proceso de instalación de esta utilidad es bastante fácil y depende del sistema operativo que estés usando. Asumiré que la mayoría de los scripts de shell están dirigidos a una máquina Unix. Instalar esto es bastante fácil ya que la mayoría de los repositorios de paquetes tienen una versión de esta herramienta.

Así que, si estás usando un sistema basado en apt, necesitas ejecutar el comando:

sudo apt-get install xmlstarlet

Si estás usando otra plataforma, no te preocupes porque tienen versiones disponibles para todos los sistemas operativos y plataformas más utilizados, como puedes ver en el enlace a continuación:

Uso

Tan pronto como tengamos este software instalado, lo primero que haremos es lanzarlo para ver las opciones disponibles.

XMLStarlet Toolkit: Utilidades de línea de comandos para XML
Uso: D:DataDownloadsxmlstarlet-1.6.1-win32xmlstarlet-1.6.1xmlstarlet.exe [<opciones>] <comando> [<opciones-cmd>]
donde <comando> es uno de:
  ed    (o edit)      - Editar/Actualizar documento(s) XML
  sel   (o select)    - Seleccionar datos o consultar documento(s) XML (XPATH, etc)
  tr    (o transform) - Transformar documento(s) XML usando XSLT
  val   (o validate)  - Validar documento(s) XML (bien formado/DTD/XSD/RelaxNG)
  fo    (o format)    - Formatear documento(s) XML
  el    (o elements)  - Mostrar estructura de elementos del documento XML
  c14n  (o canonic)   - Canonicalización XML
  ls    (o list)      - Listar directorio como XML
  esc   (o escape)    - Escapar caracteres especiales XML
  unesc (o unescape)  - Desescapar caracteres especiales XML
  pyx   (o xmln)      - Convertir XML en formato PYX (basado en ESIS - ISO 8879)
  p2x   (o depyx)     - Convertir PYX en XML
<opciones> son:
  -q o --quiet        - sin salida de error
  --doc-namespace     - extraer enlaces de espacio de nombres del documento de entrada (por defecto)
  --no-doc-namespace  - no extraer enlaces de espacio de nombres del documento de entrada
  --version           - mostrar versión
  --help              - mostrar ayuda
Dondequiera que se mencione el nombre del archivo en la ayuda del comando, se asume
que se puede usar una URL en su lugar también.

Escribe: xmlstarlet <comando> --help <ENTER> para ayuda del comando

Así que lo primero que necesitamos decidir es qué comando necesitamos usar, y estos comandos están relacionados uno a uno con la acción que queremos realizar. Me centraré en los comandos principales en este post, pero como puedes ver, esto cubre desde seleccionar valores en un XML, actualizarlo o incluso validarlo.

Caso de uso 1: Seleccionar un valor.

Vamos a comenzar con el caso de uso más simple, intentar seleccionar un valor de un XML (file.xml) como este:

<root>
<object1 name="attribute_name">valor en XML</object1>
</root>

Así que, vamos a comenzar con el comando más simple:

./xmlstarlet  sel  -t -v "/root/object1"  ./file.xml

valor en XML

Esto proporciona el valor dentro del elemento object1, usando -t para definir una nueva plantilla y -v para especificar la sentencia value-of. Si ahora, quisiéramos obtener el valor del atributo, podemos hacerlo de manera muy similar al comando anterior:

./xmlstarlet  sel  -t -v "/root/object1/@name"  ./file.xml

attribute_name

Caso de uso 2: Actualizar valor.

Ahora, seguiremos el otro enfoque basado en el mismo archivo. Actualizaremos el valor del elemento object1 para establecer el texto «texto actualizado».

Para hacer eso, ejecutamos el siguiente comando:

./xmlstarlet ed -u "/root/object1" -v "texto actualizado" ./file.xml

<?xml version="1.0"?>
<root>
  <object1 name="attribute_name">texto actualizado</object1>
</root>

Resumen

xmlstarlet nos proporcionará todas las opciones para manejar algo tan complicado como lo es XML y realizar todas las tareas que puedas imaginar de manera simple sin necesidad de codificar tú mismo toda la lógica de análisis. Espero que seas un desarrollador más feliz desde ahora cuando necesites manejar un XML dentro de un script de shell.

Prometheus Storage: ¿Cómo optimizar el uso del disco?

Prometheus Storage: ¿Cómo optimizar el uso del disco?

Aprende algunos trucos para analizar y optimizar el uso que estás haciendo de la TSDB y ahorrar dinero en tu implementación en la nube.

En publicaciones anteriores, discutimos cómo funcionaba la capa de almacenamiento para Prometheus y cuán efectiva era. Pero en los tiempos actuales, estamos en la era de la computación en la nube y sabemos que cada optimización técnica es también una optimización de costos, y es por eso que necesitamos ser muy diligentes con cualquier opción que usemos en cuanto a optimización.

Sabemos que usualmente cuando monitoreamos usando Prometheus tenemos muchos exportadores disponibles a nuestra disposición y también que cada uno de ellos expone muchas métricas muy relevantes que necesitamos para rastrear todo lo que necesitamos. Pero también, debemos ser conscientes de que hay métricas que no necesitamos en este momento o que no planeamos usar. Entonces, si no planeamos usarlas, ¿por qué queremos desperdiciar espacio en disco almacenándolas?

Así que, comencemos echando un vistazo a uno de los exportadores que tenemos en nuestro sistema. En mi caso, me gustaría usar una Aplicación de Contenedor BusinessWorks que expone métricas sobre su utilización. Si revisas su punto de acceso de métricas podrías ver algo como esto:

# HELP jvm_info Información de la versión de JVM
# TYPE jvm_info gauge
jvm_info{version="1.8.0_221-b27",vendor="Oracle Corporation",runtime="Java(TM) SE Runtime Environment",} 1.0
# HELP jvm_memory_bytes_used Bytes usados de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_used gauge
jvm_memory_bytes_used{area="heap",} 1.0318492E8
jvm_memory_bytes_used{area="nonheap",} 1.52094712E8
# HELP jvm_memory_bytes_committed Bytes comprometidos de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_committed gauge
jvm_memory_bytes_committed{area="heap",} 1.35266304E8
jvm_memory_bytes_committed{area="nonheap",} 1.71302912E8
# HELP jvm_memory_bytes_max Máximo de bytes de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_max gauge
jvm_memory_bytes_max{area="heap",} 1.073741824E9
jvm_memory_bytes_max{area="nonheap",} -1.0
# HELP jvm_memory_bytes_init Bytes iniciales de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_init gauge
jvm_memory_bytes_init{area="heap",} 1.34217728E8
jvm_memory_bytes_init{area="nonheap",} 2555904.0
# HELP jvm_memory_pool_bytes_used Bytes usados de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_used gauge
jvm_memory_pool_bytes_used{pool="Code Cache",} 3.3337536E7
jvm_memory_pool_bytes_used{pool="Metaspace",} 1.04914136E8
jvm_memory_pool_bytes_used{pool="Compressed Class Space",} 1.384304E7
jvm_memory_pool_bytes_used{pool="G1 Eden Space",} 3.3554432E7
jvm_memory_pool_bytes_used{pool="G1 Survivor Space",} 1048576.0
jvm_memory_pool_bytes_used{pool="G1 Old Gen",} 6.8581912E7
# HELP jvm_memory_pool_bytes_committed Bytes comprometidos de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_committed gauge
jvm_memory_pool_bytes_committed{pool="Code Cache",} 3.3619968E7
jvm_memory_pool_bytes_committed{pool="Metaspace",} 1.19697408E8
jvm_memory_pool_bytes_committed{pool="Compressed Class Space",} 1.7985536E7
jvm_memory_pool_bytes_committed{pool="G1 Eden Space",} 4.6137344E7
jvm_memory_pool_bytes_committed{pool="G1 Survivor Space",} 1048576.0
jvm_memory_pool_bytes_committed{pool="G1 Old Gen",} 8.8080384E7
# HELP jvm_memory_pool_bytes_max Máximo de bytes de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_max gauge
jvm_memory_pool_bytes_max{pool="Code Cache",} 2.5165824E8
jvm_memory_pool_bytes_max{pool="Metaspace",} -1.0
jvm_memory_pool_bytes_max{pool="Compressed Class Space",} 1.073741824E9
jvm_memory_pool_bytes_max{pool="G1 Eden Space",} -1.0
jvm_memory_pool_bytes_max{pool="G1 Survivor Space",} -1.0
jvm_memory_pool_bytes_max{pool="G1 Old Gen",} 1.073741824E9
# HELP jvm_memory_pool_bytes_init Bytes iniciales de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_init gauge
jvm_memory_pool_bytes_init{pool="Code Cache",} 2555904.0
jvm_memory_pool_bytes_init{pool="Metaspace",} 0.0
jvm_memory_pool_bytes_init{pool="Compressed Class Space",} 0.0
jvm_memory_pool_bytes_init{pool="G1 Eden Space",} 7340032.0
jvm_memory_pool_bytes_init{pool="G1 Survivor Space",} 0.0
jvm_memory_pool_bytes_init{pool="G1 Old Gen",} 1.26877696E8
# HELP jvm_buffer_pool_used_bytes Bytes usados de un pool de buffer JVM dado.
# TYPE jvm_buffer_pool_used_bytes gauge
jvm_buffer_pool_used_bytes{pool="direct",} 148590.0
jvm_buffer_pool_used_bytes{pool="mapped",} 0.0
# HELP jvm_buffer_pool_capacity_bytes Capacidad en bytes de un pool de buffer JVM dado.
# TYPE jvm_buffer_pool_capacity_bytes gauge
jvm_buffer_pool_capacity_bytes{pool="direct",} 148590.0
jvm_buffer_pool_capacity_bytes{pool="mapped",} 0.0
# HELP jvm_buffer_pool_used_buffers Buffers usados de un pool de buffer JVM dado.
# TYPE jvm_buffer_pool_used_buffers gauge
jvm_buffer_pool_used_buffers{pool="direct",} 19.0
jvm_buffer_pool_used_buffers{pool="mapped",} 0.0
# HELP jvm_classes_loaded El número de clases que están actualmente cargadas en la JVM
# TYPE jvm_classes_loaded gauge
jvm_classes_loaded 16993.0
# HELP jvm_classes_loaded_total El número total de clases que han sido cargadas desde que la JVM comenzó a ejecutarse
# TYPE jvm_classes_loaded_total counter
jvm_classes_loaded_total 17041.0
# HELP jvm_classes_unloaded_total El número total de clases que han sido descargadas desde que la JVM comenzó a ejecutarse
# TYPE jvm_classes_unloaded_total counter
jvm_classes_unloaded_total 48.0
# HELP bwce_activity_stats_list Lista de estadísticas de actividad BWCE
# TYPE bwce_activity_stats_list gauge
# HELP bwce_activity_counter_list Lista de contadores relacionados con la actividad BWCE
# TYPE bwce_activity_counter_list gauge
# HELP all_activity_events_count Conteo de todos los eventos de actividad BWCE por estado
# TYPE all_activity_events_count counter
all_activity_events_count{StateName="CANCELLED",} 0.0
all_activity_events_count{StateName="COMPLETED",} 0.0
all_activity_events_count{StateName="STARTED",} 0.0
all_activity_events_count{StateName="FAULTED",} 0.0
# HELP activity_events_count Conteo de todos los eventos de actividad BWCE por proceso, estado de actividad
# TYPE activity_events_count counter
# HELP activity_total_evaltime_count Tiempo total de evaluación de actividad BWCE por proceso y actividad
# TYPE activity_total_evaltime_count counter
# HELP activity_total_duration_count Tiempo total de duración de actividad BWCE por proceso y actividad
# TYPE activity_total_duration_count counter
# HELP bwpartner_instance:total_request Solicitud total para la invocación del socio que se mapeó desde las actividades
# TYPE bwpartner_instance:total_request counter
# HELP bwpartner_instance:total_duration_ms Duración total para la invocación del socio que se mapeó desde las actividades (ejecución o latencia)
# TYPE bwpartner_instance:total_duration_ms counter
# HELP bwce_process_stats Lista de estadísticas de proceso BWCE
# TYPE bwce_process_stats gauge
# HELP bwce_process_counter_list Lista de contadores relacionados con el proceso BWCE
# TYPE bwce_process_counter_list gauge
# HELP all_process_events_count Conteo de todos los eventos de proceso BWCE por estado
# TYPE all_process_events_count counter
all_process_events_count{StateName="CANCELLED",} 0.0
all_process_events_count{StateName="COMPLETED",} 0.0
all_process_events_count{StateName="STARTED",} 0.0
all_process_events_count{StateName="FAULTED",} 0.0
# HELP process_events_count Conteo de eventos de proceso BWCE por operación
# TYPE process_events_count counter
# HELP process_duration_seconds_total Duración de eventos de proceso BWCE por operación en segundos
# TYPE process_duration_seconds_total counter
# HELP process_duration_milliseconds_total Duración de eventos de proceso BWCE por operación en milisegundos
# TYPE process_duration_milliseconds_total counter
# HELP bwdefinitions:partner Conteo de eventos de proceso BWCE por operación
# TYPE bwdefinitions:partner counter
bwdefinitions:partner{ProcessName="t1.module.item.getTransactionData",ActivityName="FTLPublisher",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="TransactionService",PartnerOperation="GetTransactionsOperation",Location="internal",PartnerMiddleware="MW",} 1.0
bwdefinitions:partner{ProcessName=" t1.module.item.auditProcess",ActivityName="KafkaSendMessage",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="AuditService",PartnerOperation="AuditOperation",Location="internal",PartnerMiddleware="MW",} 1.0
bwdefinitions:partner{ProcessName="t1.module.item.getCustomerData",ActivityName="JMSRequestReply",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="CustomerService",PartnerOperation="GetCustomerDetailsOperation",Location="internal",PartnerMiddleware="MW",} 1.0
# HELP bwdefinitions:binding Repositorio de tiempo de diseño BW - definición de enlace/transporte
# TYPE bwdefinitions:binding counter
bwdefinitions:binding{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInterface="GetCustomer360:GetDataOperation",Binding="/customer",Transport="HTTP",} 1.0
# HELP bwdefinitions:service Repositorio de tiempo de diseño BW - definición de servicio
# TYPE bwdefinitions:service counter
bwdefinitions:service{ProcessName="t1.module.sub.item.getCustomerData",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
bwdefinitions:service{ProcessName="t1.module.sub.item.auditProcess",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
bwdefinitions:service{ProcessName="t1.module.sub.orchestratorSubFlow",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
bwdefinitions:service{ProcessName="t1.module.Process",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
# HELP bwdefinitions:gateway Repositorio de tiempo de diseño BW - definición de puerta de enlace
# TYPE bwdefinitions:gateway counter
bwdefinitions:gateway{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",Endpoint="bwce-demo-mon-orchestrator-bwce",InteractionType="ISTIO",} 1.0
# HELP process_cpu_seconds_total Tiempo total de usuario y sistema de CPU gastado en segundos.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 1956.86
# HELP process_start_time_seconds Hora de inicio del proceso desde la época de Unix en segundos.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.604712447107E9
# HELP process_open_fds Número de descriptores de archivo abiertos.
# TYPE process_open_fds gauge
process_open_fds 763.0
# HELP process_max_fds Número máximo de descriptores de archivo abiertos.
# TYPE process_max_fds gauge
process_max_fds 1048576.0
# HELP process_virtual_memory_bytes Tamaño de la memoria virtual en bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 3.046207488E9
# HELP process_resident_memory_bytes Tamaño de la memoria residente en bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 4.2151936E8
# HELP jvm_gc_collection_seconds Tiempo gastado en un recolector de basura JVM dado en segundos.
# TYPE jvm_gc_collection_seconds summary
jvm_gc_collection_seconds_count{gc="G1 Young Generation",} 540.0
jvm_gc_collection_seconds_sum{gc="G1 Young Generation",} 4.754
jvm_gc_collection_seconds_count{gc="G1 Old Generation",} 2.0
jvm_gc_collection_seconds_sum{gc="G1 Old Generation",} 0.563
# HELP jvm_threads_current Conteo actual de hilos de una JVM
# TYPE jvm_threads_current gauge
jvm_threads_current 98.0
# HELP jvm_threads_daemon Conteo de hilos daemon de una JVM
# TYPE jvm_threads_daemon gauge
jvm_threads_daemon 43.0
# HELP jvm_threads_peak Conteo máximo de hilos de una JVM
# TYPE jvm_threads_peak gauge
jvm_threads_peak 98.0
# HELP jvm_threads_started_total Conteo de hilos iniciados de una JVM
# TYPE jvm_threads_started_total counter
jvm_threads_started_total 109.0
# HELP jvm_threads_deadlocked Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos o sincronizadores propios
# TYPE jvm_threads_deadlocked gauge
jvm_threads_deadlocked 0.0
# HELP jvm_threads_deadlocked_monitor Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos
# TYPE jvm_threads_deadlocked_monitor gauge
jvm_threads_deadlocked_monitor 0.0

Como puedes ver, muchas métricas, pero tengo que ser honesto, no estoy usando la mayoría de ellas en mis paneles y para generar mis alertas. Puedo usar las métricas relacionadas con el rendimiento de la aplicación para cada uno de los procesos de BusinessWorks y sus actividades, también el rendimiento de la memoria JVM y el número de hilos, pero cosas como cómo está funcionando el GC de la JVM para cada una de las capas de la JVM (G1 Young Generation, G1 Old Generation) no las estoy usando en absoluto.

Entonces, si muestro el mismo punto de acceso de métricas destacando las cosas que no estoy usando, sería algo como esto:

# HELP jvm_info Información de la versión de JVM
# TYPE jvm_info gauge
jvm_info{version="1.8.0_221-b27",vendor="Oracle Corporation",runtime="Java(TM) SE Runtime Environment",} 1.0

# HELP jvm_memory_bytes_used Bytes usados de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_used gauge
jvm_memory_bytes_used{area="heap",} 1.0318492E8
jvm_memory_bytes_used{area="nonheap",} 1.52094712E8
# HELP jvm_memory_bytes_committed Bytes comprometidos de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_committed gauge
jvm_memory_bytes_committed{area="heap",} 1.35266304E8
jvm_memory_bytes_committed{area="nonheap",} 1.71302912E8
# HELP jvm_memory_bytes_max Máximo de bytes de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_max gauge
jvm_memory_bytes_max{area="heap",} 1.073741824E9
jvm_memory_bytes_max{area="nonheap",} -1.0
# HELP jvm_memory_bytes_init Bytes iniciales de un área de memoria JVM dada.
# TYPE jvm_memory_bytes_init gauge
jvm_memory_bytes_init{area="heap",} 1.34217728E8
jvm_memory_bytes_init{area="nonheap",} 2555904.0

# HELP jvm_memory_pool_bytes_used Bytes usados de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_used gauge
jvm_memory_pool_bytes_used{pool="Code Cache",} 3.3337536E7
jvm_memory_pool_bytes_used{pool="Metaspace",} 1.04914136E8
jvm_memory_pool_bytes_used{pool="Compressed Class Space",} 1.384304E7
jvm_memory_pool_bytes_used{pool="G1 Eden Space",} 3.3554432E7
jvm_memory_pool_bytes_used{pool="G1 Survivor Space",} 1048576.0
jvm_memory_pool_bytes_used{pool="G1 Old Gen",} 6.8581912E7
# HELP jvm_memory_pool_bytes_committed Bytes comprometidos de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_committed gauge
jvm_memory_pool_bytes_committed{pool="Code Cache",} 3.3619968E7
jvm_memory_pool_bytes_committed{pool="Metaspace",} 1.19697408E8
jvm_memory_pool_bytes_committed{pool="Compressed Class Space",} 1.7985536E7
jvm_memory_pool_bytes_committed{pool="G1 Eden Space",} 4.6137344E7
jvm_memory_pool_bytes_committed{pool="G1 Survivor Space",} 1048576.0
jvm_memory_pool_bytes_committed{pool="G1 Old Gen",} 8.8080384E7
# HELP jvm_memory_pool_bytes_max Máximo de bytes de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_max gauge
jvm_memory_pool_bytes_max{pool="Code Cache",} 2.5165824E8
jvm_memory_pool_bytes_max{pool="Metaspace",} -1.0
jvm_memory_pool_bytes_max{pool="Compressed Class Space",} 1.073741824E9
jvm_memory_pool_bytes_max{pool="G1 Eden Space",} -1.0
jvm_memory_pool_bytes_max{pool="G1 Survivor Space",} -1.0
jvm_memory_pool_bytes_max{pool="G1 Old Gen",} 1.073741824E9
# HELP jvm_memory_pool_bytes_init Bytes iniciales de un pool de memoria JVM dado.
# TYPE jvm_memory_pool_bytes_init gauge
jvm_memory_pool_bytes_init{pool="Code Cache",} 2555904.0
jvm_memory_pool_bytes_init{pool="Metaspace",} 0.0
jvm_memory_pool_bytes_init{pool="Compressed Class Space",} 0.0
jvm_memory_pool_bytes_init{pool="G1 Eden Space",} 7340032.0
jvm_memory_pool_bytes_init{pool="G1 Survivor Space",} 0.0
jvm_memory_pool_bytes_init{pool="G1 Old Gen",} 1.26877696E8
# HELP jvm_buffer_pool_used_bytes Bytes usados de un pool de buffer JVM dado.
# TYPE jvm_buffer_pool_used_bytes gauge
jvm_buffer_pool_used_bytes{pool="direct",} 148590.0
jvm_buffer_pool_used_bytes{pool="mapped",} 0.0
# HELP jvm_buffer_pool_capacity_bytes Capacidad en bytes de un pool de buffer JVM dado.
# TYPE jvm_buffer_pool_capacity_bytes gauge
jvm_buffer_pool_capacity_bytes{pool="direct",} 148590.0
jvm_buffer_pool_capacity_bytes{pool="mapped",} 0.0
# HELP jvm_buffer_pool_used_buffers Buffers usados de un pool de buffer JVM dado.
# TYPE jvm_buffer_pool_used_buffers gauge
jvm_buffer_pool_used_buffers{pool="direct",} 19.0
jvm_buffer_pool_used_buffers{pool="mapped",} 0.0
# HELP jvm_classes_loaded El número de clases que están actualmente cargadas en la JVM
# TYPE jvm_classes_loaded gauge
jvm_classes_loaded 16993.0
# HELP jvm_classes_loaded_total El número total de clases que han sido cargadas desde que la JVM comenzó a ejecutarse
# TYPE jvm_classes_loaded_total counter
jvm_classes_loaded_total 17041.0
# HELP jvm_classes_unloaded_total El número total de clases que han sido descargadas desde que la JVM comenzó a ejecutarse
# TYPE jvm_classes_unloaded_total counter
jvm_classes_unloaded_total 48.0

# HELP bwce_activity_stats_list Lista de estadísticas de actividad BWCE
# TYPE bwce_activity_stats_list gauge
# HELP bwce_activity_counter_list Lista de contadores relacionados con la actividad BWCE
# TYPE bwce_activity_counter_list gauge
# HELP all_activity_events_count Conteo de todos los eventos de actividad BWCE por estado
# TYPE all_activity_events_count counter
all_activity_events_count{StateName="CANCELLED",} 0.0
all_activity_events_count{StateName="COMPLETED",} 0.0
all_activity_events_count{StateName="STARTED",} 0.0
all_activity_events_count{StateName="FAULTED",} 0.0
# HELP activity_events_count Conteo de todos los eventos de actividad BWCE por proceso, estado de actividad
# TYPE activity_events_count counter
# HELP activity_total_evaltime_count Tiempo total de evaluación de actividad BWCE por proceso y actividad
# TYPE activity_total_evaltime_count counter
# HELP activity_total_duration_count Tiempo total de duración de actividad BWCE por proceso y actividad
# TYPE activity_total_duration_count counter
# HELP bwpartner_instance:total_request Solicitud total para la invocación del socio que se mapeó desde las actividades
# TYPE bwpartner_instance:total_request counter
# HELP bwpartner_instance:total_duration_ms Duración total para la invocación del socio que se mapeó desde las actividades (ejecución o latencia)
# TYPE bwpartner_instance:total_duration_ms counter
# HELP bwce_process_stats Lista de estadísticas de proceso BWCE
# TYPE bwce_process_stats gauge
# HELP bwce_process_counter_list Lista de contadores relacionados con el proceso BWCE
# TYPE bwce_process_counter_list gauge
# HELP all_process_events_count Conteo de todos los eventos de proceso BWCE por estado
# TYPE all_process_events_count counter
all_process_events_count{StateName="CANCELLED",} 0.0
all_process_events_count{StateName="COMPLETED",} 0.0
all_process_events_count{StateName="STARTED",} 0.0
all_process_events_count{StateName="FAULTED",} 0.0
# HELP process_events_count Conteo de eventos de proceso BWCE por operación
# TYPE process_events_count counter
# HELP process_duration_seconds_total Duración de eventos de proceso BWCE por operación en segundos
# TYPE process_duration_seconds_total counter
# HELP process_duration_milliseconds_total Duración de eventos de proceso BWCE por operación en milisegundos
# TYPE process_duration_milliseconds_total counter
# HELP bwdefinitions:partner Conteo de eventos de proceso BWCE por operación
# TYPE bwdefinitions:partner counter
bwdefinitions:partner{ProcessName="t1.module.item.getTransactionData",ActivityName="FTLPublisher",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="TransactionService",PartnerOperation="GetTransactionsOperation",Location="internal",PartnerMiddleware="MW",} 1.0
bwdefinitions:partner{ProcessName=" t1.module.item.auditProcess",ActivityName="KafkaSendMessage",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="AuditService",PartnerOperation="AuditOperation",Location="internal",PartnerMiddleware="MW",} 1.0
bwdefinitions:partner{ProcessName="t1.module.item.getCustomerData",ActivityName="JMSRequestReply",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="CustomerService",PartnerOperation="GetCustomerDetailsOperation",Location="internal",PartnerMiddleware="MW",} 1.0
# HELP bwdefinitions:binding Repositorio de tiempo de diseño BW - definición de enlace/transporte
# TYPE bwdefinitions:binding counter
bwdefinitions:binding{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInterface="GetCustomer360:GetDataOperation",Binding="/customer",Transport="HTTP",} 1.0
# HELP bwdefinitions:service Repositorio de tiempo de diseño BW - definición de servicio
# TYPE bwdefinitions:service counter
bwdefinitions:service{ProcessName="t1.module.sub.item.getCustomerData",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
bwdefinitions:service{ProcessName="t1.module.sub.item.auditProcess",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
bwdefinitions:service{ProcessName="t1.module.sub.orchestratorSubFlow",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
bwdefinitions:service{ProcessName="t1.module.Process",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0
# HELP bwdefinitions:gateway Repositorio de tiempo de diseño BW - definición de puerta de enlace
# TYPE bwdefinitions:gateway counter
bwdefinitions:gateway{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",Endpoint="bwce-demo-mon-orchestrator-bwce",InteractionType="ISTIO",} 1.0
# HELP process_cpu_seconds_total Tiempo total de usuario y sistema de CPU gastado en segundos.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 1956.86
# HELP process_start_time_seconds Hora de inicio del proceso desde la época de Unix en segundos.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.604712447107E9
# HELP process_open_fds Número de descriptores de archivo abiertos.
# TYPE process_open_fds gauge
process_open_fds 763.0
# HELP process_max_fds Número máximo de descriptores de archivo abiertos.
# TYPE process_max_fds gauge
process_max_fds 1048576.0
# HELP process_virtual_memory_bytes Tamaño de la memoria virtual en bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 3.046207488E9
# HELP process_resident_memory_bytes Tamaño de la memoria residente en bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 4.2151936E8
# HELP jvm_gc_collection_seconds Tiempo gastado en un recolector de basura JVM dado en segundos.
# TYPE jvm_gc_collection_seconds summary
jvm_gc_collection_seconds_count{gc="G1 Young Generation",} 540.0
jvm_gc_collection_seconds_sum{gc="G1 Young Generation",} 4.754
jvm_gc_collection_seconds_count{gc="G1 Old Generation",} 2.0
jvm_gc_collection_seconds_sum{gc="G1 Old Generation",} 0.563

# HELP jvm_threads_current Conteo actual de hilos de una JVM
# TYPE jvm_threads_current gauge
jvm_threads_current 98.0
# HELP jvm_threads_daemon Conteo de hilos daemon de una JVM
# TYPE jvm_threads_daemon gauge
jvm_threads_daemon 43.0
# HELP jvm_threads_peak Conteo máximo de hilos de una JVM
# TYPE jvm_threads_peak gauge
jvm_threads_peak 98.0
# HELP jvm_threads_started_total Conteo de hilos iniciados de una JVM
# TYPE jvm_threads_started_total counter
jvm_threads_started_total 109.0
# HELP jvm_threads_deadlocked Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos o sincronizadores propios
# TYPE jvm_threads_deadlocked gauge
jvm_threads_deadlocked 0.0
# HELP jvm_threads_deadlocked_monitor Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos
# TYPE jvm_threads_deadlocked_monitor gauge
jvm_threads_deadlocked_monitor 0.0

Entonces, puede ser un 50% de la respuesta del punto de acceso de métricas la parte que no estoy usando, entonces, ¿por qué estoy usando espacio en disco que estoy pagando para almacenarlo? Y esto es solo para un «exportador crítico», uno que trato de usar tanta información como sea posible, pero piensa en cuántos exportadores tienes y cuánta información usas para cada uno de ellos.

Ok, entonces ahora el propósito y la motivación de esta publicación están claros, pero ¿qué podemos hacer al respecto?

Descubriendo la API REST

Prometheus tiene una increíble API REST para exponer toda la información que puedas desear. Si alguna vez has usado la Interfaz Gráfica para Prometheus (mostrada a continuación) estás usando la API REST porque esto es lo que está detrás de ella.

Prometheus Storage: ¿Cómo optimizar el uso del disco?
Vista de destino de la Interfaz Gráfica de Prometheus

Tenemos toda la documentación sobre la API REST en la documentación oficial de Prometheus:

https://prometheus.io/docs/prometheus/latest/querying/api/

Pero, ¿qué nos proporciona esta API en términos de la base de datos de series temporales TSDB que utiliza Prometheus?

APIs de Administración de TSDB

Tenemos una API específica para gestionar el rendimiento de la base de datos TSDB, pero para poder usarla, necesitamos habilitar la API de Administración. Y eso se hace proporcionando la siguiente bandera donde estamos lanzando el servidor Prometheus --web.enable-admin-api.

Si estamos usando el Prometheus Operator Helm Chart para desplegar esto, necesitamos usar el siguiente elemento en nuestro values.yaml

## EnableAdminAPI habilita la API HTTP administrativa de Prometheus, que incluye funcionalidades como eliminar series temporales.    
## Esto está deshabilitado por defecto.
## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis
## enableAdminAPI: true

Tenemos muchas opciones habilitadas cuando habilitamos esta API administrativa, pero hoy nos vamos a centrar en una sola operación REST que es el «stats». Este es el único método relacionado con TSDB que no requiere habilitar la API de Administración. Esta operación, como podemos leer en la documentación de Prometheus, devuelve los siguientes elementos:

headStats: Esto proporciona los siguientes datos sobre el bloque principal de la TSDB:

  • numSeries: El número de series.
  • chunkCount: El número de fragmentos.
  • minTime: La marca de tiempo mínima actual en milisegundos.
  • maxTime: La marca de tiempo máxima actual en milisegundos.

seriesCountByMetricName: Esto proporcionará una lista de nombres de métricas y su conteo de series.

labelValueCountByLabelName: Esto proporcionará una lista de nombres de etiquetas y su conteo de valores.

memoryInBytesByLabelName Esto proporcionará una lista de nombres de etiquetas y la memoria utilizada en bytes. El uso de memoria se calcula sumando la longitud de todos los valores para un nombre de etiqueta dado.

seriesCountByLabelPair Esto proporcionará una lista de pares de valores de etiquetas y su conteo de series.

Para acceder a esa API, necesitamos acceder al siguiente punto de acceso:

GET /api/v1/status/tsdb

Entonces, cuando hago eso en mi implementación de Prometheus, obtengo algo similar a esto:

{
"status":"success",
"data":{
"seriesCountByMetricName":[
{
"name":"apiserver_request_duration_seconds_bucket",
"value":34884
},
{
"name":"apiserver_request_latencies_bucket",
"value":7344
},
{
"name":"etcd_request_duration_seconds_bucket",
"value":6000
},
{
"name":"apiserver_response_sizes_bucket",
"value":3888
},
{
"name":"apiserver_request_latencies_summary",
"value":2754
},
{
"name":"etcd_request_latencies_summary",
"value":1500
},
{
"name":"apiserver_request_count",
"value":1216
},
{
"name":"apiserver_request_total",
"value":1216
},
{
"name":"container_tasks_state",
"value":1140
},
{
"name":"apiserver_request_latencies_count",
"value":918
}
],
"labelValueCountByLabelName":[
{
"name":"__name__",
"value":2374
},
{
"name":"id",
"value":210
},
{
"name":"mountpoint",
"value":208
},
{
"name":"le",
"value":195
},
{
"name":"type",
"value":185
},
{
"name":"name",
"value":181
},
{
"name":"resource",
"value":170
},
{
"name":"secret",
"value":168
},
{
"name":"image",
"value":107
},
{
"name":"container_id",
"value":97
}
],
"memoryInBytesByLabelName":[
{
"name":"__name__",
"value":97729
},
"name":"id",
"value":21450
},
{
"name":"mountpoint",
"value":18123
},
{
"name":"name",
"value":13831
},
{
"name":"image",
"value":8005
},
{
"name":"container_id",
"value":7081
},
{
"name":"image_id",
"value":6872
},
{
"name":"secret",
"value":5054
},
{
"name":"type",
"value":4613
},
{
"name":"resource",
"value":3459
}
],
"seriesCountByLabelValuePair":[
{
"name":"namespace=default",
"value":72064
},
{
"name":"service=kubernetes",
"value":70921
},
{
"name":"endpoint=https",
"value":70917
},
{
"name":"job=apiserver",
"value":70917
},
{
"name":"component=apiserver",
"value":57992
},
{
"name":"instance=192.168.185.199:443",
"value":40343
},
{
"name":"__name__=apiserver_request_duration_seconds_bucket",
"value":34884
},
{
"name":"version=v1",
"value":31152
},
{
"name":"instance=192.168.112.31:443",
"value":30574
},
{
"name":"scope=cluster",
"value":29713
}
]
}
}

También podemos verificar la misma información si usamos la nueva y experimental Interfaz de Usuario React en el siguiente punto de acceso:

/new/tsdb-status
Prometheus Storage: ¿Cómo optimizar el uso del disco?
Visualización gráfica del conteo de las 10 series principales por nombre de métrica en la nueva interfaz de usuario de Prometheus

Entonces, con eso, obtendrás las 10 series y etiquetas principales que están dentro de tu base de datos de series temporales, por lo que en caso de que algunas de ellas no sean útiles, puedes simplemente deshacerte de ellas usando los enfoques normales para eliminar una serie o una etiqueta. Esto es genial, pero ¿qué pasa si todas las que se muestran aquí son relevantes, qué podemos hacer al respecto?

Mmmm, tal vez podamos usar PromQL para monitorear esto (enfoque de dogfooding). Así que si quisiéramos extraer la misma información pero usando PromQL, podemos hacerlo con la siguiente consulta:

topk(10, count by (__name__)({__name__=~".+"}))
Prometheus Storage: ¿Cómo optimizar el uso del disco?
Top 10 de series de métricas generadas y almacenadas en la base de datos de series temporales

Y ahora tenemos todo el poder en mis manos. Por ejemplo, echemos un vistazo no a las 10 más relevantes, sino a las 100 más relevantes o cualquier otro filtro que necesitemos aplicar. Por ejemplo, veamos las métricas relacionadas con la JVM que discutimos al principio. Y lo haremos con la siguiente consulta PromQL:

topk(100, count by (__name__)({__name__=~"jvm.+"}))
Prometheus Storage: ¿Cómo optimizar el uso del disco?
Top 100 de series de métricas relacionadas con métricas de JVM

Así que podemos ver que tenemos al menos 150 series relacionadas con métricas que no estoy usando en absoluto. Pero hagámoslo aún mejor, echemos un vistazo a lo mismo pero agrupado por nombres de trabajos:

topk(10, count by (job,__name__)({__name__=~".+"}))
Prometheus Storage: ¿Cómo optimizar el uso del disco?
Resultado de verificar el conteo de las 10 series de métricas principales con el trabajo que las está generando

📚 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.