Mecanismos de Proxy en Kubernetes
Kubernetes dispone de varios modos de operación para gestionar el tráfico de red hacia los Services:
Modo Userspace
En este modelo legacy, el flujo de tráfico implica múltiples transiciones entre el espacio de usuario y el espacio del kernel. Cuando un Pod cliente inicia una solicitud, esta pasa por las reglas del Service en el kernel, es reenviada a kube-proxy (que escucha en un puerto específico), procesada, y luego devuelta al kernel para su entrega final al Pod destino. Esta arquitectura, debido a los constantes cambios de contexto, resulta ineficiente en términos de rendimiento.
Modo Iptables
Este enfoque optimiza el proceso eliminando la intervención de kube-proxy en el plano de datos. Las reglas de iptables en el kernel interceptan las solicitudes del cliente y las reenvían directamente al Pod servidor. Al evitar el paso por el espacio de usuario, el rendimiento mejora considerablemente respecto al modo anterior.
Modo IPVS (Recomendado)
IPVS (IP Virtual Server) es la opción recomendada para entornos de producción. En este modo, kube-proxy monitorea los objetos Service y Endpoints del clúster, interactuando con la interfaz netlink para crear y sincronizar reglas IPVS. Al utilizar tablas hash como estructura de datos subyacente y operar íntegramente en el espacio del kernel, ofrece una latencia menor y soporta un throughput de red significativamente superior comparado con el modo iptables.
Ejemplo de configuración para activar el modo IPVS en kube-proxy:
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
bindAddress: "10.0.0.15"
metricsBindAddress: "10.0.0.15:10249"
hostnameOverride: "worker-node-01"
clusterCIDR: "10.244.0.0/16"
mode: "ipvs"
ipvs:
scheduler: rr
excludeCIDRs: []
Tipos de Service en Kubernetes
Kubernetes soporta cuatro tipos principales de Service, cada uno diseñado para un caso de uso específico:
1. ClusterIP
Este es el tipo por defecto. Asigna una dirección IP virtual interna al Service, accesible únicamente desde dentro del clúster. Es ideal para comunicación entre microservicios internos.
Ejemplo de definición:
apiVersion: v1
kind: Service
metadata:
name: api-backend
namespace: produccion
spec:
type: ClusterIP
selector:
componente: backend-api
ports:
- name: http-api
port: 8080
targetPort: 8080
protocol: TCP
Headless Service (ClusterIP: None)
Cuando se establece clusterIP: None, el Service no recibe una IP de clúster. En su lugar, el DNS devuelve directamente las IPs de los Pods. Este patrón es útil cuando se requiere descubrimiento directo de los endpoints, comúnmente utilizado junto con StatefulSets o controladores Ingress.
2. NodePort
Este tipo extiende ClusterIP exponiendo el Service en cada nodo del clúster a través de un puerto específico (por defecto en el rango 30000-32767). Permite el acceso externo al servicio utiilzando la dirección IP de cualquier nodo.
apiVersion: v1
kind: Service
metadata:
name: frontend-web
spec:
type: NodePort
selector:
app: web-ui
ports:
- port: 80
targetPort: 8080
nodePort: 32080
Consideraciones:
- El puerto debe ser único en todos los nodos; un puerto solo puede servir a un Service.
- El rango de puertos está limitado (configurable mediante la bandera
--service-node-port-rangedel API Server). - Cambios en la IP del nodo requieren actualización manual en el cliente.
- No es recomendado para entornos de producción debido a la gestión manual de puertos.
3. LoadBalancer
Este tipo integra el Service con proveedores de nube pública. Solicita automáticamente la provisión de un balanceador de carga externo (como AWS ELB, GCP Network Load Balancer, o Azure Load Balancer) y le asigna una IP pública estática.
apiVersion: v1
kind: Service
metadata:
name: servicio-publico
spec:
type: LoadBalancer
selector:
app: app-publica
ports:
- port: 80
targetPort: 8080
Es la solución estándar para exponer servicios a Internet en entornos de nube pública.
4. ExternalName
Este tipo especial no define selectores ni puertos. En su lugar, mapea el Service a un nombre DNS externo (CNAME). Es útil para abstraer dependencias externas, permitiendo que las aplicaciones referencien un nombre de servicio interno minetras el destino real se gestiona centralizadamente.
apiVersion: v1
kind: Service
metadata:
name: base-datos-externa
spec:
type: ExternalName
externalName: db-ejemplo.empresa.com
Esta configuración crea un registro CNAME en el DNS interno del clúster. Los Pods pueden resolver base-datos-externa.default.svc.cluster.local y obtener la dirección del recurso externo. Facilita la migración de recursos: basta con cambiar el campo externalName sin modificar el código de la aplicación.
Acceso entre Espacios de Nombres (Namespaces)
Los Services en Kubernetes son accesibles entre diferentes Namespaces mediante nombres DNS completamente cualificados (FQDN). El formato estándar es:
<nombre-servicio>.<namespace>.svc.cluster.local
Por ejemplo, para acceder a un Service llamado mysql en el namespace datos desde el namespace default, se utiliza: mysql.datos.svc.cluster.local.