SRE: SLIs, SLOs y Automatizaciones Que Realmente Ayudan

2026-02-06 | Gabriel Garrido | 12 min de lectura
Share:

Apoya este blog

Si te resulta util este contenido, considera apoyar el blog.

Introducción

En este artículo vamos a explorar el lado práctico de la Ingeniería de Confiabilidad de Sitio (SRE), específicamente cómo definir Indicadores de Nivel de Servicio (SLIs) y Objetivos de Nivel de Servicio (SLOs) como código, desplegarlos usando ArgoCD, y aprovechar servidores MCP y automatizaciones para hacer todo el proceso menos doloroso.


Si venís haciendo operaciones o ingeniería de plataformas hace un tiempo, probablemente ya sabés que el monitoreo solo no alcanza. Tener un dashboard lleno de luces verdes no significa que tus usuarios estén contentos. Los SLIs y SLOs te dan un marco para medir lo que realmente importa y tomar decisiones informadas sobre confiabilidad vs. velocidad de entrega de features.


Vamos al tema.


¿Qué es SRE?

Site Reliability Engineering es una disciplina que aplica prácticas de ingeniería de software a problemas de operaciones. Google popularizó el concepto, pero la idea central es simple: tratá tu infraestructura y procesos operativos como código, medí lo que importa, y usá presupuestos de error para balancear confiabilidad con la velocidad de entrega de nuevas funcionalidades.


Los componentes clave son:

  • SLIs (Indicadores de Nivel de Servicio): Métricas que miden la calidad de tu servicio desde la perspectiva del usuario
  • SLOs (Objetivos de Nivel de Servicio): Objetivos que definís para tus SLIs (ej: “99.9% de las requests deben ser exitosas”)
  • Presupuestos de Error: La cantidad aceptable de falta de confiabilidad (100% - objetivo del SLO)
  • SLAs (Acuerdos de Nivel de Servicio): Contratos comerciales basados en SLOs (no nos vamos a enfocar en estos acá)

Entendiendo los SLIs

Un SLI es una medida cuantitativa cuidadosamente definida de algún aspecto del nivel de servicio proporcionado. Los SLIs más comunes son:


  • Disponibilidad: La proporción de requests que son exitosas
  • Latencia: La proporción de requests que son más rápidas que un umbral
  • Calidad: La proporción de respuestas que no están degradadas

Lo importante acá es la parte de “proporción”. Los SLIs se expresan como ratios:

SLI = eventos_buenos / eventos_totales

Por ejemplo, para un servicio HTTP:

# SLI de Disponibilidad
disponibilidad = (requests_totales - errores_5xx) / requests_totales

# SLI de Latencia
latencia = requests_mas_rapidas_que_300ms / requests_totales

Esto es mucho más útil que métricas crudas porque refleja directamente la experiencia del usuario. Un pico de errores que dura 5 segundos es muy diferente de uno que dura 5 minutos, y el ratio captura esa diferencia sobre una ventana de tiempo.


Entendiendo los SLOs

Un SLO es el valor objetivo para un SLI sobre una ventana de tiempo específica. Por ejemplo:


  • “99.9% de las requests HTTP deben devolver una respuesta sin error en una ventana móvil de 30 días”
  • “99% de las requests deben completarse en menos de 300ms en una ventana móvil de 30 días”

El SLO te da un presupuesto de error. Si tu SLO es 99.9%, tu presupuesto de error es 0.1%. En 30 días, eso significa que podés permitirte aproximadamente 43 minutos de tiempo de inactividad total. Esto es increíblemente poderoso porque convierte la confiabilidad en un recurso medible que podés gastar. ¿Querés hacer un despliegue riesgoso? Revisá tu presupuesto de error primero.


Llevando los SLIs a código con Prometheus

Ahora vamos a lo práctico. La forma más común de implementar SLIs es con métricas de Prometheus. Si estás corriendo cargas de trabajo en Kubernetes, probablemente ya tenés Prometheus o un sistema compatible recolectando métricas.


Para un servicio web típico, querés exponer un histograma que rastree la duración de las requests y el estado:

# Si tu aplicación usa el cliente de Prometheus, exponé algo como:
# histogram: http_request_duration_seconds (con labels: method, path, status)
# counter: http_requests_total (con labels: method, path, status)

# Para nuestra app Phoenix/Elixir, usamos phoenix_telemetry y peep para exponer estas métricas.
# Pero el concepto aplica a cualquier lenguaje.

Con esas métricas en Prometheus, podés definir recording rules que calculen los ratios del SLI. Acá hay un ejemplo de reglas de Prometheus para un SLI de disponibilidad HTTP:

# prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: sli-availability
  namespace: monitoring
spec:
  groups:
    - name: sli.availability
      interval: 30s
      rules:
        # Tasa de requests totales en ventana de 5m
        - record: sli:http_requests:rate5m
          expr: sum(rate(http_requests_total[5m]))

        # Tasa de requests con error en ventana de 5m (respuestas 5xx)
        - record: sli:http_errors:rate5m
          expr: sum(rate(http_requests_total{status=~"5.."}[5m]))

        # SLI de disponibilidad (ratio de requests exitosas)
        - record: sli:availability:ratio_rate5m
          expr: |
            1 - (sli:http_errors:rate5m / sli:http_requests:rate5m)

Y para un SLI de latencia:

# prometheus-rules-latency.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: sli-latency
  namespace: monitoring
spec:
  groups:
    - name: sli.latency
      interval: 30s
      rules:
        # Requests más rápidas que 300ms
        - record: sli:http_request_duration:rate5m
          expr: sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))

        # Todas las requests
        - record: sli:http_request_duration_total:rate5m
          expr: sum(rate(http_request_duration_seconds_count[5m]))

        # SLI de latencia
        - record: sli:latency:ratio_rate5m
          expr: |
            sli:http_request_duration:rate5m / sli:http_request_duration_total:rate5m

Estas recording rules pre-computan los ratios del SLI para que puedas usarlos en alertas y dashboards sin ejecutar consultas costosas cada vez.


SLOs como código con Sloth

Escribir recording rules y alert rules de Prometheus a mano para cada SLO se vuelve tedioso rápido. Ahí es donde entra Sloth. Sloth es una herramienta que genera todas las reglas de Prometheus que necesitás a partir de una definición simple de SLO.


Acá hay una definición de SLO para nuestro servicio:

# slos/tr-web.yaml
apiVersion: sloth.slok.dev/v1
kind: PrometheusServiceLevel
metadata:
  name: tr-web
  namespace: default
spec:
  service: "tr-web"
  labels:
    team: "platform"
  slos:
    - name: "requests-availability"
      objective: 99.9
      description: "99.9% de las requests HTTP deben ser exitosas"
      sli:
        events:
          error_query: sum(rate(http_requests_total{status=~"5..",service="tr-web"}[{{.window}}]))
          total_query: sum(rate(http_requests_total{service="tr-web"}[{{.window}}]))
      alerting:
        name: TrWebHighErrorRate
        labels:
          severity: critical
          team: platform
        annotations:
          summary: "Tasa de error alta en tr-web"
        page_alert:
          labels:
            severity: critical
        ticket_alert:
          labels:
            severity: warning

    - name: "requests-latency"
      objective: 99.0
      description: "99% de las requests deben ser más rápidas que 300ms"
      sli:
        events:
          error_query: |
            sum(rate(http_request_duration_seconds_count{service="tr-web"}[{{.window}}]))
            -
            sum(rate(http_request_duration_seconds_bucket{le="0.3",service="tr-web"}[{{.window}}]))
          total_query: sum(rate(http_request_duration_seconds_count{service="tr-web"}[{{.window}}]))
      alerting:
        name: TrWebHighLatency
        labels:
          severity: warning
          team: platform
        annotations:
          summary: "Latencia alta en tr-web"
        page_alert:
          labels:
            severity: critical
        ticket_alert:
          labels:
            severity: warning

Después generás las reglas de Prometheus:

sloth generate -i slos/tr-web.yaml -o prometheus-rules/tr-web-slo.yaml

Sloth genera alertas multi-ventana y multi-tasa-de-quemado siguiendo las recomendaciones del libro de SRE de Google. Obtenés alertas de quemado rápido (algo está muy mal ahora) y alertas de quemado lento (estás consumiendo presupuesto de error más rápido de lo esperado). Esto es una mejora enorme comparado con definir umbrales de alerta manualmente.


Desplegando SLOs con ArgoCD

Ahora que tenemos nuestras definiciones de SLO y las reglas de Prometheus generadas como archivos YAML, podemos desplegarlos de la manera GitOps usando ArgoCD. Si leíste mi artículo anterior sobre GitOps, esto te va a resultar familiar.


La idea es simple: almacená tus definiciones de SLO y reglas generadas en un repositorio Git, y dejá que ArgoCD las sincronice con tu cluster.


Acá está la estructura del repositorio:

slo-configs/
├── slos/
│   ├── tr-web.yaml            # Definiciones de SLO de Sloth
│   └── api-gateway.yaml
├── generated/
│   ├── tr-web-slo.yaml        # Recursos PrometheusRule generados
│   └── api-gateway-slo.yaml
├── dashboards/
│   ├── tr-web-slo.json        # JSON de dashboard de Grafana
│   └── api-gateway-slo.json
└── argocd/
    └── application.yaml        # Manifiesto de Application de ArgoCD

El manifiesto de Application de ArgoCD:

# argocd/application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: slo-configs
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/kainlite/slo-configs
    targetRevision: HEAD
    path: generated
  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Con este setup, cada vez que actualizás una definición de SLO, regenerás las reglas y pusheás a Git, ArgoCD aplica automáticamente los cambios en tu cluster. Sin comandos manuales de kubectl, sin olvidarte de aplicar ese archivo que cambiaste la semana pasada.


También podés configurar un paso de CI para regenerar automáticamente las reglas de Prometheus cuando cambian las definiciones de SLO:

# .github/workflows/generate-slos.yaml
name: Generate SLO Rules

on:
  push:
    paths:
      - 'slos/**'

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Sloth
        run: |
          curl -L https://github.com/slok/sloth/releases/latest/download/sloth-linux-amd64 -o sloth
          chmod +x sloth

      - name: Generate rules
        run: |
          for slo in slos/*.yaml; do
            name=$(basename "$slo" .yaml)
            ./sloth generate -i "$slo" -o "generated/${name}-slo.yaml"
          done

      - name: Commit and push
        run: |
          git config user.name "github-actions"
          git config user.email "[email protected]"
          git add generated/
          git diff --staged --quiet || git commit -m "chore: regenerate SLO rules"
          git push

Ahora tenés un pipeline completamente automatizado: editás una definición de SLO, pusheás, CI genera las reglas, ArgoCD las despliega. Hermoso.


Servidores MCP para automatización de SRE

Acá es donde las cosas se ponen realmente interesantes. Los servidores de Model Context Protocol (MCP) te permiten darle a asistentes de IA como Claude acceso a tus herramientas de infraestructura. Imaginate poder preguntar “¿cuánto presupuesto de error me queda para tr-web?” y obtener una respuesta real de tus datos en vivo de Prometheus.


Un servidor MCP es esencialmente una API que expone herramientas que una IA puede llamar. Podés construir uno que envuelva tus APIs de Prometheus y Kubernetes:

// mcp-sre-server/src/main.rs
// Un ejemplo simplificado de un servidor MCP para consultas de SRE

use mcp_server::{Server, Tool, ToolResult};

#[derive(Tool)]
#[tool(name = "query_error_budget", description = "Consultar presupuesto de error restante")]
struct QueryErrorBudget {
    service: String,
    slo_name: String,
}

impl QueryErrorBudget {
    async fn execute(&self) -> ToolResult {
        let query = format!(
            r#"1 - (
                sli:availability:ratio_rate30d{{service="{}"}}
            ) / (1 - {}.0/100)"#,
            self.service, self.objective
        );

        let result = prometheus_query(&query).await?;
        ToolResult::text(format!(
            "Presupuesto de error para {}/{}: {:.2}% restante",
            self.service, self.slo_name, result * 100.0
        ))
    }
}

#[derive(Tool)]
#[tool(name = "list_slo_violations", description = "Listar SLOs que están quemando demasiado rápido")]
struct ListSloViolations;

impl ListSloViolations {
    async fn execute(&self) -> ToolResult {
        let query = r#"ALERTS{alertname=~".*SLO.*", alertstate="firing"}"#;
        let alerts = prometheus_query(query).await?;
        ToolResult::text(format!("Violaciones de SLO activas:\n{}", alerts))
    }
}

#[derive(Tool)]
#[tool(name = "get_deployment_risk", description = "Evaluar riesgo de despliegue basado en presupuesto de error")]
struct GetDeploymentRisk {
    service: String,
}

impl GetDeploymentRisk {
    async fn execute(&self) -> ToolResult {
        let budget = get_error_budget(&self.service).await?;
        let recent_deploys = get_recent_deploys(&self.service).await?;

        let risk = match budget {
            b if b > 0.5 => "BAJO - bastante presupuesto de error disponible",
            b if b > 0.2 => "MEDIO - el presupuesto de error se está agotando",
            b if b > 0.0 => "ALTO - muy poco presupuesto de error",
            _ => "CRÍTICO - presupuesto de error agotado, considerá congelar despliegues",
        };

        ToolResult::text(format!(
            "Riesgo de despliegue para {}: {}\nPresupuesto restante: {:.1}%\nDespliegues recientes: {}",
            self.service, risk, budget * 100.0, recent_deploys
        ))
    }
}

Con este servidor MCP corriendo, podés configurar Claude Code o cualquier cliente compatible con MCP para conectarse. Después tenés acceso en lenguaje natural a tus datos de SRE:


  • “¿Cuánto presupuesto de error tiene tr-web?” → Consulta Prometheus, devuelve el presupuesto restante
  • “¿Es seguro deployar ahora?” → Verifica presupuesto de error + incidentes recientes
  • “¿Qué SLOs están en riesgo esta semana?” → Lista SLOs con tasas de quemado altas
  • “Mostrá la tendencia de latencia de las últimas 24h” → Consulta Prometheus y resume

También podés construir herramientas MCP que se integren con ArgoCD:

#[derive(Tool)]
#[tool(name = "argocd_sync_status", description = "Verificar estado de sincronización de ArgoCD")]
struct ArgoCDSyncStatus;

impl ArgoCDSyncStatus {
    async fn execute(&self) -> ToolResult {
        let output = Command::new("argocd")
            .args(["app", "get", "slo-configs", "-o", "json"])
            .output()
            .await?;

        let app: ArgoApp = serde_json::from_slice(&output.stdout)?;
        ToolResult::text(format!(
            "Estado de sincronización de SLO configs: {}\nSalud: {}\nÚltima sincronización: {}",
            app.status.sync.status,
            app.status.health.status,
            app.status.sync.compared_to.revision
        ))
    }
}

#[derive(Tool)]
#[tool(name = "rollback_deployment", description = "Hacer rollback de un despliegue via ArgoCD")]
struct RollbackDeployment {
    service: String,
    revision: Option<String>,
}

impl RollbackDeployment {
    async fn execute(&self) -> ToolResult {
        // Esto estaría protegido detrás de confirmación en un setup real
        let revision = self.revision.as_deref().unwrap_or("HEAD~1");
        let output = Command::new("argocd")
            .args(["app", "rollback", &self.service, "--revision", revision])
            .output()
            .await?;

        ToolResult::text(format!("Rollback iniciado para {} a {}", self.service, revision))
    }
}

La configuración del servidor MCP en tu configuración de Claude Code se vería algo así:

{
  "mcpServers": {
    "sre-tools": {
      "command": "mcp-sre-server",
      "args": ["--prometheus-url", "http://prometheus:9090", "--argocd-url", "https://argocd.example.com"],
      "env": {
        "ARGOCD_AUTH_TOKEN": "tu-token-aca"
      }
    }
  }
}

Automatizaciones que unen todo

El verdadero poder viene cuando combinás SLOs, ArgoCD y servidores MCP en flujos de trabajo automatizados. Acá hay algunos patrones que funcionan bien en la práctica:


1. Puertas de despliegue automatizadas

Usá presupuestos de error como puertas de despliegue. Si el presupuesto de error está por debajo de un umbral, bloqueá despliegues automáticamente:

# En tu pipeline de CI
- name: Verificar presupuesto de error
  run: |
    BUDGET=$(curl -s "http://prometheus:9090/api/v1/query?query=error_budget_remaining{service='tr-web'}" \
      | jq -r '.data.result[0].value[1]')

    if (( $(echo "$BUDGET < 0.1" | bc -l) )); then
      echo "Presupuesto de error por debajo del 10%, bloqueando despliegue"
      exit 1
    fi

2. Creación automática de incidentes

Cuando se rompe un SLO, creá automáticamente un issue o incidente:

# alertmanager-config.yaml
receivers:
  - name: slo-breach
    webhook_configs:
      - url: http://incident-bot:8080/create
        send_resolved: true

route:
  routes:
    - match:
        severity: critical
        type: slo_breach
      receiver: slo-breach

3. Reportes semanales de SLO

Automatizá reportes semanales de SLO para mantener al equipo informado:

# Un CronJob que consulta Prometheus y envía un resumen a Slack
apiVersion: batch/v1
kind: CronJob
metadata:
  name: slo-weekly-report
  namespace: monitoring
spec:
  schedule: "0 9 * * 1"  # Todos los lunes a las 9am
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: reporter
              image: kainlite/slo-reporter:latest
              env:
                - name: PROMETHEUS_URL
                  value: "http://prometheus:9090"
                - name: SLACK_WEBHOOK
                  valueFrom:
                    secretKeyRef:
                      name: slack-webhook
                      key: url
          restartPolicy: Never

4. Congelamiento de features basado en presupuesto de error

Este es uno de los patrones más poderosos de SRE. Cuando el presupuesto de error se agota, el equipo debería cambiar el foco de features a trabajo de confiabilidad:


  • Presupuesto > 50%: Shippeá features libremente
  • Presupuesto 20-50%: Sé cauteloso con cambios riesgosos
  • Presupuesto 5-20%: Enfocate en mejoras de confiabilidad
  • Presupuesto < 5%: Congelamiento de features, todos a trabajar en confiabilidad

Podés automatizar esto haciendo que tu servidor MCP actualice una página de estado o canal de Slack con el nivel actual de presupuesto, para que todos en el equipo sepan dónde están las cosas sin tener que revisar dashboards.


Juntando todo

Acá hay un resumen de lo que construimos:


  1. SLIs como métricas de Prometheus: Recording rules que calculan ratios de disponibilidad y latencia
  2. SLOs con Sloth: Definiciones declarativas de SLO que generan alertas multi-ventana y multi-tasa-de-quemado
  3. GitOps con ArgoCD: Configuraciones de SLO almacenadas en Git, sincronizadas automáticamente al cluster
  4. Servidores MCP: Interfaz de lenguaje natural para consultar presupuestos de error, verificar riesgo de despliegue y gestionar ArgoCD
  5. Automatizaciones: Puertas de despliegue, creación de incidentes, reportes semanales y políticas de presupuesto de error

La belleza de este enfoque es que cada pieza es simple por sí sola, pero juntas crean un sistema donde la confiabilidad es medible, automatizada y parte del flujo de trabajo diario del equipo en lugar de algo que se piensa después.


Notas finales

SRE no tiene que ser complicado. Empezá con un SLI para tu servicio más importante, definí un SLO razonable y construí desde ahí. Las herramientas que cubrimos (Prometheus, Sloth, ArgoCD, servidores MCP) son todas de código abierto y probadas en batalla.


La conclusión clave es esta: medí lo que importa a tus usuarios, definí objetivos, y dejá que la automatización se encargue del resto. Tu yo del futuro durante la próxima guardia te lo va a agradecer.


¡Espero que te haya resultado útil y lo hayas disfrutado! ¡Hasta la próxima!


Errata

Si encontrás algún error o tenés alguna sugerencia, por favor mandame un mensaje para que se corrija.

También podés revisar el código fuente y los cambios en las fuentes acá



$ Comentarios

Online: 0

Por favor inicie sesión para poder escribir comentarios.

2026-02-06 | Gabriel Garrido