Herramientas para Terraform
Código Espagueti, el «anti patrón» de programación

Ejecutar Charts de Helm con helmfile

helmfile

¿Alguna vez te has preguntado cómo lograr un enfoque completo de IaC (Infraestructura como Código) para el despliegue de tus aplicaciones en el clúster Kubernetes? No importa si ya lo has conseguido o acabas de empezar a buscar la mejor herramienta, helmfile puede ser un gran aliado. En este post veremos cómo configurar un helmfile.

Antes de empezar con helmfile lo mejor es ver algo de Helm:

Guía-Tutorial Kubernetes – Helm: Control de despliegues

Apuntes de Curso Helm

La imagen de abajo presenta la solución objetivo. Dentro del cluster se desplegará el frontend (kanban-ui) y el backend (kanban-app). Para la persistencia de los datos se utilizará la base de datos Postgres. El código fuente de ambos microservicios se puede encontrar en el repositorio de GitHub – kanban-board.

Estructura helmfile a desplegar

Además está añadida la aplicación adminer, que es un cliente GUI para entrar en la base de datos.

La imagen anterior no sólo muestra las aplicaciones que se desplegarán en el clúster Kubernetes, sino también los objetos que se requieren para ejecutarlas, como Deployments o Services. Con el enfoque clásico, kubectl, nos vimos obligados a crear archivos de definición para cada uno de ellos. Incluso si en la mayoría de los casos, por ejemplo en el caso de ClusterIPs, estos objetos no difieren mucho entre aplicaciones.

Definitivamente, este enfoque no es escalable en el mundo de los microservicios, donde por lo general hay una necesidad de desplegar docenas o incluso cientos de aplicaciones. Y si para cada una de ellas tuviéramos que crear un par de archivos YAML, se convertiría rápidamente en una pesadilla. Pero este problema podría resolverse con el motor de plantillas de Kubernetes – Helm. Podemos definir una chart genérico Helm (plantilla) y reutilizarlo a través de múltiples aplicaciones sólo mediante la inyección de valores específicos en la plantilla.

Hasta cierto punto está resuelto el problema, pero hay un inconveniente en el uso de Helm. Para instalar o actualizar cualquier chart en un cluster es necesario ejecutar un comando imperativo específico. En otras palabras, para cambiar el estado de un cluster necesitas ejecutar un comando que es específico para un despliegue dado.

En el mundo Java se usa Maven o para JavaScript se usa npm. Ambas herramientas permiten ejecutar el mismo comando a través de múltiples proyectos para realizar la misma acción como ejecutar tests- mvn test. Helm actualmente no soporta esta característica, no somos capaces de instalar, actualizar o revertir todas las aplicaciones de un cluster entero con un solo comando.

Pero existe helmfile, que podría ser un remedio.

¿Qué es helmfile?

Helmfile permite declarar una definición de todo un clúster Kubernetes en un único archivo YAML, agrupa múltiples releases de Helm (instalación de charts de Helm) y permite ajustar una especificación de cada release en función de un tipo de entorno (desarrollo, pruebas, producción) en el que es posible que desee desplegar sus aplicaciones.

Puedes ver en su repositorio oficial la potencia que tiene.

Requisitos y preparación para el tutorial helmfile

Lo mejor sería mostrar cómo funciona en un ejemplo. Antes de eso tenemos que configurar un entorno de trabajo. Si quieres seguir los pasos, necesitarías instalar y configurar:

Cuando todo esté instalado, puede iniciar el clúster minikube y habilitar el complemento ingress:

minikube start
😄  minikube v1.8.1 on Ubuntu 18.04
✨  Automatically selected the docker driver
🔥  Creating Kubernetes in docker container with (CPUs=2) (8 available), Memory=2200MB (7826MB available) ...
🐳  Preparing Kubernetes v1.17.3 on Docker 19.03.2 ...
▪ kubeadm.pod-network-cidr=10.244.0.0/16
❌  Unable to load cached images: loading cached images: stat /home/wojtek/.minikube/cache/images/k8s.gcr.io/kube-proxy_v1.17.3: no such file or directory
🚀  Launching Kubernetes ...
🌟  Enabling addons: default-storageclass, storage-provisioner
⌛  Waiting for cluster to come online ...
🏄  Done! kubectl is now configured to use "minikube"$ minikube addons enable ingress
🌟  The 'ingress' addon is enabled

A continuación, tendrás que editar el archivo hosts. Su ubicación varía según el sistema operativo:

Ubuntu
Windows
MacOS

Se debe añadir las siguientes líneas:

172.17.0.2  adminer.k8s.com
172.17.0.2  kanban.k8s.com

Para asegurar de que esta configuración es correcta en minikube se comprueba si la dirección IP del cluster es la misma que la de arriba con el comando:

minikube ip
</pre

Adaptando una chart de Helm a helmfile

Vamos a reutilizar Charts de Helm para el proyecto Kanban Board del tutorial «How to deploy application on Kubernetes with Helm«. Por lo tanto copia y pega todos los archivos de aquí: k8s-helm-helmfile/helm.

Todas las carpetas – app , ingress , postgres – poner dentro de una nueva llamada charts y todos los archivos YAML poner dentro de una nueva carpeta llamada values. A continuación, añadir un nuevo archivo helmfile.yaml a un directorio raíz, por lo que la estructura resultante se verá como sigue:

Estructura charts helm

Vamos a ver brevemente lo que significa cada una de estas carpetas:

  • ./charts – aquí están los tres charts de Helm que son plantillas para cada release – app (para adminer, kanban-ui, kanban-app), postgres e ingress
  • helmfile.yaml – aquí habrá una configuración para un helmfile, actualmente en blanco
  • ./values – una carpeta con valores específicos para cada aplicación que se desplegará.

Antes de pasar a rellenar un helmfile.yaml quiero ajustar una cosa. En una solución anterior, nativa de Helm, hay un chart ingress, que tiene una dependencia con el chart de Helm nginx-ingress disponible en Helm Hub. Antes de instalarlo en un cluster necesitábamos descargarlo (se guardará en la carpeta .charts/ingress/charts) usando un comando helm separado.

Si utilizamos helmfile, el último paso no sería necesario, porque averiguará y descargará todas las dependencias necesarias dentro de cada chart. Así que podríamos mantener ingress chart como es, pero me gustaría tener un enfoque diferente esta vez. Me gustaría tratar el chart nginx-ingress como una release separada de Helm, aparte de la configuración del Controlador Ingress para el enrutamiento.

Por lo tanto, elimina las siguientes líneas del archivo ./charts/ingress/Chart.yaml:

dependencies:
    - name: nginx-ingress
      version: 1.36.0
      repository: https://charts.helm.sh/stable

También puedes eliminar el archivo Chart.lock por completo.

Después de esos cambios el chart de Helm Ingress es responsable sólo de definir el Controlador Ingress. El servicio backend Ingress requerido se introducirá con la release de Helm.

Ahora, finalmente podemos pasar a organizar un helmfile.yaml.

Primero necesitamos indicar de qué repositorios Helm queremos descargar los charts. Debido a que vamos a descargar sólo uno – stable/nginx-ingress – chart de un único repositorio, ponemos una entrada:

repositories:
    - name: stable
      url: https://charts.helm.sh/stable

Entonces podemos pasar a la siguiente sección – definir las releases de Helm. Contendrá una lista de todas las aplicaciones que helmfile necesitará desplegar. Empezando por la primera – postgres:

releases:
    - name: postgres
      chart: ./charts/postgres
      values:
          - ./values/kanban-postgres.yaml

No hay mucho aquí, pero para esclarecer:

– name – es el nombre de la release, podemos llamarla como queramos,
– chart – le dice a helmfile donde se encuentra el chart base de Helm,
– values – porque estamos usando una plantilla de chart Helm, nos gustaría inyectarle algunos valores, así que aquí hay una lista de archivos YAML que los contienen.

Ahora vamos a definir los lanzamientos que se basan en el chart de la aplicación:

releases:
    - name: adminer
      chart: ./charts/app
      values:
          - ./values/adminer.yaml    - name: kanban-app
      chart: ./charts/app
      values:
          - ./values/kanban-app.yaml    - name: kanban-ui
      chart: ./charts/app
      values:
          - ./values/kanban-ui.yaml

Y a continuación, definimos un release Helm para un backend Ingress, que se descargará de un repositorio público:

releases:
    - name: ingress-backend
      chart: stable/nginx-ingress
      version: 1.36.0

En chart proporcionamos información de qué chart queremos descargar e instalar. El prefijo stable/ es el nombre de un repositorio que se ha definido antes.

En versión especificamos qué versión de un chart utilizar. No tiene perdida.

Y por último una definición para la release de Ingress Controller Helm:

releases:
    - name: ingress-controller
      chart: ./charts/ingress
      values:
          - ./values/ingress.yaml

Con lo cuál, el helmfile.yaml definitivo tendrá el siguiente aspecto:

repositories:
  - name: stable
    url: https://kubernetes-charts.storage.googleapis.com

releases:
  - name: postgres
    chart: ./charts/postgres
    values:
      - ./values/kanban-postgres.yaml

  - name: adminer
    chart: ./charts/app
    values:
      - ./values/adminer.yaml

  - name: kanban-app
    chart: ./charts/app
    values:
      - ./values/kanban-app.yaml
  
  - name: kanban-ui
    chart: ./charts/app
    values:
      - ./values/kanban-ui.yaml

  - name: ingress-backend
    chart: stable/nginx-ingress
    version: 1.36.0

  - name: ingress-controller
    chart: ./charts/ingress
    values:
      - ./values/ingress.yaml

Desplegar helmfile

Si lo tenemos todo bien, ahora viene la parte divertida, con solo dos comandos podemos desplegar todas las aplicaciones.

Primero, tenemos que añadir el repositorio a nuestra instancia de Helm (sólo tendrás que hacerlo una vez):

helmfile repos
Adding repo stable https://charts.helm.sh/stable 
"stable" has been added to your repositoriesUpdating repo
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈

A continuación, instale todos los charts en un clúster:

helmfile sync
Adding repo stable https://charts.helm.sh/stable 
"stable" has been added to your repositoriesUpdating repo
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈Building dependency release=postgres, chart=charts/postgres
Building dependency release=adminer, chart=charts/app
Building dependency release=kanban-app, chart=charts/app
Building dependency release=kanban-ui, chart=charts/app
Building dependency release=ingress-controller, chart=charts/ingress
Affected releases are:
  adminer (./charts/app) UPDATED
  ingress-backend (stable/nginx-ingress) UPDATED
  ingress-controller (./charts/ingress) UPDATED
  kanban-app (./charts/app) UPDATED
  kanban-ui (./charts/app) UPDATED
  postgres (./charts/postgres) UPDATEDUpgrading release=postgres, chart=charts/postgres
Upgrading release=kanban-app, chart=charts/app
Upgrading release=adminer, chart=charts/app
Upgrading release=kanban-ui, chart=charts/app
Upgrading release=ingress-controller, chart=charts/ingress
Upgrading release=ingress-backend, chart=stable/nginx-ingress
Release "adminer" does not exist. Installing it now.
NAME: adminer
LAST DEPLOYED: Wed Apr 15 16:16:31 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: NoneListing releases matching ^adminer$
Release "kanban-ui" does not exist. Installing it now.
NAME: kanban-ui
LAST DEPLOYED: Wed Apr 15 16:16:31 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: NoneListing releases matching ^kanban-ui$
adminer default   1        2020-04-15 16:16:31.990139954 +0200 CEST deployed app-0.1.0 1.16.0Release "kanban-app" does not exist. Installing it now.
NAME: kanban-app
LAST DEPLOYED: Wed Apr 15 16:16:31 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: NoneListing releases matching ^kanban-app$
kanban-ui default   1        2020-04-15 16:16:31.968291217 +0200 CEST deployed app-0.1.0 1.16.0Release "postgres" does not exist. Installing it now.
NAME: postgres
LAST DEPLOYED: Wed Apr 15 16:16:31 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: NoneListing releases matching ^postgres$
kanban-app default   1        2020-04-15 16:16:31.958860307 +0200 CEST deployed app-0.1.0 1.16.0postgres default   1        2020-04-15 16:16:31.958951797 +0200 CEST deployed postgres-0.1.0 1.16.0Release "ingress-controller" does not exist. Installing it now.
NAME: ingress-controller
LAST DEPLOYED: Wed Apr 15 16:16:31 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: NoneListing releases matching ^ingress-controller$
ingress-controller default   1        2020-04-15 16:16:31.958844983 +0200 CEST deployed ingress-0.1.0 1.16.0Release "ingress-backend" does not exist. Installing it now.
NAME: ingress-backend
LAST DEPLOYED: Wed Apr 15 16:16:35 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The nginx-ingress controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace default get services -o wide -w ingress-backend-nginx-ingress-controller'An example Ingress that makes use of the controller:apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: nginx
    name: example
    namespace: foo
  spec:
    rules:
      - host: www.example.com
        http:
          paths:
            - backend:
                serviceName: exampleService
                servicePort: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
        - hosts:
            - www.example.com
          secretName: example-tlsIf TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: 
    tls.key: 
  type: kubernetes.io/tlsListing releases matching ^ingress-backend$
ingress-backend default   1        2020-04-15 16:16:35.070513181 +0200 CEST deployed nginx-ingress-1.36.0 0.30.0UPDATED RELEASES:
NAME                 CHART                  VERSION
adminer              ./charts/app             0.1.0
kanban-ui            ./charts/app             0.1.0
kanban-app           ./charts/app             0.1.0
postgres             ./charts/postgres        0.1.0
ingress-controller   ./charts/ingress         0.1.0
ingress-backend      stable/nginx-ingress    1.36.0

Después de unos minutos podrás entrar en http://kanban.k8s.com.

Conclusión

¡Y eso es todo! Muy simple y con el repositorio externo configurado y una lista de cada una de las releases de Helm en un solo archivo, que puede ser almacenado bajo el sistema de control de versiones ( git por ejemplo).

Y lo que es más importante, estas no son las únicas características de helmfile. Puedes encontrar más en la documentación oficial (Doc obsoleta).

Artículo original

Más apuntes

Invítame a un café con bitcoins:
1QESjZDPxWtZ9sj3v5tvgfFn3ks13AxWVZ

Bitcoins para café
También puedes invitarme a algo para mojar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Rellena este campo
Rellena este campo
Por favor, introduce una dirección de correo electrónico válida.
Tienes que aprobar los términos para continuar