Índice de contenidos
- 1. Introducción
- 2. ¿Que es Helm?
- 3. ¿Qué son los charts de Helm y que los componen?
- 4. Configurando Helm
- 5. Desplegar una aplicación en Kubernetes con Helm
- 6. Conclusión
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://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.
Si quieres saber más sobre las principales diferencias entre Helm 2 y 3 y cómo hacer la migración entre las versiones puedes ver este otro tutorial.
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:
nginx-ingress/ Chart.yaml # Fichero YAML que contiene información sobre el chart LICENSE # OPCIONAL: Fichero plano que contiene la licencia del chart README.md # OPCIONAL: Fichero README del chart values.yaml # Valores de configuración por defecto del chart values.schema.json # OPCIONAL: Esquema JSON para forzar la estructura del fichero values.yaml charts/ # OPCIONAL:Directorio que contiene los charts de los que depende este chart. crds/ # OPCIONAL: Custom Resource Definitions (concepto de Kubernetes, más info) templates/ # Directorio de plantillas que combinado con el fichero values.yaml generan ficheros válidos de manifiesto de Kubernetes templates/NOTES.txt # OPCIONAL: Fichero plano de texto que contiene notas sobre el chart
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:
apiVersion: Versión de la API del chart (obligatorio). name: Nombre del chart (obligatorio) version: Versión del chart. Sigue las reglas del versionado semántico 2.0.0 (obligatorio) description: Descripción de una línea del proyecto (opcional) appVersion: La versión de la app que contiene este chart. (opcional). En cualquier formato.
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
kubectl config current-context
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
brew install helm
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
helm init --upgrade
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
helm version
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
helm repo add "nombreRepositorio" "urlRepositorio"
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
helm repo add stable https://Kubernetes-charts.storage.googleapis.com/ helm repo update
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
helm repo list
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:
helm search hub "nombre o parte del nombre del chart"
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:
helm search repo “nombre del repo” "nombre o parte del nombre del chart"
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”.
helm install “nombre en Kubernetes” “repositorio/nombre chart”
Como ejemplo voy a usar nginx-ingress
helm install nginx-ingress stable/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.
kubectl create namespace "nombre namespace"
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:
helm install nginx-ingress -n ingress -f common.yaml -f environment.yaml stable/nginx-ingress
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.
helm update -i -n ingress -f common.yaml -f environment.yaml nginx-ingress stable/nginx-ingress
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.
helm uninstall nginx-ingress -n ingress
Si estáis usado Helm 2 (habría que cambiar a Helm 3) el comando análogo sería:
helm delete nginx-ingress --purge
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.
Que bien!. Me viene de lujo , estoy justo ahora adentrándome en esta historia.
Como siempre gracias.
Como manejar diferentes certificados para los distintos ambientes, tenemos distintos dominios para integracion, qa, pre-produccion y produccion?