Depurando con contenedores efímeros en Kubernetes

Miguel Fontanilla
Computación en la nube
July 6, 2020

Depurando con contenedores efímeros en Kubernetes 

Seguro que alguna vez te has encontrado en una situación en la que un pod no funciona tal y como debería en un clúster de Kubernetes y te ha tocado depurarlo. En esta situación, el primer paso a seguir debería ser inspeccionar los logs del contenedor con el fin de entender qué es lo que puede estar fallando. Pero la experiencia nos dice que no todas las aplicaciones proporcionan logs útiles, y algunas, ni siquiera generan logs!

¿No hay logs? No hay problema: siempre queda la opción de conectarse al contenedor ejecutando kubectl exec para poder inspeccionar el proceso corriendo en el contenedor desde dentro. Pero puede ocurrir que la imagen no contenga herramientas de depuración, o ni siquiera un terminal para poder ejecutar comandos. Así que, ahora qué? 

Este es el momento en el que nos damos cuenta de que sería muy útil tener un contenedor auxiliar, lo que se conoce como 'sidecar', corriendo dentro del mismo pod que estamos intentando arreglar. De hecho, es una práctica habitual cuando la imagen o imágenes dentro de un pod, no pueden o no deben ser modificadas para añadirles herramientas de depuración. Sin embargo, esto implicaría que el contenedor auxiliar estaría ejecutándose siempre, consumiendo recursos, se utilice o no.

A partir de la versión v1.18, Kubectl permite crear contenedores efímeros y añadirlos a pods que ya estén corriendo en el clúster. Esto es especialmente útil para situaciones como la que venimos describiendo anteriormente.



kubectl alpha debug -it pod-name --image=busybox --target=pod-name

Desde un punto de vista de procesos, el comando desencadena la creación de un contenedor efímero que se añade al namespace de procesos del contenedor definido en el pod original.

Si no tienes muy claro lo que es el namespace de un proceso en Linux/Unix, puedes echarle un ojo a este artículo (Inglés). Resumiendo un poco: un proceso corriendo dentro de un namespace solo ve aquellos recursos y procesos dentro de ese mismo namespace, evitando así que acceda a recursos o procesos corriendo en otros namespaces (contenedores). Esta separación por medio de namespaces es gran parte de la magia que se esconde en los runtimes de contenedores modernos.

Así, al añadir el contenedor efímero al namespace del contenedor que queremos investigar, es posible inspeccionar los procesos dentro del namespace, utilizando una imagen de nuestra elección.

Para este ejemplo, el contenedor principal utiliza una imagen de nginx. En la captura de terminal inferior se puede ver cómo un contenedor efímero, basado en la imagen busybox es añadido al pod. Al inspeccionar los procesos desde el contenedor efímero, es posible ver los procesos del contenedor de nginx.

Si inspeccionas el pod de nuevo, utilizando el comando kubectl describe podverás que el nuevo contenedor efímero aparece en la especificación del pod de Kubernetes. En este caso, muestra un error ya que la sesión de depuración se cerró al terminar el shell utilizado para inspeccionar el contenedor.

Habilitando el uso de contenedores efímeros

Como podrás imaginarte, el nombre del comando no es casualidad. Se trata aún de una funcionalidad en fase alfa, y no viene activada por defecto en los clústers de Kubernetes. Para poder utilizar contenedores efímeros, es necesario añadir un flag específico a los elementos del plano de control de Kubernetes: API Server, Controller Manager, Scheduler y Kubelet. Si el clúster en cuestión se creó utilizando kubeadm, puedes encontrar los manifiestos a modificar de los tres primeros elementos en /etc/kubernetes/manifests en los master nodes. Añade la siguiente línea a los argumentos del comando de arranque de cada componente.



- --feature-gates=EphemeralContainers=true

Puedes tomar como referencia el fichero de configuración del API Server: kube-apiserver.yaml. Al añadir el flag, el fichero de configuración del API Sever debe quedar parecido a los ejemplos que se muestran a continuación. Repite el mismo proceso para el Controller Manager y el Scheduler.



spec:
  containers:
  - command:
    - kube-apiserver
    - .....
    - .....
    - --feature-gates=EphemeralContainers=true

Con el Kubelet, la cosa se complica un poco más, ya que es el único componente del plano de control que no puede correr dentro de un contenedor, pues es la pieza que interactúa con el runtime y lanza los contenedores. El Kubelet es gestionado mediante systemd, por lo que tendrás que chequear el fichero de configuración del servicio /etc/systemd/system/kubelet.service.d/10-kubeadm.conf tanto en los nodos worker y master . En este fichero, busca la variable EnvironmentFile, ya que ésta indica dónde se definen las variables adicionales para el Kubelet y los ficheros de configuración utilizados. En este caso, los flags adicionales se definen en /var/lib/kubelet/kubeadm-flags.env.

Añade el flag de los feature gates para contenedores efímeros en /var/lib/kubelet/kubeadm-flags.env.

Finalmente, es necesario reiniciar el servicio de Kubelet.



sudo service  kubelet restart

Una vez que el flag ha sido añadido, y el Kubelet ha sido reiniciado, se puede comprobar si el proceso ha arrancado correctamente inspeccionándolo.

IMPORTANTE

Si el clúster se instaló sin utilizar la herramienta kubeadm (lo que se conoce como una instalación de Kubernetes 'The Hard Way'), el API Server, Controller Manager y Scheduler corren como procesos controlados por systemd y no dentro de contenedores. Por lo tanto, para activar el feature gate de los contenedores efímeros, tendrás que inspeccionar los ficheros de configuración de cada servicio.


Miguel Fontanilla

DevOps/Cloud Engineer at Orange. Cloud Architecture, Virtualization, Services Orchestration, Automation and Optimization. Always learning.

Related Posts

Boletin informativo SpainClouds.com

Thank you! Your submission has been received!

Oops! Something went wrong while submitting the form