Istio: Plataforma de malla de servicios para aplicaciones nativas de la nube
- Descripción general de Istio
1.1 ¿Qué es Istio?
Istio constituye una infraestructura de malla de servicios diseñada específicamente para orquestar y administrar la comunicación entre microservicios en arquitecturas nativas de la nube.
1.2 Características fundamentales
- Observabilidad integrada del tráfico
- Mecanismos de seguridad robustos
- Gestión avanzada del flujo de datos
1.3 Capacidades principales
Mediante el patrón sidecar, se inyecta un proxy adyacente a cada servicio que habilita las siguientes funcionalidades:
- Descubrimiento de servicios: el proxy identifica los endpoints disponibles detrás de cada servicio y distribuye el tráfico según estrategias de balanceo configuradas.
- Aislamiento de instancias defectuosas.
- Protección del servicio: limitación de conexiones y solicitudes máximas.
- Fallo rápido y tiempos de espera configurables.
- Limitación de velocidad para endpoints específicos.
- Reintentos automáticos ante fallos de comunicación.
- Modificación dinámica de encabezados HTTP.
- Inyección de fallos para pruebas de resiliencia.
- Redirección de peticiones hacia otros destinos.
- Publicaciones graduales: distribución de tráfico por peso o contenido de la petición.
- Cifrado mutuo TLS entre cliente y servidor.
- Autorización granular de acceso.
- Registro automático de logs y detalles de cada petición.
- Instrumentación de trazas distribuidas.
- Generación de métricas y topología completa de la aplicación.
Todas estas funcionalidades se activan dinámicamente mediante configuración, sin necesidad de modificar el código de la aplicación.
1.4 Componentes arquitectónicos
1.4.1 Envoy (plano de datos)
Envoy se despliega como contenedor sidecar junto a cada servicio. Coordina todo el tráfico entrante y saliente dentro de la malla.
Características integradas:
- Descubrimiento dinámico de servicios
- Balanceo de carga
- Terminación TLS
- Proxy para HTTP/2 y gRPC
- Circuit breaker
- Verificación de salud
- Despliegue gradual por porcentajes de tráfico
- Inyección de fallos
- Métricas detalladas
Extensiones de Istio sobre Envoy:
- Control de tráfico
- Resiliencia de red
- Seguridad y autenticación
- Extensiones basadas en WebAssembly
1.4.2 Istiod (plano de control)
Integra los componentes Pilot, Galley y Citadel. Gestiona el descubrimiento de servicios, la distribución de configuración y la administración de certificados.
- Instalación de Istio
2.1 Despliegue mediante Helm
# Registrar el repositorio oficial
helm repo add istio-repo https://istio-release.storage.googleapis.com/charts
helm repo update
# Descargar los charts necesarios
helm pull istio-base istio/base
helm pull istiod istio/istiod
helm pull istio-ingress istio/gateways
# Crear el namespace dedicado
kubectl create namespace istio-system
# Instalar los componentes base
helm install istio-base ./charts/base -n istio-system
helm install istiod ./charts/istiod -n istio-system
helm install istio-ingress ./charts/gateways -n istio-system
helm install istio-egress ./charts/egress -n istio-system
# Verificar la instalación
helm list -A
kubectl get pods -n istio-system
- Configuración y uso
3.1 Despliegue de servicios de ejemplo
Para demostrar las capacidades de Istio, se despliega una aplicación de ejemplo compuesta por varios microservicios:
apiVersion: v1
kind: Service
metadata:
name: catalogo
labels:
app: catalogo
servicio: catalogo
spec:
ports:
- port: 8080
name: http
selector:
app: catalogo
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-catalogo
labels:
cuenta: catalogo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalogo-v1
labels:
app: catalogo
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: catalogo
version: v1
template:
metadata:
labels:
app: catalogo
version: v1
spec:
serviceAccountName: sa-catalogo
containers:
- name: catalogo-app
image: registry.example.com/catalogo:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: puntuacion
labels:
app: puntuacion
spec:
ports:
- port: 8080
name: http
selector:
app: puntuacion
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-puntuacion
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: puntuacion-v1
labels:
app: puntuacion
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: puntuacion
version: v1
template:
metadata:
labels:
app: puntuacion
version: v1
spec:
serviceAccountName: sa-puntuacion
containers:
- name: puntuacion-app
image: registry.example.com/puntuacion:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: opiniones
labels:
app: opiniones
spec:
ports:
- port: 8080
name: http
selector:
app: opiniones
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-opiniones
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: opiniones-v1
labels:
app: opiniones
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: opiniones
version: v1
template:
metadata:
labels:
app: opiniones
version: v1
spec:
serviceAccountName: sa-opiniones
containers:
- name: opiniones-app
image: registry.example.com/opiniones:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: opiniones-v2
labels:
app: opiniones
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: opiniones
version: v2
template:
metadata:
labels:
app: opiniones
version: v2
spec:
serviceAccountName: sa-opiniones
containers:
- name: opiniones-app
image: registry.example.com/opiniones:2.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: tienda
labels:
app: tienda
spec:
ports:
- port: 8080
name: http
selector:
app: tienda
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-tienda
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tienda-v1
labels:
app: tienda
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: tienda
version: v1
template:
metadata:
labels:
app: tienda
version: v1
spec:
serviceAccountName: sa-tienda
containers:
- name: tienda-app
image: registry.example.com/tienda:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
3.2 Inyección automática del sidecar
# Etiquetar el namespace para activar la inyección automática
kubectl label namespace <nombre_ns> istio-injection=enabled
3.3 Inyección manual del sidecar
# Generar el manifiesto con el sidecar incorporado
istioctl kube-inject -f manifiesto.yaml > manifiesto_con_sidecar.yaml
# Aplicar el manifiesto modificado
kubectl apply -f manifiesto_con_sidecar.yaml
- Observabilidad
4.1 Métricas
Istio genera métricas basadas en los cuatro indicadores dorados de monitoreo: latencia, tráfico, errores y saturación. Se distinguen tres niveles:
- Métricas de gestión del proxy (configuración y salud)
- Métricas a nivel de servicio
- Métricas del plano de control
4.1.1 Métricas integradas
kubectl exec -ti -n <namespace> <nombre_pod> -c istio-proxy -- \
pilot-agent request GET /stats/prometheus
4.1.2 Personalización de métricas
Modificar dimensiones de métricas existentes:
# Instalar los recursos personalizados
istioctl install -f configuracion-metricas.yaml
kubectl get istiooperator -n istio-system
# Agregar dimensiones bajo spec.values.telemetry.v2.prometheus
configOverride:
gateway:
metrics:
- name: requests_total
dimensions:
host_destino: request.host
metodo_http: request.method
tags_to_remove:
- response_flags
inboundSidecar:
metrics:
- dimensions:
host_destino: request.host
metodo_http: request.method
outboundSidecar:
metrics:
- dimensions:
host_destino: request.host
metodo_http: request.method
Definir métricas personalizadas nuevas:
# Agregar definición bajo spec.values.telemetry.v2.prometheus
configOverride:
outboundSidecar:
definitions:
- name: contador_personalizado
type: COUNTER
value: "1"
metrics:
- name: contador_personalizado
dimensions:
origen: "'proxy'"
4.2 Trazas distribuidas
Los proxies Envoy generan automáticamente spans de rastreo. La aplicación únicamente necesita reenviar el contexto de la petición adecuado. Istio es compatible con múltiples sistemas de trazas como Zipkin, Jaeger, LightStep y Datadog. El operador controla la tasa de muestreo de las trazas generadas.
4.3 Registro de acceso
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: registro-malla
namespace: istio-system
spec:
accessLogging:
- providers:
- name: envoy
- Gestión de tráfico
5.1 Publicaciones graduales (segmentación de tráfico)
5.1.1 Definir subconjuntos de servicio
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: regla-opiniones
namespace: entorno-pruebas
spec:
host: opiniones
subsets:
- name: estable
labels:
version: v1
- name: beta
labels:
version: v2
- name: canario
labels:
version: v3
5.1.2 Distribución por proporción de tráfico
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs-opiniones
namespace: entorno-pruebas
spec:
hosts:
- opiniones
http:
- route:
- destination:
host: opiniones
subset: estable
weight: 70
- destination:
host: opiniones
subset: beta
weight: 30
5.1.3 Enrutamiento basado en contenido de la petición
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs-opiniones
namespace: entorno-pruebas
spec:
hosts:
- opiniones
http:
- match:
- headers:
User-Agent:
regex: .*(Firefox/([\d.]+)).*
route:
- destination:
host: opiniones
subset: beta
- route:
- destination:
host: opiniones
subset: estable
5.1.4 Condiciones múltiples combinadas
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-frontend
namespace: entorno-produccion
spec:
hosts:
- "*"
gateways:
- istio-system/gateway-produccion
http:
- match:
- headers:
User-Agent:
regex: .*((iOS)).*
route:
- destination:
host: frontend
subset: estable
weight: 60
- destination:
host: frontend
subset: beta
weight: 40
- route:
- destination:
host: frontend
subset: estable
5.1.5 Enrutamiento multi-servicio con versiones cruzadas
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-frontend
spec:
hosts:
- "*"
gateways:
- istio-system/gateway-produccion
http:
- match:
- headers:
cookie:
regex: ^(.*?;)?(rol=administrador)(;.*)?$
route:
- destination:
host: frontend
subset: beta
- route:
- destination:
host: frontend
subset: estable
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-prevision
spec:
hosts:
- prevision
http:
- match:
- sourceLabels:
version: beta
route:
- destination:
host: prevision
subset: beta
- route:
- destination:
host: prevision
subset: estable
5.2 Gobernanza del tráfico
Las reglas de DestinationRule definen cómo se distribuye el tráfico entre las instancias del backend.
5.2.1 Balanceo de carga
Algoritmos simples (round-robin y aleatorio):
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: regla-anuncios
spec:
host: anuncios
subsets:
- labels:
version: v1
name: v1
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN # Alternativas: RANDOM, ROUND_ROBIN
Distribución por topología geográfica:
# Etiquetas en nodos: topology.kubernetes.io/region, topology.kubernetes.io/zone
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: distribucion-anuncios
spec:
host: anuncios.produccion.svc.cluster.local
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
distribute:
- from: region-sur/zona-sur-1/*
to:
"region-sur/zona-sur-1/ciudad-a": 20
"region-sur/zona-sur-2/ciudad-b": 60
"region-sur/zona-sur-2/ciudad-c": 20
Conmutación por error:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: conmutacion-recomendacion
spec:
host: recomendacion.produccion.svc.cluster.local
trafficPolicy:
connectionPool:
http:
maxRequestsPerConnection: 1
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting:
enabled: true
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 2m
5.2.2 Persistencia de sesión
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: regla-anuncios
namespace: produccion
spec:
host: anuncios
subsets:
- labels:
version: v1
name: v1
trafficPolicy:
loadBalancer:
consistentHash:
httpCookie:
name: sesion_usuario
ttl: 120s
5.2.3 Inyección de fallos
Inyección de retardo:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-anuncios
spec:
hosts:
- anuncios
http:
- fault:
delay:
fixedDelay: 5s
percentage:
value: 50
route:
- destination:
host: anuncios
subset: v1
Inyección de error:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-anuncios
spec:
hosts:
- anuncios
http:
- fault:
abort:
httpStatus: 503
percentage:
value: 100
route:
- destination:
host: anuncios
subset: v1
5.2.4 Tiempos de espera
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-prevision
spec:
hosts:
- prevision
http:
- route:
- destination:
host: prevision
subset: beta
timeout: 3s
5.2.5 Reintentos
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-prevision
spec:
hosts:
- prevision
http:
- route:
- destination:
host: prevision
subset: beta
retries:
attempts: 3
perTryTimeout: 2s
retryOn: "5xx,reset,connect-failure"
5.2.6 Redirección
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-anuncios
spec:
hosts:
- anuncios
http:
- match:
- uri:
prefix: /publicidad
redirect:
uri: /mantenimiento
authority: anuncios.produccion.svc.cluster.local
5.2.7 Reescritura de URI
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-anuncios
spec:
hosts:
- anuncios
http:
- match:
- uri:
prefix: /prueba/
rewrite:
uri: /
route:
- destination:
host: anuncios
subset: v1
5.2.8 Circuit breaker
Configuración del circuit breaker:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: regla-prevision
spec:
host: prevision
subsets:
- labels:
version: v1
name: v1
- labels:
version: beta
name: beta
trafficPolicy:
connectionPool:
tcp:
maxConnections: 5
http:
http1MaxPendingRequests: 10
maxRequestsPerConnection: 1
outlierDetection:
consecutive5xxErrors: 3
interval: 15s
baseEjectionTime: 1m
maxEjectionPercent: 50
Detección de anomalías y exclusión de instancias:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: regla-prevision
spec:
host: prevision
subsets:
- labels:
version: v1
name: v1
- labels:
version: beta
name: beta
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 3
interval: 15s
baseEjectionTime: 1m
maxEjectionPercent: 50
5.2.9 Limitación de velocidad
Limitación global (compartida entre todas las instancias):
# ConfigMap con las reglas de limitación
apiVersion: v1
kind: ConfigMap
metadata:
name: config-limitador
data:
config.yaml: |
domain: limitador-anuncios
descriptors:
- key: RUTA
value: "/api/promociones"
rate_limit:
unit: minute
requests_per_unit: 10
- key: RUTA
rate_limit:
unit: minute
requests_per_unit: 200
# Despliegue de Redis como backend de almacenamiento
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-store
spec:
replicas: 1
selector:
matchLabels:
app: redis-store
template:
metadata:
labels:
app: redis-store
spec:
containers:
- image: redis:7-alpine
imagePullPolicy: Always
name: redis
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-store
spec:
ports:
- name: redis
port: 6379
selector:
app: redis-store
# Servicio limitador de velocidad
apiVersion: apps/v1
kind: Deployment
metadata:
name: limitador
spec:
replicas: 1
selector:
matchLabels:
app: limitador
template:
metadata:
labels:
app: limitador
spec:
containers:
- image: registry.example.com/envoyproxy/ratelimit:latest
imagePullPolicy: Always
name: limitador
command: ["/bin/ratelimit"]
env:
- name: LOG_LEVEL
value: debug
- name: REDIS_SOCKET_TYPE
value: tcp
- name: REDIS_URL
value: redis-store:6379
- name: USE_STATSD
value: "false"
- name: RUNTIME_ROOT
value: /data
- name: RUNTIME_SUBDIRECTORY
value: ratelimit
ports:
- containerPort: 8080
- containerPort: 8081
volumeMounts:
- name: vol-config
mountPath: /data/ratelimit/config/config.yaml
subPath: config.yaml
volumes:
- name: vol-config
configMap:
name: config-limitador
---
apiVersion: v1
kind: Service
metadata:
name: limitador
spec:
ports:
- name: http
port: 8080
targetPort: 8080
- name: grpc
port: 8081
targetPort: 8081
selector:
app: limitador
# EnvoyFilter para integrar el limitador global
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: limitador-global
spec:
workloadSelector:
labels:
app: anuncios
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
domain: limitador-anuncios
failure_mode_deny: true
rate_limit_service:
grpc_service:
envoy_grpc:
cluster_name: cluster_limitador
timeout: 10s
transport_api_version: V3
- applyTo: CLUSTER
match:
cluster:
service: limitador.produccion.svc.cluster.local
patch:
operation: ADD
value:
name: cluster_limitador
type: STRICT_DNS
connect_timeout: 10s
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: cluster_limitador
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: limitador.produccion.svc.cluster.local
port_value: 8081
Limitación local (por instancia individual):
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: limitador-local
spec:
workloadSelector:
labels:
app: anuncios
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.local_ratelimit
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
value:
stat_prefix: http_limitador_local
token_bucket:
max_tokens: 5
tokens_per_fill: 5
fill_interval: 60s
filter_enabled:
runtime_key: local_rate_limit_enabled
default_value:
numerator: 100
denominator: HUNDRED
filter_enforced:
runtime_key: local_rate_limit_enforced
default_value:
numerator: 100
denominator: HUNDRED
response_headers_to_add:
- append: false
header:
key: x-limitador-local
value: 'true'
5.2.10 Aislamiento de servicios
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
name: aislamiento-frontend
spec:
workloadSelector:
labels:
app: frontend
egress:
- hosts:
- "produccion/anuncios.produccion.svc.cluster.local"
- "istio-system/*"
5.2.11 Espejo de tráfico
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-prevision
spec:
hosts:
- prevision
http:
- route:
- destination:
host: prevision
subset: v1
weight: 100
mirror:
host: prevision
subset: beta
mirrorPercentage:
value: 50.0
5.3 Exposición de servicios
5.3.1 Publicar servicio HTTPS
# Crear un Secret con los certificados TLS
kubectl create secret tls tls-mi-servicio \
--cert=certificado.crt --key=clave-privada.key -n produccion
---
# Definir el Gateway
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: gw-mi-servicio
namespace: produccion
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- 'mi-dominio.com'
port:
name: https-entrada
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: tls-mi-servicio
---
# Definir el VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-mi-servicio
namespace: produccion
spec:
hosts:
- "mi-dominio.com"
gateways:
- produccion/gw-mi-servicio
http:
- route:
- destination:
host: mi-servicio
port:
number: 8080
5.3.2 Exponer servicio HTTP
# Gateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gw-tienda
namespace: ingress
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 9090
name: http-tienda
protocol: HTTP
hosts:
- "tienda.local"
---
# VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-tienda
namespace: entorno-pruebas
spec:
hosts:
- "tienda.local"
gateways:
- ingress/gw-tienda
http:
- match:
- port: 9090
route:
- destination:
host: tienda
port:
number: 8080
# Agregar el puerto 9090 al servicio del ingress gateway
# Editar el Service istio-ingressgateway para incluir:
ports:
- name: tienda
nodePort: 31234
port: 9090
protocol: TCP
targetPort: 9090
# Configurar resolución DNS local
# En /etc/hosts agregar:
# 10.0.0.1 tienda.local
- Flujo del tráfico en Istio
Cliente → Ingress Gateway → VirtualService → DestinationRule → Backend
- Gateway: Define qué tráfico externo puede entrar a la malla. Se conecta con VirtualService.
- VirtualService: Establece las rutas de enrutamiento. Debe referenciar un servicio real.
- DestinationRule: Define políticas de ditsribución hacia las instancias del backend (balanceo, TLS, circuit breaker).
- Recursos fundamentales
7.1 VirtualService
Configura cómo las solicitudes se enrutan dentro de la malla de servicios hacia destinos específicos.
7.2 DestinationRule
Define políticas de tráfico aplicables después del enrutamiento: balanceo de carga, configuración TLS, circuit breaker.
7.3 Gateway
Selecciona un punto de entrada y el puerto por el cual el tráfico externo ingresa a la malla. El VirtualService debe vincularse explícitamente al Gateway.
7.4 ServiceEntry
Registra servicios externos a la malla para integrarlos en el mecanismo de descubrimiento.
7.5 Sidecar
Configura políticas de aislamiento de red, controlando qué servicios puede alcanzar cada workload.
- Seguridad
8.1 Arquitectura de seguridad
El sistema de seguridad de Istio comprende:
- Una autoridad certificadora (CA)
- Un servidor API para distribuir certificados, políticas de autenticación, autorización y nombres seguros
- Un agente sidecar para ejecutar políticas
- Extensiones del proxy Envoy para auditoría y telemetría
El plano de control proporciona certificados y los proxies sidecar ejecutan las políticas, logrando cifrado de tráfico sin modificar las aplicaciones.
8.2 Conceptos clave
Nombres seguros
La identidad del servidor se codifica en el certificado. El mapeo entre identidad y nombre de servicio determina qué servicio está autorizado a ejecutarse. Nota: en capas inferiores a la 7, la seguridad de nombres no está garantizada ya que la comunicación ocurre por IP antes del proxy.
8.3 Gestión de identidades y certificados
El agente istio-agent (proceso pilot-agent dentro del contenedor sidecar) ejecuta el siguiente flujo:
- Istiod expone un servicio gRPC para recibir solicitudes de firma de certificados (CSR).
- Al iniciarse, istio-agent genera una clave privada y una CSR, enviándolas a Istiod para firma.
- La CA de Istiod valida las credenciales y firma la CSR.
- Cuando el workload arranca, Envoy solicita certificados al istio-agent mediante SDS (Secret Discovery Service).
- El istio-agent entrega los certificados y claves a Envoy a través de SDS.
- El agente vigila la expiración y repite el proceso para renovación automática.
8.4 Autenticación
Las políticas de autenticación tienen alcance jerárquico, desde el workload individual hasta toda la malla.
8.4.1 Autenticación entre pares (mTLS)
Autenticación mutua entre servicios para verificar la identidad del cliente. Utiliza mTLS con versión mínima 1.2.
Flujo de funcionamiento:
- Istio redirige el tráfico de salida al sidecar Envoy del cliente.
- El Envoy del cliente inicia el handshake TLS mutuo con el Envoy del servidor, verificando además que la cuenta de servicio esté autorizada.
- Se establece la conexión cifrada entre ambos proxies.
- El Envoy del servidor autoriza la petición y la reenvía al backend.
Despliegue de servicios de prueba:
# Crear namespaces de prueba
kubectl create ns entorno-a entorno-b entorno-legacy
kubectl label ns entorno-a istio-injection=enabled
kubectl label ns entorno-b istio-injection=enabled
kubectl label ns entorno-legacy istio-injection=enabled
# Desplegar servicios de prueba
kubectl apply -f dormir.yaml -n entorno-a
kubectl apply -f dormir.yaml -n entorno-b
kubectl apply -f dormir.yaml -n entorno-legacy
kubectl apply -f httpbin.yaml -n entorno-a
kubectl apply -f httpbin.yaml -n entorno-b
kubectl apply -f httpbin.yaml -n entorno-legacy
# dormir.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: dormir
---
apiVersion: v1
kind: Service
metadata:
name: dormir
labels:
app: dormir
spec:
ports:
- port: 80
name: http
selector:
app: dormir
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dormir
spec:
replicas: 1
selector:
matchLabels:
app: dormir
template:
metadata:
labels:
app: dormir
spec:
terminationGracePeriodSeconds: 0
serviceAccountName: dormir
containers:
- name: dormir
image: registry.example.com/curl:latest
command: ["/bin/sleep", "infinity"]
imagePullPolicy: IfNotPresent
Aplicar política de mTLS estricta:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: "politica-mtls-global"
namespace: "istio-system"
spec:
mtls:
mode: STRICT
8.4.2 Autenticación de solicitudes (JWT)
Autenticación de usuarios finales mediante tokens JWT.
Despliegue de prueba:
kubectl create ns entorno-jwt
kubectl label ns entorno-jwt istio-injection=enabled
kubectl apply -f httpbin.yaml -n entorno-jwt
kubectl apply -f httpbin-gateway.yaml
# httpbin-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gw-httpbin
namespace: ingress
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-httpbin
namespace: entorno-jwt
spec:
hosts:
- "*"
gateways:
- ingress/gw-httpbin
http:
- route:
- destination:
host: httpbin
port:
number: 8000
Configurar validación JWT en el gateway:
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
name: jwt-ingress
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
jwtRules:
- issuer: "testing@seguro.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.20/security/tools/jwt/samples/jwks.json"
8.5 Autorización
Istio proporciona control de acceso a nivel de malla, namespace y workload. Soporta políticas ALLOW y DENY con semántica flexible basada en atributos del sistema.
Componentes de una política de autorización:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: politica-httpbin
namespace: entorno-jwt
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/dormir"]
to:
- operation:
methods: ["GET"]
when:
- key: request.auth.claims[iss]
values: ["https://accounts.google.com"]
8.5.1 Control de acceso en capa 7
# Permitir solo peticiones GET
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: solo-lectura-tienda
namespace: default
spec:
selector:
matchLabels:
app: tienda
action: ALLOW
rules:
- to:
- operation:
methods: ["GET"]
---
# Autorización por cuenta de servicio
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: catalogo-autorizado
namespace: default
spec:
selector:
matchLabels:
app: catalogo
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/sa-tienda"]
to:
- operation:
methods: ["GET"]
8.5.2 Control de acceso en capa 4
# Permitir tráfico TCP en puertos específicos
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: politica-tcp
namespace: entorno-pruebas
spec:
selector:
matchLabels:
app: echo-tcp
action: ALLOW
rules:
- to:
- operation:
ports: ["9000", "9001"]
---
# Denegar tráfico HTTP
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: denegar-http
namespace: entorno-pruebas
spec:
selector:
matchLabels:
app: echo-tcp
action: DENY
rules:
- to:
- operation:
methods: ["GET"]
8.5.3 Control de acceso en el gateway
# Restringir acceso por IP de origen
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: politica-ingress
namespace: istio-system
spec:
selector:
matchLabels:
app: istio-ingressgateway
action: ALLOW
rules:
- from:
- source:
ipBlocks: ["192.168.1.0/24", "10.0.0.5"]
- Registro de servicios externos
Istio permite incorporar servicios que se ejecutan fuera de Kubernetes, como aplicaciones en máquinas virtuales.
9.1 Conceptos
- WorkloadGroup: Define un conjunto lógico de workloads de VM con atributos comunes. Equivalente a un Deployment en Kubernetes.
- WorkloadEntry: Representa una instancia individual de un workload de VM. Equivalente a un Pod.
9.2 Proceso de integración
9.2.1 Variables necesarias
NOMBRE_APP="mi-app-vm"
NAMESPACE_VM="mi-namespace"
DIR_TRABAJO="/ruta/certificados"
CUENTA_SERVICIO="sa-vm"
RED_CLUSTER=""
RED_VM=""
CLUSTER="kubernetes-principal"
9.2.2 Configuración del operador Istio
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio-vm
spec:
values:
global:
meshID: malla1
multiCluster:
clusterName: kubernetes-principal
network: 10.200.0.0/16
9.2.3 Despliegue del gateway este-oeste
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: gateway-este-oeste
spec:
profile: empty
components:
ingressGateways:
- name: istio-eastwestgateway
label:
istio: eastwestgateway
app: istio-eastwestgateway
enabled: true
k8s:
service:
ports:
- name: status-port
port: 15021
targetPort: 15021
- name: tls
port: 15443
targetPort: 15443
- name: tls-istiod
port: 15012
targetPort: 15012
- name: tls-webhook
port: 15017
targetPort: 15017
values:
gateways:
istio-ingressgateway:
injectionTemplate: gateway
9.2.4 Gateway y VirtualService para Istiod
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gw-istiod
spec:
selector:
istio: eastwestgateway
servers:
- port:
name: tls-istiod
number: 15012
protocol: tls
tls:
mode: PASSTHROUGH
hosts:
- "*"
- port:
name: tls-webhook
number: 15017
protocol: tls
tls:
mode: PASSTHROUGH
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-istiod
spec:
hosts:
- "*"
gateways:
- gw-istiod
tls:
- match:
- port: 15012
sniHosts:
- "*"
route:
- destination:
host: istiod.istio-system.svc.cluster.local
port:
number: 15012
- match:
- port: 15017
sniHosts:
- "*"
route:
- destination:
host: istiod.istio-system.svc.cluster.local
port:
number: 443
9.2.5 Cuenta de servicio y permisos
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-nginx-vm
namespace: vm
---
apiVersion: v1
kind: Secret
metadata:
name: secreto-sa-nginx
namespace: vm
annotations:
kubernetes.io/service-account.name: sa-nginx-vm
type: kubernetes.io/service-account-token
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: binding-vm
subjects:
- kind: ServiceAccount
name: sa-nginx-vm
namespace: vm
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: istiod-istio-system
apiGroup: rbac.authorization.k8s.io
9.2.6 WorkloadGroup y archivos de configuración
apiVersion: networking.istio.io/v1alpha3
kind: WorkloadGroup
metadata:
name: nginx-vm
namespace: vm
spec:
metadata:
labels:
app: nginx-vm
template:
serviceAccount: sa-nginx-vm
probe:
httpGet:
port: 80
# Generar archivos de configuración para la VM
istioctl x workload entry configure \
-f workloadgroup.yaml \
-o "${DIR_TRABAJO}" \
--clusterID "${CLUSTER}" \
--ingressIP=10.0.1.100
# Archivos generados:
# cluster.env - Metadatos del namespace y red
# istio-token - Token para obtener certificados
# mesh.yaml - Configuración del proxy
# root-cert.pem - Certificado raíz
# hosts - Entradas adicionales para /etc/hosts
9.2.7 Configuración de la máquina virtual
# Instalar certificado raíz
sudo mkdir -p /etc/certs
sudo cp root-cert.pem /etc/certs/root-cert.pem
# Instalar token
sudo mkdir -p /var/run/secrets/tokens
sudo cp istio-token /var/run/secrets/tokens/istio-token
# Instalar el paquete sidecar (Debian)
curl -LO https://storage.googleapis.com/istio-release/releases/1.18.2/deb/istio-sidecar.deb
sudo dpkg -i istio-sidecar.deb
# Para CentOS:
# curl -LO https://storage.googleapis.com/istio-release/releases/1.18.2/rpm/istio-sidecar.rpm
# sudo rpm -i istio-sidecar.rpm
# Copiar configuración
sudo cp cluster.env /var/lib/istio/envoy/cluster.env
sudo cp mesh.yaml /etc/istio/config/mesh
# Actualizar /etc/hosts
sudo sh -c 'cat hosts >> /etc/hosts'
# Asignar permisos al proxy
sudo mkdir -p /etc/istio/proxy
sudo chown -R istio-proxy \
/var/lib/istio \
/etc/certs \
/etc/istio/proxy \
/etc/istio/config \
/var/run/secrets
9.2.8 Iniciar el servicio en la VM
sudo systemctl start istio
# Verificar logs
tail -f /var/log/istio/istio.log
9.3 ServiceEntry
Registra servicios externos para integrarlos en el mecanismo de descubrimiento de Istio, tratándolos como si fueran servicios nativos de la malla.
9.4 WorkloadGroup
Sirve como plantilla para el registro automático de instancias de VM. Equivalente al Deployment de Kubernetes.
9.5 WorkloadEntry
Representa y registra instancias individuales de servicios que se ejecutan fuera de Kubernetes.