En la entrada anterior, MinIO en Kubernetes, explicaba cómo desplegar MinIO en Kubernetes (de forma manual).
mc
se puede usar como herramienta de línea de comandos o como contenedor minio/mc
; sin embargo, en esta entrada veremos cómo usarlo en Jobs de Kubernetes para configurar el alias de un servidor de MinIO y crear un bucket.
En primer lugar, definimos un Persistent Volume Claim para almacenar la configuración del cliente de MinIO y no tener que configurarlo en cada ejecución.
La configuración de mc consiste en unos ficheros JSON, por lo que creamos un pvc de sólo 1 Mi.
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
namespace: minio
name: minio-config
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Mi
La configuración de mc se almacena en ~/.mc/
; como el usuario en el contenedor minio/mc
es root
, montamos el volumen en /root/.mc
.
Crear un alias para el servidor de MinIO
Para simplificar la interacción entre el cliente de MinIO y el servidor, podemos asociar un alias al endpoint de MinIO. Por defecto, el cliente de MinIO tiene definidos -aunque no están configurados- alias para Google Cloud Storage (gcs
), AWS S3 (s3
) y un sandbox público de pruebas (play
).
En nuestro caso, vamos a denominar minio
al servidor de MinIO desplegado en Kubernetes.
Definimos un Job para crear el alias:
---
kind: Job
apiVersion: batch/v1
metadata:
namespace: minio
generateName: mc-alias-set
spec:
template:
metadata:
labels:
app: minio
spec:
restartPolicy: Never
containers:
- name: mc-alias-set
image: minio/mc
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: minio-secret
key: minio-root-user
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: minio-secret
key: minio-root-password
command: ["mc"]
args: ["alias", "set", "minio", "http://minio:9000", "--debug"]
El Job se completa con éxito, pero el alias creado no contiene las credenciales de acceso a MinIO (debido a limitaciones de mc). Sigue leyendo…
Algunos detalles a destacar:
- El Job usa
metadata.generatedName
y nometadata.name
, lo que permite lanzar el Job múltipes veces, ya que en cada ejecución el Job tiene un nombre diferente. Si usasmetadata.name
, la segunda ejecución del Job falla porque ya existe un Job con el mismo nombre. - Al usar
metadata.generatedName
no puedes usarkubectl apply
para lanzar el Job; tienes que usarkubectl create
. - El nombre del alias está fijado (
minio
); se podría obtener el valor del alias añadiendo un campo adicional en el Secret del que obtenemos las credenciales, por ejemplo… - Si MinIO está desplegado en otro Namespace o fuera de Kubernetes, debes ajustar la URL de MinIO.
Limitaciones del cliente de MinIO
Revisando la documentación del cliente de MinIO mc MinIO Client Complete Guide, vemos que se indica que mc sólo acepta las credenciales como argumento o a través de standard input; es decir, no recoge las credenciales si se especifican como variables de entorno.
Al ejecutar el Job anterior, se crea el alias minio
, pero las credenciales están en blanco:
...
minio
URL : http://minio:9000
AccessKey :
SecretKey :
API :
Path : auto
...
Esto es debido al comportamiento actual de mc, ignorando las variables de entorno, aunque estén definidas.
Especificando las variables de entorno como argumentos del comando ejecutado por el Job anterior, tampoco funciona:
...
command: ["mc"]
args: ["alias", "set", "minio", "http://minio:9000", $MINIO_ROOT_USER , $MINIO_ROOT_PASSWORD ,"--debug"]
En este caso, $MINIO_ROOT_USER
y $MINIO_ROOT_PASSWORD
se interpretan como cadenas literales, no se sustituyen con los valores de las variables de entorno.
Tampoco funcionan el resto de opciones indicadas en la documentación: Pipe from STDIN, Specify temporary host configuration through environment variable, con export MC_HOST_<alias>=https://<Access Key>:<Secret Key>@<YOUR-S3-ENDPOINT>
).
Plan B: usar un script
Después de comprobar que no es posible configurar el alias usando directamente el cliente de MinIO mc, modificamos el comando ejecutado por el Job para ejecutar bash en el contenedor:
...
command: ["/bin/bash"]
args:
- "-c"
- "mc alias set minio http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD"
A través de los logs del Pod generado por el Job, vemos que de esta forma sí que se configura el alias para MinIO:
$ kubectl logs mc-alias-set-832smd-8md3l -n minio
...
minio
URL : http://minio:9000
AccessKey : ACCESSKEYEXAMPLE123
SecretKey : wdvb5rtghn76yujm
API : s3v4
Path : auto
...
Persistiendo la configuración del cliente de MinIO mc
Una vez hemos validado que el Job configura el alias para mc correctamente, modificamos la definición del Job para montar el PVC definido al principio del artículo; para ello, añadimos el bloque volumeMounts
montando el PVC en /root/.mc
:
...
volumeMounts:
- name: minio-config
mountPath: "/root/.mc"
...
También añadimos la referencia al volumen (en spec.template.spec
):
...
volumes:
- name: minio-config
persistentVolumeClaim:
claimName: minio-config
Para validar que la configuración del cliente de MinIO mc se guarda correctamente en el volumen creado, definimos un Job que consulte los alias definidos:
---
kind: Job
apiVersion: batch/v1
metadata:
namespace: minio
generateName: mc-alias-list-
spec:
template:
metadata:
labels:
app: minio
spec:
restartPolicy: Never
containers:
- name: mc-alias-list
image: minio/mc
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: minio-secret
key: minio-root-user
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: minio-secret
key: minio-root-password
command: ["mc"]
args: ["alias", "list", "--debug"]
volumeMounts:
- name: minio-config
mountPath: "/root/.mc"
volumes:
- name: minio-config
persistentVolumeClaim:
claimName: minio-config
En los logs del Job reconocemos la configuración del alias creado por el Job definido anteriormente:
$ kubectl logs mc-alias-list-9l9md-k6w2h -n minio
...
minio
URL : http://minio:9000
AccessKey : ACCESSKEYEXAMPLE123
SecretKey : wdvb5rtghn76yujm
API : s3v4
Path : auto
...
Crear un bucket en MinIO
Para crear el bucket desde un Job podemos usar la “sintaxis” del script o directamente el cliente de MinIO mc. Prefiero usar directamente el cliente de MinIO en este caso.
Copiamos la definición del Job para listar los alias y modificamos el comando y los argumentos para crear el bucket en MinIO:
kind: Job
apiVersion: batch/v1
metadata:
namespace: minio
name: mc-makebucket-velero-backups
spec:
template:
metadata:
labels:
app: minio
spec:
restartPolicy: Never
containers:
- name: mc-makebucket-velero-backups
image: minio/mc
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: minio-secret
key: minio-root-user
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: minio-secret
key: minio-root-password
command: ["mc"]
args: ["mb", "mino/velero-backups"]
volumeMounts:
- name: minio-config
mountPath: "/root/.mc"
volumes:
- name: minio-config
persistentVolumeClaim:
claimName: minio-config
En los logs del Job comprobamos que se ha creado el bucket correctamente:
$ kubectl logs mc-makebucket-velero-backup-fwxg7 -n minio
Bucket created successfully `minio/velero-backup`.
En este caso, en la definición del Job he usado metadata.name
y no metadata.generatedName
; la creación de un bucket sólo debe realizarse una vez. Si lanzamos de nuevo el mismo Job, como la definición no ha cambiado, el Job no se ejecuta de nuevo:
$ kubectl -n minio apply -f minio-mc-job-makebucket-velero-backups.yaml
job.batch/mc-makebucket-velero-backups unchanged