Agregar binarios a un Kubernetes Pod sin modificar la imagen de contenedor

Advertisements

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 –.

Advertisements

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.

Referencias

Advertisements

Leave a Reply

Your email address will not be published. Required fields are marked *