Challenge ·Medium

Descarga una imagen de un registro privado

La tienda ha movido sus imágenes a un registro privado y el clúster se ha quedado sin poder descargarlas. Distingue en los Events un fallo de credenciales de un fallo de nombre, crea el Secret de tipo dockerconfigjson y decide dónde colgarlo: en el Pod o en la ServiceAccount del Namespace.

La tienda ha sacado sus imágenes de Docker Hub y las ha subido a un registro privado, registry.iximiuz.com. La migración se hizo anoche, se actualizaron los manifiestos, y esta mañana no arranca nada.

Los manifiestos están en /home/laborant/manifests y el contexto ya apunta al Namespace tienda. Empieza por ver el estropicio desde la pestaña dev-machine:

kubectl get pods

Tres cosas rotas y no todas por el mismo motivo, aunque en kubectl get pods se vean exactamente igual. Las credenciales del registro son:

Servidorregistry.iximiuz.com
Usuarioiximiuzlabs
Contraseñarules!

El Pod api

El caso base: una imagen que existe, en un registro que pide credenciales que nadie le ha dado.

Pista 1

kubectl get pods dice ImagePullBackOff, que es el síntoma, no la causa. La causa está en los Events: kubectl describe pod api, y mira el último mensaje del kubelet. Un 401 Unauthorized es un problema de credenciales; un 404 not found es un problema de nombre o de tag.

Pista 2

Las credenciales de un registro se guardan en un Secret de tipo kubernetes.io/dockerconfigjson, y es el único tipo de Secret que en la práctica nadie escribe a mano: hay un subcomando de kubectl create secret que lo genera a partir del servidor, el usuario y la contraseña.

Pista 3

Con el Secret creado, el Pod tiene que referenciarlo en spec.imagePullSecrets. Y ojo: ese campo es inmutable, así que no basta con editar el Pod que ya existe. Corrige el manifiesto en /home/laborant/manifests/api.yaml, borra el Pod y vuelve a aplicarlo.

El Pod reports

Con las credenciales puestas, este sigue sin arrancar. Y ahí está la gracia: hasta que no te autenticas, el registro no te cuenta la verdad.

Pista 4

Un registro no le dice a un desconocido qué imágenes tiene: mientras no te autentiques, todo es 401, exista o no. Repite el kubectl describe pod reports después de haber resuelto lo de las credenciales y verás aparecer otro mensaje distinto.

Pista 5

Averigua qué tags existen de verdad en ese repositorio. Desde dev-machine puedes preguntárselo al registro con sus credenciales:

curl -s -u iximiuzlabs:'rules!' https://registry.iximiuz.com/v2/tienda/reports/tags/list

El Deployment web

El equipo que mantiene web no quiere ni oír hablar de tocar su manifiesto: dicen, con razón, que de qué registro salen las imágenes no es asunto de su aplicación. Y tienen razón, porque hay un sitio mejor donde ponerlo.

Restricción: el template del Deployment web no puede declarar imagePullSecrets.

Pista 6

Todo Pod que no dice lo contrario corre con la ServiceAccount default de su Namespace. Y una ServiceAccount también tiene un campo imagePullSecrets, que se le inyecta a todos los Pods que la usan sin que ellos declaren nada.

Pista 7

Esa inyección ocurre cuando se crea el Pod. Los Pods que ya estaban ahí antes de que tocaras la ServiceAccount no se enteran de nada: hay que recrearlos, y en un Deployment eso tiene su propio comando.

Por qué importa

Un ImagePullBackOff es de los pocos fallos que ocurren antes de que exista tu contenedor: lo provoca el kubelet descargando la imagen, cuando todavía no hay proceso, ni logs, ni identidad de Pod que ofrecer. Por eso ninguna identidad del proveedor de nube (IRSA, Workload Identity, Pod Identity) sirve para esto: cuando la imagen se descarga, tu Pod todavía no es nadie.

Y por eso quedan solo dos respuestas: un Secret en el Namespace, o un nodo que sepa autenticarse solo. La primera es la que acabas de practicar. La segunda es la que usan EKS, GKE y AKS por debajo, con un credential provider instalado en el kubelet, y es la razón de que en un clúster gestionado esto muchas veces "ya funcione" sin que nadie declare nada.