0%
Monitorización y logging en Kubernetes: herramientas y estrategias

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.

I

InSkillCoach

· min

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:

  1. Recolector de logs: recopila los logs de todos los pods
  2. Almacenamiento: almacena los logs para su análisis posterior
  3. 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.

InSkillCoach

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+
1.3k
247

Comentarios

Los comentarios funcionan con GitHub Discussions

Inicia sesión con GitHub para participar en la discusión

¡Enlace copiado!