AKS no puede descargar la imagen de un registro privado detrás de tu VPN
El kubelet descarga por la red del nodo, no por la VPN del pod. Decide por rutas del nodo, DNS del nodo, cada endpoint que toca la descarga, y luego TLS e identidad.
Tu portátil descarga la imagen sin problema, pero el pod se queda en ImagePullBackOff y alguien propone ejecutar el cliente VPN corporativo como sidecar. No ayudará: la descarga ocurre antes de que exista tu contenedor. El kubelet pide al runtime del nodo que traiga la imagen, y el runtime usa el espacio de red del nodo. Una VPN dentro del workload no tiene ruta que ofrecer a ese camino, y su propia imagen auxiliar tendría que descargarse primero.
El orden de las operaciones decide la capa
Primero viene la resolución del nombre. El kubelet, mediante el runtime, resuelve el nombre del registro, se conecta, se autentica, descarga las capas y solo entonces inicia el contenedor. Todo lo que tu pod hace con una VPN ocurre después de esa secuencia, así que un túnel que funciona en el clúster no es prueba sobre la descarga.
Por eso una imagen en caché es una mentira tan convincente. Un nodo que descargó la imagen hace semanas la sigue sirviendo, el despliegue parece sano y el fallo solo aparece cuando el planificador coloca una réplica en un nodo más nuevo. Si la línea de tiempo incluye un escalado, un reemplazo de nodo o una actualización del pool, trátalos como el disparador, no como la causa.
Tres condiciones deciden la reparación
La accesibilidad a un registro privado desde un pool gestionado se reduce a enrutamiento, resolución de nombres y conjunto de endpoints. Si la subred del nodo no puede enrutar a la red del registro, ninguna credencial ayudará. Si enruta pero no resuelve el nombre por la ruta DNS del nodo, la conexión nunca empieza. Si ambos funcionan para el endpoint de manifiesto pero no para el de blob al que el registro redirige, la descarga falla a medias.
| Condition | Typical symptom | Where to look |
|---|---|---|
| Node subnet has no route to the registry network | Timeout, no connection | Effective routes on the node NIC, gateway transit, return path on-premises |
| Node resolver cannot see the private zone | Name resolution failure in events | VNet DNS settings and the resolver the node actually uses |
| Only the manifest endpoint is reachable | Auth succeeds, layer download fails | Every hostname the registry hands out during the pull |
| TLS or identity is wrong | Certificate error, 401 or 403 | Server certificate name and trust, scoped pull identity |
El peering de VNet por sí solo no te da todas las combinaciones de gateway transit, y una ruta que existe en un sentido no es una ruta que funcione. El nodo necesita un camino admitido por la puerta de enlace VPN prevista o un dispositivo aprobado, y el lado del registro necesita una ruta de retorno a la subred del nodo.
Lee el fallo antes de elegir la solución
Empieza por los eventos del pod y el nodo donde cayó, con tus nombres reales: kubectl describe pod app-example -n team-example y kubectl get pod app-example -n team-example -o wide. El texto del evento separa un nombre de host sin resolver de un timeout, un rechazo de certificado de una imagen ausente y un fallo de autorización de todos ellos. Esos cuatro tienen cuatro dueños distintos.
La autenticación es la palanca más sobrevalorada. imagePullSecret da credenciales del registro al runtime; no instala una ruta, no cambia el resolutor del nodo ni hace válido un certificado no confiable. Si el evento dice que la descarga no estaba autorizada, mira el alcance de la identidad. Si dice que la conexión expiró, las credenciales son irrelevantes.
La documentación de imágenes de Kubernetes es la referencia sobre el comportamiento de descarga y las credenciales de registros privados, y vale la pena leerla una vez antes de cambiar la red, porque hace explícita la frontera entre autenticación y transporte.
Construye el camino por debajo del pod
Trabaja en este orden, porque cada paso carece de sentido hasta que se cumple el anterior. Enruta primero la red del nodo: confirma que la subred tiene un camino admitido a la red del registro, revisa las rutas efectivas en el nodo, las reglas de seguridad en ambos extremos y la ruta de retorno en el lado del registro.
Después resuelve el nombre desde el contexto del nodo. El resolutor del nodo no es la configuración DNS del pod, y el éxito dentro de un pod no es prueba sobre el runtime del host. Usa DNS privado gestionado en lugar de una entrada permanente en hosts; la entrada sobrevive hasta que el nodo se reemplaza y luego desaparece en silencio.
Luego demuestra cada endpoint. Un registro puede dar al cliente un servicio de autenticación separado y una ubicación de blob separada. Llegar al endpoint de manifiesto no demuestra casi nada sobre las capas. Por último completa TLS y autorización: un certificado válido para el nombre del registro y confiado mediante configuración de nodo admitida, más una identidad de descarga limitada a leer ese repositorio.
Verifícalo en un nodo que no hayas reparado a mano
La prueba que cuenta es una descarga nueva y una bajada completa de todas las capas en un nodo apto, idealmente uno creado por escalado o reemplazo. Eso cubre todos los pools que podrían programar el workload, incluidos los que olvidaste. Una reparación manual en un nodo no es un modelo de despliegue, y el próximo evento de autoscalado encontrará el hueco.
Recrear el clúster en otra VNet puede cambiar el camino, pero es el último recurso y no el primer paso de diagnóstico. Compara la red de nodos existente con la ruta privada necesaria y con los controles de red de AKS admitidos antes de proponer una migración, y mantén la conectividad de la aplicación tras el arranque como verificación aparte: el pod hablando con su backend es una comprobación distinta de la del nodo descargando la imagen.