Helm v3 para desplegar PowerDNS sobre Kubernetes

En el artículo PowerDNS sobre Docker o Podman, fácil y rápido dejamos un punto pendiente sobre Kubernetes, esto es así porque la estructura de servicios de Kubernetes es mucho más compleja que la de Docker o Podman y por tanto hay que hacer un planteamiento completamente diferente.

Helm v3 para desplegar PowerDNS sobre Kubernetes 1

Empaquetar con Helm v3

Lo primero que debemos tener en mente es empaquetar aplicaciones para que su despliegue no requiera de amplios conocimientos sobre Kubernetes (hacer la vida al usuario más fácil) y lo segundo es que podemos tener muchos usuarios sobre el mismo entorno deseando querer la misma aplicación y no podemos crear un paquete para cada uno, debemos poder reutilizar el paquete creado.

En Kubernetes el estándar de paquetes es Helm que nos va a permitir gestionar despliegues de forma fácil y siendo reutilizables por usuario, proyecto, etc. El paquete Helm está formado por:

  • Chart.yaml: Que es la metainformación sobre el propio paquete.
  • templates: Carpeta donde vamos a definir los objetos que van a ser desplegados en Kubernetes, pero que van a tener ciertas modificaciones para que sean flexibles.
  • values.yaml: En los objetos a desplegar existirán una serie de variables que habrán de definirse (p.e. servidores a los que acceder, claves de acceso, bases de datos en un servidor, etc), en este fichero se definen los valores predefinidos de cada variable, para que posteriormente el usuario que lance el paquete pueda ajustarlo a su gusto.
  • NOTES.txt: Dentro de “templates” se coloca este archivo que contendrá un mensaje sobre el resultado de la instalación del paquete, como puede ser como obtener la IP o URL de acceso.
  • _helpers.tpl: Este archivo que también encontraremos dentro de la carpeta “templates” contiene definiciones de variables que podremos usar en las objetos, como es por ejemplo el nombre del paquete correctamente definido y que nos permitirá realizar múltiples despliegues de la misma aplicación en el mismo espacio de nombres simplemente cambiando el nombre de versión del despliegue.

Helm v3 es la versión en desarrollo de Helm (en el momento de escribir estas lineas Helm va por la versión v3 beta3) pero que dispone de capacidades tan interesantes como gestión del ciclo de vida o no requerir de servicios integrados en Kubernetes para desplegar paquetes (para realizar algo parecido en la versión 2 ver Como lanzar un esquema (Chart) de Helm sin instalar Helm, que requiere de un job y un pod lanzador con Tiller, lo que representa una mayor complejidad).

Usando Helm

Una vez dispuesto nuestro cluster Kubernetes (ver Kubernetes: Crear un entorno mínimo para demos o K3s: Kubernetes más simple) procedemos a descargar en el nodo master el binario de Helm con:

$ curl -sLS https://get.helm.sh/helm-v3.0.0-beta.3-linux-amd64.tar.gz|sudo tar --no-overwrite-dir --strip=1 -C /usr/local/sbin/. -xz

Y ya está, no hay que instalar nada y podemos instalar los paquetes que necesitemos directamente, eso si, hay que tener en cuenta que no crea automáticamente los espacios de nombres (namespaces) ya que se considera que eso no es una tarea de despliegue sino de gestión de la infraestructura..

En el caso de Powerdns, que tiene como dependencia una base de datos mariadb y al que podemos acoplar opcionalmente un dashboard con PowerDNS-Admin vamos a requerir este tipo de paquetes, porque son útiles si queremos que los clientes dispongan de su propio servidor DNS gestionado por ellos mismos. En próximos artículos veremos que además este servidor es integrable con External-DNS, que nos permitirá publicar en PowerDNS las modificaciones en los proxy de entrada de Kubernetes (por ejemplo un Ingress con Traefik).

Para crear un paquete con la estructura mínima hacemos:

$ helm create powerdns

Que nos creará una infraestructura con los elementos indicados anteriormente, como la solución PowerDNS consta de un deployment (deployment.yaml) para la disponibilidad del servicio, un servicio para publicar la API (opcional: powerdns-api-service.yaml), un servicio para publicar el Dashboard (opcional: powerdnsadmin-service.yaml), un servicio para publicar el servicio DNS (requerido: powerdns-dns-service.yaml), una petición de volumen persistente (PVC, opcional: mariadb-pvc.yaml) para la base de datos, una configuración de acceso por URL (Ingress, opcional: ingress.yaml) y por último las claves de acceso a la API de PowerDNS y a la base de datos (powerdns-secret.yaml), hemos de crear esos objetos en la carpeta powerdns/templates, en nuestro caso la carpeta queda con el siguiente contenido:

$ ls -1 powerdns/templates/
deployment.yaml
_helpers.tpl
ingress.yaml
mariadb-pvc.yaml
NOTES.txt
powerdnsadmin-service.yaml
powerdns-api-service.yaml
powerdns-dns-service.yaml
powerdns-secret.yaml

Las plantillas de Helm

Podemos ver objetos “service”, “secret”, “ingress”, “pvc” y “deployment”, cada uno de ellos describe un objeto kubernetes como si fuese un despliegue directo, por ejemplo, un servicio opcional para PowerDNS-Admin lo definimos:

{{- if .Values.powerdnsadmin.enabled }}
apiVersion: v1
kind: Service
metadata:
  name: {{ template "powerdns.fullname" . }}-service-admin
  labels:
{{ include "powerdns.labels" . | indent 4 }}
spec:
  type: {{ .Values.powerdnsadmin.service.type }}
  ports:
    - port: {{ .Values.powerdnsadmin.service.port }}
      targetPort: pdns-admin-http
      protocol: TCP
      name: pdns-admin-http
  selector:
    app.kubernetes.io/name: {{ .Release.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

A simple vista no se parece en nada aun despliegue normal, pero tenemos una serie de puntos interesantes: “{{ template “powerdns.fullname” . }}” va a ser el nombre completo del despliegue que se compone de powerdns más un identificador único del despliegue en el espacio de nombres donde vamos a desplegar, esto nos permite disponer de múltiples despliegues del mismo servicio con diferentes nombres sin necesidad de crear nuevos “yaml”.

Las plantillas incluyen características de lenguaje como son asignaciones, bucles y condicionales, en este caso podemos ver “{{- if .Values.powerdnsadmin.enabled }}” … “{{- end }}” que nos va a permitir que este servicio sea opcional, característica que se gestiona con el atributo:

powerdnsadmin:
  enabled: 'true'

Que se define en la raíz del Chart dentro del archivo values.yaml, este archivo define todos los valores predefinidos en el Chart en formato yaml. Que en el caso de el despliegue de powerdns+mariadb+powerdns-admin son unos 60 parámetros de configuración. Es importante recordad que cada parámetro de configuración debe definirse claramente en la documentación del Chart que irá en el archivo README.md

Más información sobre manejar este tipo de plantillas en https://golang.org/pkg/text/template/ y sobre los valores predefinidos en https://helm.sh/docs/chart_template_guide/

Desplegando el Chart para PowerDNS

Una vez empaquetado el Chart con helm package powerdns (que nos generará un archivo comprimido con el Chart) procedemos a instalarlo con helm install -n NAMESPACE NOMBRE_RELEASE PAQUETE, en el caso de Powerdns y si antes hemos creado el espacio de nombres “powerdns” y disponemos de un PV libre o de un sistema de asignación dinámica de almacenamiento haremos:

helm install -n powerdns powerdns https://raw.githubusercontent.com/aescanero/helm-powerdns/master/test/powerdns.tgz

Dentro del espacio de nombres powerdns nos creará una serie de objetos que lanzarán los servicios y un PVC que usará un volumen para el almacenamiento persistente de la solución, en el caso de disponer de Traefik, se creará una ruta/dominio para el acceso web a la aplicación.

De está manera tenemos varios niveles de despliegues: Espacios de nombres para los diferentes clientes, Releases para que cada cliente pueda lanzar los servicios que crea convenientes (por ejemplo un servicio DNS por dominio de cliente) y cada servicio dispone de su propio almacenamiento persistente, sus propios servicios de acceso y sus propias consolas de gestión. Convirtiéndose en una solución totalmente multi-tenant a partir de una solución prácticamente estática para una solución específica.

Conclusiones

Los fuentes de este artículo están en https://github.com/aescanero/helm-powerdns y son un ejercicio demostrativo de las capacidades de Helm v3, a espera de que la versión definitiva traiga las modificaciones del API de Kubernetes 1.16 y que convierta a Helm es una herramienta imprescindible en el mundo Kubernetes.

Volver arriba