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í:
GitHub – kubernetes/kubernetes: Production-Grade Container Scheduling and Management
Production-Grade Container Scheduling and Management – GitHub – kubernetes/kubernetes: Production-Grade Container Scheduling and Management
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.
Kubernetes Just Deprecated Docker Support. What Now?
Will this kill Docker?
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.
Imagen a través de la Cloud Native Computing Foundation
Estos son los que me gustaría destacar hoy:
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
La antigua empresa Docker que ha sido adquirida por Mirantis es otra de las opciones habituales cuando hablamos de plataformas soportadas.
VMware Tanzu
VMware Tanzu, también proveniente de la adquisición de Pivotal por parte de VMware, es una plataforma de Kubernetes.
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
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.
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.
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:
Opción A: Visual Diff de tus procesosOpció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!
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 — 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 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 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 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 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!
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.
XMLStarlet Command Line XML Toolkit: News
XMLStarlet Command Line XML Toolkit
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:
XMLStarlet Command Line XML Toolkit: Download
XMLStarlet Command Line XML Toolkit
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
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.
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.
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:
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:
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
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__=~".+"}))
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.+"}))
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__=~".+"}))
Resultado de verificar el conteo de las 10 series de métricas principales con el trabajo que las está generando
Prometheus es uno de los sistemas clave en las arquitecturas de nube actuales. El segundo proyecto graduado de la Cloud Native Computing Foundation (CNCF) después de Kubernetes, y es la solución de monitoreo por excelencia en la mayoría de las cargas de trabajo que se ejecutan en Kubernetes.
Si ya has usado Prometheus por algún tiempo, sabes que se basa en una base de datos de series temporales, por lo que el almacenamiento de Prometheus es uno de los elementos clave. Basado en sus propias palabras de la página oficial de Prometheus:
Storage | Prometheus
An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.
Cada serie temporal se identifica de manera única por su nombre de métrica y pares clave-valor opcionales llamados etiquetas, y esa serie es similar a las tablas en un modelo relacional. Y dentro de cada una de esas series, tenemos muestras que son similares a las tuplas. Y cada una de las muestras contiene un valor flotante y una marca de tiempo con precisión de milisegundos.
Enfoque predeterminado en disco
Por defecto, Prometheus utiliza un enfoque de almacenamiento local guardando todas esas muestras en disco. Estos datos se distribuyen en diferentes archivos y carpetas para agrupar diferentes fragmentos de datos.
Así que, tenemos carpetas para crear esos grupos, y por defecto, son un bloque de dos horas y pueden contener uno o más archivos dependiendo de la cantidad de datos ingeridos en ese período de tiempo, ya que cada carpeta contiene todas las muestras para esa línea de tiempo específica.
Además, cada carpeta también tiene algún tipo de archivos de metadatos que ayudan a localizar las métricas de cada uno de los archivos de datos.
Un archivo es persistente de manera completa cuando el bloque ha terminado, y antes de eso, se mantiene en memoria y utiliza una técnica de registro de escritura anticipada para recuperar los datos en caso de un fallo del servidor de Prometheus.
Así que, a un nivel alto, la estructura de directorios del directorio de datos de un servidor de Prometheus se verá algo así:
Integración de Almacenamiento Remoto
El almacenamiento predeterminado en disco es bueno y tiene algunas limitaciones en términos de escalabilidad y durabilidad, incluso considerando la mejora de rendimiento de la última versión de TSDB. Así que, si queremos explorar otras opciones para almacenar estos datos, Prometheus proporciona una manera de integrarse con ubicaciones de almacenamiento remoto.
Proporciona una API que permite escribir muestras que se están ingiriendo en una URL remota y, al mismo tiempo, poder leer datos de muestra para esa URL remota como se muestra en la imagen a continuación:
Como siempre en cualquier cosa relacionada con Prometheus, el número de adaptadores creados usando este patrón es enorme, y se puede ver en el siguiente enlace en detalle:
Integrations | Prometheus
An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.
Resumen
Saber cómo funciona el almacenamiento de Prometheus es crítico para entender cómo podemos optimizar su uso para mejorar el rendimiento de nuestra solución de monitoreo y proporcionar un despliegue rentable.
En las siguientes publicaciones, vamos a cubrir cómo podemos optimizar el uso de esta capa de almacenamiento, asegurándonos de que solo se almacenen las métricas y muestras que son importantes para usar, y también cómo analizar cuáles métricas son las más utilizadas de la base de datos de series temporales para poder tomar buenas decisiones sobre qué métricas deben ser eliminadas y cuáles deben mantenerse.
Aprende cómo puedes aprovechar el uso de Snyk dentro de tu instalación del motor Docker
La seguridad es el tema más relevante en la arquitectura moderna. Necesita ser manejado desde todas las diferentes perspectivas. Tener un solo equipo auditando las plataformas y los desarrollos que construimos no es suficiente.
La introducción de DevSecOps como la nueva normalidad, incluyendo a los equipos de seguridad y las políticas como parte del proceso de desarrollo para evitar que la seguridad se convierta en un obstáculo para la innovación y asegurar que los artefactos que desplegamos estén seguros, ha dejado esto claro.
El escaneo de imágenes Docker es uno de los temas más importantes que podemos cubrir respecto a las imágenes de contenedores para saber que todos los componentes internos que forman parte de la imagen están a salvo de vulnerabilidades. Usualmente confiamos en algunos sistemas para hacerlo.
Escribí un artículo sobre el uso de una de las opciones más relevantes (Harbor) del mundo de código abierto para hacer este trabajo.
Y esto también está siendo realizado por diferentes repositorios Docker de proveedores de nube como Amazon ECR a partir de este año. Pero, ¿por qué necesitamos esperar hasta que subamos las imágenes a un registro Docker externo? ¿Por qué no podemos hacerlo en nuestro entorno local?
Ahora podemos. La versión 2.5.0.1 del motor Docker también incluye los componentes de Snyk necesarios para inspeccionar las imágenes Docker directamente desde la línea de comandos:
Entonces, comencemos. Abramos un nuevo terminal y escribamos el siguiente comando:
docker scan <nombre-de-imagen>
Tan pronto como escribamos esto, el comando nos dirá que este proceso de escaneo usará Snyk para hacerlo y necesitamos autorizar el acceso a esos servicios para realizar el proceso de escaneo.
Después de eso, obtenemos una lista de todas las vulnerabilidades detectadas, como puedes ver en la imagen a continuación:
Escaneo de vulnerabilidades usando tu cliente Docker local
Para cada una de las vulnerabilidades, puedes ver los siguientes datos:
Información detallada proporcionada para cada una de las vulnerabilidades detectadas
Obtenemos la biblioteca con la vulnerabilidad, el nivel de severidad y una breve descripción de la misma. Si necesitas más detalles, también puedes consultar la URL proporcionada que está vinculada a una página de descripción para esa vulnerabilidad:
Página detallada de vulnerabilidades de snyk
Finalmente, también proporciona las fuentes que introducen esta biblioteca en tu imagen para que esto pueda resolverse rápidamente.
También proporciona una vista de alto nivel de toda la imagen, como puedes ver aquí:
Visión general de tus imágenes Docker con todas las vulnerabilidades detectadas
Así que ahora no tienes excusa para no tener todas tus imágenes seguras antes de subirlas a tu repositorio local. ¡Hagámoslo!
Descubre cómo puedes mejorar el tamaño de tus imágenes de Docker para una mejor experiencia y ahorros dentro de tu organización.
La contenedorización es la nueva normalidad. Todos somos conscientes de eso. Todas las nuevas versiones del software corporativo y todos los proyectos de código abierto están incluyendo las opciones para usar una imagen de Docker para ejecutar su software. Probablemente ya hayas estado haciendo tus pruebas o incluso ejecutando cargas de trabajo en producción basadas en imágenes de Docker que has construido tú mismo. Si ese es el caso, probablemente conozcas uno de los grandes desafíos cuando realizas este tipo de tarea: ¿Cómo optimizar el tamaño de la imagen que generas? Una de las principales razones por las que la imagen de Docker puede ser tan grande es porque se construyen siguiendo un concepto de capas. Y eso significa que cada una de las imágenes se crea como la adición de capas, cada una asociada con los diferentes comandos que tienes en tu Dockerfile.Explicación gráfica de cómo se compone una imagen de Docker.
Usa dive para analizar el tamaño de tus imágenes
dive es un proyecto de código abierto que proporciona una vista detallada de la composición de tus imágenes de Docker. Funciona como una aplicación de interfaz de línea de comandos que tiene una gran vista del contenido de las capas, como puedes ver en la imagen a continuación:Ejecución de Dive de una imagen de BusinessWorks Container Edition La herramienta sigue una interfaz n-curses (si eres lo suficientemente mayor para recordar cómo eran las herramientas antes de que las interfaces gráficas de usuario fueran algo; debería parecerte familiar) y tiene estas características principales:
Esta herramienta proporcionará la lista de capas en la parte superior izquierda de la pantalla y el tamaño asociado con cada una de ellas.
Proporciona estadísticas generales sobre la eficiencia de la imagen (un valor porcentual), una vista potencial del tamaño desperdiciado y el tamaño total de la imagen.
Para cada una de las capas seleccionadas, obtienes una vista en el sistema de archivos para esta vista con los datos del tamaño de cada carpeta.
También obtén una vista de los elementos más grandes y el número de replicaciones de estos objetos.
Ahora, tienes una herramienta que te ayudará primero a saber cómo se construye tu imagen y obtener datos de rendimiento de cada uno de los ajustes que haces para mejorar ese tamaño. Así que, comencemos con los trucos.
1.- ¡Limpia tu imagen!
Este primero es bastante obvio, pero eso no significa que no sea importante. Por lo general, cuando creas una imagen de Docker, sigues el mismo patrón:
Declaras una imagen base para aprovechar.
Agregas recursos para hacer algún trabajo.
Haces algún trabajo.
Por lo general, olvidamos un paso adicional: ¡Limpiar los recursos agregados cuando ya no son necesarios! Por lo tanto, es importante asegurarse de eliminar cada uno de los archivos que ya no necesitamos. Esto también se aplica a otros componentes como la caché de apt cuando estamos instalando un nuevo paquete que necesitamos o cualquier carpeta temporal que necesitemos para realizar una instalación o algún trabajo para construir la imagen.
2.- Ten cuidado con cómo creas tu Dockerfile
Como ya mencionamos, cada uno de los comandos que declaramos en nuestro Dockerfile genera una nueva capa. Por lo tanto, es importante tener mucho cuidado con las líneas que tenemos en el Dockerfile. Incluso si esto es un compromiso con respecto a la legibilidad del Dockerfile, es importante intentar fusionar comandos en la misma primitiva RUN para asegurarnos de no estar creando capas adicionales.Ejemplo de un Dockerfile con comandos fusionados También puedes usar linters de Docker como Hadolint que te ayudarán con esto y otros anti-patrones que deberías evitar cuando estás creando un Dockerfile.
3.- Opta por docker build — squash
Las últimas versiones del motor de Docker proporcionan una nueva opción cuando construyes tus imágenes para crear con el tamaño minimizado squashing de las capas intermedias que pueden ser creadas como parte del proceso de creación del Dockerfile. Eso funciona, proporcionando una nueva bandera cuando estás haciendo la construcción de tu imagen. Así que, en lugar de hacer esto:
Para poder usar esta opción, debes habilitar las características experimentales en tu Docker Engine. Para hacer eso, necesitas habilitarlo en tu archivo daemon.json y reiniciar el motor. Si estás usando Docker para Windows o Docker para Mac, puedes hacerlo usando la interfaz de usuario como se muestra a continuación:
Resumen
Estos ajustes te ayudarán a hacer tus imágenes de Docker más delgadas y mucho más agradable el proceso de extraer y empujar y, al mismo tiempo, incluso ahorrar algo de dinero con respecto al almacenamiento de las imágenes en el repositorio de tu elección. Y no solo para ti, sino para muchos otros que pueden aprovechar el trabajo que estás haciendo. Así que piensa en ti mismo, pero también piensa en la comunidad.
En el post anterior de esta serie sobre cómo configurar un clúster EKS híbrido utilizando tanto máquinas EC2 tradicionales como opciones sin servidor usando Fargate, pudimos crear el clúster EKS con ambas modalidades de implementación disponibles. ¡Si aún no lo has visto, hazlo ahora! https://medium.com/@alexandrev/hybrid-aws-kubernetes-cluster-using-eks-ec2-and-fargate-13198d864baa En ese punto, tenemos un clúster vacío con todo listo para desplegar nuevas cargas de trabajo, pero aún necesitamos configurar algunas cosas antes de realizar el despliegue. Lo primero es decidir qué cargas de trabajo se van a desplegar usando la opción sin servidor y cuáles usarán la opción tradicional de EC2. Por defecto, todas las cargas de trabajo desplegadas en los espacios de nombres default y kube-system como puedes ver en la imagen a continuación desde la Consola de AWS: Eso significa que todas las cargas de trabajo del espacio de nombres default y del espacio de nombres kube-system se desplegarán de manera sin servidor. Si eso es lo que deseas, perfecto. Pero a veces te gustaría comenzar con un conjunto delimitado de espacios de nombres donde te gustaría usar la opción sin servidor y confiar en el despliegue tradicional. Podemos verificar esa misma información usando eksctl y para hacerlo necesitamos escribir el siguiente comando:
eksctl get fargateprofile --cluster cluster-test-hybrid -o yaml
La salida de ese comando debería ser algo similar a la información que podemos ver en la Consola de AWS:
NOTA: Si no recuerdas el nombre de tu clúster solo necesitas escribir el comando eksctl get clusters
Entonces, esto es lo que vamos a hacer y para hacerlo lo primero que necesitamos hacer es crear un nuevo espacio de nombres llamado “serverless” que va a contener nuestro despliegue sin servidor y para hacerlo usamos un comando kubectl de la siguiente manera:
kubectl create namespace serverless
Y ahora, solo necesitamos crear un nuevo perfil de fargate que va a reemplazar el que tenemos en este momento y para hacerlo necesitamos usar nuevamente eksctl para manejar ese trabajo:
NOTA: También podemos usar no solo el espacio de nombres para limitar el alcance de nuestro despliegue sin servidor sino también etiquetas, por lo que podemos tener en el mismo espacio de nombres cargas de trabajo que se despliegan usando el despliegue tradicional y otras usando la modalidad sin servidor. Eso nos dará todas las posibilidades para diseñar tu clúster como desees. Para hacerlo, añadiremos el argumento labels en un formato clave=valor.
Y obtendremos una salida similar a esta:
[ℹ] creando perfil de Fargate “fp-serverless-profile” en el clúster EKS “cluster-test-hybrid”
[ℹ] creado perfil de Fargate “fp-serverless-profile” en el clúster EKS “cluster-test-hybrid”
Si ahora verificamos el número de perfiles que tenemos disponibles deberíamos obtener dos perfiles manejando tres espacios de nombres (los que son gestionados por el perfil por defecto — default y kube-system — y el que — serverless — es gestionado por el que acabamos de crear ahora) Solo usaremos el siguiente comando para eliminar el perfil por defecto:
Y la salida de ese comando debería ser similar a esta:
[ℹ] eliminado perfil de Fargate “fp-default” en el clúster EKS “cluster-test-hybrid”
Y después de eso, ahora tenemos listo nuestro clúster con un alcance limitado para despliegues sin servidor. En el próximo post de la serie, solo desplegaremos cargas de trabajo en ambas modalidades para ver la diferencia entre ellas. Así que, no te pierdas las actualizaciones sobre esta serie asegurándote de seguir mis publicaciones, y si te gustó el artículo, o tienes algunas dudas o comentarios, por favor deja tus comentarios usando los comentarios a continuación!
Cluster de Kubernetes EKS Fargate AWS: Aprende cómo crear un clúster de Kubernetes que también pueda utilizar todo el poder de la computación sin servidor usando AWS Fargate
Sabemos que hay varios movimientos y paradigmas que nos están empujando fuertemente a cambiar nuestras arquitecturas tratando de aprovechar mucho más los servicios gestionados y cuidando el nivel operativo para que podamos centrarnos en lo que realmente es importante para nuestro propio negocio: crear aplicaciones y entregar valor a través de ellas.
AWS de Amazon ha sido un socio crítico durante ese viaje, especialmente en el mundo de los contenedores. Con el lanzamiento de EKS hace algún tiempo, pudieron proporcionar un servicio de Kubernetes gestionado que todos pueden usar, pero también introduciendo la solución CaaS Fargate también nos da el poder de ejecutar una carga de trabajo de contenedor de manera sin servidor, sin necesidad de preocuparse por nada más.
Pero podrías estar pensando si esos servicios pueden trabajar juntos. Y la respuesta corta es sí. Pero aún más importante que eso, estamos viendo que también pueden trabajar en un modo mixto:
Así que puedes tener un clúster EKS que tiene algunos nodos que son servicios Fargate y algunos nodos que son máquinas EC2 normales para cargas de trabajo que están trabajando de manera con estado o se ajustan mejor a un enfoque tradicional de EC2. Y todo funciona bajo las mismas reglas y es gestionado por el mismo clúster EKS.
Entonces, eso suena increíble, pero, ¿cómo podemos hacer eso? Vamos a ver.
eksctl
Para llegar a ese punto hay una herramienta que necesitamos presentar primero, y esa herramienta se llama eksctl y es una utilidad de línea de comandos que nos ayuda a realizar cualquier acción para interactuar con el servicio EKS y simplifica mucho el trabajo a realizar y también permite automatizar la mayoría de las tareas en un modo no requerido por humanos. Así que, lo primero que necesitamos es tener eksctl listo en nuestras plataformas. Veamos cómo podemos obtener eso.
Aquí tenemos todos los detalles de Amazon sobre cómo instalar eksctl en diferentes plataformas, no importa si estás usando Windows, Linux o MacOS X:
Installing or updating eksctl – Amazon EKS
Learn how to install or update the eksctl command line tool. This tool is used to create and work with an Amazon EKS cluster.
Después de hacer eso, podemos verificar que hemos instalado el software eksctl ejecutando el comando:
eksctl version
Y deberíamos obtener una salida similar a esta:
Salida del comando eksctl version
Así que después de hacer eso, podemos ver que tenemos acceso a todo el poder detrás del servicio EKS simplemente escribiendo estos simples comandos en nuestra ventana de consola.
Creando el Clúster Híbrido EKS
Ahora, vamos a crear un entorno mixto con algunas máquinas EC2 y habilitar el soporte Fargate para EKS. Para hacer eso, comenzaremos con el siguiente comando:
eksctl create cluster --version=1.15 --name=cluster-test-hybrid --region=eu-west-1 --max-pods-per-node=1000 --fargate
[ℹ] eksctl version 0.26.0
[ℹ] usando la región eu-west-1
[ℹ] configurando zonas de disponibilidad a [eu-west-1c eu-west-1a eu-west-1b]
[ℹ] subredes para eu-west-1c - pública:192.168.0.0/19 privada:192.168.96.0/19
[ℹ] subredes para eu-west-1a - pública:192.168.32.0/19 privada:192.168.128.0/19
[ℹ] subredes para eu-west-1b - pública:192.168.64.0/19 privada:192.168.160.0/19
[ℹ] usando la versión de Kubernetes 1.15
[ℹ] creando el clúster EKS "cluster-test-hybrid" en la región "eu-west-1" con perfil Fargate
[ℹ] si encuentras algún problema, revisa la consola de CloudFormation o intenta 'eksctl utils describe-stacks --region=eu-west-1 --cluster=cluster-test-hybrid'
[ℹ] el registro de CloudWatch no estará habilitado para el clúster "cluster-test-hybrid" en "eu-west-1"
[ℹ] puedes habilitarlo con 'eksctl utils update-cluster-logging --region=eu-west-1 --cluster=cluster-test-hybrid'
[ℹ] el acceso al punto final de la API de Kubernetes usará el valor predeterminado de {publicAccess=true, privateAccess=false} para el clúster "cluster-test-hybrid" en "eu-west-1"
[ℹ] 2 tareas secuenciales: { crear el plano de control del clúster "cluster-test-hybrid", crear perfiles fargate }
[ℹ] construyendo la pila del clúster "eksctl-cluster-test-hybrid-cluster"
[ℹ] desplegando la pila "eksctl-cluster-test-hybrid-cluster"
[ℹ] creando el perfil Fargate "fp-default" en el clúster EKS "cluster-test-hybrid"
[ℹ] creado el perfil Fargate "fp-default" en el clúster EKS "cluster-test-hybrid"
[ℹ] "coredns" ahora es programable en Fargate
[ℹ] "coredns" ahora está programado en Fargate
[ℹ] los pods de "coredns" ahora están programados en Fargate
[ℹ] esperando la disponibilidad del plano de control...
[✔] guardado kubeconfig como "C:\Users\avazquez/.kube/config"
[ℹ] sin tareas
[✔] todos los recursos del clúster EKS para "cluster-test-hybrid" han sido creados
[ℹ] el comando kubectl debería funcionar con "C:\Users\avazquez/.kube/config", intenta 'kubectl get nodes'
[✔] el clúster EKS "cluster-test-hybrid" en la región "eu-west-1" está listo
Este comando configurará el clúster EKS habilitando el soporte Fargate.
NOTA: Lo primero que deberíamos notar es que el soporte Fargate para EKS aún no está disponible en todas las regiones de AWS. Por lo tanto, dependiendo de la región que estés utilizando, podrías obtener un error. En este momento, esto solo está habilitado en US East (N. Virginia), US East (Ohio), US West (Oregon), Europa (Irlanda), Europa (Frankfurt), Asia Pacífico (Singapur), Asia Pacífico (Sídney), Asia Pacífico (Tokio) según la información de los Anuncios de AWS: https://aws.amazon.com/about-aws/whats-new/2020/04/eks-adds-fargate-support-in-frankfurt-oregon-singapore-and-sydney-aws-regions/
Así que, ahora, deberíamos agregar a ese clúster un Grupo de Nodos. Un Grupo de Nodos es un conjunto de instancias EC2 que van a ser gestionadas como parte de él. Y para hacer eso, utilizaremos el siguiente comando:
eksctl create nodegroup --cluster cluster-test-hybrid --managed
[ℹ] eksctl version 0.26.0
[ℹ] usando la región eu-west-1
[ℹ] se usará la versión 1.15 para el/los nuevo(s) grupo(s) de nodos basado en la versión del plano de control
[ℹ] el grupo de nodos "ng-1262d9c0" está presente en la configuración dada, pero falta en el clúster
[ℹ] 1 grupo de nodos (ng-1262d9c0) fue incluido (basado en las reglas de inclusión/exclusión)
[ℹ] se creará una pila de CloudFormation para cada uno de los 1 grupos de nodos gestionados en el clúster "cluster-test-hybrid"
[ℹ] 2 tareas secuenciales: { corregir la compatibilidad del clúster, 1 tarea: { 1 tarea: { crear grupo de nodos gestionado "ng-1262d9c0" } } }
[ℹ] comprobando la pila del clúster para recursos faltantes
[ℹ] la pila del clúster tiene todos los recursos requeridos
[ℹ] construyendo la pila del grupo de nodos gestionado "eksctl-cluster-test-hybrid-nodegroup-ng-1262d9c0"
[ℹ] desplegando la pila "eksctl-cluster-test-hybrid-nodegroup-ng-1262d9c0"
[ℹ] sin tareas
[✔] creado 0 grupo(s) de nodos en el clúster "cluster-test-hybrid"
[ℹ] el grupo de nodos "ng-1262d9c0" tiene 2 nodo(s)
[ℹ] el nodo "ip-192-168-69-215.eu-west-1.compute.internal" está listo
[ℹ] el nodo "ip-192-168-9-111.eu-west-1.compute.internal" está listo
[ℹ] esperando que al menos 2 nodo(s) estén listos en "ng-1262d9c0"
[ℹ] el grupo de nodos "ng-1262d9c0" tiene 2 nodo(s)
[ℹ] el nodo "ip-192-168-69-215.eu-west-1.compute.internal" está listo
[ℹ] el nodo "ip-192-168-9-111.eu-west-1.compute.internal" está listo
[✔] creado 1 grupo(s) de nodos gestionado(s) en el clúster "cluster-test-hybrid"
[ℹ] comprobando la configuración del grupo de seguridad para todos los grupos de nodos
[ℹ] todos los grupos de nodos tienen la configuración actualizada
Así que ahora deberíamos poder usar kubectl para gestionar este nuevo clúster. Si no tienes instalado kubectl o no has oído hablar de él. Esta es la herramienta de línea de comandos que nos permite gestionar tu Clúster de Kubernetes y puedes instalarla basándote en la documentación mostrada aquí:
Installing or updating eksctl – Amazon EKS
Learn how to install or update the eksctl command line tool. This tool is used to create and work with an Amazon EKS cluster.
Así que, ahora, deberíamos empezar a echar un vistazo a la infraestructura que tenemos. Así que si escribimos el siguiente comando para ver los nodos a nuestra disposición:
kubectl get nodes
Vemos una salida similar a esta:
NAME STATUS ROLES AGE VERSION
fargate-ip-192-168-102-22.eu-west-1.compute.internal Ready <none> 10m v1.15.10-eks-094994
fargate-ip-192-168-112-125.eu-west-1.compute.internal Ready <none> 10m v1.15.10-eks-094994
ip-192-168-69-215.eu-west-1.compute.internal Ready <none> 85s v1.15.11-eks-bf8eea
ip-192-168-9-111.eu-west-1.compute.internal Ready <none> 87s v1.15.11-eks-bf8eea
Como puedes ver, tenemos 4 “nodos”, dos que comienzan con el nombre fargate que son nodos fargate y dos que solo comienzan con ip-… y esos son las instancias EC2 tradicionales. Y después de ese momento, eso es todo, tenemos nuestro entorno mixto listo para usar.
Podemos verificar el mismo clúster usando la página de AWS EKS para ver esa configuración con más detalle. Si ingresamos en la página de EKS para este clúster, vemos en la pestaña de Computación la siguiente información:
Vemos bajo Grupos de Nodos los datos sobre las máquinas EC2 que son gestionadas como parte de este clúster y como puedes ver vimos 2 como la Capacidad Deseada y por eso tenemos 2 instancias EC2 en nuestro clúster. Y con respecto al perfil Fargate, vemos los espacios de nombres configurados como predeterminado y kube-system y eso significa que todos los despliegues a esos espacios de nombres se van a desplegar usando Tareas Fargate.
Resumen
En los siguientes artículos de esta serie, veremos cómo progresar en nuestro clúster Híbrido, desplegar cargas de trabajo, escalarlo en función de la demanda que estamos recibiendo, habilitar la integración con otros servicios como AWS CloudWatch, y así sucesivamente. Así que, mantente atento, y no olvides seguir mis artículos para no perderte ninguna nueva actualización tan pronto como esté disponible para ti.