En 05-04 dejamos abierto el canary con peso exacto entre servicios internos: el Service de Kubernetes reparte por conexión y por número de réplicas, y para enviar exactamente el 10 % de las llamadas del gateway a servicio-pedidos v2 hace falta algo que entienda HTTP entre pods. Ese "algo" es la misma pieza que resolvería otros problemas que cada servicio de TechCorp está repitiendo en su código: timeouts, reintentos, cifrado entre servicios, métricas de tráfico. Un service mesh saca todo eso de las aplicaciones y lo pone en la infraestructura, con un proxy junto a cada pod y un plano de control que los configura. Esta lección explica cómo funciona (con Istio como referencia y Linkerd como alternativa), muestra los recursos YAML que cierran el canary de 05-04 y declaran timeouts y reintentos para Pedidos→Catálogo, enumera con honestidad lo que cuesta, y termina con la decisión de TechCorp: si adoptarlo ya, y qué hacer si no. Lo que el mesh toca de seguridad (mTLS, 07-02), de resiliencia en código (06-03) y de trazas (06-02) solo se nombra aquí como capacidad.

Contenido

  1. Los problemas transversales que se repiten en cada servicio
  2. Qué es un service mesh: plano de datos y plano de control
  3. Instalar Istio en el clúster de TechCorp y qué cambia en los pods
  4. Enrutamiento por peso: VirtualService y DestinationRule (el canary 90/10 de Pedidos)
  5. Timeouts y reintentos declarativos: Pedidos → Catálogo
  6. Circuit breaking con outlierDetection
  7. Seguridad como capacidad: PeerAuthentication y AuthorizationPolicy
  8. La observabilidad que regala el mesh (y la que no)
  9. Linkerd como alternativa más ligera
  10. Lo que cuesta un mesh
  11. ¿Necesita TechCorp un mesh? La decisión
  12. Qué hacer mientras tanto

  1. Los problemas transversales que se repiten en cada servicio

Repasa lo que hemos ido pidiendo a cada servicio a lo largo del curso:

Preocupación Dónde la resolvemos hoy Repetida en
Timeout al llamar a otro servicio TIMEOUT_HTTP_MS en el cliente HTTP de cada servicio (04-03, 04-04) Los seis servicios y el gateway
Reintentos ante fallos transitorios Código en catalogoCliente.js (y su lógica completa en 06-03) Cada cliente HTTP
Circuit breaker Código (06-03) Cada cliente HTTP
Cifrado y autenticación entre servicios Nada aún; TLS solo en el Ingress (07-02) Todos
Métricas de tráfico (peticiones, errores, latencia) por servicio y ruta Middleware de @techcorp/comun-http que exporta a Prometheus (06-01) Todos
Enrutamiento por peso / por cabecera Ingress NGINX o el gateway Express (05-04), solo en el borde Solo el borde
Balanceo por petición (capa 7) No: kube-proxy balancea por conexión (03-05)

Todo esto tiene tres características: es idéntico para todos los servicios, no es lógica de negocio, y depende del lenguaje (la librería @techcorp/comun-http solo sirve para Node; si el segundo servicio en Go de 04-01 llega, habrá que reescribirla). La idea del mesh: si son problemas de red, que los resuelva la red.

  1. Qué es un service mesh: plano de datos y plano de control

Un service mesh tiene dos partes:

  • Plano de datos: un proxy ligero desplegado junto a cada pod (sidecar: Envoy en Istio, linkerd2-proxy en Linkerd) que intercepta todo el tráfico entrante y saliente del contenedor de la aplicación. La aplicación cree que llama a http://servicio-catalogo:3001; en realidad habla con su sidecar en localhost, que aplica reglas (timeout, reintento, mTLS, métricas) y reenvía al sidecar del destino. Istio ofrece además el modo ambient (sin sidecar: un proxy por nodo, ztunnel, para capa 4 y waypoints opcionales para capa 7).
  • Plano de control: un componente central (istiod en Istio; el control plane de Linkerd) que lee los recursos de Kubernetes y los del mesh (VirtualService, DestinationRule...), y empuja la configuración a todos los proxies, además de emitir los certificados para mTLS.
flowchart TB
    subgraph CP["Plano de control (namespace istio-system)"]
        ISTIOD[istiod<br/>config + certificados]
    end
    subgraph NS["namespace techcorp (istio-injection=enabled)"]
        subgraph PG["pod gateway"]
            G[gateway :8080] --- GE[envoy sidecar]
        end
        subgraph PP1["pod servicio-pedidos v1"]
            P1[servicio-pedidos :3002] --- PE1[envoy]
        end
        subgraph PP2["pod servicio-pedidos v2"]
            P2[servicio-pedidos :3002] --- PE2[envoy]
        end
        subgraph PC["pod servicio-catalogo"]
            C[servicio-catalogo :3001] --- CE[envoy]
        end
    end
    ISTIOD -.->|xDS: reglas| GE
    ISTIOD -.-> PE1
    ISTIOD -.-> PE2
    ISTIOD -.-> CE
    GE -->|90 %, mTLS| PE1
    GE -->|10 %, mTLS| PE2
    PE1 -->|timeout 2s, retry GET, mTLS| CE

Lo importante del dibujo: ninguna línea toca el código de los servicios. Pedidos sigue haciendo fetch(CATALOGO_URL + '/v1/productos?ids=...') con su TIMEOUT_HTTP_MS; el sidecar añade lo demás.

  1. Instalar Istio en el clúster de TechCorp y qué cambia en los pods

Conceptualmente (los detalles varían por versión), tres pasos:

istioctl install --set profile=default -y        # instala istiod y el ingress gateway de Istio en istio-system
kubectl label namespace techcorp istio-injection=enabled     # a partir de ahora, cada pod NUEVO del namespace recibe un sidecar
kubectl rollout restart deploy -n techcorp       # recrear los pods existentes para que se inyecte
kubectl get pods -n techcorp                     # servicio-pedidos-...  2/2 Running   ← dos contenedores: la app y istio-proxy

Qué cambia en cada pod, sin tocar ningún manifiesto de 05-02: un contenedor istio-proxy (Envoy) al lado del de la aplicación, un init container (o el CNI de Istio) que redirige con iptables todo el tráfico del pod a través del proxy, y unas decenas de MB de memoria más por pod. La readinessProbe sigue apuntando al contenedor de la aplicación (Istio la reescribe para pasar por el proxy, de forma transparente). Y con Kustomize/GitOps (05-02, 05-03), la etiqueta del namespace es un cambio en namespace.yaml, revisado y aplicado como todo lo demás.

  1. Enrutamiento por peso: VirtualService y DestinationRule (el canary 90/10 de Pedidos)

Retomamos 05-04: Deployment servicio-pedidos (etiqueta version: v1) y servicio-pedidos-canary (version: v2), ambos seleccionados por el Service servicio-pedidos. Con Istio, el número de réplicas deja de importar para el reparto: se declara el peso.

# k8s/servicio-pedidos/base/destinationrule.yaml
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata: { name: servicio-pedidos, namespace: techcorp }
spec:
  host: servicio-pedidos                 # el Service de Kubernetes (05-02)
  subsets:                               # subconjuntos de pods, por etiqueta
    - name: v1
      labels: { version: v1 }
    - name: v2
      labels: { version: v2 }
---
# k8s/servicio-pedidos/base/virtualservice.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata: { name: servicio-pedidos, namespace: techcorp }
spec:
  hosts: [servicio-pedidos]              # se aplica a quien llame a http://servicio-pedidos:3002 dentro del mesh (el gateway)
  http:
    - match:                             # canary por cabecera (05-04, 03-04): el equipo prueba v2 en producción
        - headers: { x-canary: { exact: pedidos } }
      route:
        - destination: { host: servicio-pedidos, subset: v2 }
    - route:                             # todos los demás: reparto por peso EXACTO por petición
        - destination: { host: servicio-pedidos, subset: v1 }
          weight: 90
        - destination: { host: servicio-pedidos, subset: v2 }
          weight: 10

Avanzar el canary es cambiar 90/10 por 50/50 y por 0/100 (tres commits en plataforma, o lo que Argo Rollouts/Flagger hagan solos con métricas, 05-04); retirarlo es 100/0. Con una réplica de v2 y tres de v1, el 10 % es el 10 %, no "una de cuatro". Esto es lo que 05-04 no podía dar sin mesh.

  1. Timeouts y reintentos declarativos: Pedidos → Catálogo

La llamada GET /v1/productos?ids= desde Pedidos (04-04) con timeout y reintentos en el mesh:

# k8s/servicio-catalogo/base/virtualservice.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata: { name: servicio-catalogo, namespace: techcorp }
spec:
  hosts: [servicio-catalogo]
  http:
    - match:
        - method: { exact: GET }         # SOLO lecturas: son idempotentes (03-01), reintentar es seguro
      route:
        - destination: { host: servicio-catalogo }
      timeout: 2s                        # tiempo TOTAL de la petición, incluidos los reintentos
      retries:
        attempts: 2                      # hasta 2 reintentos (3 intentos en total)
        perTryTimeout: 800ms             # cada intento como mucho 0,8 s
        retryOn: 5xx,connect-failure,reset   # cuándo: error del servidor, no se pudo conectar, conexión cortada
    - route:                             # todo lo demás (si Catálogo tuviera POST/PUT): sin reintentos
        - destination: { host: servicio-catalogo }
      timeout: 2s

Tres advertencias que el YAML no dice solo:

  • Reintentar solo operaciones idempotentes. Un GET repetido no hace daño; un POST /v1/pedidos reintentado por el proxy crearía dos pedidos si el primero llegó y la respuesta se perdió, salvo que el servidor aplique la Idempotency-Key (03-01), y aun así el proxy no la conoce. Por eso el match por método, y por eso nunca se pone retries en un VirtualService genérico de Pedidos.
  • El timeout del mesh y el del código conviven. TIMEOUT_HTTP_MS=2000 (04-03) sigue en Pedidos: el sidecar corta a los 2 s y la aplicación también. Deben ser coherentes (el de la aplicación algo mayor o igual que el del mesh, para que sea el mesh quien reintente dentro de su ventana); si el de la app fuese 1 s, cortaría antes de que el mesh reintentase.
  • El mesh no sustituye la lógica de fallo. Qué hace Pedidos cuando Catálogo no responde tras los reintentos (degradar con el precio del último traductorProducto, rechazar el pedido, encolar) es decisión de negocio y vive en el código: 06-03.

  1. Circuit breaking con outlierDetection

El DestinationRule también puede expulsar temporalmente del balanceo a los pods que fallan (outlier detection, un circuit breaker pasivo por instancia) y limitar conexiones:

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata: { name: servicio-catalogo, namespace: techcorp }
spec:
  host: servicio-catalogo
  trafficPolicy:
    connectionPool:
      http: { http1MaxPendingRequests: 100, maxRequestsPerConnection: 10 }
    outlierDetection:
      consecutive5xxErrors: 5            # cinco 5xx seguidos de un mismo pod...
      interval: 10s                      # ...evaluado cada 10 s...
      baseEjectionTime: 30s              # ...lo sacan del balanceo 30 s (creciente si reincide)
      maxEjectionPercent: 50             # nunca se expulsa a más de la mitad de los pods

Aquí solo lo presentamos: protege del "pod enfermo" sin tocar código, pero no decide qué responder al usuario ni abre el circuito para una dependencia entera; el circuit breaker de aplicación (estados cerrado/abierto/semiabierto, respuesta alternativa) es de 06-03, y ambos se complementan.

  1. Seguridad como capacidad: PeerAuthentication y AuthorizationPolicy

Con una línea, todo el tráfico entre sidecars del namespace pasa a ser mTLS (cifrado y con identidad de cada servicio, certificados emitidos y rotados por istiod):

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata: { name: default, namespace: techcorp }
spec:
  mtls: { mode: STRICT }                 # solo se acepta tráfico mTLS; PERMISSIVE admitiría también texto plano durante la migración

Y una AuthorizationPolicy puede decir "solo el gateway puede llamar a servicio-pedidos" o "nadie salvo Pedidos e Inventario habla con Catálogo", por identidad de servicio, no por IP. Es una capacidad enorme por muy poco esfuerzo, y una de las razones típicas para adoptar un mesh. Cómo funciona mTLS, qué certificados hay debajo y cómo se consigue sin mesh es 07-02; aquí basta con saber que el mesh lo regala.

  1. La observabilidad que regala el mesh (y la que no)

Como todo el tráfico pasa por los proxies, el mesh produce sin instrumentar nada: métricas RED (peticiones, errores, duración) por servicio origen/destino, ruta y código de respuesta, en formato Prometheus; el grafo de llamadas en Kiali (quién habla con quién, con qué tasa de error, en tiempo real); y spans de traza por salto. Lo que no regala: la correlación de esos spans en una traza de la petición completa. Envoy no puede saber que la llamada saliente Pedidos→Catálogo pertenece a la petición entrante gateway→Pedidos; para eso la aplicación tiene que propagar las cabeceras de traza (traceparent, o las x-b3-*) de la petición entrante a las salientes. Ese es exactamente el trabajo de OpenTelemetry en 06-02, con o sin mesh.

  1. Linkerd como alternativa más ligera

Sin mesh (hoy en TechCorp) Linkerd Istio
Plano de datos linkerd2-proxy (Rust), muy pequeño (~10-20 MB por pod) Envoy (C++), más pesado (~50-100 MB por pod), o ambient sin sidecar
mTLS No (TLS en el borde) Por defecto, automático, sin configurar Sí, con PeerAuthentication
Enrutamiento por peso / cabecera Solo en el borde Sí (HTTPRoute de Gateway API, TrafficSplit) Sí, muy completo (VirtualService)
Reintentos / timeouts Código Sí (HTTPRoute, ServiceProfile) Sí, muy configurable
Circuit breaking Código Básico outlierDetection, connectionPool
Políticas de autorización NetworkPolicy (07-04) Sí (Server, AuthorizationPolicy propias) Sí, muy expresivas
Observabilidad incluida La que instrumente cada servicio Métricas dorada + panel linkerd viz Métricas + Kiali + integración Jaeger
Salida a servicios externos, multi-clúster, VMs Multi-clúster; menos opciones Todo, con más recursos y conceptos
Complejidad y curva Ninguna Baja: pocas CRDs, "funciona al instalar" Alta: muchas CRDs, muchas opciones, muchas formas de equivocarse
Consumo de recursos Ninguno Bajo Medio-alto

Linkerd instala con linkerd install | kubectl apply -f - y la anotación linkerd.io/inject: enabled en el namespace, y en muchos equipos pequeños es "todo el mesh que necesitan": mTLS y métricas por defecto, reintentos y pesos declarativos, sin la extensión de Istio.

  1. Lo que cuesta un mesh

  • Latencia: cada salto pasa por dos proxies; el coste es de milisegundos (menos con Linkerd), pero se suma en cadenas largas.
  • Recursos: un sidecar por pod. Con 6 servicios × 3 réplicas más gateway y jobs, unos 25 proxies; con Envoy, entre 1 y 2 GB de memoria del clúster solo en sidecars.
  • Complejidad operativa: otro plano de control que puede caer (si istiod cae, los proxies siguen con la última configuración, pero no arrancan pods nuevos correctamente), CRDs que aprender, depuración más difícil ("¿falla la app o el sidecar?"), interacción con jobs (un Job con sidecar no termina hasta que se mate el proxy: hay que anotarlo o usar ambient).
  • Actualizaciones: el mesh tiene su propio ciclo de versiones, acoplado a versiones de Kubernetes; actualizarlo implica reiniciar todos los pods para renovar sidecars.
  • Falsa sensación: "ya tenemos reintentos" sin haber pensado en idempotencia; "ya tenemos mTLS" sin políticas de autorización.

  1. ¿Necesita TechCorp un mesh? La decisión

Los datos: seis servicios más el gateway, todos en Node con la misma librería, un equipo de Plataforma de cuatro personas que acaba de montar Kubernetes, CI/CD y GitOps y que aún tiene por delante observabilidad (módulo 6) y seguridad (módulo 7). Los beneficios que TechCorp aprovecharía hoy: el peso exacto del canary de Pedidos y Pagos, mTLS interno y métricas de tráfico gratis. Los costes: complejidad para un equipo que ya está al límite, y una capa más que depurar cuando falle la saga a las 3 de la mañana.

Decisión de Marta y del equipo de Plataforma: no adoptar un mesh en la primera fase. Se reevaluará cuando se cumpla cualquiera de estas condiciones: (a) más de 10 servicios o un segundo lenguaje (la librería deja de cubrir a todos); (b) un requisito de mTLS obligatorio entre servicios (por ejemplo, una auditoría del área de Pagos), momento en que el mesh es la forma más barata de conseguirlo; (c) el canary manual por réplicas de Pedidos y Pagos se convierta en un cuello de botella real. Cuando llegue, la primera opción a evaluar será Linkerd, por coste y curva, con Istio ambient como segunda si hacen falta sus capacidades de enrutamiento.

  1. Qué hacer mientras tanto

Necesidad Solución sin mesh en TechCorp Lección
Timeouts, reintentos idempotentes, circuit breaker Cliente HTTP de @techcorp/comun-http (TIMEOUT_HTTP_MS, reintentos solo en GET, breaker) 06-03
Métricas RED por servicio Middleware Prometheus de la librería 06-01
Trazas OpenTelemetry en la librería (propagación de cabeceras: hace falta igual con mesh) 06-02
Enrutamiento por peso y cabecera Ingress NGINX canary-weight en el borde; canary por réplicas entre servicios 05-04
Cifrado y autenticación entre servicios TLS en el Ingress; JWT propagado y verificado en cada servicio; NetworkPolicy para "quién habla con quién" 07-01, 07-02, 07-04
Balanceo Service de Kubernetes (capa 4) y el gateway (capa 7 en el borde) 03-05

La ventaja de haber concentrado lo transversal en @techcorp/comun-http desde 04-01 es que, si un día llega el mesh, se quita de la librería lo que el mesh asuma (reintentos, métricas de tráfico) sin tocar los servicios; y si no llega, la librería sigue siendo el "mesh en proceso" de TechCorp.

Errores Comunes y Consejos

  • Reintentos en el mesh para todo (retryOn: 5xx sin match por método): pedidos duplicados. Solo idempotentes.
  • Adoptar el mesh "porque lo usa todo el mundo" con cinco servicios y dos personas de plataforma. Los problemas que resuelve tienen que existir antes.
  • PeerAuthentication STRICT de golpe con servicios aún sin sidecar (o con Prometheus haciendo scraping desde fuera del mesh): todo deja de hablar. PERMISSIVE primero, STRICT cuando el 100 % tiene proxy.
  • Un Job con sidecar que nunca termina: el contenedor de la app acaba, Envoy sigue. Anotación para no inyectar en jobs o ambient.
  • Creer que el mesh da trazas completas sin tocar la app: sin propagar traceparent, cada salto es una traza suelta.
  • Consejo: si adoptas un mesh, empieza por un namespace y una capacidad (mTLS PERMISSIVE + métricas), y añade enrutamiento solo cuando lo necesites; y mide la latencia p99 antes y después.

Ejercicios

Ejercicio 1. Escribe el VirtualService que permitiría al equipo de Pedidos, con Istio, reproducir la estrategia del ejercicio de 03-04 pero para Pedidos: durante una semana, solo las peticiones internas con X-Canary: pedidos van a servicio-pedidos v2; el resto, a v1; y explica en dos frases qué recurso más necesita y por qué no hay que tocar el Deployment ni el Service.

Ejercicio 2. Un compañero propone declarar en el VirtualService de servicio-pedidos retries: { attempts: 3, retryOn: 5xx } "para que el gateway no vea errores en los picos". Explica qué pasaría con POST /v1/pedidos y con GET /v1/pedidos/{id}, y cómo se puede conseguir lo que quiere sin riesgo.

Ejercicio 3. Marta te pide un criterio en una frase para cada una de las tres condiciones de reevaluación del apartado 11 (más de 10 servicios o segundo lenguaje, mTLS obligatorio, canary como cuello de botella), y que indiques para cada una si el primer candidato sería Linkerd o Istio y por qué.

Soluciones

Solución 1.

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata: { name: servicio-pedidos, namespace: techcorp }
spec:
  hosts: [servicio-pedidos]
  http:
    - match: [ { headers: { x-canary: { exact: pedidos } } } ]
      route: [ { destination: { host: servicio-pedidos, subset: v2 } } ]
    - route: [ { destination: { host: servicio-pedidos, subset: v1 } } ]     # 100 % v1 para el resto

Necesita el DestinationRule del apartado 4 que define los subsets v1/v2 por la etiqueta version. No se toca el Deployment ni el Service porque ambos ya existen tal como los dejó 05-04 (dos Deployment con version: v1/v2, un Service que selecciona por app); el mesh enruta por encima del Service, leyendo etiquetas de los pods. Retirar el canary es borrar la primera regla; ningún manifiesto de 05-02 cambia.

Solución 2. POST /v1/pedidos no es idempotente desde el punto de vista del proxy: si Pedidos crea el pedido y la respuesta se pierde (o el pod devuelve 500 tras haber confirmado la transacción, o muere justo después de escribir), el sidecar reintenta y el segundo intento llega con la misma Idempotency-Key; si el servicio implementó bien la clave (03-01, 04-04), responde el mismo resultado y no hay duplicado, pero se está dependiendo de que todos los POST del servicio sean idempotentes; y en un pico de carga, tres intentos por petición triplican la carga que causa el pico (tormenta de reintentos). GET /v1/pedidos/{id} sí puede reintentarse. Solución: match por method: GET para la ruta con retries, retryOn: connect-failure,reset (no 5xx) como mucho para el resto, perTryTimeout corto, y en el gateway un timeout claro; el pico se trata con réplicas (05-02, HPA en 06-04) y con rate limiting en el gateway (03-04), no con reintentos.

Solución 3. (a) Más de 10 servicios o segundo lenguaje: "cuando la librería no pueda garantizar el mismo comportamiento en todos los servicios, el comportamiento pasa a la red"; primer candidato Linkerd (cubre timeouts, reintentos, mTLS y métricas con poco coste). (b) mTLS obligatorio: "cuando una auditoría exija cifrado e identidad entre servicios, el mesh es más barato que gestionar certificados en seis servicios"; Linkerd, porque el mTLS es automático y por defecto. (c) Canary como cuello de botella: "cuando el porcentaje por réplicas o el Ingress no baste para Pedidos y Pagos y queramos automatizarlo con Argo Rollouts/Flagger"; aquí Istio (o Linkerd con Gateway API) por la riqueza de enrutamiento, salvo que Linkerd cubra lo necesario, en cuyo caso se mantiene la opción ligera.

Conclusión

Un service mesh mueve a la infraestructura lo que cada servicio repite en su código: un proxy junto a cada pod (Envoy con Istio, linkerd2-proxy con Linkerd, o el modo ambient sin sidecar) y un plano de control (istiod) que lo configura, activado con istioctl install y la etiqueta istio-injection=enabled en techcorp. Con DestinationRule (subsets v1/v2 por etiqueta version) y VirtualService hemos cerrado el canary de 05-04 con peso exacto 90/10 y por cabecera X-Canary; hemos declarado timeout: 2s y retries solo para los GET de Pedidos→Catálogo, con la advertencia de no reintentar POST /v1/pedidos; hemos presentado outlierDetection como circuit breaking pasivo, PeerAuthentication STRICT y AuthorizationPolicy como capacidades de seguridad (07-02), y las métricas y Kiali como observabilidad regalada que aun así necesita que la aplicación propague las cabeceras de traza (06-02); hemos comparado Istio, Linkerd y no tener mesh, y contado sus costes. La decisión de TechCorp es no adoptarlo en la primera fase y reevaluar Linkerd al superar diez servicios, con mTLS obligatorio o cuando el canary manual estorbe; hasta entonces, la librería @techcorp/comun-http, el gateway y el código de resiliencia hacen ese papel.

Con esto termina el módulo de despliegue y orquestación: cada servicio es una imagen Docker construida con la misma plantilla y levantada en local con Docker Compose (05-01), se ejecuta en Kubernetes con sus Deployment, Service, ConfigMap, Secret, Job e Ingress gestionados con Kustomize (05-02), llega a staging y a producción por un pipeline de GitHub Actions con pactos, imágenes etiquetadas y GitOps (05-03), cambia de versión sin cortes con rolling, blue-green o canary (05-04) y sabe qué le daría un mesh y por qué aún no lo tiene (05-05). Lo que aún no tenemos es visibilidad: cuando el sistema esté en producción, ¿cómo sabremos que la saga de un pedido se ha atascado, qué servicio responde lento, o si el canary de Pedidos va bien? El módulo 6 empieza por ahí: logging estructurado con Loki y métricas con Prometheus y Grafana (06-01), trazas distribuidas con OpenTelemetry y Jaeger (06-02), la gestión de errores y la resiliencia en código que este módulo ha ido remitiendo (06-03), escalabilidad y rendimiento con el HPA (06-04) y, por último, SLOs, alertas y gestión de incidentes (06-05). Empieza por los logs y las métricas.

Curso de Microservicios

Módulo 1: Introducción a los Microservicios

Módulo 2: Diseño de Microservicios

Módulo 3: Comunicación entre Microservicios

Módulo 4: Implementación de Microservicios

Módulo 5: Despliegue y Orquestación

Módulo 6: Monitoreo y Mantenimiento

Módulo 7: Seguridad en Microservicios

Módulo 8: Casos de Estudio y Ejemplos Prácticos

© Copyright 2026. Todos los derechos reservados