Introducción
En este documento trataremos de hacer una breve introducción al monitoreo de aplicaciones, específicamente con herramientas como Kubernetes, Prometheus y Grafana, entre otras.
Más que nada apunta a ser una guía práctica para poder desplegar nuestra aplicación, recopilar información sobre la misma y poder consumirla mediante dashboards, con el fin de detectar, prevenir y mejorar nuestros servicios de cara al usuario final.
El enfoque será en un ambiente local, donde podremos desplegar nuestra app en un cluster. Esto es con el fin específico de que uno, al momento de desarrollar, pueda monitorear cómo se comporta cada servicio, tanto a nivel de aplicación (requests, read/writes a la BD) como al de infraestructura (CPU, memoria, redes).
Vale mencionar que existen herramientas cloud que también nos permiten llevar a cabo todo esto, como EKS de AWS, GKS de Google Cloud y AKS de Azure y Grafana Cloud de Grafana.
Requisitos
- docker
- kubectl
- kind
- helm
- node
Desde un repositorio hasta un cluster
¿Cómo pasamos de un repositorio a un cluster? Bueno, precisamente pasamos a un nodo dentro de un cluster. Cada cluster puede tener varios nodos, generalmente cuenta con un master node y con otros workers nodes. Pero lo que nos interesa aquí es poder "alojar” nuestro código dentro del cluster, que en última instancia es lo que será monitoreado.
Primer paso: creando nuestra imagen
Asumiendo que ya tenemos nuestro microservicio listo, o al menos funcionando, lo primero que vamos a hacer es crear un archivo Dockerfile en la raíz del repositorio. Se vería como algo así:
La versión de Node dependerá de la versión que utilices en tu microservicio. Lo mismo para el puerto en que hayas elegido servir tu aplicación.
Una vez que tenemos el archivo listo, en nuestra consola, parados en el proyecto, correremos: docker build -t <image:latest> .
En el comando de arriba tendremos que reemplazar <image:latest> con el nombre que le queremos dar a nuestra imagen, por ejemplo: <identity:latest>
El punto al final del comando es para indicar donde tiene que buscar el Dockerfile para construir la imagen. Entonces, nos quedaría así:
docker build -t identity:latest .
Ahora si corremos un docker images deberíamos poder ver nuestra nueva imagen:
Aquí podemos ver múltiples imágenes ya que varias fueron creadas. A modo de ejemplo, podemos ver la imagen de identity con el tag latest.
Con respecto a las imágenes kindest/node y node, son imágenes que fueron creadas automáticamente con el paquete Kind (Kubernetes in Docker) al momento de crear un cluster con dicha herramienta, que es en lo que nos centraremos a continuación.
Segundo paso: creando un cluster con Kind
Como recién comentábamos, para crear un cluster utilizaremos Kind. Es una herramienta para crear, correr y administrar clusters locales de Kubernetes usando contenedores de Docker.
Crear un cluster es bastante simple:
kind create cluster --name identity
Kind va a construir un cluster con un nodo llamado kind-identity. Para ver la cantidad de nodos en nuestro cluster, usaremos la herramienta kubectl:
kubectl get nodes
Ahora ya tenemos nuestro cluster creado. Lo siguiente es cargar nuestra imagen de Docker del microservicio de identity al cluster de Kind.
Tercer paso: cargando nuestra imagen al cluster
Para poder monitorear nuestro microservicio, primero, tenemos que cargarlo al cluster, porque es lo que se monitorea realmente. Siguiendo nuestro ejemplo:
kind load docker-image identity:latest --name identity
Aquí lo que estamos haciendo es, justamente, cargar la imagen que construimos a partir del microservicio de identity a nuestro cluster de Kind.
Ahora que tenemos un cluster funcionando, con una imagen de nuestro microservicio y todo, veamos el cluster desde adentro:
El comando utilizado fue
kubectl get all -n kube-system
En la imagen se pueden apreciar varios servicios o componentes, por ejemplo, los de Prometheus, que es una herramienta para hacer queries y obtener data sobre nuestros clusters, para poder ser posteriormente consumida.
Todo cluster tiene un control plane o plano de control, que es el nodo maestro. En este nodo es donde los principales componentes del clúster están alojados.
El comando de arriba nos permite consultar información específica del cluster, en este caso del namespace kube-system. Dentro de un cluster podemos tener varios namespaces.
Podemos obtener todos los namespaces de nuestro cluster con:
kubectl get namespace
Podemos ver que hay varios namespaces, y particularmente monitoring es el único que no fue creado por default.
Cuarto paso: deployando con Helm
Helm es otra herramienta que nos permite interactuar con nuestro cluster: instalar, manejar, deployar y actualizar recursos. Es como package manager para Kubernetes.
Lo primero que vamos a hacer es pararnos en la raíz de nuestro proyecto y ejecutar
helm create chart-name
Esto creará un archivo values.yaml y una carpeta /templates. Dentro de la carpeta tendremos diferentes archivos de tipo YAML, que son básicamente archivos de configuración para el deploy de servicios y recursos en nuestro cluster. Estos archivos tomarán valores para sus variables del archivo values.yaml. Sin embargo, nos concentraremos en este último archivo, siendo que desplegaremos nuestro cluster con dos herramientas enfocadas en el monitoreo, Prometheus y Grafana:
Al momento de crear nuestro Helm chart, este archivo se verá diferente, con muchas más configuraciones, pero lo importante son estos dos servicios, Prometheus para recolectar información y Grafana para poder consumirla mediante dashboards. Agregar lo siguiente al archivo:
prometheus:
prometheusSpec:
serviceMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelector: {}
serviceMonitorNamespaceSelector: {}
scrapeTimeout: "90s"
scrapeInterval: "90s"
grafana:
sidecar:
datasources:
defaultDatasourceEnabled: true
Una vez que creamos nuestro chart, tendremos que agregar el kube stack de Prometheus a nuestro Helm Registry, que es como un repositorio, para que nuestra instalación local de Helm esté al tanto:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
Este repositorio contiene nuestros charts (que pueden ser varios). Luego actualizamos nuestro chart: helm repo update
Vamos a crear un namespace para desplegar nuestro chart y servicios de monitoreo:
kubectl create ns monitoring
Suele ser buena práctica mantener nuestros charts y servicios separados, dependiendo de la lógica/fin de los mismos.
Ahora que tenemos todo podemos instalar nuestro chart y todos sus servicios:
helm upgrade --install prom prometheus-community/kube-prometheus-stack -n monitoring --values values.yaml
Veremos un mensaje como este en la consola:
❯ helm upgrade --install prom prometheus-community/kube-prometheus-stack -n monitoring --values values.yaml
Release "prom" does not exist. Installing it now.
NAME: prom
LAST DEPLOYED: Fri Jul 14 16:31:37 2023
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
NOTES:
kube-prometheus-stack has been installed. Check its status by running:
kubectl --namespace monitoring get pods -l "release=prom"
Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator.
Listo, nuestro Helm chart fue instalado y deployado a nuestro cluster de Kind.
Quinto paso: dashboards en Grafana
En este último paso veremos como nos conectamos a nuestra aplicación corriendo en el cluster, para poder consumir data y mostrarla en dashboards. Lo haremos mediante port-forwarding:
kubectl port-forward service/prometheus-operated -n monitoring 9090:9090
Nos conectamos al servicio de Prometheus para consumir data. Para conectarnos a Grafana y ver la data en dashboards:
kubectl port-forward service/prom-grafana -n monitoring 3000:80
Vamos a localhost:3000 y las credenciales serán:
username: admin
password: prom-operator
En Grafana contaremos con múltiples dashboards predeterminados, sin embargo también se pueden crear algunos personalizados. El dashboard de nodes es especialmente útil, ya que nos permite ver información relacionada al nodo (corriendo dentro del cluster) y los recursos que consume en el sistema operativo. Veremos algo así:

Ese fue el paso a paso para deployar nuestra app con una imagen de Docker y monitorearla a través de un cluster de Kubernetes con Prometheus para recolectar data y Grafana para visualizarla. Más tutoriales en https://grafana.com/grafana/dashboards.