Monitorización y logging en Kubernetes: herramientas y estrategias
Descubre las mejores prácticas y herramientas para monitorizar y registrar los logs de tus aplicaciones en Kubernetes, desde la recopilación de métricas hasta el análisis de logs.
InSkillCoach
Introducción
En un entorno Kubernetes, la visibilidad es crucial para mantener la salud y el rendimiento de tus aplicaciones. La monitorización y el logging son dos aspectos fundamentales de la observabilidad que te permiten detectar problemas, comprender su causa y adoptar medidas preventivas.
Este artículo explora las herramientas y estrategias para implantar un sistema completo de monitorización y logging en Kubernetes.
Monitorización en Kubernetes
La monitorización en Kubernetes consiste en recopilar, analizar y visualizar métricas sobre el estado de tu clúster y de tus aplicaciones. Estos son los principales enfoques y herramientas.
Métricas básicas con kubectl
Kubernetes proporciona comandos básicos para supervisar el estado de tu clúster:
# Vérifier l'état des nœuds
kubectl get nodes
# Vérifier l'état des pods
kubectl get pods
# Vérifier l'état des services
kubectl get services
# Vérifier les événements du cluster
kubectl get events
# Vérifier l'utilisation des ressources des nœuds
kubectl top nodes
# Vérifier l'utilisation des ressources des pods
kubectl top pods
Métricas de Kubernetes con Metrics Server
Metrics Server es un componente que recopila las métricas básicas de Kubernetes (CPU, memoria) y las expone a través de la API de Kubernetes.
apiVersion: v1
kind: ServiceAccount
metadata:
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:aggregated-metrics-reader
labels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: metrics-server-auth-delegator
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
name: metrics-server
namespace: kube-system
labels:
kubernetes.io/name: Metrics-server
kubernetes.io/cluster-service: "true"
spec:
selector:
k8s-app: metrics-server
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: metrics-server
namespace: kube-system
labels:
k8s-app: metrics-server
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
name: metrics-server
labels:
k8s-app: metrics-server
spec:
serviceAccountName: metrics-server
containers:
- name: metrics-server
image: k8s.gcr.io/metrics-server/metrics-server:v0.5.0
args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --kubelet-insecure-tls
ports:
- name: https
containerPort: 4443
protocol: TCP
livenessProbe:
httpGet:
path: /livez
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
readinessProbe:
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 200m
memory: 400Mi
volumeMounts:
- name: tmp-dir
mountPath: /tmp
volumes:
- name: tmp-dir
emptyDir: {}
Prometheus: recopilación avanzada de métricas
Prometheus es un sistema de monitorización de código abierto que recopila y almacena métricas en forma de series temporales. Es especialmente adecuado para entornos cloud-native.
Instalación de Prometheus con Helm
# Ajouter le repo Helm de Prometheus
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# Installer Prometheus
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace
Configuración de Prometheus para Kubernetes
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-monitor
labels:
release: prometheus
spec:
selector:
matchLabels:
app: myapp
endpoints:
- port: http
interval: 15s
path: /metrics
Grafana: visualización de métricas
Grafana es una herramienta de visualización que permite crear paneles de control interactivos para tus métricas de Prometheus.
Instalación de Grafana con Helm
# Ajouter le repo Helm de Grafana
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
# Installer Grafana
helm install grafana grafana/grafana \
--namespace monitoring \
--create-namespace
Ejemplo de dashboard de Grafana
{
"annotations": {
"list": []
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"default\"}[5m])) by (pod) * 100",
"refId": "A"
}
],
"title": "CPU Usage by Pod",
"type": "timeseries"
}
],
"refresh": "5s",
"schemaVersion": 38,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Kubernetes Monitoring",
"uid": "kubernetes",
"version": 1,
"weekStart": ""
}
Alertmanager: gestión de alertas
Alertmanager gestiona las alertas enviadas por Prometheus y las enruta hacia distintos canales de notificación.
Configuración de Alertmanager
apiVersion: monitoring.coreos.com/v1
kind: AlertmanagerConfig
metadata:
name: app-alerts
namespace: default
spec:
route:
receiver: 'slack'
groupBy: ['alertname', 'namespace']
groupWait: 30s
groupInterval: 5m
repeatInterval: 4h
receivers:
- name: 'slack'
slackConfigs:
- apiURL: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#alerts'
sendResolved: true
Logging en Kubernetes
El logging en Kubernetes consiste en recopilar, almacenar y analizar los logs de tus aplicaciones y del sistema. Estos son los principales enfoques y herramientas.
Logging básico con kubectl
Kubernetes proporciona comandos básicos para acceder a los logs de tus pods:
# Voir les logs d'un pod
kubectl logs <pod-name>
# Voir les logs d'un conteneur spécifique dans un pod
kubectl logs <pod-name> -c <container-name>
# Voir les logs en temps réel
kubectl logs -f <pod-name>
# Voir les logs d'un pod précédent (en cas de redémarrage)
kubectl logs <pod-name> --previous
Arquitectura de logging centralizada
Para una solución de logging completa, puedes implantar una arquitectura centralizada con los siguientes componentes:
- Recolector de logs: recopila los logs de todos los pods
- Almacenamiento: almacena los logs para su análisis posterior
- Interfaz de visualización: permite buscar y analizar los logs
ELK Stack: Elasticsearch, Logstash, Kibana
El ELK Stack es una solución popular para la recopilación, el almacenamiento y el análisis de logs.
Instalación del ELK Stack con Helm
# Ajouter le repo Helm d'Elastic
helm repo add elastic https://helm.elastic.co
helm repo update
# Installer Elasticsearch
helm install elasticsearch elastic/elasticsearch \
--namespace logging \
--create-namespace
# Installer Kibana
helm install kibana elastic/kibana \
--namespace logging \
--create-namespace
# Installer Logstash
helm install logstash elastic/logstash \
--namespace logging \
--create-namespace
Configuración de Filebeat para la recopilación de logs
Filebeat es un agente ligero que recopila los logs y los envía a Elasticsearch o Logstash.
apiVersion: beat.k8s.elastic.co/v1beta1
kind: Filebeat
metadata:
name: filebeat
namespace: logging
spec:
version: 7.14.0
elasticsearchRef:
name: elasticsearch
config:
filebeat.inputs:
- type: container
paths:
- /var/log/containers/*.log
processors:
- add_kubernetes_metadata:
host: ${NODE_NAME}
matchers:
- logs_path:
logs_path: "/var/log/containers/"
daemonSet:
podTemplate:
spec:
containers:
- name: filebeat
volumeMounts:
- name: varlogcontainers
mountPath: /var/log/containers
- name: varlogpods
mountPath: /var/log/pods
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
volumes:
- name: varlogcontainers
hostPath:
path: /var/log/containers
- name: varlogpods
hostPath:
path: /var/log/pods
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
EFK Stack: Elasticsearch, Fluentd, Kibana
Una alternativa al ELK Stack es el EFK Stack, que utiliza Fluentd en lugar de Logstash.
Instalación del EFK Stack con Helm
# Ajouter le repo Helm de Fluentd
helm repo add fluent https://fluent.github.io/helm-charts
helm repo update
# Installer Fluentd
helm install fluentd fluent/fluentd \
--namespace logging \
--create-namespace
Configuración de Fluentd
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-config
namespace: logging
data:
fluent.conf: |
<source>
@type tail
path /var/log/containers/*.log
pos_file /var/log/fluentd-containers.log.pos
tag kubernetes.*
read_from_head true
<parse>
@type json
time_format %Y-%m-%dT%H:%M:%S.%NZ
</parse>
</source>
<filter kubernetes.**>
@type kubernetes_metadata
</filter>
<match kubernetes.**>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix k8s
<buffer>
@type memory
flush_interval 5s
retry_max_times 5
</buffer>
</match>
Loki: una solución de logging ligera
Loki es una solución de logging ligera desarrollada por Grafana Labs, diseñada para ser muy eficiente y fácil de usar.
Instalación de Loki con Helm
# Ajouter le repo Helm de Grafana
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
# Installer Loki
helm install loki grafana/loki-stack \
--namespace logging \
--create-namespace
Configuración de Promtail
Promtail es el agente de recopilación de logs para Loki.
apiVersion: v1
kind: ConfigMap
metadata:
name: promtail-config
namespace: logging
data:
promtail.yaml: |
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_name]
regex: (.+)
target_label: pod
- source_labels: [__meta_kubernetes_namespace_name]
regex: (.+)
target_label: namespace
pipeline_stages:
- docker: {}
- cri: {}
Buenas prácticas de monitorización y logging
1. Recopilación de métricas a nivel de aplicación
Instrumente sus aplicaciones para exponer métricas en formato Prometheus:
// Exemple avec Micrometer pour Java
@RestController
public class MetricsController {
private final Counter requestCounter;
public MetricsController(MeterRegistry registry) {
this.requestCounter = Counter.builder("app_requests_total")
.description("Total number of requests")
.register(registry);
}
@GetMapping("/api/resource")
public String handleRequest() {
requestCounter.increment();
return "Response";
}
}
2. Estructuración de los logs
Utilice un formato estructurado para sus logs (JSON) con el fin de facilitar el análisis:
// Exemple avec SLF4J et Logback
<configuration>
<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeMDC>true</includeMDC>
<customFields>{"app_name":"myapp"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="JSON" />
</root>
</configuration>
3. Etiquetado de métricas y logs
Añada etiquetas pertinentes a sus métricas y logs para facilitar el filtrado y el análisis:
# Exemple de configuration Prometheus
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_name]
regex: (.+)
target_label: pod
- source_labels: [__meta_kubernetes_namespace_name]
regex: (.+)
target_label: namespace
- source_labels: [__meta_kubernetes_pod_label_app]
regex: (.+)
target_label: app
4. Definición de alertas pertinentes
Defina alertas que detecten los problemas reales sin generar falsos positivos:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: app-alerts
namespace: monitoring
spec:
groups:
- name: app
rules:
- alert: HighErrorRate
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: High error rate detected
description: Error rate is above 5% for the last 5 minutes
5. Retención y archivado
Configure una estrategia de retención y archivado para sus métricas y logs:
# Exemple de configuration Elasticsearch pour la rétention
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: elasticsearch
spec:
version: 7.14.0
nodeSets:
- name: default
count: 3
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
indices:
lifecycle:
policies:
- name: logs-policy
phases:
hot:
min_age: 0s
actions:
rollover:
max_age: 1d
max_size: 50gb
warm:
min_age: 7d
actions:
forcemerge:
max_num_segments: 1
cold:
min_age: 30d
actions:
freeze: {}
delete:
min_age: 90d
actions:
delete: {}
Ejemplo completo: stack de monitorización y logging
A continuación se muestra un ejemplo completo de configuración de un stack de monitorización y logging en Kubernetes:
# Prometheus Operator
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: prometheus
namespace: monitoring
spec:
serviceAccountName: prometheus
serviceMonitorSelector:
matchLabels:
release: prometheus
resources:
requests:
memory: 2Gi
cpu: 1
limits:
memory: 4Gi
cpu: 2
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
---
# Grafana
apiVersion: integreatly.org/v1alpha1
kind: Grafana
metadata:
name: grafana
namespace: monitoring
spec:
config:
auth:
adminUser: admin
adminPassword: admin
dashboard:
defaultDashboard: kubernetes
dashboardLabelSelector:
- matchLabels:
grafana_dashboard: "1"
resources:
requests:
memory: 1Gi
cpu: 500m
limits:
memory: 2Gi
cpu: 1
---
# Loki
apiVersion: loki.grafana.com/v1
kind: Loki
metadata:
name: loki
namespace: logging
spec:
size: 1x.small
storage:
type: filesystem
size: 10Gi
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 1Gi
cpu: 500m
---
# Promtail
apiVersion: v1
kind: ConfigMap
metadata:
name: promtail-config
namespace: logging
data:
promtail.yaml: |
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_name]
regex: (.+)
target_label: pod
- source_labels: [__meta_kubernetes_namespace_name]
regex: (.+)
target_label: namespace
pipeline_stages:
- docker: {}
- cri: {}
---
# ServiceMonitor pour l'application
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-monitor
namespace: monitoring
labels:
release: prometheus
spec:
selector:
matchLabels:
app: myapp
endpoints:
- port: http
interval: 15s
path: /metrics
---
# Service pour l'application avec métriques
apiVersion: v1
kind: Service
metadata:
name: app-service
labels:
app: myapp
spec:
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 8080
- name: metrics
port: 8080
targetPort: 8080
Conclusión
Un sistema robusto de monitorización y logging es esencial para mantener la salud y el rendimiento de sus aplicaciones en Kubernetes. Combinando herramientas como Prometheus, Grafana y Loki, podrá obtener una visibilidad completa de su clúster y de sus aplicaciones.
Las buenas prácticas, como la recopilación de métricas a nivel de aplicación, la estructuración de los logs y la definición de alertas pertinentes, le ayudarán a detectar y resolver los problemas antes de que afecten a sus usuarios.
En el próximo artículo exploraremos la seguridad en Kubernetes, un aspecto crucial para proteger sus aplicaciones y sus datos.
Acerca de InSkillCoach
Experto en formación y tecnologías
Coach especializado en tecnologías avanzadas e IA, impulsado por GNeurone Inc.
Certificaciones:
- AWS Certified Solutions Architect – Professional
- Certificaciones de Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comentarios
Los comentarios funcionan con GitHub Discussions
Inicia sesión con GitHub para participar en la discusión