Desplegar aplicaciones en Kubernetes con Helm

2
347

Índice de contenidos

​1.​ Introducción

En este tutorial vamos a ver cómo utilizar Helm para desplegar aplicaciones en Kubernetes partiendo de cualquier rango de conocimiento de Kubernetes, ya seamos principiantes o maestros de Kubernetes. En este tutorial mencionaré algunos conceptos avanzados de Kubernetes, si no conoces esos conceptos no pasa nada, no es necesario para entender el tutorial.

Hacer un despliegue en Kubernetes de una aplicación, aunque la conozcamos, es laborioso al tener que partir de cero y definir en distintos ficheros todos los componentes de esa aplicación de cara a utilizarlo. Esta tarea es además muy compleja si no se tiene ni idea de cómo funciona internamente Kubernetes y qué clase de recursos hay que definir para conseguir el funcionamiento esperado de la aplicación.

Si tenemos conocimientos básicos de Kubernetes nos podemos hacer muchas preguntas sobre cómo abordar la tarea. 

¿Es mejor desplegar los pods directamente, o mejor hacer un replicaSet que se encargue de ellos? 

¿Es mejor hacer un deployment de Kubernetes que defina el replicaSet que se encargue de desplegar y mantener constante el número de pods deseados? 

¿Y si en vez de un deployment debo de hacer un daemonSet y que haya un pod único en cada nodo?

¿A lo mejor es más útil un Stateful Set para facilitar la persistencia de la información de los pods?

Lo mas seguro es que se acabe buscando en un tutorial para desplegar esa aplicación en Kubernetes como este https://www.adictosaltrabajo.com/2018/11/21/configurar-nginx-ingress-en-k8s/, que casualmente usa Helm para el despliegue. 

Si el tutorial usa kubectl, habrá que utilizar los ficheros que otra persona ya haya hecho previamente, teniendo que ejecutar cada fichero con la definición del recurso de Kubernetes uno a uno con kubectl apply y esperando que las variables definidas en el fichero consigan desplegar correctamente la aplicación. 

Cuantas más aplicaciones están desplegadas en Kubernetes más complicado es mantenerlas y gestionarlas si hemos tenido que desplegar los ficheros de Kubernetes uno a uno con kubectl, ya que para hacer cambios habría que volver a desplegar todos los ficheros afectados y para eliminar el despliegue hay que ejecutar otra vez múltiples comandos de kubectl. Helm simplifica la tarea haciendo más rápidos y mantenibles los despliegues.

​2.​ ¿Que es Helm?

Helm es el gestor de paquetes (package manager) de Kubernetes. Ayuda a manejar el despliegue de aplicaciones en Kubernetes. Helm es un proyecto de la CNCF y está mantenido por la comunidad de helm. 

Helm ofrece un marco de referencia de un despliegue de una aplicación en Kubernetes, evitando que tengamos que pensar desde 0 cómo montar el despliegue. Se apoya en el trabajo de la comunidad que se ha tenido que enfrentar a esas preguntas y combina las soluciones y procedimientos que conjuntamente hayan logrado. Evoluciona gracias a la compartición de conocimiento y por ese mismo motivo está abierto a cualquier sugerencia de mejora, ya sea en forma de issue que detectemos o en forma de pull request para añadir funcionalidad a la ya existente.

​2.1.​ Ventajas de Helm

Con solo ejecutar un comando de Helm podemos hacer las siguientes operaciones sobre un chart: instalar, actualizar, desinstalar, hacer rollback a otra versión, listar todos los charts desplegados. Helm se encarga de contactar con la API de Kubernetes y hacer lo necesario, lo cual nos abstrae de entrar en detalles técnicos de cada chart. 

Para desplegar aplicaciones en Kubernetes en Helm existe el concepto de chart. Todos los charts oficiales de Helm garantizan que su despliegue en Kubernetes funciona sin tener que configurar ningún valor. Esto no quiere decir que podemos desplegar un chart de Helm tal cual y ya está todo el trabajo hecho. En la mayoría de casos tendremos que leer la documentación del chart y hacer algunos cambios para que el despliegue de la aplicación sea el deseado para el uso que vayamos a darle.

​2.2.​ Versiones de Helm

Actualmente la última mayor versión de Helm es Helm 3. Esta versión tiene diferencias sustanciales con Helm 2 y no son totalmente compatibles, por ello los clusters de Kubernetes que usen Helm 2 van a tener que acabar emigrando a Helm 3 puesto que en noviembre de 2020 ya no se dará soporte a Helm 2.

En otro tutorial abordaré las principales diferencias entre Helm 2 y 3 y cómo hacer la migración entre las versiones. 

​3.​ ¿Qué son los charts de Helm y qué los componen?

Helm usa un formato de empaquetado llamado charts. Un chart es una colección de archivos que describen un conjunto relacionado de recursos de Kubernetes. Los charts de Helm ayudan a definir un marco común de uso básico de la aplicación y todas las configuraciones posibles. Se puede usar un solo chart para implementar algo simple, como un pod memcached, o algo complejo, como una pila completa de aplicaciones web con servidores HTTP, bases de datos, cachés, etc.

​3.1.​ Estructura de los charts

Los charts se agrupan como un directorio con los archivos en forma de árbol. Este directorio se empaquetará en un archivo versionado listo para ser desplegado. El nombre del directorio es el nombre del chart (sin información de versión). Por lo tanto, una chart que describe Nginx-ingress se almacenaría en el directorio nginx-ingress/.

Dentro de este directorio, Helm esperará una estructura que coincida con esto:

Helm reserva el uso de los directorios charts/ , crds/ y templates/ además de los ficheros arriba nombrados. El resto de ficheros o directorios que pueda haber en el chart no serán utilizados por Helm. 

Para simplificar la tarea de ver cómo funciona Helm sin abrumar con todas las opciones configurables que existen, solo vamos a profundizar en los ficheros y el directorio obligatorios que cada chart tiene que tener.

​3.1.1.​ Fichero Chart.yaml

Este fichero contiene muchos valores opcionales como las dependencias de este chart con otros charts o las personas que se encargan de mantener el chart (útil para los charts en repositorios públicos mantenidos por la comunidad), etc. Vamos a obviar esos valores y centrarnos en los que son obligatorios que siempre vamos a ver en el fichero. Estos son:

El campo apiVersion tendrá el valor v2 si el chart requiere Helm 3 y v1 si el chart se puede usar con versiones anteriores de Helm, incluido Helm 3. 

El campo appVersion no tiene nada que ver con el campo version. Por ejemplo, si el chart contiene elasticsearch, se puede especificar que usa la versión 7.6.1 de elasticsearch aunque la versión del chart sea la 1.2.3. 

​3.1.2.​ Directorio Templates

Las plantillas de los charts de Helm están escritas en el lenguaje de plantillas de Go, con la suma de 50 funciones de plantilla adicionales de la biblioteca Sprig y algunas otras funciones especiales.

Todos los archivos de plantilla se almacenan en este directorio. Cuando Helm procesa los charts, pasará todos los archivos de ese directorio a través del motor de plantillas.

Los valores para las plantillas se proporcionan de dos maneras:

  • Los desarrolladores de charts pueden proporcionar un archivo llamado values.yaml dentro del chart. Este archivo contiene los valores predeterminados.
  • Los usuarios de charts pueden proporcionar uno o varios archivos YAML que contenga valores. Estos ficheros se pueden proporcionar con un flag en la línea de comandos de Helm al instalar o actualizar un chart.

Cuando un usuario proporciona valores personalizados, estos valores anularán los valores por defecto en el archivo values.yaml del chart.

La cantidad de ficheros de la carpeta templates es variable, depende del objetivo del chart y lo que se necesite. Como ejemplos de lo que puede haber dentro de la carpeta templates y de los muchos o pocos ficheros que la pueden componer, están estos 2 charts oficiales, publicados en el repositorio público de charts de GitHub. Nginx-ingress contiene más de 30 ficheros: https://github.com/helm/charts/tree/master/stable/nginx-ingress/templates. En cambio Cerebro solo contiene 6 ficheros: https://github.com/helm/charts/tree/master/stable/cerebro/templates

​3.1.3.​ Fichero Values.yaml

Los valores de este fichero dependen exclusivamente de las variables de Helm que hayamos utilizado en los ficheros dentro del directorio Templates. Values.yaml tiene que contener todos los valores necesarios para esas variables de tal forma que se pueda usar el chart sin tener que modificar ninguna variable. 

​3.2.​ Versionado de los charts

Cada chart debe tener un número de versión. Todas las versiones deben seguir las reglas del estándar de versionado semántico 2.0.0 (SemVer 2). Helm usa los números de versión como indicador de los despliegues. Los paquetes en repositorios se identifican por nombre más versión.

Por ejemplo, un chart de nginx-ingress cuya versión sea la 1.2.3, una vez empaquetado tendrá el siguiente nombre: nginx-ingress-1.2.3.tgz

​4.​ Configurando Helm

Para usar Helm necesitamos tener un cluster de Kubernetes, kubectl instalado y configurado y descargar Helm. La versión que tenga el cluster de Kubernetes o de kubectl no es lo importante puesto que Helm funciona sin problemas con las versiones de Kubernetes superiores a la 1.6. A fecha del tutorial Kubernetes está en la versión 1.18, con lo que si se da el caso de que tienes el cluster en una versión inferior a la 1.6 (12 versiones por debajo de la última), habría que actualizarlo a una versión más reciente.

Asumo que ya tenemos el cluster de Kubernetes y kubectl listo para usar Helm. 

Importante: Helm siempre apuntará al cluster de Kubernetes al que apunte kubectl. En cualquier momento en el que se cambie el cluster al que apunta kubectl, Helm cambiará y apuntará a ese cluster.

Para saber qué cluster de Kubernetes es al que apunta Helm ejecuta

​4.1.​ Instalando Helm

Así que vamos a instalar Helm. Las releases de Helm se pueden encontrar aquí: https://github.com/helm/helm/releases

Si contáis con un sistema gestor de paquetes para vuestro sistema operativo, instaladlo con él, si no podéis acceder al link y seguir los pasos para instalarlo.

En mac uso homebrew, con él instalar Helm es tan sencillo como escribir en la consola

Con este comando tal cual instalaremos la última versión de Helm, que es la 3.x.x. Si estás trabajando en un proyecto que maneja un cluster de Kubernetes con Helm 2, tendrás que instalar la versión 2 de Helm puesto que no son retrocompatibles. 

Para poder usar Helm 2 después de instalarlo, tendrás que ejecutar el comando 

para que cree todas las carpetas en el ordenador necesarias para usar Helm. Esta parte la hacen en Helm automáticamente sin tener que ejecutar nada.

Recomiendo que si es tu primera vez, uses Helm 3 y te olvides de Helm 2.

Para comprobar que Helm se ha instalado correctamente solo hay que escribir

​4.2.​ Añadiendo repositorios a Helm

Ya instalado, necesitamos añadir a Helm los repositorios donde están los charts de Helm que vamos a usar.

Esto se hace fácilmente con

Por ejemplo, si queremos añadir el repositorio stable (contiene la mayoría de charts oficiales), alojado en esta url https://Kubernetes-charts.storage.googleapis.com/, el comando quedaría

Siempre después de añadir un repositorio a Helm hay que ejecutar el comando repo update para que Helm recargue la configuración de los repositorios. Hasta que no se ejecute ese comando, Helm no tendrá en cuenta los repositorios añadidos. 

Ayuda: Siempre que Helm muestre un problema con los repositorios, ejecutad helm repo update para que se vuelva a cargar la configuración y se solucione.

Nota Importante: el 13 de Noviembre de 2020, coincidiendo con la muerte de Helm 2, marcaran los repositorios stable e incubator como obsoletos, esto quiere decir que todos los charts que ahora están alojados en stable e incubator se moverán a otros repositorios que habrá que añadirlos con el comando de arriba. Helm ya recomienda buscar los charts en Helm Hub. Dentro de Helm Hub están todos los charts con soporte y las instrucciones para añadir los nuevos repositorios e instalar cada chart.

Para asegurarnos que se ha añadido bien el repositorio y ver los distintos repositorios añadidos a Helm podemos ejecutar

5. Desplegar una aplicación en Kubernetes con Helm

Ya tenemos Helm listo. Vamos a desplegar una aplicación en Kubernetes. Si no sabemos el repositorio en el que está el chart de la aplicación que queremos desplegar, podemos pedir a Helm que nos indique en qué repositorios hay un chart de esa aplicación haciendo una búsqueda en Helm Hub (agregador de todos los repositorios de charts de Helm) por el nombre:

Si en vez de buscar por el hub, queremos buscar por un repositorio que ya hayamos añadido a Helm, podemos modificar el comando para buscar en ese repo:

5.1.​ Instalar aplicaciones con Helm

Si sabemos el nombre del chart y el repositorio donde está, solo tenemos que añadirlo a Helm y ejecutar el siguiente comando para instalarlo sin configurar nada. El namespace por defecto en el que Helm instalará el chart será “default”.​

Como ejemplo voy a usar nginx-ingress

Hemos visto la forma básica y rápida de instalar, ahora vamos a ver las opciones que más frecuentemente vamos a tener que añadir al comando de Helm para personalizar la instalación y adaptarla a nuestras necesidades. Helm nos ofrece bastantes flags para usar en sus comandos de instalación. 

Los más útiles en mi opinión son -n y -f. Con -n podemos decirle a Helm el namespace de Kubernetes en el que se va a desplegar todos los componentes del chart. Un namespace es una división lógica de Kubernetes, no es obligatorio usar varios, sí recomendable, más info.

El namespace a usar en Helm tiene que haber sido creado previamente en Kubernetes. Para crear un namespace en Kubernetes con ejecutar el siguiente comando podemos hacerlo. 

Con -f podemos especificarle ficheros de valores, en formato yaml, que sobreescribiran los valores por defecto del fichero values.yaml del que antes he hablado. Podemos usar el flag -f tantas veces queramos en el mismo comando. En el caso de que un valor aparezca varias veces, Helm prioriza los valores del último flag -f que aparezca sobre el resto de valores, sobreescribiéndolos.

Ahora vamos a ver un ejemplo de cómo usar estos flags con el comando install de antes:

Aquí le estamos indicando a Helm que nos instale nginx-ingress en el namespace ingress, para tener este despliegue separado de otras aplicaciones que tengamos en otro namespace. Además estamos sobreescribiendo los valores por defecto primero con el contenido del fichero common.yaml y luego con el contenido del fichero environment.yaml.

Esta separación de ficheros es útil cuando tienes múltiples entornos donde desplegar la aplicación y quieres tener unos valores generales para todos los entornos, que irá en el fichero common.yaml y luego tener un fichero distinto por entorno, este caso llamado environment.yaml en el que cambiar el nombre de certificados o cualquier valor específico de un entorno. Al tener varios ficheros reutilizamos todo lo posible lo genérico y hacemos más fácil de ver las diferencias.

​5.2.​ Actualizar aplicaciones con Helm

Ahora que hemos visto el comando install para desplegar aplicaciones en Kubernetes por primera vez, tengo una noticia que daros: este comando ya no lo uso. Hasta ahora no había comentado que el comando install sólo funciona si no hay una aplicación desplegada con ese mismo nombre. Si ya hay una, el comando dará error.  

Hay otro comando mejor que hace las funciones de este comando de install y a la vez actualiza el chart si se han introducido cambios nuevos, es el comando update.

Este comando añade el flag -i, que indica a Helm que si no encuentra el chart para actualizarlo, lo que queremos es que Helm lo instale. Si solo queremos la actualización del comando, quitad el flag y Helm dará error si el chart no está desplegado.

Lo más fácil es dejar siempre el flag -i y utilizar el comando update para ambos usos.

Otros flags que pueden ser útiles y que se pueden utilizar tanto con install como con update son: 

  • –wait: Obliga a Helm a retrasar la notificación de éxito del despliegue hasta que Kubernetes le responda que los recursos necesarios han sido desplegados correctamente. Si algún recurso de Kubernetes no está listo, se espera hasta que esté listo o hasta que se alcance el timeout, que por defecto es de 5 minutos. En ese caso fallaría el comando ejecutado. Si no ponemos el flag, en cuanto Helm haya transmitido a Kubernetes correctamente la información para hacer el despliegue, Helm nos notificara que el despliegue es correcto, sin tener que ser realmente cierto y teniendo que ir a Kubernetes a comprobarlo.
  • –timeout: Permite modificar el timeout usado en el comando –wait. Solo tiene sentido usarlo junto a –wait, si wait no esta no se tendrá en cuenta el valor de este comando. Por defecto es de 5 minutos. El formato es número seguido de la unidad. Ejemplo 5m30s.
  • –set: Este comando permite configurar los valores de una variable del fichero values.yaml sin tener que usar un fichero aparte y el flag -f. Para hacer más fácil la gestión del cambio y saber los valores configurados en cada momento recomiendo usar el fichero y no usar este flag. Ejemplo de uso –set image.tag=1.0.0.

​5.3.​ Desinstalar aplicaciones con Helm

Además de instalar con Helm 3, desinstalar un chart es muy sencillo. Con solo poner el nombre del despliegue y el namespace en el que está desplegado Helm, se encarga de borrar lo necesario (ciertos config maps, secretos, pvc y pv asociados al chart no se borrarán) para no dejar rastro de la aplicación.

Si estáis usado Helm 2 (habría que cambiar a Helm 3) el comando análogo sería:

Con estos comandos tenéis la funcionalidad básica de Helm para desplegar aplicaciones en Kubernetes. 

​6.​ Conclusión

Como hemos visto, Helm nos facilita la vida al trabajar con Kubernetes y nos da la flexibilidad de poder configurar cada despliegue a nuestro antojo. También es una herramienta genial para poder compartir al mundo implementaciones propias de despliegues y permitir que evolucionen hasta se conviertan en estándar. Desplegar aplicaciones en Kubernetes nunca fue tan fácil.

Una vez lo hayáis probado estoy seguro que nunca más desplegareis una aplicación con kubectl sin antes buscar si hay un chart de Helm de esa aplicación. 

2 Comentarios

  1. Como manejar diferentes certificados para los distintos ambientes, tenemos distintos dominios para integracion, qa, pre-produccion y produccion?

Dejar respuesta

Please enter your comment!
Please enter your name here