|

Cómo se descubren servicios en Kubernetes y AWS

El descubrimiento de servicios en Kubernetes resuelve un problema concreto: las IPs cambian constantemente, y si tus pods se hablan entre sí por dirección IP directa, en algún momento vas a tener conexiones que apuntan a la nada. CoreDNS, el servidor DNS interno del cluster, asigna nombres estables a cada servicio para que cualquier pod pueda resolver a quién hablar sin importar cuántas veces murió y resucitó ese destino.

En 30 segundos

  • Las IPs en Kubernetes y AWS son inestables por diseño: un pod que muere y vuelve tiene una IP distinta. El service discovery soluciona esto con nombres DNS estables.
  • En Kubernetes, CoreDNS corre como pods dentro del cluster y resuelve nombres del tipo servicio.namespace.svc.cluster.local a la IP del servicio correspondiente.
  • En AWS, Route 53 Resolver cumple el mismo rol dentro de una VPC: resuelve hostnames internos como ip-10-0-1-15.ec2.internal y nombres de load balancers privados.
  • Cuando usás EKS, necesitás que CoreDNS sepa reenviar consultas a Route 53 Resolver para que los pods resuelvan recursos AWS como RDS o ElastiCache.
  • Desde el mismo namespace, alcanza con el nombre corto del servicio. Entre namespaces, necesitás el FQDN completo.

El problema: por qué las direcciones IP no son confiables

Imaginate que tenés un microservicio de pagos que necesita hablar con el servicio de usuarios. Lo configurás con la IP 10.96.0.25 y funciona. Al día siguiente, el pod de usuarios se cae, Kubernetes lo reinicia, y ahora tiene la IP 10.96.0.41. Tu servicio de pagos sigue apuntando a la IP vieja, que ya no existe, y el deploy falla silenciosamente.

Esto describe bien el problema que enfrenta cualquiera que arranca con Kubernetes: las IPs son inestables por naturaleza. Reiniciás una instancia EC2 y cambia la IP. Un pod muere, uno nuevo arranca, y tiene una IP distinta. No es un bug, es el modelo de operación.

La solución no es tratar de mantener las IPs fijas (podés intentarlo, pero vas a pelear contra el sistema). La solución es dejar de usar IPs y empezar a usar nombres.

Service Discovery y DNS: de IPs a nombres estables

El descubrimiento de servicios en Kubernetes se basa en un principio simple: en vez de conectarte a una IP, te conectás a un nombre. El sistema se encarga de resolver ese nombre a la IP correcta en cada momento. Si el pod detrás cambió de IP, el nombre sigue apuntando al servicio correcto (que a su vez sabe a cuál pod mandar el tráfico).

Esto no es magia nueva. DNS hace esto hace décadas. Lo que hacen Kubernetes y AWS es implementar resolvers DNS privados, internos a tu infraestructura, que conocen tu topología y la mantienen actualizada.

CoreDNS: el servidor DNS interno de Kubernetes

CoreDNS es el servidor DNS que corre dentro de tu cluster de Kubernetes. No es un proceso externo: corre como pods en el namespace kube-system, y Kubernetes se encarga de decirle qué nombres resolver. Esto se conecta con lo que analizamos en fundamentos de infraestructura en la nube.

El flujo es directo: cuando creás un Service llamado backend en el namespace default, Kubernetes le comunica a CoreDNS automáticamente la asociación:

  • backend.default.svc.cluster.local10.96.0.25

A partir de ese momento, cualquier pod del cluster puede hacer una consulta DNS a ese nombre y CoreDNS responde con la IP del Service. Si el pod detrás muere y vuelve con otra IP, el Service actualiza su endpoint y CoreDNS empieza a devolver la nueva. El cliente nunca se enteró.

Lo que vale la pena notar: CoreDNS resuelve el nombre del Service, no del pod. El Service es la abstracción estable; los pods son efímeros. Esto es intencional.

Cómo se arman los nombres: FQDN y namespaces

El nombre completo de un servicio en Kubernetes sigue este formato:

  • nombre-servicio.namespace.svc.cluster.local

Ese es el FQDN (Fully Qualified Domain Name). Pero no siempre necesitás el nombre completo.

Desde un pod en el mismo namespace, podés usar solo el nombre corto: backend. CoreDNS completa el resto por contexto. Esto es lo que usás el 80% del tiempo.

Desde un namespace diferente, necesitás al menos incluir el namespace: backend.default. O el FQDN completo si querés ser explícito.

¿Por qué importa? Porque un error clásico cuando movés workloads entre namespaces es que los servicios dejan de resolverse porque tenías hardcodeado el nombre corto y ahora ese nombre no existe en el nuevo namespace. (Spoiler: es difícil de debuggear a las 2 AM cuando el cluster está en producción.) Más contexto en resolver conflictos de conectividad entre servicios.

En cuanto a los tipos de registros: Kubernetes crea registros tipo A/AAAA para servicios que tienen una clusterIP asignada, y registros SRV para los puertos nombrados de esos servicios. Los pods headless (sin clusterIP) tienen sus propios registros A por pod, lo que los hace útiles para StatefulSets donde necesitás hablarle a un pod específico.

Route 53 Resolver: DNS privado dentro de una VPC en AWS

Cuando pasamos a AWS, el equivalente de CoreDNS es Route 53 Resolver. Ojo: no confundir Route 53 (para hosting de dominios públicos) con Route 53 Resolver (un componente que vive dentro de cada VPC).

Por defecto, todas las VPCs tienen acceso a Route 53 Resolver en la dirección base de la VPC + 2. Si tu VPC tiene el CIDR 10.0.0.0/16, el resolver está en 10.0.0.2. No lo instalás, no lo configurás, está ahí.

Lo que resuelve Route 53 Resolver internamente:

  • Hostnames de EC2: ip-10-0-1-15.ec2.internal
  • Endpoints de servicios AWS: bases de datos RDS, cachés ElastiCache, endpoints de S3 privados
  • Internal load balancers: internal-api-alb.us-east-1.elb.amazonaws.com
  • Nombres definidos en Private Hosted Zones que creaste vos

Cualquier instancia EC2, contenedor en ECS, o pod en EKS que corra dentro de la VPC puede resolver estos nombres. No hay configuración adicional para el caso básico.

Private Hosted Zones y resolver endpoints

Una Private Hosted Zone (PHZ) es básicamente un dominio interno que solo existe dentro de tu VPC. Podés crear internal.miempresa.com y agregar registros A que apunten a IPs privadas. Nadie fuera de tu VPC puede resolver esos nombres.

Esto es útil para darle nombres legibles a recursos internos: en vez de acordarte que tu base de datos principal está en db-prod-cluster.cluster-xyz123.us-east-1.rds.amazonaws.com, la registrás como db.internal.miempresa.com.

Ahora bien, si tenés múltiples VPCs o necesitás integrar resolución con un datacenter on-premises, los inbound/outbound endpoints de Route 53 Resolver son lo que necesitás. Los inbound endpoints permiten que sistemas externos hagan consultas DNS a tu VPC. Los outbound endpoints te dejan configurar reglas para reenviar consultas de ciertos dominios a servidores DNS externos. Cubrimos ese tema en detalle en configurar infraestructura como código.

¿Alguien lo configura mal habitualmente? Sí. El error más común es crear los endpoints pero olvidarse de las reglas de forwarding, y terminar con endpoints que no reenvían nada.

Combinando CoreDNS con Route 53 en EKS

Acá viene el caso práctico real: tenés un cluster EKS y querés que tus pods resuelvan tanto servicios de Kubernetes como recursos AWS privados (una base RDS, un ElastiCache, otro servicio en una VPC diferente).

El problema: por defecto, CoreDNS en EKS resuelve nombres del cluster, pero para nombres externos (incluyendo dominios AWS privados), necesita un upstream. Y ese upstream tiene que ser Route 53 Resolver.

La configuración típica modifica el ConfigMap de CoreDNS para agregar una regla de forwarding: cualquier consulta que no matchee cluster.local se reenvía al resolver de la VPC (169.254.20.10 en EKS, o la IP base + 2 de tu VPC). Esto permite que un pod llame a mi-rds.us-east-1.rds.amazonaws.com y la resolución funcione a través de la cadena: CoreDNS → Route 53 Resolver → respuesta.

Sin esta configuración, el pod intenta resolver el hostname de RDS, CoreDNS no lo conoce, y la conexión falla. El error que ves en los logs no siempre es obvio sobre la causa real.

AspectoCoreDNS (Kubernetes)Route 53 Resolver (AWS VPC)
Dónde correPods en kube-systemIntegrado en la VPC, sin instancias
Qué resuelveServicios y pods del clusterHostnames AWS, PHZs, dominios privados
ConfiguraciónConfigMap corednsConsole/CLI/Terraform de AWS
Multi-clusterRequiere configuración manualSoportado con Resolver Rules
On-premisesForwarding a DNS externoInbound/Outbound Endpoints
EscalabilidadAumentás réplicas del pod CoreDNSAutomática, gestionada por AWS
descubrimiento de servicios en kubernetes diagrama explicativo

Errores comunes que se repiten

Usar IPs directas en lugar de nombres de Service

Es el error de principiante, pero aparece más seguido de lo que uno esperaría, sobre todo en configuraciones migradas desde Docker Compose. Si usás la IP de un pod directamente, en algún momento ese pod va a morir y tu aplicación va a dejar de funcionar. Usá siempre el nombre del Service.

Asumir que el nombre corto funciona entre namespaces

Dentro del mismo namespace: backend resuelve. Desde otro namespace: backend no resuelve (o peor, resuelve al servicio equivocado si existe un servicio con el mismo nombre en ese namespace). Siempre que cruces namespaces, usá el FQDN o al menos servicio.namespace. Sobre eso hablamos en automatizar despliegues en Kubernetes.

Confundir Route 53 público con Route 53 Resolver

Route 53 como hosting de zonas públicas y Route 53 Resolver son cosas distintas. Uno es para que el mundo resuelva tu dominio público. El otro es para que tus recursos dentro de la VPC se resuelvan entre sí. No se configuran igual ni sirven para lo mismo.

No configurar el forwarding de CoreDNS en EKS

Si no configurás el ConfigMap de CoreDNS para reenviar consultas externas al Route 53 Resolver de la VPC, tus pods no van a poder resolver hostnames de RDS, ElastiCache ni otras zonas privadas de AWS. La conexión falla y el mensaje de error muchas veces no menciona DNS, lo que hace que la gente busque el problema en el lugar equivocado.

Para profundizar en cómo interconectan estos sistemas, revisá nuestro artículo sobre How Resources Discover Each Other in Kubernetes and AWS.

Esto se conecta con service discovery, donde cubrimos el tema en detalle.

Preguntas Frecuentes

¿Cómo descubren los servicios en Kubernetes sin usar direcciones IP?

Kubernetes crea un Service object que tiene una clusterIP estable (que no cambia aunque los pods de atrás cambien). CoreDNS registra el nombre de ese Service y lo asocia a esa clusterIP. Cualquier pod que consulte ese nombre DNS recibe la clusterIP del Service, que a su vez balancea el tráfico a los pods disponibles. Las IPs de los pods individuales nunca se exponen al cliente.

¿Qué es CoreDNS y cómo funciona en un cluster de Kubernetes?

CoreDNS es el servidor DNS estándar de Kubernetes desde la versión 1.13, y corre como uno o más pods en el namespace kube-system. Cuando Kubernetes crea o elimina un Service, actualiza automáticamente los registros DNS en CoreDNS. Los pods del cluster tienen CoreDNS configurado como su nameserver por defecto, así que cualquier resolución DNS que hagan pasa por ahí primero.

¿Cómo resuelve Route 53 nombres privados en una VPC de AWS?

Cada VPC de AWS tiene acceso por defecto a Route 53 Resolver en la dirección IP base de la VPC más 2 (ejemplo: 10.0.0.2 para una VPC con CIDR 10.0.0.0/16). Este resolver conoce los hostnames internos de EC2, los endpoints de servicios AWS como RDS y ElastiCache, y los registros de cualquier Private Hosted Zone que asocies a esa VPC. No requiere instalación ni configuración para el caso básico.

¿Por qué cambian las IPs en Kubernetes y qué hacer al respecto?

Las IPs de los pods en Kubernetes son efímeras por diseño: cuando un pod se reinicia, migra a otro nodo, o escala, recibe una nueva IP del pool del cluster. La solución es nunca apuntar directamente a IPs de pods. En su lugar, usá un Service de Kubernetes que mantiene una clusterIP estable y enruta el tráfico a los pods disponibles en cada momento.

¿Cuál es la diferencia entre service discovery en Kubernetes y AWS?

CoreDNS en Kubernetes resuelve servicios dentro del cluster: pods hablando con otros pods o servicios. Route 53 Resolver en AWS resuelve recursos dentro de una VPC: instancias EC2, bases de datos, load balancers privados. Cuando usás EKS, necesitás ambos: CoreDNS para la comunicación interna del cluster, y Route 53 Resolver (configurado como upstream de CoreDNS) para que los pods puedan resolver recursos AWS externos al cluster.

Conclusión

El descubrimiento de servicios no es una feature opcional: es la base sobre la que funciona cualquier arquitectura distribuida a escala. Si tus servicios se hablan por IP, estás construyendo sobre arena.

En Kubernetes, CoreDNS resuelve el problema dentro del cluster con un modelo declarativo: creás el Service, Kubernetes actualiza el DNS, y tus pods pueden resolverlo por nombre. En AWS, Route 53 Resolver hace lo mismo dentro de la VPC sin que tengas que hacer nada.

El caso más complejo, y el que más gente se tropieza, es EKS: ahí necesitás que CoreDNS y Route 53 Resolver trabajen juntos, con forwarding configurado correctamente en el ConfigMap. Una vez que está bien, funciona de forma invisible. Si lo salteás, vas a estar debuggeando conexiones que “deberian funcionar” por horas.

Si estás armando infraestructura propia y necesitás un proveedor confiable para el hosting o los recursos de red base, donweb.com tiene opciones de cloud y VPS donde podés implementar este tipo de arquitecturas.

Fuentes

Te puede interesar...