Dado un escenario en el que necesita agregar algunos archivos binarios en un pod de Kubernetes que ejecuta una imagen docker, ¿cómo podría lograrlo? El primer enfoque podría ser modificar la imagen de docker y crear una nueva imagen personalizada encima de la “existente”, agregando una nueva capa que incluya los nuevos archivos binarios, descargando, instalando los paquetes y creando esa nueva imagen. Finalmente, usemos la nueva imagen personalizada.
Ese enfoque es válido y útil en la mayoría de los casos, pero ¿qué pasa con una situación en la que es necesario hacerlo sin crear una nueva imagen? ¿Es eso posible? Sí, existe una pequeña solución sucia para lograrlo, mediante el uso de un Init Container, donde los binarios se descargan, se instalan y finalmente se comparten como un volumen en el “contenedor principal” del pod.
En otras palabras, “inyectará” los binarios en el “contenedor principal” del pod delegando a otro contenedor el descargarlos y ponerlos a disposición en una ubicación compartida con el “contenedor principal”. La imagen de docker del “contenedor principal” se mantuvo sin ningún cambio.
Comencemos con la definición del pod para el contenedor principal.
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deployment spec: template: spec: containers: - name: my-app-container image: "my-app-image:latest"
For some use case, it’s required to have some binaries available on the pod but the image should not be modified. For example, adding a tool in the environment for monitoring, logs, creating some statistics, the cases will vary depending on the needs. – And remember modifying the existing docker image is not an option -.
Para algunos casos de uso, es necesario tener algunos archivos binarios disponibles en el pod, pero la imagen no debe modificarse. Por ejemplo, agregar una herramienta en el entorno para monitoreo, registros, crear algunas estadísticas, los casos variarán según las necesidades. – Y recuerde que modificar la imagen de la ventana acoplable existente no es una opción –.
El siguiente código es un ejemplo de un Init Container en un pod que descarga algunos archivos binarios.
spec: template: spec: initContainers: - name: download-additional-tools image: alpine:3.15 command: - sh - -c args: - echo Downloading additional tools; wget -O /tools/another-tool https://another-tool.com/releases/download/v42.0.1/another-tool-amd64; chmod 755 /tools/another-tool; echo Finished downloading;
¡Bien! pero el contenedor principal todavía no tiene acceso a esos binarios. Esto se puede hacer agregando un volumen al pod y el volumen se monta en los contenedores, compartiendo la ubicación donde se descargó el binario con el contenedor principal.
spec: template: spec: volumes: - name: tools emptyDir: {} initContainers: - name: download-additional-tools .... volumeMounts: - mountPath: /tools name: tools containers: - name: my-app-container ... volumeMounts: - mountPath: /usr/local/bin/another-tool name: tools subPath: another-tool
Crea un nuevo volumen llamadotools
de tipo emptyDir
(directorio temporal que se crea con el pod y su contenido se elimina cuando se elimina el pod). Tanto el Init Container
como el principal compartieron el volumen tools
, por lo que el “contenedor principal” puede acceder en la ubicación /usr/local/bin/another-tool
a lo que sea que el “contenedor init” contenga en la ubicación /tools/
.
Veamos el archivo yaml completo para el pod de Kubernetes.
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deployment spec: template: spec: volumes: - name: tools emptyDir: {} initContainers: - name: download-additional-tools image: alpine:3.15 command: - sh - -c args: - echo Downloading additional tools; wget -O /tools/another-tool https://another-tool.com/releases/download/v42.0.1/another-tool-amd64; chmod 755 /tools/another-tool; echo Finished downloading; volumeMounts: - mountPath: /tools name: tools containers: - name: my-app-container image: "my-app-image:latest" volumeMounts: - mountPath: /usr/local/bin/another-tool name: tools subPath: another-tool
Listo, al aplicar los cambios a la implementación se creará un nuevo pod que incluirá los binarios sin modificar la imagen de docker original.
kubectl patch deployments/myapp-deployment --patch-file=deployment-patch.yaml
Al verificar en el pod, los binarios deberían estar disponibles para el contenedor principal.