Cómo Configurar un Container Registry Local en vSphere Kubernetes Service (VKS)

Contenido

  1. Login al Harbor local
  2. Configurar un cliente Docker con el certificado de registro Harbor
  3. Descarga de Imágenes
  4. Tagear Imágenes
  5. Subir imagen al Container Registry Privado (Harbor)
  6. Referenciar Imagen desde Registry Local

¿Tu clúster de Kubernetes no tiene salida a internet y te está bloqueando los despliegues?
Es más común de lo que parece… y lo peor: muchas veces ya tienes la solución dentro de tu propia plataforma.

En entornos empresariales es habitual encontrar restricciones de red que impiden el acceso a repositorios públicos, lo que complica la descarga de imágenes necesarias para desplegar aplicaciones contenedorizadas en Kubernetes (K8s).

Aquí es donde entra una solución simple, segura y muchas veces subutilizada: un Container Registry local como Harbor, integrado a través de los Supervisor Services de vSphere Supervisor.

En este contenido te voy a mostrar cómo descargar imágenes desde fuentes externas, cargarlas en tu registry local y dejarlas listas para ser consumidas por tus despliegues en Kubernetes.

Login al Harbor local

Asumiendo que ya tienes un Harbor habilitado en la infraestructura, vamos a seguir los siguientes pasos para poder descargar las imágenes de repositorios publicos y subirlas a nuestro repositorio privado o Container Registry basado en Harbor.

Para esto debemos hacer Login al Harbor desde el navegador web https://fqdn-harbor-local

Pasted image 20260209194504.png

Para almacenar nuestra imágenes es necesario crear un Proyecto, para esto vamos a crearlo haciendo clic en New Project, este puede ser definido como Public o Private. El nombre de este proyecto será opencart

En Harbor existen dos tipos de proyectos:

  • Público : Cualquier usuario puede descargar imágenes de este proyecto. Esta es una forma práctica de compartir repositorios con otros.
  • Privado : Solo los usuarios que son miembros del proyecto pueden descargar imágenes.
Pasted image 20260209194514.png

Dentro de este proyecto alojarémos las imágenes a tráves del comando push desde un cliente Docker.

Pasted image 20260209194607.png

Configurar un cliente Docker con el certificado de registro Harbor

Para trabajar con imágenes de contenedor en un registro con Docker, es necesario agregar el certificado de Registry al cliente de Docker. Este certificado se utiliza para autenticar Docker durante el inicio de sesión en el Registry.

Nota: Para esto vamos usar la siguiente documentacion oficial Configurar un cliente Docker con el certificado de registro Harbor que por supuesto explicaremos paso a paso.

Nota: Los siguientes pasos asumen que estas usando una VM Linux (Ubuntu) con el Docker daemon instalado. Sino ha instalado el Docker Engine (daemon) sobre una VM Ubuntu, vaya un momento a Install Docker Engine on Ubuntu y siga los pasos.

Una vez instalado el Docker Engine (Deamon) debemos verificar que esté instalado y que puedas extraer imágenes del concentrador Docker, ejecuta el siguiente comando:

docker run hello-world

Resultado esperado:

Hello from Docker!
This message shows that your installation appears to be working correctly.

Nota: Estos comandos se verificaron utilizando Ubuntu 20.04 y Docker 19.03.

Configure su cliente Docker para interactuar con un container regsitry, como Harbor Registry o Docker Hub. Este ejemplo asume que está usando Harbor del Servicio de Supervisor.

  1. Inicie sesión en Harbor Registry.

  2. Seleccionar > Administration > Configuration > Registry Root Certificate.

  3. Hacer clic Download para descargar el certificado de Harbor Registry llamado ca.crt.

    Nota: Si es necesario, cambie el nombre del certificado a ca.crt.

  4. Copiar de forma segura el archivo ca.crt a su cliente host Docker.

  5. En el host Docker, cree una ruta de directorio para el registro privado utilizando la dirección IP de Harbor.

    /etc/docker/certs.d/IP-address-or-FQDN-of-harbor/
    Por ejemplo:
    mkdir /etc/docker/certs.d/10.179.145.77
  6. Mueva el ca.crt a este directorio.

    Por ejemplo:

    mv ca.crt /etc/docker/certs.d/10.179.145.77/ca.crt

  7. Reinicie el Docker deamon.

    sudo systemctl restart docker.service

  8. Inicie sesión en el Harbor Registry integrado usando su cliente Docker.

    docker login ip-fqdn-harbor

    Ejemplo:

    docker harbor-01a.site-a.vcf.lab

    Deberías ver el siguiente mensaje:

    WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded


Pasted image 20260209194657.png

Descarga de Imágenes

El siguiente paso es descargar las imágenes desde el repositorio publico a la VM, preferiblemente basada en Linux, donde instalamos el docket client, para ejecutar los siguientes comando:

Para ver las imagenes que estan descargadas en la libreria del Docker Client local podemos usar los siguientes comando:

docker image ls
docker images

Pasted image 20260212171337.png

El signidicado de algunas de las columnas que puede devolver el comando anterior es el siguiente:

  • IMAGE: El tag completo de la imagen (lo que acabamos de explicar: registry/proyecto/nombre:versión)
  • ID: El identificador único de la imagen en tu máquina local, Docker lo genera automáticamente. Es un hash, pero aquí solo muestra los primeros 12 caracteres (el hash completo es mucho más largo)
  • DISK USAGE: Cuánto espacio está ocupando esa imagen en tu disco duro local
  • CONTENT SIZE: El tamaño real del contenido de la imagen sin contar metadatos ni capas compartidas. Nota que ambas tienen 0B, lo cual puede indicar que el comando fue ejecutado con una versión de Docker que no calcula ese campo, o que están siendo referenciadas de otra forma
  • REPOSITORY: El nombre del repositorio de la imagen (por ejemplo, gitea/gitea y una imagen de Broadcom)
  • TAG: La etiqueta o versión de la imagen (latest, 4.0.1-1-debian-11-r66)
  • IMAGE ID: Identificador único de la imagen
  • CREATED: Cuándo fue creada la imagen (3 weeks ago, 2 years ago)
  • SIZE: El tamaño que ocupa la imagen en disco (180MB, 487MB)

Para descargar la imagen desde los respositorios de Docker Hub podemos usar el siguiente comando
docker pull [image:version]
Ejemplo: docker pull busybox:latest

Pasted image 20260212171320.png

o podemos seguir los ejemplos que estan en la siguiente nota para bajar la imagenes de otros respositorios.

Nota: Imagenes de algunos repostorios podrian requerir un usuario y contraseña para poderse descargar

Nota: Algunas imágenes podrían no estar disponible en Docker Hub por lo que se hace necesario descargarlas desde otros repositorio como bitnami, registry.k8s, gcr.io, public.ecr.aws, etc

Probar imágenes 100% públicas
docker pull bitnami/wordpress:latest
docker pull bitnami/mysql:8.0
# O usar el registry oficial de Kubernetes
docker pull registry.k8s.io/pause:3.2

Podemos probar diferentes Registries Publicos que funcionan bastante bien

# Estos deberían funcionar SIN usuario:
docker pull gcr.io/google-containers/pause:3.2
docker pull ghcr.io/bitnami/wordpress:latest # GitHub Container Registry
docker pull public.ecr.aws/bitnami/wordpress:latest # AWS Public Registry

NOTA: Importante tener presente que NO NECESITAS CREDENCIALES para la mayoria de registries públicos.

Tagear Imágenes

Ahora debemos colocarle un tag siguiendo el formato que nos indica el mismo Harbor dentro del proyecto en el enlace PUSH COMMAND. Esto es necesario porque Docker no sabe a dónde subir una imagen a menos que el nombre de la imagen comience con la dirección del servidor (harbor-01a.site-a.vcf.lab).

Tag una Imagen para el proyecto Opencart

Para tagear una imagen antes de subirla debemos ajustar el siguiente comando:

docker tag SOURCE_IMAGE[:TAG] fqdn-habor/project/REPOSITORY[:TAG]

A continuacion, la explicacion de que hace este comando.

Lado izquierdo → la imagen que ya tienes local, o incluso puede ser que este en el repositorio publico:

  • SOURCE_IMAGE = el nombre de tu imagen local o en el repositorio publico
  • [:TAG] = la versión de esa imagen local. Aunque se llama TAG no es el tag que le vamos a colocar es solo la version de la imagen, podríamos decir que es el tag de la version.

Lado derecho → el destino completo en Harbor, y esto todo junto es lo que Docker llama «el tag»:

  • fqdn-harbor = dominio de tu Harbor
  • project = proyecto dentro de Harbor
  • REPOSITORY = nombre que tendrá en Harbor
  • [:TAG] = la versión. De nuevo es el tag pero solo de la version.

Entonces, el tag que le estás poniendo es todo el lado derecho completo: fqdn-harbor/project/REPOSITORY[:TAG]. Eso es lo que Docker entiende por tag — no solo el :TAG del final.

Ejemplo:
docker tag busybox:latest harbor-01a.site-a.vcf.lab/busybox/busybox:latest

Pasted image 20260212171837.png
Pasted image 20260212170952.png


Nota: Este comando no duplica la imagen, solo le crea un alias o apodo. Le dice a Docker que la imagen que descargaste originalmente (como busybox:latest) ahora también debe ser reconocida con el nombre largo de tu servidor Harbor.

Subir imagen al Container Registry Privado (Harbor)

Ahora lo que hacemos es tomar las imágenes que ya etiquetaste y las transferimos por la red desde tu computadora o desde el repositorio publico hasta el servidor Harbor. Para esto se hace necesario hacer el push para publicar la imagen en harbor

Push una imagen en este proyecto
docker push fqdn-habor/project/REPOSITORY[:TAG]

Este es el comando que hace el trabajo pesado: la carga (upload). Una vez que termine, cualquier otra persona (o tu clúster de Tanzu) podrá descargar la imagen directamente desde Harbor sin necesidad de internet.

Ejemplo: docker push harbor-01a.site-a.vcf.lab/busybox/busybox:latest

Pasted image 20260212173957.png

Esta acción sube la imagen a Harbor, específicamente a nuestro proyecto y la deja disponible para que podamos usarla después en nuestros archivos YAML.

Pasted image 20260212174311.png
Pasted image 20260212174323.png
Pasted image 20260212174335.png


Nota (Opcional): Otra forma es crear un puntero o Alias local para que desde el repositorio original se haga push directamente al Harbor. De esta forma evitamos bajar la imagen con el pull. Creamos unicamente el apuntador y hacemos el push directamente desde el repositorio publico hacia el harbor.

docker tag SOURCE_IMAGE_ONLINE_REPO[:TAG] fqdn-habor/project/REPOSITORY[:TAG]

Ejemplo:
docker tag vcf-automation-docker-dev-local.usw5.packages.broadcom.com/bitnami/opencart:4.0.1-1-debian-11-r66 harbor-01a.site-a.vcf.lab/opencart/opencart:4.0.1-1-debian-11-r66

Pasted image 20260213175947.png

docker push fqdn-habor/project/REPOSITORY[:TAG]

Ejemplo:
docker push harbor-01a.site-a.vcf.lab/opencart/opencart:4.0.1-1-debian-11-r66

Pasted image 20260213175955.png

Referenciar Imagen desde Registry Local

Y eso es todo, lo que haríamos despues cuando estemos instalando la aplicación en nuetro cluster de Kubernetes, es simplemente referenciar el path de la imagen que subimos, que ahora vive en nuestro Image Registry local (Harbor), en el archivo YAML que instala la aplicación.

Pasted image 20260417135558.png

¡IMPORTANTE! He migrado blog del dominio nachoaprendevirtualizacion.com a nachoaprendeit.com. Si te ha servido este artículo deja tu buen Like y compártelo con tus colegas, estas aciones me ayudarán a optimizar los motores de búsqueda para llegar a más personas, y a motivarme a seguir compartiendo este tipo de artículos.

TODOS LOS NOMBRES DE VMS USADOS EN ESTE BLOG SON INVENTADOS Y OBEDECEN A UN AMBIENTE DE LABORATORIO PROPIO, UTILIZADO PARA FINES DE ESTUDIO.

Cómo conectarse a los nodos del TKG/VKS Cluster via SSH

En esta oportunidad vamos a responder a una pregunta muy frecuente de nuestros clientes. Y es ¿Como inicio sesión SSH a los nodos del cluster de Tanzu Kubernetes Grid (TKG), recientemente renombrado a vSphere Kubernetes Service (VKS)?. Pues bien, vSphere with Tanzu ahora vSphere IaaS Control Plane, esta diseñado para que no haya necesidad de tener que ingresar a estos nodos. Sin embargo, algunos clientes son curiosos y quieren acceder a darle una mirada a estos nodos.

CONTENIDO

  1. Prerrequisitos
  2. Procedimiento para iniciar sesión SSH a los nodos TKG
  3. Conclusion

Lo primero que debemos decir es que hay varia forma de hacerlo incluyendo una en donde nos conectamos a traves del vCenter a las Control Plane del Supervisor Cluster y desde ahi saltamos a las control VM de los TKG. Sin embargo, esta opción no parece ser la mejor para los clientes que no quiere compartir un acceso ssh al vCenter solo para poder acceder a la VMs del cluster de K8s que hemos llamado acá TKG (Tanzu Kubernetes Grid) recientemente renombrado como VKS (vSphere Kubernetes Services).

Sin mas preámbulo, te explico la forma correcta de hacerlo, basado en la documentación oficial SSH to TKG Service Cluster Nodes as the System User Using a Password aunque podemos también encontrar los pasos resumidos en el siguiente VMware KB Accessing vSphere with Tanzu workload clusters using SSH

Prerrequisito

Create a Linux Jump Host VM

Este prerrequisito es muy facil de cumplir y basicamente vamos a necesitar una VM basada en Linux. Sino tenemos una, podemos seguir la documentación oficial Create a Linux Jump Host VM para desplegar un Photon OS.

Pasted image 20250828161201.png

Pero si como en mi caso ya tienen una, pueden usar esa. Lo único que debemos hacer es agregarle una segunda interface, que tenga acceso a la red de Workload Network > Namespace Network del Supervisor Cluster.

Así que agrégale una segunda interface a tu VM existente o nueva y déjala hasta ahi. Mas adelante veremos cuál IP, Subnet o NSX Segment configurarle.

Identificar la Workload Network

Antes de continuar, es importante entender que los objetos de Kubernetes crean objetos en NSX
• Un Kubernetes namespace crea un logical segment.
• Un vSphere Pod crea un logical port conectado al logical segment.
• Kubernetes crea un correspondiente virtual server en NSX para su servicio load balancer.

Para saber cual es la red de Workload Network, vamos a ver la configuración de Supervisor Cluster en Workload Management > Supervisors > [Supervisor-Name] > Network > Workload Network

Pasted image 20250828192503.png

Nota: Aqui vemos que la Namespace Network es la 10.244.0.0/20 y es subneteada con /28 para cada Namespace (vSphere Namespace) que se crea en el Supervisor Cluster.

Ahora bien, en el NSX que soporta el despliegue de Supervisor Cluster, solo si su solucion de Supervisor fue desplegada usando NSX, vamos a ver que por cada Namespace en el Supervisor Cluster se crea un T1 Gateway y que estos tienen un sufijo que contiene el nombre de los cluster TKGs ha creado.

Pasted image 20250828194355.png

Y en la columna Linked Segments tenemos un numero que nos indica a cuantos segmentos NSX esta conectado. Por lo general hay mínimo dos segmentos asociados, seg-domain-xxx y un vnet-domain-yyy. Puede haber mas si el Namespace tiene mas de un cluster vSphere Pods por dentro. En este caso solo tengo un Cluster de TKG desplegado en ese vSphere Namespace. Para mas información acerca de objectos creados en NSX por favor visitar NSX Networking Objects for VKS Clusters.

Lo importante a entender aquí, es que las VM de Control y Worker de los cluster TKG esta conectados al segmento vnet-domain-yyy de esos T1 Gateways. Por lo que nuestra tarea es agregar un IP de ese Segmento a la VM Jump que teníamos disponible o que tuvimos que crear.

De lo anterior, podemos hacer el siguiente análisis. Si el segmento vnet-domain-yyy tiene configurado el gateway 10.244.0.145, la VM de control del TKG la 10.244.0.146 y la de Worker del TKG la 10.244.0.147 y ya sabemos que nuestra solución Supervisor Cluster hace subnet /28 para cada vSphere Namespace. Quiere decir aun tenemos 11 IPs de la subnet disponibles para poder asignársela a la interface de nuestra VM Jump. Solo para aclarar, recordemos que /28 no da 16 IPs disponibles y 14 IPs usables, pero aca ya tenemos 3 IPs utilizadas.

Nota: Esto puede cambiar si tiene mas componentes dentro del su vSphere Namespace, o mas nodos en sus cluster de TKG.

Pasted image 20250828195424.png
  1. En este caso, como mencionamos anteriormente, ya tenia una VM linux en el ambiente, de manera que solamente le voy a conectar una segunda interface. Si usted no tiene una siga la documentación para descarga el ISO o el OVA y desplegar el Photon OS y cuando este listo continue con este paso.
Pasted image 20250828205058.png
Pasted image 20250828205115.png

Nota: Recordemos que las IPs que ha tomado las Control VM y Worker nodes de TKG son del Segmento vnet-domain-xxxxxx-Namespace-Name-yyy. Por esta razon debemos conectar ese Segmento NSX a nuestra VM en la segunda interface.

  1. Configure la máquina virtual con una dirección IP desde Red de Workload > Red del Namespace.
# sudo ip addr add 10.244.0.158/28 dev ens35
# ip addr show ens35

Nota: Se recomienda utilizar para esto la ultima IP disponible de esa subnet /28 o una de las ultimas para evitar overlapping si agregamos mas recursos a ese vSphere Namespace.

  1. Una vez configurada la IP vamos a verificar que podemos hacer ping al gateway
Pasted image 20250828210559.png

Nota: En este punto ya estamos listos para iniciar sesión a nuestros TKG clusters.

Procedimiento para iniciar sesión SSH a los nodos TKG

En este punto ya deberíamos poder hacer SSH a la VM. Sin embargo. Primero debemos obtener la contraseña de esas VMs, siguiendo SSH to TKG Service Cluster Nodes as the System User Using a Password, pero como siempre acá lo vamos a resumir. Entonces lo primero es hacer login al supervisor cluster

kubectl vsphere login --server=https://<SUPERVISOR_IP> [--vsphere-username <VSPHERE_USERNAME>]

Pasted image 20250829123816.png
  1. Cambiar el contexto (vSphere Namespace) donde esta aprovisionado el clúster TKG.
kubectl config get-contexts
kubectl config use-context [vSPHERE_NAMESPACE_NAME]

Ejemplo: En este caso queremos hacer login a un TKG que esta en el vSphere Namespace `terraform-cli`
Pasted image 20250829124044.png
  1. Ahora listamos las VMs para saber cuales conforman el cluster TKG
kubectl get virtualmachines
Pasted image 20250829124338.png
  1. (Opcional) podemos ejecutar el siguiente comando para ver la IP de las VMs desde kubectl o podriamos verla directamente en el inventario de vSphere

kubectl describe virtualmachine VM_NAME

Pasted image 20250829124722.png

Acá vamos a poder ver la IP configurada

Pasted image 20250829124828.png

Aunque podemos verla también desde el vSphere Client

Pasted image 20250829124907.png
  1. Ahora vamos a visualizar los secrets que esta configurados en este vSphere Namespace con el siguiente comando

kubectl get secrets

Pasted image 20250829125024.png
  1. De la salida anterior nos interesa obtener el Password SSH de las VM de Control y Worker del TKG cluster y para eso vamos a utilizar el siguiente comando

kubectl get secrets TKG-CLUSTER-NAME-ssh-password -o yaml

Pasted image 20250829125421.png

Nota: El comando anterior nos devuelve el password de ssh

Nota (solo Windows nodes): Si su TKG usa nodos Windows. Dado que los nodos Windows no permiten un mecanismo SSH basado en contraseña, utilice la Private Key para acceder por SSH a los nodos de Control y Worker. Para eso utilice el siguiente comando.

kubectl get secrets TKG-CLUSTER-NAME-ssh -o jsonpath='{.data.ssh-privatekey}

  1. Ahora debemos decodifica el Password SSH o Private Key segun sea el caso de nuestros nodos, Linux o Windows

Descifrar el Password SSH (Nodos basados en Linux):
El secreto está codificado en Base64. Para decodificarlo,

  • En Linux use base64 –decode (o base64 -d);
  • En MacOS, use base64 –decode (o base64 -D);
  • En Windows, use an online tool.

Debido a que nuestro jump es Ubuntu usaremos la opcion base64 --decode

echo <ssh-passwordkey> | base64 --decode

Pasted image 20250829130810.png

Nota: Por alguna razon, el password decodificado no se mostro en una linea nueva, pero es esa. Si queremos comprobarlo podemos copiar el password y pegarlos en el online tool.

Pasted image 20250829130919.png

Descodificar la Private Key (Nodos basados en Windows)
Utilice el mismo mecanismo que utilizó para decodificar el Password SSH. Guarde la Private Key SSH decodificada en un archivo y configure los permisos chmod 400 FILE_NAME.

  1. Si hemos seguido las pasos hasta el momento, ya deberíamos poder iniciar sesión SSH a nuestros nodos del TGK desde nuestra Jump VM, ya sea con la Password SSH o Private Key decodificados, según corresponda (nodos linux o Windows).

Iniciamos entonces SSH a cualquiera de los nodos del clúster TKG con el usuario del sistema vmware.

Para utilizar Password SSH (nodos Linux), use este comando.

ssh vmware-system-user@TKG-CLUSTER-NODE-IP-ADDRESS

Pasted image 20250829131911.png

Para utilizar Private Key (nodos Windows), utilice el siguiente comando.

ssh -i filename vmware-system-user@TKG-CLUSTER-NODE-IP-ADDRESS

Nota: filename Es el archivo donde almacenaste la Private Key SSH para los nodos Windows.

Conclusion

Con este procedimiento habrá logrado iniciar sesión en los nodos de Control o Worker de su TKG cluster, utilizando el Password o Private Key que decodificó.

¡IMPORTANTE! He migrado blog del dominio nachoaprendevirtualizacion.com a nachoaprendeit.com. Si te ha servido este artículo deja tu buen Like y compártelo con tus colegas, estas aciones me ayudarán a optimizar los motores de búsqueda para llegar a más personas, y a motivarme a seguir compartiendo este tipo de artículos.

TODOS LOS NOMBRES DE VMS USADOS EN ESTE BLOG SON INVENTADOS Y OBEDECEN A UN AMBIENTE DE LABORATORIO PROPIO, UTILIZADO PARA FINES DE ESTUDIO.