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
- Los problemas transversales que se repiten en cada servicio
- Qué es un service mesh: plano de datos y plano de control
- Instalar Istio en el clúster de TechCorp y qué cambia en los pods
- Enrutamiento por peso:
VirtualServiceyDestinationRule(el canary 90/10 de Pedidos) - Timeouts y reintentos declarativos: Pedidos → Catálogo
- Circuit breaking con
outlierDetection - Seguridad como capacidad:
PeerAuthenticationyAuthorizationPolicy - La observabilidad que regala el mesh (y la que no)
- Linkerd como alternativa más ligera
- Lo que cuesta un mesh
- ¿Necesita TechCorp un mesh? La decisión
- Qué hacer mientras tanto
- 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.
- 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-proxyen Linkerd) que intercepta todo el tráfico entrante y saliente del contenedor de la aplicación. La aplicación cree que llama ahttp://servicio-catalogo:3001; en realidad habla con su sidecar enlocalhost, 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 (
istioden 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.
- 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-proxyQué 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.
- Enrutamiento por peso:
VirtualService y DestinationRule (el canary 90/10 de Pedidos)
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: 10Avanzar 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.
- 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: 2sTres advertencias que el YAML no dice solo:
- Reintentar solo operaciones idempotentes. Un
GETrepetido no hace daño; unPOST /v1/pedidosreintentado por el proxy crearía dos pedidos si el primero llegó y la respuesta se perdió, salvo que el servidor aplique laIdempotency-Key(03-01), y aun así el proxy no la conoce. Por eso elmatchpor método, y por eso nunca se poneretriesen unVirtualServicegené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.
- Circuit breaking con
outlierDetection
outlierDetectionEl 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 podsAquí 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.
- Seguridad como capacidad:
PeerAuthentication y AuthorizationPolicy
PeerAuthentication y AuthorizationPolicyCon 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ónY 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.
- 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.
- 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.
- 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
istiodcae, 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 (unJobcon 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.
- ¿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.
- 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: 5xxsinmatchpor 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 STRICTde golpe con servicios aún sin sidecar (o con Prometheus haciendo scraping desde fuera del mesh): todo deja de hablar.PERMISSIVEprimero,STRICTcuando el 100 % tiene proxy.- Un
Jobcon 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 restoNecesita 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
- Conceptos Básicos de Microservicios
- Ventajas y Desventajas de los Microservicios
- Comparación con la Arquitectura Monolítica
- Cuándo Adoptar Microservicios: Criterios de Decisión
- El Caso Práctico del Curso: la Tienda Online de TechCorp
Módulo 2: Diseño de Microservicios
- Principios de Diseño de Microservicios
- Descomposición de Aplicaciones Monolíticas
- Definición de Bounded Contexts
- Gestión de Datos: una Base de Datos por Servicio
- Consistencia Distribuida: Sagas, CQRS y Event Sourcing
Módulo 3: Comunicación entre Microservicios
- APIs RESTful
- Mensajería Asíncrona
- Protocolos de Comunicación: gRPC, GraphQL
- API Gateway y Backend for Frontend
- Descubrimiento de Servicios y Balanceo de Carga
- Contratos y Versionado de APIs
Módulo 4: Implementación de Microservicios
- Elección de Tecnologías y Herramientas
- Desarrollo de un Microservicio Simple
- Gestión de Configuración
- Integración Práctica: Consumir APIs y Publicar Eventos
- Pruebas en Microservicios: Unitarias, de Integración y de Contrato
Módulo 5: Despliegue y Orquestación
- Contenedores y Docker
- Orquestación con Kubernetes
- CI/CD para Microservicios
- Estrategias de Despliegue: Rolling, Blue-Green y Canary
- Service Mesh: Istio y Linkerd
Módulo 6: Monitoreo y Mantenimiento
- Monitoreo y Logging
- Trazabilidad Distribuida con OpenTelemetry
- Gestión de Errores y Recuperación
- Escalabilidad y Rendimiento
- SLOs, Alertas y Gestión de Incidentes
Módulo 7: Seguridad en Microservicios
- Autenticación y Autorización
- Seguridad en la Comunicación
- Prácticas de Seguridad
- Seguridad en Contenedores y Kubernetes
