Salta el contingut

Monitorització de Sistemes Big Data

Introducció

En un entorn de producció Big Data, un clúster Hadoop de 50 nodes pot gestionar petabytes de dades i executar centenars de jobs paral·lels. Quan alguna cosa falla —un DataNode que s'omple de disc, un job Spark que consumeix tota la memòria del clúster, un consumer de Kafka que queda enrere— cada minut de temps de resposta té un cost directe. Les empreses que depenen d'analítica en temps real per a prendre decisions de negoci no es poden permetre descobrir un problema gràcies a una trucada d'un usuari.

La monitorització en Big Data és crítica per tres raons fonamentals:

1. Costos — Un clúster en el cloud (AWS EMR, Google Dataproc, Azure HDInsight) pot costar milers d'euros al mes. Un job mal optimitzat que s'executa 10 vegades més lent del necessari o que no acaba mai i consumeix recursos indefinidament és diners tirats. La monitorització permet detectar i corregir aquetes anomalies abans que disparin la factura.

2. SLAs (Service Level Agreements) — Els acords de nivell de servei defineixen el temps màxim tolerable de processament. Si el pipeline ETL nocturn ha d'acabar abans de les 06:00 per a que els equips de vendes tinguin les dades actualitzades quan arriben a la feina, un job que s'allargui fins les 08:00 incompleix el SLA i genera un impacte de negoci real.

3. MTTR (Mean Time To Repair) — El temps mitjà de reparació és la mètrica clau d'un equip d'operacions. Amb una bona monitorització, un enginyer pot diagnosticar i resoldre un incident en minuts; sense ella, pot trigar hores en identificar el problema. La diferència és la disponibilitat de telemetria: mètriques, logs i traces que expliquen exactament on, quan i per qué ha fallat el sistema.


1. Stack Prometheus + Grafana

1.1 Per qué Prometheus i Grafana el 2025

El stack Prometheus + Grafana s'ha convertit en l'estàndard de facto per a monitorització en entorns cloud-native i Big Data. Les raons del seu èxit:

  • Pull model: Prometheus consulta activament els endpoints de mètriques, cosa que simplifica la seguretat (no cal obrir ports d'entrada als serveis)
  • TSDB nativa: Prometheus emmagatzema les dades en una base de dades de sèries temporals molt eficient, optimitzada per a consultes de monitoratge
  • PromQL: un llenguatge de consulta expressiu que permet calcular percentils, taxes de canvi, agregacions, etc.
  • Alertmanager: desacoplament entre les regles d'alerta i la seva gestió (deduplicació, silenciament, enrutament)
  • Grafana: la millor eina de visualització de sèries temporals, amb suport per a centenars de fonts de dades (Prometheus, Elasticsearch, PostgreSQL, CloudWatch, etc.)

1.2 Arquitectura del stack

flowchart TB
    Hadoop --> NodeExporter
    Kafka --> KafkaExporter
    Spark --> SparkHistory
    NodeExporter --> Prometheus
    KafkaExporter --> Prometheus
    SparkHistory --> Prometheus
    Prometheus --> Grafana
    Prometheus --> Alertmanager
    Alertmanager --> Slack
    Alertmanager --> Email

Components del flux:

  • Exporters: Petits programes que exposen mètriques en format Prometheus (text pla amb format nom_metrica{etiquetes} valor timestamp) als endpoints HTTP /metrics. Cada tecnologia té el seu exporter: node-exporter per al sistema operatiu, kafka-exporter per a Kafka, JMX Exporter per a serveis Java (Hadoop, Spark).
  • Prometheus: Servidor central que recull (scrapes) els endpoints dels exporters cada 15-30 segons i emmagatzema les mètriques. Avalua les regles d'alerta.
  • Alertmanager: Rep les alertes de Prometheus i les enruta als canals correctes (Slack, email, PagerDuty), aplicant deduplicació i silenciaments.
  • Grafana: Connectat a Prometheus com a font de dades, renderitza dashboards i visualitzacions a partir de consultes PromQL.

1.3 Desplegament complet amb Docker Compose

# docker-compose-monitoring.yml
services:
  prometheus:
    image: prom/prometheus:v2.52.0
    container_name: prometheus-iabd
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./alertes.yml:/etc/prometheus/alertes.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=30d'
    restart: unless-stopped
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:11.0.0
    container_name: grafana-iabd
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=iabd2025
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana_data:/var/lib/grafana
    restart: unless-stopped
    networks:
      - monitoring

  node-exporter:
    image: prom/node-exporter:v1.8.0
    container_name: node-exporter-iabd
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
    restart: unless-stopped
    networks:
      - monitoring

  alertmanager:
    image: prom/alertmanager:v0.27.0
    container_name: alertmanager-iabd
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    restart: unless-stopped
    networks:
      - monitoring

networks:
  monitoring:
    name: monitoring-iabd

volumes:
  prometheus_data:
  grafana_data:

1.4 Configuració de Prometheus

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alertes.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

scrape_configs:
  # Mètriques del propi Prometheus
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Mètriques del sistema operatiu
  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']
        labels:
          cluster: 'hadoop-local'

  # Hadoop NameNode (via JMX Exporter)
  - job_name: 'hadoop-namenode'
    static_configs:
      - targets: ['namenode:9870']

  # Kafka (via kafka-exporter)
  - job_name: 'kafka'
    static_configs:
      - targets: ['kafka-exporter:9308']

  # Spark History Server
  - job_name: 'spark-history'
    static_configs:
      - targets: ['spark-history:18080']

1.5 Dashboards per a Big Data

Dashboard Hadoop NameNode — Les mètriques clau del NameNode exposades via JMX:

Mètrica PromQL Alertar quan
Espai HDFS usat (%) hadoop_namenode_capacityused / hadoop_namenode_capacitytotal * 100 > 80%
DataNodes vius hadoop_namenode_numlivedatanodes < 3
Blocs corromputs hadoop_namenode_corruptblocks > 0
Operacions de fitxers/s rate(hadoop_namenode_totalfileops[5m])

Dashboard Kafka — Consumer lag, el KPI més important de Kafka:

# Consumer lag total per grup
sum(kafka_consumergroup_lag) by (consumergroup, topic)

# Lag per partició
kafka_consumergroup_lag{consumergroup="pipeline-vendes", topic="comandes"}

# Taxa de missatges per segon
rate(kafka_topic_partition_current_offset[5m])

Dashboard Spark — Jobs i stages en execució, fallades i durades:

# Jobs completats en les darreres 24h
increase(spark_job_succeeded_total[24h])

# Jobs fallats (alerta crítica)
increase(spark_job_failed_total[1h])

# Temps mitjà d'execució dels jobs
rate(spark_job_duration_seconds_sum[1h]) / rate(spark_job_duration_seconds_count[1h])

1.6 Regles d'alerta

# alertes.yml
groups:
  - name: bigdata-alertes
    rules:
      # Disc crític (>80%)
      - alert: DiscUsatAlt
        expr: (1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Disc quasi ple al node {{ $labels.instance }}"
          description: "El disc {{ $labels.mountpoint }} esta al {{ $value | printf \"%.1f\" }}% de capacitat"

      # Memòria critica (>90%)
      - alert: MemoriaAlt
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Memòria critica al node {{ $labels.instance }}"
          description: "Us de memòria al {{ $value | printf \"%.1f\" }}%"

      # Job Spark fallat
      - alert: SparkJobFallat
        expr: increase(spark_job_failed_total[15m]) > 0
        labels:
          severity: critical
        annotations:
          summary: "Job Spark ha fallat"
          description: "{{ $value }} jobs Spark han fallat en els darrers 15 minuts"

      # Consumer lag de Kafka alt
      - alert: KafkaConsumerLagAlt
        expr: kafka_consumergroup_lag > 10000
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Consumer lag de Kafka elevat"
          description: "El grup {{ $labels.consumergroup }} te un lag de {{ $value }} missatges"

2. Ganglia

2.1 Arquitectura Ganglia

Ganglia és un sistema de monitoratge distribuït especialitzat en clústers d'alt rendiment (HPC), molt popular en instal·lacions Hadoop tradicionals (pre-2020). Malgrat que Prometheus ha pres el relleu en entorns nous, Ganglia segueix actiu en molts clústers corporatius:

flowchart LR
    subgraph Nodes["Nodes del cluster"]
        N1[Node 1\ngmond]
        N2[Node 2\ngmond]
        N3[Node 3\ngmond]
    end
    N1 -->|UDP multicast| Gmetad
    N2 -->|UDP multicast| Gmetad
    N3 -->|UDP multicast| Gmetad
    Gmetad[gmetad\nServidor central] --> Gweb[gweb\nInterficie web]

Components:

  • gmond (Ganglia Monitor Daemon): S'executa a cada node, recull mètriques locals (CPU, memòria, xarxa, disc) i les difon per UDP multicast al port 8649.
  • gmetad (Ganglia Meta Daemon): S'executa al node central, escolta el multicast, agrega les mètriques de tots els nodes i les emmagatzema en fitxers RRD.
  • gweb: Interfície web (PHP + Apache) que visualitza les mètriques de gmetad.

2.2 Configuració bàsica gmond

<!-- /etc/ganglia/gmond.conf -->
globals {
  daemonize = yes
  setuid = yes
  user = ganglia
  debug_level = 0
  max_udp_msg_len = 1472
}

cluster {
  name = "Cluster Hadoop Institut Sa Palomera"
  owner = "IABD"
  latlong = "41.68 2.79"
  url = "http://hadoop.sapalomera.cat/"
}

udp_send_channel {
  mcast_join = 239.2.11.71
  port = 8649
  ttl = 1
}

udp_recv_channel {
  mcast_join = 239.2.11.71
  port = 8649
  bind = 239.2.11.71
}

2.3 Integració Ganglia-Hadoop

Hadoop pot publicar mètriques a Ganglia afegint al fitxer hadoop-metrics2.properties:

# hadoop-metrics2.properties
*.sink.ganglia.class=org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31
*.sink.ganglia.period=10
*.sink.ganglia.servers=ganglia-master:8649

namenode.sink.ganglia.class=org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31
datanode.sink.ganglia.class=org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31
resourcemanager.sink.ganglia.class=org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31

3. ELK Stack

3.1 Centralització de logs

Prometheus és excel·lent per a mètriques (valors numèrics en el temps), però per a logs (missatges de text estructurats o semi-estructurats) la solució estàndard és l'ELK Stack:

  • Elasticsearch: Motor de cerca i anàlisi distribuït, emmagatzema i indexa els logs
  • Logstash: Pipeline de processament de logs (filtratge, transformació, enriquiment)
  • Kibana: Interfície web per a cercar, visualitzar i analitzar els logs

El 2025, moltes empreses substitueixen Logstash per Filebeat o Fluent Bit (més lleugers) per a la recollida i Logstash per a transformacions complexes.

3.2 Desplegament ELK amb Docker Compose

# docker-compose-elk.yml
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
    container_name: elasticsearch-iabd
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
    ports:
      - "9200:9200"
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data
    networks:
      - elk

  kibana:
    image: docker.elastic.co/kibana/kibana:8.13.0
    container_name: kibana-iabd
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
    networks:
      - elk

  logstash:
    image: docker.elastic.co/logstash/logstash:8.13.0
    container_name: logstash-iabd
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    ports:
      - "5044:5044"
    depends_on:
      - elasticsearch
    networks:
      - elk

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.13.0
    container_name: filebeat-iabd
    user: root
    volumes:
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/log:/var/log:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
    depends_on:
      - logstash
    networks:
      - elk

networks:
  elk:
    name: elk-iabd

volumes:
  elasticsearch_data:

3.3 Pipeline Logstash per a logs Spark

# logstash.conf
input {
  beats {
    port => 5044
  }
}

filter {
  # Parsejar logs de Spark executors
  if [fields][service] == "spark-executor" {
    grok {
      match => {
        "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:log_level} %{JAVACLASS:java_class}: %{GREEDYDATA:log_message}"
      }
    }
    date {
      match => ["timestamp", "yyyy-MM-dd HH:mm:ss,SSS"]
      target => "@timestamp"
    }
    mutate {
      add_field => { "service" => "spark" }
    }
  }

  # Parsejar logs HDFS
  if [fields][service] == "hdfs" {
    grok {
      match => {
        "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:log_level} %{DATA:component}: %{GREEDYDATA:log_message}"
      }
    }
    mutate {
      add_field => { "service" => "hadoop" }
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "bigdata-logs-%{+YYYY.MM.dd}"
  }
}

3.4 Kibana: crear index patterns i dashboards

Passos per crear un index pattern a Kibana:

  1. Anar a Stack Management → Index Patterns
  2. Crear un nou pattern: bigdata-logs-*
  3. Seleccionar @timestamp com a camp de temps
  4. Confirmar la creació

Dashboard de logs recomanat:

  • Gràfic de barres: Distribució de logs per log_level (INFO, WARN, ERROR) al llarg del temps
  • Taula: Últims 50 errors amb java_class i log_message
  • Pie chart: Distribució per servei (spark, hadoop, kafka)
  • Metric: Nombre d'errors en les darreres 24h
  • Timeline: Errors crítics en ordre cronològic

4. YARN ResourceManager UI

4.1 Interpretació de mètriques

El YARN ResourceManager exposa una interfície web al port 8088 que permet monitorar en temps real l'estat del clúster. Les mètriques principals:

Cluster Metrics (panell superior):

Mètrica Descripció Signe d'alarma
Apps Running Jobs actius simultanis > capacitat del clúster
Apps Failed Jobs fallats (acumulat sessió) > 0
Memory Used RAM consumida del clúster > 85% del total
VCores Used CPUs virtuals en ús > 80% del total
Active Nodes DataNodes actius Menys dels esperats
Lost Nodes Nodes perduts (timeout) > 0

4.2 Gestió de cues (YARN Capacity Scheduler)

El YARN Capacity Scheduler permet dividir els recursos del clúster en cues amb capacitats reservades. Configuració típica:

<!-- capacity-scheduler.xml -->
<configuration>
  <property>
    <name>yarn.scheduler.capacity.root.queues</name>
    <value>produccio,desenvolupament,batch</value>
  </property>

  <!-- Producció: 60% dels recursos garantits -->
  <property>
    <name>yarn.scheduler.capacity.root.produccio.capacity</name>
    <value>60</value>
  </property>
  <property>
    <name>yarn.scheduler.capacity.root.produccio.maximum-capacity</name>
    <value>80</value>
  </property>

  <!-- Desenvolupament: 30% garantit -->
  <property>
    <name>yarn.scheduler.capacity.root.desenvolupament.capacity</name>
    <value>30</value>
  </property>

  <!-- Batch nocturn: 10% garantit -->
  <property>
    <name>yarn.scheduler.capacity.root.batch.capacity</name>
    <value>10</value>
  </property>
</configuration>

4.3 Matar jobs problemàtics

Des de la UI o via línia de comandes:

# Llistar aplicacions actives
yarn application -list

# Veure l'estat d'una aplicació concreta
yarn application -status application_1234567890_0042

# Matar una aplicació que bloqueja recursos
yarn application -kill application_1234567890_0042

# Veure logs d'una aplicació (un cop acabada)
yarn logs -applicationId application_1234567890_0042

5. Apache Airflow: monitoratge de pipelines

5.1 DAGs View i estat de tasques

Apache Airflow no és només un orquestrador de workflows: és també un sistema de monitoratge dels pipelines. La interfície web d'Airflow (port 8080) mostra:

  • DAGs View: Vista de tots els DAGs amb el darrer estat d'execució, durada i si estan en error
  • Grid View (ex-Tree View): Historial d'execucions d'un DAG, amb el color de cada tasca (verd=OK, vermell=error, groc=en execució, gris=skipped)
  • Graph View: Dependències visuals entre tasques
  • Gantt View: Durada de cada tasca i solapaments temporals
  • Task Logs: Logs complets de cada execució de cada tasca

5.2 SLA Misses

Els SLA Miss d'Airflow permeten definir el temps màxim que una tasca pot trigar a completar-se. Si una tasca excedeix el temps definit, Airflow enregistra un SLA miss i pot enviar una notificació:

# dag_pipeline_vendes.py
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.python import PythonOperator

def processar_vendes():
    # Lògica del pipeline
    pass

def notificar_slack(context):
    """Callback executat quan una tasca falla"""
    task_instance = context['task_instance']
    dag_id = context['dag'].dag_id
    task_id = task_instance.task_id
    execution_date = context['execution_date']
    log_url = task_instance.log_url

    missatge = f"""
    :red_circle: *Job Airflow fallat*
    DAG: `{dag_id}`
    Tasca: `{task_id}`
    Data execucio: {execution_date}
    Logs: {log_url}
    """

    # Enviar a Slack via webhook (necessita airflow-provider-slack)
    from airflow.providers.slack.hooks.slack_webhook import SlackWebhookHook
    slack = SlackWebhookHook(slack_webhook_conn_id='slack_webhook')
    slack.send(text=missatge)

default_args = {
    'owner': 'iabd',
    'retries': 2,
    'retry_delay': timedelta(minutes=5),
    'on_failure_callback': notificar_slack,
    'sla': timedelta(hours=2),
}

with DAG(
    dag_id='pipeline_vendes_diari',
    default_args=default_args,
    schedule_interval='0 2 * * *',  # Cada dia a les 02:00
    start_date=datetime(2025, 1, 1),
    catchup=False,
    tags=['vendes', 'produccio'],
) as dag:

    extraccio = PythonOperator(
        task_id='extraccio_dades',
        python_callable=processar_vendes,
        sla=timedelta(hours=1),
    )

    transformacio = PythonOperator(
        task_id='transformacio_dbt',
        python_callable=processar_vendes,
    )

    carrega = PythonOperator(
        task_id='carrega_datamart',
        python_callable=processar_vendes,
    )

    extraccio >> transformacio >> carrega

6. Alertes i notificacions

6.1 Configuració Alertmanager

Alertmanager desacobla la generació d'alertes (Prometheus) de la seva gestió. Permet:

  • Deduplicació: Si molts nodes fixen la mateixa alerta alhora, Alertmanager les agrupa en una sola notificació
  • Silenciaments: Suspendre alertes durant manteniments planificats
  • Enrutament: Enviar alertes crítiques a PagerDuty, advertències a Slack, informatius per email
  • Inhibició: Si el servidor està caigut, suprimir totes les alertes de serveis que corren en ell
# alertmanager.yml
global:
  slack_api_url: 'https://hooks.slack.com/services/TOKEN/SUBTOKEN/HASHSECRET'
  smtp_smarthost: 'smtp.sapalomera.cat:587'
  smtp_from: 'alertes-bigdata@sapalomera.cat'
  smtp_auth_username: 'alertes-bigdata@sapalomera.cat'
  smtp_auth_password: 'password-smtp'

route:
  group_by: ['alertname', 'cluster']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'slack-general'

  routes:
    # Alertes critiques van a PagerDuty i Slack
    - match:
        severity: critical
      receiver: 'pagerduty-i-slack'
      continue: true

    # Alertes de disc van a Slack de ops
    - match:
        alertname: DiscUsatAlt
      receiver: 'slack-ops'

receivers:
  - name: 'slack-general'
    slack_configs:
      - channel: '#alertes-bigdata'
        title: 'Alerta BigData: {{ .GroupLabels.alertname }}'
        text: |
          {{ range .Alerts }}
          *Severitat*: {{ .Labels.severity }}
          *Descripció*: {{ .Annotations.description }}
          {{ end }}
        send_resolved: true

  - name: 'slack-ops'
    slack_configs:
      - channel: '#ops-infraestructura'
        title: 'Disc quasi ple'
        text: '{{ range .Alerts }}Node: {{ .Labels.instance }} - {{ .Annotations.description }}{{ end }}'

  - name: 'pagerduty-i-slack'
    pagerduty_configs:
      - routing_key: 'PAGERDUTY_INTEGRATION_KEY'
        description: '{{ .GroupLabels.alertname }}: {{ .CommonAnnotations.summary }}'
    slack_configs:
      - channel: '#alertes-critigues'
        text: ':fire: CRITIC: {{ .CommonAnnotations.summary }}'

inhibit_rules:
  - source_match:
      alertname: NodeCaigut
    target_match_re:
      alertname: '.*'
    equal: ['instance']

7. Databricks: monitoratge en cloud

7.1 Cluster Metrics

Databricks és una plataforma cloud que simplifica la gestió de clústers Spark. Per a monitoratge ofereix:

Ganglia UI integrat: Cada clúster Databricks inclou una UI Ganglia accessible des del panell del clúster → pestaña Metrics. Mostra CPU, memòria, xarxa i disc de cada node en temps real.

Spark UI: Accessible des del clúster → pestaña Spark UI. Mostra jobs, stages, tasks, SQL plans d'execució i storage.

Cluster Event Log: Historial d'esdeveniments del clúster: escalats automàtics, nodes afegits/eliminats, errors de driver.

7.2 Job Runs i alertes

Des del panell Workflows de Databricks:

  • Vista de tots els jobs amb darrer estat i durada
  • Historial d'execucions amb possibilitat de veure els logs
  • Alertes de job: Notificació per email o Slack quan un job falla o supera un temps límit
{
  "email_notifications": {
    "on_failure": ["equip-data@empresa.cat"],
    "on_success": [],
    "no_alert_for_skipped_runs": true
  },
  "notification_settings": {
    "no_alert_for_skipped_runs": true,
    "no_alert_for_canceled_runs": false
  },
  "timeout_seconds": 3600
}

8. Optimització de costos cloud

8.1 AWS EMR

AWS EMR (Elastic MapReduce) és el servei gestionat de Hadoop/Spark d'Amazon. Estratègies d'optimització:

Spot Instances (instàncies puntuals): Les instàncies EC2 spot costen fins a un 90% menys que les instàncies on-demand. Són ideals per als nodes de dades (task nodes) que poden ser interromputs sense perdre dades críticament. Configuració recomanada:

{
  "InstanceGroups": [
    {
      "Name": "Master",
      "InstanceRole": "MASTER",
      "InstanceType": "m5.xlarge",
      "InstanceCount": 1,
      "Market": "ON_DEMAND"
    },
    {
      "Name": "Core",
      "InstanceRole": "CORE",
      "InstanceType": "m5.2xlarge",
      "InstanceCount": 2,
      "Market": "ON_DEMAND"
    },
    {
      "Name": "Task",
      "InstanceRole": "TASK",
      "InstanceType": "m5.2xlarge",
      "InstanceCount": 4,
      "Market": "SPOT",
      "BidPrice": "0.20"
    }
  ]
}

EMR Autoscaling: Ajusta automàticament el nombre de task nodes en funció de la càrrega (YARN container pending, memòria disponible).

8.2 Databricks: optimització de costos

Estratègia Estalvi estimat Quan usar
Job Clusters en comptes d'All-Purpose 40-60% Jobs batch programats
Autoscaling habilitat 30-50% Càrregues variables
Spot instances (AWS) o preemptible (GCP) 60-80% Jobs tolerants a interrupció
Cluster policies Evita despeses accidentals Entorns d'equip
Auto-terminate (idle timeout) 10-20% Evita clústers oblidades

Job Cluster vs All-Purpose Cluster: Un All-Purpose cluster es pot compartir entre notebooks i users, però factura per hora mentre està actiu. Un Job Cluster s'engega automàticament quan el job comença i s'apaga quan acaba: ideal per a pipelines de producció.

8.3 GCP Dataproc: Preemptible VMs

# Crear clúster Dataproc amb VMs preemptibles
gcloud dataproc clusters create cluster-iabd \
  --region=europe-southwest1 \
  --master-machine-type=n1-standard-4 \
  --worker-machine-type=n1-standard-4 \
  --num-workers=2 \
  --num-secondary-workers=4 \
  --secondary-worker-type=preemptible \
  --enable-component-gateway

Miniactivitat

Configura una alerta de Prometheus que s'activi quan el disc d'un node superi el 80% de capacitat.

Passos:

  1. Crea el fitxer alertes.yml amb la regla DiscUsatAlt de la secció 1.6
  2. Modifica prometheus.yml per a incloure rule_files: ["alertes.yml"]
  3. Aixeca el docker-compose de la secció 1.3
  4. Accedeix a Prometheus (http://localhost:9090) → Alerts → Verifica que apareix la regla
  5. A Prometheus → Status → Rules, confirma que la regla s'ha carregat correctament
  6. Comprova a PromQL: (1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100

Lliurament: Captura de pantalla de la pàgina "Alerts" de Prometheus amb la regla activa.


Exercici pràctic: Monitoratge complet amb Prometheus + Grafana

Objectiu: Desplegar un entorn de monitoratge complet i crear un dashboard funcional.

Pas 1: Crea l'estructura de fitxers:

mkdir -p monitoratge-iabd
cd monitoratge-iabd
# Crear docker-compose-monitoring.yml (de la secció 1.3)
# Crear prometheus.yml (de la secció 1.4)
# Crear alertes.yml (de la secció 1.6)
# Crear alertmanager.yml (de la secció 6.1, adaptat sense Slack real)

Pas 2: Adapta alertmanager.yml per a usar un receptor null (sense notificacions externes reals):

route:
  receiver: 'null'
receivers:
  - name: 'null'

Pas 3: Aixeca l'entorn:

docker compose -f docker-compose-monitoring.yml up -d
# Verificar que tots els serveis estan actius
docker compose -f docker-compose-monitoring.yml ps

Pas 4: Accedeix a les UIs:

  • Prometheus: http://localhost:9090 — verifica que node-exporter apareix a Status → Targets
  • Grafana: http://localhost:3001 — user admin, password iabd2025

Pas 5: Configura Grafana:

  1. Afegeix font de dades: Configuration → Data Sources → Add data source → Prometheus
  2. URL: http://prometheus:9090
  3. Fes clic a Save & Test
  4. Importa el dashboard oficial de Node Exporter: Dashboards → Import → ID 1860

Pas 6: Crea una alerta visual a Grafana:

  1. Obre el panell de "Disk Space Used Basic"
  2. Edit → Alert → Create alert rule
  3. Condició: quan l'ús de disc superi el 70%
  4. Nom: "Disc quasi ple - [el teu nom]"

Lliurament: Captura de pantalla del dashboard de Grafana amb les mètriques en temps real i l'alerta configurada.