Capítulo 4. Construir un gráfico

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Los gráficos son el corazón de Helm. Además de instalarlos en un clúster de Kubernetes o gestionar las instancias de gráficos que hayas instalado, puedes crear gráficos nuevos o modificar los existentes. En los próximos tres capítulos cubriremos muchos detalles sobre los gráficos, como su creación, los elementos que contienen, las plantillas de los manifiestos de Kubernetes, las pruebas de los gráficos, las dependencias y mucho más.

En este capítulo aprenderás a crear un nuevo gráfico y a conocer las distintas partes que lo componen. Esto incluirá el uso de varios comandos incorporados que pueden ayudarte en el proceso de desarrollo del gráfico.

Los gráficos son los paquetes con los que trabaja Helm. Son conceptualmente similares a paquetes Debian utilizados por APT o Formula utilizados por Homebrew para macOS. La similitud conceptual es donde acaban las similitudes. Los gráficos están diseñados para Kubernetes como plataforma que tiene su propio estilo. En el corazón de Charts están las plantillas para generar manifiestos de Kubernetes que pueden instalarse y gestionarse en un clúster.

Antes de profundizar en las plantillas en el Capítulo 5, empecemos por crear un gráfico básico totalmente funcional. Para ello, utilizaremos un gráfico de ejemplo llamado yunque. Con ese gráfico aprenderás a utilizar Helm para generar un gráfico, la estructura de los gráficos y los archivos que contienen, el empaquetado de gráficos y la creación de gráficos de pelusa. Consulta la fuente en línea de este gráfico en https://github.com/Masterminds/learning-helm/tree/main/chapter4/anvil.

El comando de creación de gráficos

Helm incluye el comando create para facilitarte la creación de tu propio gráfico, y es una forma estupenda de empezar. Este comando crea un nuevo gráfico Nginx, con el nombre que elijas, siguiendo las buenas prácticas para el diseño de un gráfico. Dado que los clusters de Kubernetes pueden tener diferentes métodos para exponer una aplicación, este gráfico hace configurable la forma en que Nginx se expone al tráfico de red, de modo que pueda exponerse en una amplia variedad de clusters.

El comando create crea un gráfico por ti, con toda la estructura y archivos gráficos necesarios. Estos archivos están documentados para ayudarte a entender lo que se necesita, y las plantillas que proporciona muestran múltiples manifiestos de Kubernetes trabajando juntos para implementar una aplicación. Además, puedes instalar y probar este gráfico nada más sacarlo de la caja.

A lo largo de este capítulo veremos una aplicación de ejemplo llamada yunque. Es una aplicación sencilla que te mostrará la estructura de un gráfico y te dará la posibilidad de modificar un gráfico para una aplicación diferente. Para crear el nuevo gráfico, ejecuta el siguiente comando desde un símbolo del sistema:

$ helm create anvil

Esto creará un nuevo gráfico como subdirectorio de tu directorio actual con el nombre yunque.

El nuevo gráfico es un directorio que contiene una serie de archivos y carpetas. Esto no incluye todos los archivos y carpetas: descubrirás algunos más en los próximos capítulos. Éstos son los básicos necesarios para que un gráfico funcione:

anvil
├── Chart.yaml 1
├── charts 2
├── templates 3
│   ├── NOTES.txt 4
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml 5
└── values.yaml 6
1

El archivo Chart.yaml contiene metadatos y algunos controles de funcionalidad para el gráfico.

2

Los gráficos dependientes pueden mantenerse opcionalmente en el directorio de gráficos. Las gráficas dependientes se tratan en el Capítulo 6. Por ahora será un directorio vacío.

3

Las plantillas utilizadas para generar manifiestos de Kubernetes se almacenan en el directorio de plantillas.

4

El archivo NOTES.txt es una plantilla especial. Cuando se instala un gráfico, la plantilla NOTES. txt se renderiza y se muestra en lugar de instalarse en un cluster.

5

Las plantillas pueden incluir pruebas que no se instalan como parte de los comandos install o upgrade. Este gráfico incluye una prueba que utiliza el comando helm test. Las pruebas se tratan en el Capítulo 6.

6

Los valores por defecto que se pasan a las plantillas cuando Helm está renderizando los manifiestos están en el archivo values.yaml. Cuando instancias un gráfico, estos valores se puedenanular.

Puedes instalar este gráfico recién creado sin ninguna modificación ejecutando el siguiente comando:

$ helm install myapp anvil

Cuando ejecutes este comando, Helm creará una instancia de la tabla que se ejecuta en el clúster con el nombre myapp. La instalará utilizando la conexión y el contexto actualmente configurados que utilizas para Kubernetes. Helm está utilizando la misma configuración que usas cuando utilizas kubectl, la aplicación de línea de comandos para Kubernetes. En ese comando el argumento final de yunque es el directorio donde se encuentra el gráfico.

La salida de este comando incluye el contenido generado al renderizar la plantilla NOTAS.txt, como se muestra aquí:

NAME: myapp
LAST DEPLOYED: Sun Apr  5 08:12:59 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default ↵
    -l "app.kubernetes.io/name=anvil,app.kubernetes.io/instance=myapp" ↵
    -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:80

La sección NOTES contiene información sobre la conexión a la aplicación. Dependiendo de los valores que pases al gráfico cuando se instancie, esta información puede ser muy diferente. Este gráfico puede configurarse para utilizar un ClusterIP, un NodePort, un LoadBalancer y un Ingress para exponer una aplicación. Por defecto, se utiliza un ClusterIP.

Si sigues las instrucciones de las notas, verás la página web predeterminada de Nginx para mostrarte que se está ejecutando, como se muestra en la Figura 4-1.

Nginx
Figura 4-1. Página web predeterminada de Nginx cuando visitas la aplicación en ejecución

Los métodos para exponer la aplicación están vinculados a tipos de recursos incorporados de Kubernetes, y no a características de la aplicación. Eso los hace portables a tus aplicaciones personalizadas. Los métodos para exponer aplicaciones incluyen:

ClusterIP

Una opción de configuración en el tipo de recurso Kubernetes Service que expone el servicio en una dirección IP interna a nivel de clúster.

PuertoNodo

Una opción alternativa para los recursos de Kubernetes Service que expone el servicio en un puerto estático de cada nodo. También se crea automáticamente una ClusterIP.

LoadBalancer

Una opción de configuración de Kubernetes Service que expone una aplicación externamente utilizando un equilibrador de carga proporcionado por el proveedor de alojamiento.

Entrada

Los recursos Ingress son recursos adicionales a Services que exponen un servicio a través de HTTP y HTTPS. Para que esto funcione se necesita un controlador de entrada, como ingress-nginx.

Si instalaste este gráfico en tu cluster para probarlo, puedes eliminar la instancia de tu cluster ejecutando el siguiente comando:

$ helm delete myapp
Nota

Cuando se instala el gráfico, la imagen utilizada para Nginx, por defecto, es la última versión de la imagen de las Imágenes Oficiales de Docker. Si el clúster de Kubernetes con el que trabajas no tiene acceso a hub.docker. com no podrás instalar la imagen. Tendrías que configurar la imagen a una a la que tu clúster tenga acceso.

Ahora que ya tenemos un gráfico funcional, echemos un vistazo a su interior y modifiquémoslo para la aplicación Anvil.

El archivo Chart.yaml

Mira dentro del directorio anvil y encontrarás un archivo llamado Chart.yaml. El archivo Chart. yaml informa a Helm y a otras herramientas sobre tu gráfico. Otras herramientas son Kubeapps (un catálogo e instalador de aplicaciones local), el Artifact Hub (un listado de artefactos nativos de la nube) y muchas otras.

Cuando abras el archivo Chart.yaml, verás el contenido que se muestra en el Ejemplo 4-1.

Ejemplo 4-1. El archivo Chart.yaml generado
apiVersion: v2 1
name: anvil 2
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into ↵
  versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer.↵
  They're included as
# a dependency of application charts to inject those utilities and functions ↵
  into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be ↵
  deployed.
type: application

# This is the chart version. This version number should be incremented each ↵
  time you make changes
# to the chart and its templates, including the app version.
version: 0.1.0 3

# This is the version number of the application being deployed. This version ↵
  number should be
# incremented each time you make changes to the application. Versions are not ↵
  expected to
# follow Semantic Versioning. They should reflect the version the application ↵
  is using.
appVersion: 1.16.0
1

El apiVersion indica a Helm qué estructura está utilizando el gráfico. Un apiVerison de v2 está diseñado para Helm v3.

2

El nombre se utiliza para identificar la carta en varios lugares.

3

Las cartas pueden tener muchas versiones. Helm utiliza la información de la versión para ordenar e identificar los gráficos.

Este archivo Chart.yaml contiene numerosas claves, de las cuales sólo tres son necesarias. La propiedad apiVersion indica a Helm de qué versión de un gráfico se trata. Helm v3 puede trabajar con gráficos cuyo apiVersion sea v1 o v2. Los gráficos v1 son los diseñados para trabajar con versiones anteriores de Helm. Si tus gráficos están diseñados para funcionar con Helm v3 o versiones más recientes, debes establecer este valor en v2. El valor de name se suele utilizar como parte del nombre de los recursos de Kubernetes. Esto significa que los nombres están limitados a caracteres alfanuméricos en minúsculas, -, y . y deben empezar y terminar con un carácter alfanumérico. Los nombres suelen ser caracteres alfanuméricos en minúsculas. La última clave requerida esversionque contiene la versión del gráfico. Se espera que las versiones sigan el Versionado semántico, que se trató en el Capítulo 2.

Puede que notes que el estilo de un archivo Chart.yaml es similar pero ligeramente diferente al de los manifiestos de Kubernetes. Los archivos Chart. yaml no tienen el mismo formato que los recursos personalizados, pero contienen algunas de las mismas propiedades. Los archivos Chart. yaml originales se diseñaron en 2015, mucho antes de que existieran las definiciones de recursos personalizados de Kubernetes. Aunque Helm ha progresado en las principales versiones, ha mantenido cierta compatibilidad con versiones anteriores a lo largo del tiempo para no perturbar demasiado a los usuarios. Esto ha dado lugar a diferencias entre el formato de archivo Chart.yaml y los manifiestos de Kubernetes.

Los archivosChart.yaml también contienen información descriptiva, que resulta útil al presentarse en las interfaces de usuario. El campo description del Ejemplo 4-1 es uno de ellos, pero puedes añadir campos adicionales, como los siguientes:

  • home es una URL a la página de inicio del gráfico o del proyecto.

  • icon es una imagen (por ejemplo, un archivo PNG o SVG) en forma de URL.

  • maintainers contiene una lista de mantenedores. Cada mantenedor de la lista puede tener un nombre, un correo electrónico y una URL.

  • keywords puede contener una lista de palabras clave sobre el proyecto.

  • sources es para una lista de URL al código fuente del proyecto o gráfico.

En el Apéndice A encontrarás una descripción completa de las propiedades del archivo Chart.yaml, como referencia.

El archivo Chart.yaml generado puede modificarse para la aplicación Anvil. Las siguientes modificaciones actualizan los campos obligatorios, añaden algunos archivos descriptivos y eliminan comentarios:

apiVersion: v2
name: anvil
description: A surprise to catch something speedy.
version: 0.1.0
appVersion: 9.17.49
icon: https://wile.example.com/anvil.svg
keywords:
  - road runner
  - anvil
home: https://wile.example.com/
sources:
  - https://github.com/Masterminds/learning-helm/tree/main/chapter4/anvil
maintainers:
  - name: ACME Corp
    email: maintainers@example.com
  - name: Wile E. Coyote
    email: wile@example.com

Una propiedad que estaba en el archivo Chart.yaml generado pero que no está en el de para Anvil es type. Yunque es una aplicación cuyo valor por defecto es el campo type, por lo que el campo type no es necesario. El otro tipo de gráfico es un gráfico de biblioteca, que se trata en el Capítulo 7.

La propiedad appVersion es única. Es descriptiva y se utiliza habitualmente en las plantillas. La propiedad appVersion representa la versión de la aplicación primaria o combinada. Por ejemplo, si la aplicación empaquetada fuera WordPress, sería la versión de WordPress.

Consejo

La propiedad icon es una URL, y eso puede incluir URLs de datos. Las URL de datos permiten a incrustar archivos pequeños en forma de URL. Esto es especialmente útil si el logotipo es un pequeño archivo SVG. Si es posible que un gráfico se ejecute en entornos locales protegidos por el aire o no quieres que las interfaces de usuario descarguen constantemente un archivo de tu servidor web, una URL de datos es una opción útil.

Modificar plantillas

Para modificar este gráfico para la aplicación Anvil o tu propia aplicación personalizada, necesitarás entender y modificar las plantillas. Fuera de la caja, las plantillas creadas por el comando helm create ejecutan Nginx como una aplicación sin estado. En el ejemplo en el que estamos trabajando, será necesario sustituir Nginx por Anvil.

Helm está escrito en el lenguaje de programación Go, y Go incluye paquetes de plantillas. Helm aprovecha el paquete de plantillas de texto como base para sus plantillas. Este lenguaje de plantillas es similar a otros lenguajes de plantillas e incluye bucles, lógica if/then, funciones y mucho más. A continuación se muestra un ejemplo de plantilla de un archivo YAML:

product: {{ .Values.product | default "rocket" | quote }}

En este archivo YAML hay un nombre clave de product. El valor se genera utilizando una plantilla. {{ y }} son los corchetes de apertura y cierre para entrar y salir de la lógica de la plantilla. Hay tres partes en la lógica de la plantilla separadas por un |. Esto se denomina canalización, y funciona igual que una canalización en los sistemas basados en Unix. El valor o salida de una función de la izquierda se pasa como último argumento al siguiente elemento de la canalización. En este caso, la cadena comienza con el valor de la propiedad en .Values.product. Éste procede del objeto de datos que se pasa al renderizar las plantillas. El valor de estos datos se pasa como último argumento a la función default, que es una de las funciones que proporciona Helm. Si el valor pasado está vacío, la función default utiliza el valor por defecto de "rocket", asegurándose de que hay un valor. A continuación, se envía a la función quote, que se asegura de que la cadena está entre comillas antes de escribirla en la plantilla.

El . al principio de .Values.product es importante. Se considera el objeto raíz en el ámbito actual. .Values es una propiedad del objeto raíz.

La Implementación

Los gráficos de Helm pueden contener plantillas para cualquier tipo de recurso de Kubernetes que puedas utilizar. Esto incluye StatefulSets, Jobs, PersistentVolumeClaims, Services y muchos más. El gráfico creado con helm create está diseñado para ejecutar un servicio sin estado como Implementación de Kubernetes. La aplicación de ejemplo que utilizamos aquí para Anvil es una aplicación sin estado, lo que significa que funcionará bien como implementación.

Para entender la plantilla Deployment, podemos echar un vistazo al archivo deployment.yaml en el directorio de plantillas del gráfico. A continuación se muestra la versión de la plantilla Deployment hasta la sección spec:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "anvil.fullname" . }}
  labels:
    {{- include "anvil.labels" . | nindent 4 }}

Se parece mucho al inicio de un manifiesto de Kubernetes. Tiene un apiVersion, el kind, y metadata. Una vez que entres en el metadata te darás cuenta de que comienza la creación de plantillas.

Consejo

Si no estás familiarizado con la estructura de las Implementaciones de Kubernetes, puedes leer sobre ellas en la documentación de Kubernetes.

La función de plantilla include permite incluir la salida de una plantilla en otra plantilla, y esto funciona en pipelines. El primer argumento de la función include es el nombre de la plantilla que se va a utilizar. El . que se pasa como segundo argumento es el objeto raíz. Se introduce para que las propiedades y funciones del objeto raíz puedan utilizarse en la plantilla llamada.

anvil.fullname y anvil.labels son dos plantillas reutilizables incluidas en el gráfico a través del archivo _helpers.tpl. (La _ al principio del nombre hace que aparezca en la parte superior de los listados de directorios para que puedas encontrarla fácilmente entre tus plantillas; Helm no las convierte en manifiestos de Kubernetes, pero hace que las plantillas que contienen estén disponibles para su uso). anvil.fullname proporciona un nombre basado en el nombre elegido al instanciar el gráfico, y anvil.labels proporciona etiquetas que siguen las buenas prácticas de Kubernetes. Las funciones se tratan con más profundidad en el Capítulo 5.

Después de la sección metadata de la plantilla está la sección spec, que dice lo siguiente:

spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "anvil.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "anvil.selectorLabels" . | nindent 8 }}
    spec:
    {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
    {{- end }}
      serviceAccountName: {{ include "anvil.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default↵
            .Chart.AppVersion }}" 1
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
    {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
    {{- end }}
    {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
    {{- end }}
1

La ubicación y la versión de la imagen del contenedor son configurables mediante valores.

La sección spec completa la implementación. La mayor parte de esta sección consiste en rellenar los datos con las propiedades de .Values. Hay algunos elementos que están codificados, como los puertos utilizados para exponer la aplicación. Anvil se expone a través de HTTP en el puerto 80, por lo que no necesitamos cambiar el puerto. Si tus contenedores están expuestos en puertos diferentes, tendrás que hacer cambios aquí.

El valor de image para el contenedor se establece mediante valores. Aquí no encontrarás la ubicación de la imagen codificada. Esto es útil para aquellos casos en los que la ubicación de la imagen deba establecerse en una ubicación diferente cuando se instancie un gráfico. Esto significa que tenemos que cambiar la ubicación en los valores por defecto.

Las propiedades de .Values se calculan en función de varios factores. Los valores por defecto y el punto de partida se basan en los valores proporcionados por el archivo values.yaml del gráfico. El archivo values.yaml se trata en la siguiente sección. Estos valores pueden anularse mediante valores introducidos al crear el gráfico. La CLI de helm tiene banderas para pasar valores directamente (por ejemplo, --set, --set-file y --set-string) o para pasar un archivo con valores (por ejemplo, -f o --values). Los valores se fusionan entre sí, teniendo prioridad los que se pasen más tarde.

Las plantillas son un tema extenso y suelen constituir la mayor parte de un gráfico. El Capítulo 5 está dedicado a las plantillas.

Utilizar el Archivo de Valores

Cuando alguien instancie una aplicación en un clúster de Kubernetes a partir de un gráfico, no necesita proporcionar todos los valores utilizados en las plantillas. Si lo hicieran, la experiencia del usuario sería difícil. Aquí es donde entra en juego el archivo values.yaml.

Los gráficos incluyen un archivo values.yaml que se encuentra junto al archivo Chart.yaml en la raíz de un gráfico. El archivo values.yaml contiene los valores por defecto utilizados por el gráfico, y es una forma de documentación para los valores personalizados que pueden pasarse a un gráfico.

values.yaml es un archivo YAML no estructurado. Existen algunas prácticas comunes y útiles, que se tratarán en breve, pero no se exige nada en el formato del YAML. Esto permite a los creadores de gráficos proporcionar una estructura e información que les funcione bien. Un archivo values.yaml puede contener numerosas cosas, desde la simple sustitución de propiedades del manifiesto de Kubernetes hasta elementos necesarios para la lógica empresarial específica de la aplicación.

Imágenes de contenedores

La parte de apertura del archivo values.yaml creado por helm create contiene la información de la imagen junto con algo de documentación de apertura e información sobre las réplicas:

# Default values for anvil.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: ghcr.io/masterminds/learning-helm/anvil-app 1
  pullPolicy: IfNotPresent 2
  # Overrides the image tag whose default is the chart version.
  tag: "" 3

imagePullSecrets: [] 4
1

La ubicación de la imagen. Se ha actualizado para reflejar la ubicación de Yunque.

2

Una política de IfNotPresent significa que la imagen se almacenará en caché en el clúster de Kubernetes según la versión que se esté utilizando. Always es otra opción que se salta la caché y se descarga siempre del repositorio.

3

Por defecto, este gráfico utiliza appVersion como etiqueta. Si se especifica una etiqueta de imagen, se utilizará en lugar de appVersion.

4

Una lista de pull secrets se utiliza cuando se necesitan credenciales para acceder a una ubicación del registro de contenedores que está protegida con un nombre de usuario y una contraseña.

Este gráfico y los valores representan una aplicación empaquetada como una sola imagen. Los patrones utilizados en el archivo values.yaml están diseñados teniendo esto en cuenta. Por ejemplo, sólo hay una ubicación para la imagen. Si tus aplicaciones tienen varias imágenes, cada imagen tendría una sección que contendría gran parte de la información que aparece aquí. Esto incluye replicaCount, que es el número de replicas que Kubernetes utilizará cuando secree Deployment.

La sección image contiene detalles sobre la imagen. repository contiene la ubicación de la imagen que se va a utilizar, mientras que pullPolicy indica a Kubernetes con qué frecuencia debe obtener o almacenar en caché las imágenes. Si se utiliza una etiqueta móvil, como stable, la pullPolicy debe ajustarse a Always para que se recojan los cambios. Como se está utilizando una versión, el valor por defecto de pullPolicy se establece en IfNotPresent para que se pueda utilizar una versión almacenada en caché si está disponible. La propiedad tag ofrece la oportunidad de establecer una etiqueta diferente de la appVersion establecida en el archivo Chart.yaml.

Puede que notes que no hay ningún método para establecer un resumen cuando se obtiene una imagen. Los compendios pueden ser diferentes cuando las imágenes están en repositorios distintos. Por ejemplo, si la imagen Anvil se copiara de Docker Hub a Quay, otro repositorio de imágenes, el resumen cambiaría para la misma imagen aunque la etiqueta y el contenido siguieran siendo los mismos. El Capítulo 5 proporciona un ejemplo de cómo añadir soporte para un resumen a un gráfico, si así se desea.

Si necesitas extraer una imagen de un registro de contenedores con controles de acceso, Kubernetes necesita saber cómo hacerlo. Esto ocurre mediante el uso de pull secrets. imagePullSecrets te permite listar los nombres de pull secrets con acceso a registros privados. Consulta la documentación para crear un pull secret.

El gráfico generado tiene incorporadas algunas consideraciones de seguridad que pueden activarse o configurarse de otro modo. Por defecto, se crea una cuenta de servicio para la instancia del gráfico, mientras que las demás opciones son opcionales. Esto es lo que genera helmcreate:

serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname ↵
    template
  name:

podSecurityContext: {}
  # fsGroup: 2000

securityContext: {}
  # capabilities:
  #   drop:
  #   - ALL
  # readOnlyRootFilesystem: true
  # runAsNonRoot: true
  # runAsUser: 1000

Observarás que la mayoría de las propiedades de la configuración son comentarios y están inactivas. Cuando el gráfico se representa con los valores como comentarios, no hay ningún valor para esas propiedades. El valor está vacío. Al tener una estructura y valores como comentarios, el gráfico está documentando la estructura y los valores por defecto que se pueden utilizar, pero no está activando esas características.

Exponer servicios

La siguiente sección del archivo values.yaml se ocupa de exponer la aplicación para que otros la consuman:

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  hosts:
    - host: chart-example.local
      paths: []
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

En Kubernetes hay dos objetos integrados que puedes utilizar para exponer aplicaciones. El primero es un Service. La propiedad service te permitirá seleccionar el tipo de Service que se utiliza. Aunque por defecto se utiliza ClusterIP, pueden utilizarse otras opciones como NodePort yLoadBalancer pueden utilizarse. Las pocas líneas de YAML de la sección service se emparejan con la plantilla service.yaml generada para crear un manifiesto de Servicio completo que subir a Kubernetes.

El segundo objeto incorporado es el manifiesto Ingress, que puede emparejarse con un Service, y el gráfico tiene capacidad para generarlos. La configuraciónIngress proporciona un medio para mostrar un patrón común que se encuentra en los gráficos: el uso de una propiedad enabled para activar y desactivar características. En este caso ingress.enabled se establece en false. Cuando Helm renderiza las plantillas y ve un valor de false, el manifiesto Ingress se omite. Esto se debe al uso de una declaración lógica if en la plantilla Ingress que se encuentra en el archivo ingress.yaml generado.

Límites de recursos

Cuando ejecutas aplicaciones en producción, es una buena práctica establecer límites de recursos. Esto evita, por ejemplo, que una fuga de memoria en un contenedor afecte a otros contenedores. Cuando un autor de gráficos crea un gráfico que otros van a utilizar, es posible que no sepa dónde se instalará y cuántos recursos estarán disponibles allí. ¿Podría instalarlo en un ordenador portátil un desarrollador o alguien que esté probando el gráfico? ¿O podría instalarse en grandes servidores de producción? Para manejar esta variación en el entorno, la recomendación es poner límites de recursos y luego convertirlos en comentarios. Esto se encuentra en la siguiente sección del archivo values.yaml:

resources: {}
  # We usually recommend not to specify default resources and to leave this as
  # a conscious choice for the user. This also increases chances charts run on
  # environments with little resources, such as Minikube. If you do want to
  # specify resources, uncomment the following lines, adjust them as necessary,
  # and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #   cpu: 100m
  #   memory: 128Mi

Quienes instalan aplicaciones utilizan estos números como recomendaciones cuando instancian un gráfico. Estos números son los valores por defecto que se han establecido para una configuración simple de Nginx tal y como se generó. Funcionan para la aplicación Anvil. Si tu aplicación necesita valores diferentes, tendrás que actualizarlos.

Las cargas de trabajo tienen la posibilidad de especificar detalles sobre dónde se ejecutan en un clúster mediante los ajustes selector de nodo, tolerancias y afinidad. Aunque estas funciones más avanzadas no suelen utilizarse, es una buena idea incluirlas en un gráfico para quienes las necesiten. El archivo values.yaml generado y las plantillas tienen esto en cuenta. El siguiente ejemplo ha generado claves YAML para estasfunciones avanzadas. Los valores están vacíos por defecto, con la expectativa de que la persona que instale el gráfico establezca los valores adecuados para su instalación:

nodeSelector: {}

tolerations: []

affinity: {}

Empaquetar el gráfico

Puedes empaquetar los archivos y directorios de un gráfico en un único archivo comprimido. Esto es útil por muchas razones, entre ellas

  • Para su distribución a otras personas. Uno de los aspectos más potentes de un gestor de paquetes es que alguien con conocimientos sobre la ejecución de una aplicación la empaqueta para que otros, que no tienen un conocimiento profundo de la plataforma o la aplicación, puedan ejecutarla.

  • Cuando una versión de una aplicación debe someterse a un proceso de pruebas en varios entornos. Un ejemplo de este proceso es cuando hay entornos de desarrollo, control de calidad (QA) y producción, y la aplicación tiene que pasar el control de calidad antes de pasar a producción.

  • Cuando se desarrolla una aplicación multiservicio y los desarrolladores necesitan ejecutar servicios creados o gestionados por otros como parte de su configuración de desarrollo.

En cada una de estas situaciones suele ser más sencillo pasar un único archivo para el gráfico que una estructura de directorios.

Las versiones de gráficos aportan otra arruga a la forma de distribuir y consumir gráficos. Puede que tú o alguien que consuma tu gráfico necesitéis utilizar diferentes versiones del mismo. Por eso es útil almacenar y compartir diferentes versiones utilizando repositorios de gráficos o registros de la Iniciativa de Contenedores Abiertos (OCI), que se tratan en el Capítulo 7. En estos entornos, almacenar y compartir muchos archivos en una colección de estructuras de directorios para cada versión no es nada sencillo.

Helm puede crear un archivo de gráficos. Cada archivo gráfico es un archivo TAR comprimido con la extensión .tgz. Cualquier herramienta que pueda crear, extraer y trabajar con archivos TAR comprimidos con gzip funcionará con los archivos de gráficos de Helm.

Cuando Helm genera los archivos comprimidos, los nombra utilizando un patrón dechart name-version.tgz. Helm espera este mismo patrón al consumirlos. El chart name es el nombre que encontrarás dentro del archivo Chart.yaml y el version es la versión del gráfico. Esto permite almacenar varias versiones del mismo gráfico juntas. Puedes empaquetar Anvil como un archivo comprimido ejecutando

$ helm package anvil

En este caso anvil es la ruta a la ubicación donde se encuentra el origen del gráfico de yunque. Por defecto, el comando helm package colocará el archivo en el directorio en el que te encontrabas cuando ejecutaste el comando.

Hay algunas banderas útiles que puedes utilizar al empaquetar un gráfico:

--dependency-update (-u)

Indica a Helm que actualice los gráficos dependientes antes de crear el archivo. Esto actualizará el archivo Chart.lock y colocará una copia de los gráficos dependientes en el directorio de gráficos. Las cartas dependientes se tratan con más detalle en el Capítulo 6.

--destination (-d)

Te permite establecer la ubicación donde colocar el archivo gráfico si es diferente del directorio de trabajo actual.

--app-version

Se puede utilizar para establecer la propiedadappVersion del archivo Chart.yaml. Esto es especialmente útil si creas nuevas versiones del gráfico para cada nueva versión de tu aplicación que se ejecuta dentro del contenedor y no hay ningún otro cambio en el gráfico. La automatización puede utilizar una bandera como ésta como parte del proceso para construir la nueva versión.

--version

Actualiza la versión del gráfico. Esto es útil si estás actualizando el appVersion utilizando la línea de comandos como parte del proceso para empaquetar un gráfico.

Banderas para las cartas de firma de Pretty Good Privacy (PGP)

Los gráficos de Helm pueden firmarse y verificarse criptográficamente. El comando package tiene indicadores para la parte de firma del proceso, mientras que comandos como install y upgrade tienen indicadores para la parte de verificación del proceso. El Capítulo 6 cubre este proceso.

A veces tendrás archivos en un directorio de gráficos que no quieres incluir en el archivo de gráficos. Opcionalmente, en un directorio gráfico puede haber un archivo .helmignore. Esto es similar a un archivo .gitignore para Git. El comando helm create utilizado anteriormente creó uno con el siguiente contenido:

# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

Muchas de estas extensiones y patrones pueden resultarte familiares porque proceden de diversos sistemas de control de versiones y editores de código.

Cuando se crea el archivo gráfico, normalmente no quieres incluir elementos como los datos de tu sistema de control de versiones. El archivo .helmignore proporciona un lugar para especificar qué omitir. Este archivo debe estar en el nivel superior del gráfico.

Helm está diseñado para trabajar con los ficheros de archivo del mismo modo que con las estructuras de directorios. A comandos como helm install y helm lint, de los que hablaremos en breve, se les puede pasar un fichero de archivo del mismo modo que se les puede pasar un directorio.

Tablas de pelusas

Al desarrollar gráficos, especialmente cuando se trabaja con plantillas YAML, puede ser fácil cometer un error o pasar algo por alto. Para ayudarte a detectar errores, fallos, problemas de estilo y otros elementos sospechosos, el cliente Helm incluye un linter. Este linter puede utilizarse durante el desarrollo de gráficos y como parte de cualquier proceso de prueba.

Para utilizar el linter, utiliza el comando lint en un gráfico como directorio o archivo empaquetado:

$ helm lint anvil
==> Linting anvil

1 chart(s) linted, 0 chart(s) failed

La primera línea es el comando que ejecutas, mientras que las siguientes líneas son la salida de Helm. En este caso no hubo ningún problema. Podrías utilizar este comando en un fichero de archivo como el de la sección anterior. Para ello, cambia el argumento anvil, establecido en la ubicación del directorio para el gráfico, por el archivo anvil-0.1.0.tgz.

Este comando es capaz de eliminar varios gráficos con un solo comando. Por ejemplo, si tuvieras un segundo gráfico llamado mychart y quisieras eliminarlo junto con anvil, podrías ejecutar la siguiente orden:

$ helm lint anvil mychart

Los tres niveles de información procesable sobre gráficos que proporciona Helm son info, advertencia y errores. La información de nivel info es informativa; los gráficos pueden instalarse con información de nivel info. La información de nivel info hace que Helm tenga un código de salida de 0. La información de nivel error significa que hay un problema con el gráfico. Si un gráfico genera un manifiesto no válido para Kubernetes, como que YAML no es válido, Helm generará un error. Los errores hacen que Helm tenga un código de salida distinto de cero, lo que resulta útil para detectar problemas en herramientas de pruebas automatizadas. En el medio hay mensajes de advertencia. Estos mensajes se refieren a hallazgos que pueden causar problemas. Por defecto, los mensajes de advertencia hacen que Helm tenga un código de salida 0, pero Helm añade una bandera --strict que hace que los códigos de salida sean distintos de cero. Puedes elegir cómo manejarlos en la automatización.

En este caso no se encontraron problemas con el gráfico de yunque. Un gráfico predeterminado, creado por helm create, tendrá un único mensaje informativo sobre una propiedad icon que falta en el archivo Chart.yaml. Se trata de un aviso a nivel informativo para que la gente sepa que falta. La falta no afectará al funcionamiento del gráfico, pero sí a la forma en que se muestra en las interfaces de usuario.

Conclusión

Crear un gráfico simple para tu aplicación es sencillo cuando utilizas el comando helm create. Incluso cuando tus aplicaciones son más complicadas, la estructura de los gráficos es capaz de adaptarse a ellas, y el comando helm create puede ayudarte. Con unas pequeñas modificaciones realizadas en este capítulo, puedes instalar el gráfico Anvil utilizando helm install y ver cómo se ejecuta la aplicación personalizada en tu clúster. Puedes utilizar este mismo flujo para crear tus propios gráficos.

En el siguiente capítulo aprenderás a crear plantillas, haciendo hincapié en cómo funciona el lenguaje de plantillas y cómo puedes aplicarlo a las plantillas de Kubernetes almacenadas en gráficos. Las plantillas suelen ser la parte más grande de un gráfico en la que pasarás más tiempo. Comprender lo que tienes a tu disposición cuando creas plantillas hará que el proceso de desarrollarlas sea más rápido y sencillo.

Get Timón de aprendizaje now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.