HELM
Helm es una muy buena herramienta para empaquetar, compartir y desplegar objetos en Kubenetes.
En esta entrada no nos vamos a detener en explicar o detallar lo que es Helm, ni siquiera en cómo instalarlo. Hay suficiente documentación en internet que explica esos extremos. Suponemos, por tanto, que ya está instalado y operativo.
Lo que vamos a hacer aquí es mostrar cómo crear un repositorio propio, en el que podremos ubicar tantos charts como queramos, para nuestro uso y disfrute... y como decíamos arriba, para compartirlos con la comunidad.
El chart que compartiremos servirá para desplegar un servicio Springboot estandar. En nuestro caso, la imagen que invocaremos será una propia tipo "hola mundo", creada a partir de un simple código Springboot, con un endpoint /hello que muestra un mensaje de saludo y el nombre del pod donde corre.
El repositorio lo subiremos a nuestra cuenta de github, y lo publicaremos mediante github pages.
PREPARACIÓN
Bien, comenzaremos por crear el repositorio en github, con nombre "helm-charts". Una vez creado, lo clonaremos a un directorio de trabajo local
git clone https://github.com/gincol/helm-charts.git
cd helm-charts
Crearemos una carpeta "charts" donde ubicaremos cualquiera de los charts que deseemos crear
mkdir charts
cd charts
Generamos a continuación la estructura de nuestro chart, como digo, destinado a servirnos aplicaciones Springboot
helm create springboot
Con este comando se nos ha generado la siguiente estructura:
Subimos lo creado hasta el momento
git add .
git commit -m "commit inicial"
git push origin main
Para hacerlo visible vía github pages crearemos una rama "gh-pages"
git checkout -b gh-pages
git push origin gh-pages
Vamos a ver si tenemos habilitado github pages en nuestro repo... y efectivamente lo está en la siguiente ruta https://gincol.github.io/helm-charts/, según la configuración siguiente:
Para que sea accesible, en la raíz del proyecto hemos de tener un fichero README, que será el que se muestre:
Para construir y subir todo lo necesario para que nuestro repo sea usable usaremos "chart-releaser". En nuestro caso, que usamos mac, lo instalaremos mediante el gestor brew (https://github.com/helm/chart-releaser)
brew tap helm/tap
brew install chart-releaser
cr help
Para usar de forma cómoda este comando, crearemos el fichero "~/.cr/cr.yaml" con los siguientes datos
owner: XXXXX #nuestro id de github
git-repo: helm-charts
package-path: .deploy
token: XXXXXXXXXX #el token generado en "Settings/Developer settings/Personal access tokens"
git-base-url: https://api.github.com/
git-upload-url: https://uploads.github.com/
El token:
Antes de nada, los templates que se generan con el comando "helm create...." están preparados para desplegar un nginx. Por ello haremos algunos cambios en el fichero "templates/deployment.yaml":
Ahora si, empaquetamos (es conveniente añadir la carpeta .deploy en el .gitignore) y subimos
helm package charts/springboot --destination .deploy
cr upload
Creamos el index.yaml (donde se describen los charts configurados)
cr index -i ./index.yaml
La estructura final será:
Finalmente subimos todos los cambios
git add .
git commit -m "release 0.1.0"
git push origin gh-pages
Podemos ver la release en github
PRUEBA
El test lo haremos en un kubernetes ligero, k3s (https://k3s.io/), instalado sobre una MV RHEL9 en un mac vía VirtualBox.
Una vez arrancada la MV y el K3s (por defecto arranca el servicio al arrancar la MV) creamos un directorio de trabajo, y configuramos el values.yaml, en nuestro caso (marco en negrita lo más relevante)
[user@localhost helm-charts]$ cat values.yaml
# Default values for springboot.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: gines/springboot-normal
pullPolicy: Always
# Overrides the image tag whose default is the chart appVersion.
tag: "1.0.0"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: false
# 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: ""
podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
probe:
livenessPath: "/actuator/health/liveness"
readinessPath: "/actuator/health/readiness"
service:
type: ClusterIP
port: 80
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: traefik
# kubernetes.io/tls-acme: "true"
hosts:
- host: rhel.springboot.local
paths:
- path: /
pathType: Prefix
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
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
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity: {}
Instalamos el repo
helm repo add gincol-charts https://gincol.github.io/helm-charts/
e instalamos el paquete
helm install -f values.yaml springboot-normal --namespace dev gincol-charts/springboot
Accedemos al servicio vía curl
curl http://rhel.springboot.local/hello
springboot normal - hello from springboot-normal-6c48557547-5z2hg
Añadimos una réplica modificando el atributo replicaCount del values.yaml, "replicaCount: 2" y hacemos upgrade del servicio desplegado
helm upgrade springboot-normal gincol-charts/springboot -f values.yaml -n dev
Así nos queda:
Probamos vía navegador la respuesta de ambos pods:
Y eso es todo. Ahora se podrían añadir tantos charts (para node, python, angular...) como nos sea necesario. A partir de ahí, creando el values adecuado podríamos desplegar de una forma sencilla y productiva las aplicaciones que deseemos.
Se podría crear un values por entorno (dev, qa, prod, ...) en una carpeta separada. El comando de despliegue sólo debería utilizar el values de la carpeta que tocase, etc...