DEV Community

Guillermo Garcia
Guillermo Garcia

Posted on • Originally published at ahioros.info on

Monitoreo y Observabilidad: Instalando Prometheus - Parte 1

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í.

Image description

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:
Image description

Aquí te dejo una imágen de la integración de Prometheus con otros sistemas.
Image description

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
---
Enter fullscreen mode Exit fullscreen mode

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
---
Enter fullscreen mode Exit fullscreen mode

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
---
Enter fullscreen mode Exit fullscreen mode

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: {}
---
Enter fullscreen mode Exit fullscreen mode

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
---
Enter fullscreen mode Exit fullscreen mode

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
---
Enter fullscreen mode Exit fullscreen mode

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:

Image description

Acá una imagen del loadbalancer y la IP que fue asignada:

Image description

Aquí una imagen del administrador web Prometheus:

Image description

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.

Image description

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:

Image description

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)