StackPractices
advanced Por Mathias Paulenko

Asegurar y Observar Microservicios con un Service Mesh

Cómo desplegar Istio o Linkerd para agregar mTLS, gestión de tráfico, observabilidad y enforcement de políticas a microservicios sin cambiar código de aplicación.

Visión general

Los microservicios se comunican a través de la red, y la red no es confiable. Cada llamada inter-servicio cruza límites de pod, límites de nodo y potencialmente límites de cluster. Sin encriptación, atacantes con acceso a la red pueden leer o modificar tráfico. Sin identidad, cualquier servicio comprometido puede impersonar a otro. Sin observabilidad, debuggear un request que atraviesa 10 servicios es casi imposible.

Un service mesh resuelve estos problemas insertando un proxy — un sidecar container — al lado de cada pod de aplicación. Todo el tráfico entrante o saliente del pod fluye a través del sidecar. El sidecar maneja mTLS mutuo, enrutamiento de tráfico, retries, timeouts, métricas y políticas de acceso. El código de aplicación permanece completamente inconsciente. Aqui se explica como conceptos de service mesh, despliegue de Istio, políticas de tráfico y observabilidad.

Cuándo usarlo

Usa esta receta cuando:

  • Ejecutando 10+ microservicios en Kubernetes con comunicación inter-servicio compleja
  • Requiriendo encriptación para todo el tráfico servicio-a-servicio sin modificar aplicaciones
  • Implementando despliegues canary, A/B testing o mirroring de tráfico entre versiones de servicios
  • Necesitando observabilidad unificada (métricas, logs, traces) a través de todos los microservicios
  • Haciendo enforcement de políticas de acceso (ej. “el servicio de pagos solo puede hablar con billing y fraud detection”)

Solución

Instalación de Istio (istioctl)

istioctl install --set profile=default -y

kubectl label namespace default istio-injection=enabled

kubectl rollout restart deployment -n default

Enrutamiento de Tráfico con VirtualService

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: user-service-route
spec:
  hosts:
    - user-service
  http:
    - match:
        - headers:
            x-canary:
              exact: "true"
      route:
        - destination:
            host: user-service
            subset: v2
          weight: 100
    - route:
        - destination:
            host: user-service
            subset: v1
          weight: 90
        - destination:
            host: user-service
            subset: v2
          weight: 10

---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: user-service-dr
spec:
  host: user-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 50
    outlierDetection:
      consecutiveErrors: 5
      interval: 30s
      baseEjectionTime: 30s
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2

mTLS con PeerAuthentication

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT

---
# Permitir solo servicios específicos a acceder payment-service
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: payment-policy
  namespace: default
spec:
  selector:
    matchLabels:
      app: payment-service
  action: ALLOW
  rules:
    - from:
        - source:
            principals:
              - "cluster.local/ns/default/sa/order-service"
              - "cluster.local/ns/default/sa/billing-service"

Explicación

  • Sidecar proxy: Envoy corre como sidecar en cada pod. Intercepta todo el tráfico de red vía reglas de iptables. Las aplicaciones aún hablan a localhost:8080, pero Envoy enruta, encripta y loguea el request real. El código de aplicación no requiere cambios.
  • Mutual TLS (mTLS): el sidecar proporciona un certificado para probar su identidad y valida el certificado del peer. El tráfico está encriptado en tránsito y autenticado en ambos extremos. Incluso dentro del mismo cluster, los servicios no pueden impersonarse entre sí sin robar un certificado.
  • Gestión de tráfico: VirtualService define reglas de enrutamiento — despliegues canary, retries, timeouts, inyección de fallos. Las políticas de tráfico son declarativas y versionadas en Git.
  • Observabilidad: Istio agrega esto en Kiali (topología), Grafana (métricas) y Jaeger (traces). Ves el grafo completo de servicios sin agregar instrumentación a las aplicaciones.

Variantes

FeatureIstioLinkerdConsul ConnectCilium Service Mesh
ComplejidadAltaBajaMediaMedia
PerformanceBuenaExcelenteBuenaExcelente (eBPF)
mTLSSíSíSíSí
Enrutamiento de tráficoCompletoBásicoBásicoBásico
Uso de recursosMayorMenorMediaBajo

Lo que funciona

  • Empieza con mTLS permisivo, luego enforce estricto: Después de validar flujos de tráfico, cambia a STRICT para rechazar conexiones no encriptadas. El modo estricto repentino puede romper servicios que no tienen sidecars.
  • Define service accounts por workload: las cuentas de servicio de Kubernetes se mapean a identidades de Istio. Esto habilita políticas de autorización granulares.
  • Configura retry budgets, no solo retries: retries ingenuos pueden amplificar fallos. Retries ilimitados crean retry storms.
  • Usa circuit breakers en cada llamada saliente: Si un servicio downstream retorna 5xx en el 50% de requests durante 30 segundos, échalo durante 30 segundos. Esto previene fallos en cascada.
  • Monitorea el uso de recursos del sidecar: Envoy consume CPU y memoria. Setea resource requests/limits en el sidecar. En servicios de alto throughput, el sidecar puede convertirse en el bottleneck antes que la aplicación. Profilea y tunea la concurrencia del proxy.

Errores comunes

  • Olvidar inyección de sidecar: un pod sin sidecar bypassa el mesh completamente. Su tráfico no está encriptado, no es observado y no tiene restricciones. Siempre verifica la inyección con kubectl get pod -o yaml | grep istio-proxy.
  • Políticas de autorización demasiado permisivas: una política ALLOW * por defecto derrota el propósito. Empieza con DENY all explícito, luego agrega reglas ALLOW para paths legítimos. Zero-trust significa denegar por defecto.
  • Ignorar ordering de startup: durante rolling updates, pods antiguos sin sidecar pueden hablar con pods nuevos con mTLS estricto.
  • Sin control de egress: por defecto, el tráfico mesh-internal está controlado pero el egress (APIs externas, bases de datos) no.

Preguntas frecuentes

¿Un service mesh reemplaza un API gateway?

No. El gateway maneja north-south (externo al cluster). El mesh maneja east-west (servicio-a-servicio). Úsalos ambos. Algunos meshes incluyen un ingress gateway, pero complementa, no reemplaza, tu gateway primario.

¿Cuál es el overhead de performance de un service mesh?

Espera 1-5ms de latencia por hop y 10-20% de overhead de CPU para el sidecar. Linkerd está optimizado para overhead mínimo. Istio ofrece más capacidades a mayor costo. Para paths sensibles a latencia, haz benchmarking antes de desplegar.

¿Puedo usar un service mesh sin Kubernetes?

Istio y Linkerd son Kubernetes-native. Consul Connect soporta VMs. Para entornos no-K8s, usa mTLS a nivel de aplicación (ej. AWS App Mesh con ECS) o librerías específicas del lenguaje.

¿Cómo debuggeo un 503 en el mesh?

Verifica tres cosas: (1) ¿el pod de destino está healthy? (2) ¿el sidecar proxy está healthy? (logs del container istio-proxy). (3) ¿hay una política de autorización o destination rule bloqueando tráfico? Usa istioctl proxy-config para inspeccionar la configuración de Envoy.