Cuando uno empieza con Kubernetes, la tentación es fuerte: si quiero que mi aplicación se vea, la saco con un NodePort o un LoadBalancer y listo, ¿no? Parece la solución obvia. Bueno, no tan rápido. De hecho, muchas veces, la forma más simple y segura es la que menos expone tu servicio.
Yo mismo caí en esa. Al principio, mi cabeza iba directo a cómo hacer mi app accesible. Y sí, es clave que se vea, pero la pregunta real es: ¿desde dónde y para quién? Entender la diferencia entre ClusterIP, NodePort y LoadBalancer es fundamental para no sobreingenierizar tu infraestructura.
ClusterIP: El corazón interno del cluster
Este es el tipo de servicio por defecto, y por una buena razón. Un ClusterIP expone tu servicio en una IP interna, solo accesible desde dentro del cluster. Es como tener una red privada para tus aplicaciones. Si tienes un frontend, un backend y una base de datos, lo más probable es que tu backend y tu base de datos sean servicios ClusterIP.
En mi caso, la mayoría de los servicios que despliego son ClusterIP. Son los trabajadores silenciosos que hacen que todo funcione tras bambalinas. No necesitan hablar con el mundo exterior directamente, solo con otros servicios dentro de Kubernetes.
Un ejemplo sencillo de cómo se ve:
apiVersion: v1
kind: Service
metadata:
name: mi-backend-service
spec:
selector:
app: mi-backend
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
Con esto, tu backend es accesible por otros pods usando mi-backend-service:80. Simple, directo, y seguro.
NodePort: Cuando necesitas un agujero en el firewall (con cautela)
Un NodePort expone tu servicio en cada IP de tus nodos, en un puerto estático que tú defines o que Kubernetes asigna. Esto significa que puedes acceder a tu servicio desde fuera del cluster usando <IP_del_Nodo>:<Puerto_del_Nodo>.
Confieso que al principio usaba mucho NodePort para probar cosas. Era lo más rápido para ver si mi API respondía desde mi máquina. Es útil para entornos de desarrollo o cuando estás en un on-premise y no tienes un LoadBalancer a mano. Ojo que crea un ClusterIP automáticamente y le rutea el tráfico.
El problema con NodePort es que te expone en todos los nodos. Si tienes 10 nodos, tu servicio estará disponible en 10 IPs diferentes. Además, los puertos NodePort suelen estar en un rango alto (30000-32767), lo que no es muy amigable para los usuarios finales. Y claro, si un nodo se cae, pierdes esa IP.
apiVersion: v1
kind: Service
metadata:
name: mi-frontend-dev
spec:
selector:
app: mi-frontend
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080 # Opcional, Kubernetes asigna uno si no lo pones
type: NodePort
Aunque nodePort sea opcional, me gusta especificarlo para no tener sorpresas. Pero insisto: piénsalo dos veces antes de usarlo en producción.
LoadBalancer: La puerta principal a la nube
Para producción, si estás en la nube (AWS, GCP, Azure), el LoadBalancer es casi siempre la opción que eliges para servicios que deben ser accesibles desde Internet. Este tipo de servicio provisiona un balanceador de carga externo en tu proveedor de nube, que luego rutea el tráfico a tus nodos.
La ventaja es clara: obtienes una IP pública estable y gestionada por la nube. El balanceador de carga se encarga de distribuir el tráfico, hacer health checks y escalar según sea necesario. Detrás de escenas, un LoadBalancer utiliza un NodePort, que a su vez usa un ClusterIP. Es una cadena.
apiVersion: v1
kind: Service
metadata:
name: mi-api-publica
spec:
selector:
app: mi-api
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
Este es el que usas para tu página web, tu API pública, o cualquier cosa que necesite estar disponible 24/7 con alta disponibilidad y una IP amigable.
¿Cuándo usar cada uno? La opinión de Jorge
- ClusterIP: Tu valor por defecto. Si tu servicio no necesita ser visto desde fuera del cluster, casi seguro es un ClusterIP. Bases de datos, colas de mensajes, servicios internos de microservicios.
- NodePort: Para desarrollo local, demos rápidas, o en entornos on-premise donde no tienes un LoadBalancer gestionado y necesitas un acceso directo (quizás detrás de un proxy inverso que tú controlas). No me convence para producción sin un buen motivo.
- LoadBalancer: Tu opción para cualquier cosa que deba ser pública en la nube. Páginas web, APIs, cualquier servicio que necesite una IP externa dedicada y la robustez que ofrece un balanceador de carga gestionado.
Me acuerdo una vez, en un proyecto anterior, un colega estaba empeñado en sacar una base de datos con un NodePort para que el cliente pudiera acceder directo y hacer unas pruebas puntuales. La discusión de arquitectura fue intensa. Mi punto era: no solo es una brecha de seguridad innecesaria, sino que lo estás exponiendo de una forma poco fiable. ¿Qué pasa si ese nodo se reinicia? ¿O si el puerto colisiona? Al final, lo convencí de que si se necesitaba acceso externo, se usara un VPN o un bastion host. La sobreingeniería aquí era querer exponer algo que no debía, y de la forma incorrecta.
La simplicidad es clave. No expongas tus servicios más allá de lo estrictamente necesario. Cada puerto abierto es una superficie de ataque y una complejidad más que gestionar.
Si tuviera que empezar de cero con Kubernetes...
Una de las primeras cosas que me enfocaría en entender a fondo es el ClusterIP. Al principio, uno ve el NodePort o el LoadBalancer como la solución fácil para que tu app se vea. Y claro, sirven. Pero la realidad es que la mayoría de tus servicios van a ser ClusterIP.
Yo perdí tiempo al inicio tratando de forzar exposiciones que no eran necesarias o usando NodePort para cosas que debían ir con LoadBalancer. Me habría ahorrado varios dolores de cabeza y discusiones si hubiera internalizado antes que la comunicación interna es la base, y la exposición externa es solo una capa más, con sus propias reglas y consideraciones de seguridad. Entender el propósito de cada tipo te ahorrará muchos problemas en el futuro.