Como parte del ciclo CI/CD en la implementación de la cultura DevOps, después de realizar el Deploy necesitamos tener visibilidad de lo que está pasando dentro de nuestro cluster de kubernetes, tanto a nivel de hardware (uso de CPU, Memoria, Red, etc) sino también a nivel de aplicaciones que se están ejecutando en el cluster, podemos ver los hits que está teniendo o la memoria y CPU que está usando, esto nos puede servir para determinar cuándo escalar la aplicación y que se vuelva elástica, lo que nos ahorra dinero, así como para lanzar alertas cuando algo "pasa" y toca enviar una alarte para levantar al que está de guardia, incluso puedes integrar las alertas con una central telefónica y que llame al número del equipo que está de guardia/oncall, pero eso ya es una integración que te toca hacer a tí.
Antes de entrar en materia aquí te dejo el video en Youtube para que lo sigas conmigo:
Prometheus
Empecemos por el principio, ¿Qué es Prometheus? Lo podemos definir como un sistema de monitoreo y alertas de código abierto. Esta escrito en Go. Todos los datos y métricas se almacenan como series temporales.
Arquitectura de Prometheus
Consta de componentes principales:
Servidor: Cuenta con un sistema de monitoreo y alertas de código abierto. Es el encargado de llevar a cabo la administración.
Librería de Cliente: Cuenta con un sistema de monitoreo y alertas de código abierto. Es el encargado de llevar a cabo la lectura de los datos y exponer las métricas.
Gestor de Alertas: Cuenta con un sistema de monitoreo y alertas de código abierto. Es el encargado de llevar a cabo la escritura de las alertas.
Nota: Aunque no es parte de su arquitectura principal Prometheus también cuenta con un componente llamado exporters , básicamente sirve para recolectar datos, por ejemplo de bases de datos (MySQL, Mongo, etc), e incluso de otro tipo de hardware como un IBM Z.
Aquí te dejo una imágen de los componentes:
Aquí te dejo una imágen de la integración de Prometheus con otros sistemas.
El duo dinámico Prometheus y Grafana
Grafana es una aplicación que se utiliza para visualizar los datos que recolecta Prometheus, creando dashboards para comprender lo que está pasando en el sistema que se está monitoreando. En el siguite post veremos como instalar y configurar.
Prometheus se encarga de recolectar, mientras que grafana de interpretar y mostrar gráficas (dashboards).
Instalación de Prometheus
Vamos a crear un namespace llamado monitoring donde instalaremos Prometheus.
01-namespace.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
---
Vamos a necesitar crear un rol de solo lectura para poder ver, listar y obtener las méstricas de los recursos (nodos, services, pods, endpoints, etc) de Kubernetes, para eso es el siguiente yaml 02.
02-clusterRole.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources:
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
----
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus
subjects:
- kind: ServiceAccount
name: default
namespace: monitoring
---
El siguiente yaml 03 , vamos a configurar alertas demo, por ejemplo vamos crear una alerta que se llama High Pod Memory , nos va alertar cuando un Pod tiene un consumo de memoria de más de 1 bytes por más de 1 minuto. Si bien no pienso profundizar mucho en la configuración de las alertas, te recuerdo que estas las puedes configurar una vez hayamos instalado Prometheus y accedas a él desde su administrador web, y siempre empieces de las más fáciles a las más complejas ya que puedes monitorear todo lo que ocurre en tu cluster de kubernetes. Poder llegar a la configuración óptima para tu cluster es un trabajo muy artesanal.
03-prometheus-configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-server-conf
labels:
name: prometheus-server-conf
namespace: monitoring
data:
prometheus.rules: |-
groups:
- name: devopscube demo alert
rules:
- alert: High Pod Memory
expr: sum(container_memory_usage_bytes) > 1
for: 1m
labels:
severity: slack
annotations:
summary: High Memory Usage
prometheus.yml: |-
global:
scrape_interval: 5s
evaluation_interval: 5s
rule_files:
- /etc/prometheus/prometheus.rules
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets:
- "alertmanager.monitoring.svc:9093"
scrape_configs:
- job_name: 'node-exporter'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_endpoints_name]
regex: 'node-exporter'
action: keep
- job_name: 'kubernetes-apiservers'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace,__ meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'kubernetes-nodes'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__ , __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
- job_name: 'kube-state-metrics'
static_configs:
- targets: ['kube-state-metrics.kube-system.svc.cluster.local:8080']
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__ , __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
---
Yaml 04, aquí definimos el deployment, como estoy en un cluster "pequeño" usaré solamente una réplica.
04-prometheus-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-deployment
namespace: monitoring
labels:
app: prometheus-server
spec:
replicas: 1
selector:
matchLabels:
app: prometheus-server
template:
metadata:
labels:
app: prometheus-server
spec:
containers:
- name: prometheus
image: prom/prometheus
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus/"
ports:
- containerPort: 9090
volumeMounts:
- name: prometheus-config-volume
mountPath: /etc/prometheus/
- name: prometheus-storage-volume
mountPath: /prometheus/
volumes:
- name: prometheus-config-volume
configMap:
defaultMode: 420
name: prometheus-server-conf
- name: prometheus-storage-volume
emptyDir: {}
---
Yaml 05, es la creación del service:
05-prometheus-service.yaml
---
apiVersion: v1
kind: Service
metadata:
name: prometheus-service
namespace: monitoring
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9090'
spec:
selector:
app: prometheus-server
ports:
- port: 8082
targetPort: 9090
---
Hasta aquí puedes crear un port-forward y acceder a Prometheus si estás probando en un minikube o cualquier herramienta de kubernetes "casera", lo siguiente que haré es crear un loadbalancer como si estuviera en un proveedor de la nube, si no tienes metallb puedes omitir este paso y hacer el port-forward. Incluso puedes crear tu propio ingress.
Creación del loadbalancer yaml 06:
Nota: En mi ejemplo estoy usando metallb como load balancer, este me asigna una IP, eso lo hago para que sea un comportamiento "similar" a cuando estas en cualquier proveedor de nube. Si deseas que hable un poco más de cómo implementar metallb por favor déjame saberlo.
06-prometheus-metallb.yaml
---
apiVersion: v1
kind: Service
metadata:
name: loadbalancer
namespace: monitoring
spec:
ports:
- port: 80
targetPort: 9090
protocol: TCP
type: LoadBalancer
selector:
app: prometheus-server
---
En mi caso por usar metallb puedo entrar a mi cluster con la IP asignada por el puerto 80 y tengo la IP en mi /etc/hosts, no hay que introducir usuario ni password:
Acá una imagen del loadbalancer y la IP que fue asignada:
Aquí una imagen del administrador web Prometheus:
Puedes ir al menú superior a Alerts donde veremos la alerta que definimos en el 03-prometheus-configmap.yaml que se llama High Pod Memory.
Si tienes una aplicación o Pod corriendo en tu cluster puedes ver el uso del CPU, mira la expresión que estoy usando, pueden ser expresiones complejas, por ejemplo:
Está de más decir que puedes poner en Argo CD un repositorio con los yaml para instalar prometheus cada vez que salga una versión o para automatizar el despliegue cuando creas un cluster nuevo de kubernetes.
En el siguiente post veremos como instalar Grafana para usar los datos obtenidos de Prometheus.
Top comments (0)