¿Qué es un Registry?. Pues es un lugar donde guardar las imágenes que van a utilizar los despliegues de Kubernetes. ¿Sencillo no?
Hasta ahora he utilizado las imágenes disponibles en el repositorio oficial, pero lo habitual es que una vez vas creando imágenes propias, necesites un repositorio privado.
El propio registro de imágenes, no deja de ser otra imagen también disponible en el sitio oficial, y para subir el nivel de abstracción también puede ser un Deploy que corra dentro del cluster.
Voy a describir entonces los despliegues y utilidades que he utilizado para disfrutar de mi propio registro.
- Para los kind; namespace, service, ingress.
Aquí he utilizado lo mismo que para los anteriores despliegues. Solo me he tenido que pelear con el ingress ya que cuando subía las imágenes de daba un error “413 Request Entity Too Large“. Este error es del estandard html para cuando el servidor web no acepta la petición por ser ésta muy grande. Para solucionarlo es necesario incluir una annotation.
annotations:
# Añado para eliminar el límite de tamaño de las imágenes que se pueden
# subir al registry
nginx.ingress.kubernetes.io/proxy-body-size: "0"
- El el deploy es donde está el grueso de la configuración y donde más problemas he encontrado y tenido que solucionar sobre la marcha.
Uno de estos problemas ha sido la autenticación del registro y de su uso por los deploy. Para el propio registry lo más sencillo es optar por autenticación básica generando una contraseña con htpasswd. La configuración se le pasa a la imagen como variables y son suficientes las siguientes; REGISTRY_AUTH, REGISTRY_AUTH_HTPASSWD_REALM y REGISTRY_AUTH_HTPASSWD_PATH. La última yo la guardo en un recurso de servidor NAS que monto en /auth. También guardo en recursos nfs todo lo relativo a la persistencia. Por el momento no veo la necesidad de utilizar la persistencia de kubernetes mediante los PV y PVC.
...
env:
- name: REGISTRY_AUTH
value: "htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "Registry Realm"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"
...
nfs:
server: nfs-server
path: /DPVs/registro/auth
readOnly: false
...
- name: nfs-registro-auth
mountPath: /auth
Para generar la contraseña si no dispones del binario de htpasswd puedes utilizar el propio docker, podman, …
$ docker run --entrypoint htpasswd httpd:2 -Bbn usuario contraseña > htpasswd
Aunque el método de autenticación no sea el más seguro hay que tener en cuenta que viaja sobre el ssl del ingress.
Al proporcionar autenticación al registry, es necesario que los despliegues que lo utilicen, realicen los Push y Pull autenticándose previamente. Se puede definir un pequeño script que ejecute algo similar a esto:
kubectl create secret docker-registry regcred --docker-server=tuservidor --docker-username=usuario --docker-password=contraseña --docker-email=tucorreo --namespace=tunamespace
Al ejecutarse se genera en el namespace indicado un secret con un JSON que codifica usuario y contraseña.
- Comprobación básica.
Aunque no existe un UI como tal, sí que puedes comprobar si funciona desde un navegador, si pones https://tudominio.com/v2/_catalog, te aparece un listado con las imágenes que tiene disponibles. Por ejemplo:
{“repositories”:[“imagen1”]}
Faltaría ahora describir el uso como tal del registro pero eso lo dejo para otro día.
- El yaml completo sería el siguiente.
apiVersion: v1
kind: Namespace
metadata:
name: registro
---
apiVersion: v1
kind: Service
metadata:
labels:
app: registro
name: registro
namespace: registro
spec:
ports:
- port: 5000
targetPort: 5000
selector:
app: registro
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# Añado el cluster-issuer definido para letsencrypt
cert-manager.io/cluster-issuer: letsencrypt-production
# Añado para eliminar el límite de tamaño de las imágenes que se pueden
# subir al registry
nginx.ingress.kubernetes.io/proxy-body-size: "0"
name: registro
namespace: registro
spec:
rules:
- host: tudominio.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: registro
port:
number: 5000
tls:
- hosts:
- tudominio.com
# En este certificate cert-manager guarda el certificado.
# kubectl get certificate -n motioneye
secretName: registro-cert
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: registro
namespace: registro
labels:
app: registro
spec:
replicas: 1
selector:
matchLabels:
app: registro
template:
metadata:
labels:
app: registro
spec:
volumes:
- name: nfs-registro-var-lib
nfs:
server: nfs-server
path: /DPVs/registro/var-lib-registry
readOnly: false
- name: nfs-registro-auth
nfs:
server: nfs-server
path: /DPVs/registro/auth
readOnly: false
- name: localtime
hostPath:
path: "/etc/localtime"
containers:
- image: registry:2
name: registro
imagePullPolicy: IfNotPresent
env:
- name: REGISTRY_AUTH
value: "htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "Registry Realm"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"
ports:
- containerPort: 5000
volumeMounts:
- name: nfs-registro-var-lib
mountPath: /var/lib/registry
- name: nfs-registro-auth
mountPath: /auth
Sólo te queda el consiguiente apply del fichero anterior y, ya estaría! (0‿~).