En la entrada anterior hemos visto como utilizar las herramientas que nos proporciona Kubernetes para construir nuestra aplicación. Ahora vamos a ver lo fácil que es construir un paquete con toda la información que va a necesitar nuestra aplicación para funcionar.
El gestor de paquetes de Kubernetes
El gestor de paquete de Kubernetes se llama Helm. También es el nombre del comando.
Para instalar Helm simplemente nos descargamos el binario y lo colocamos en el PATH.
$ wget http://storage.googleapis.com/kubernetes-helm/helm-v2.1.3-linux-amd64.tar.gz
$ mv linux-amd64/helm /usr/local/bin/helm
Podemos ver que está instalado con:
$ helm version
Client: &version.Version{SemVer:"v2.1.2", GitCommit:"58e545f47002e36ca71ac5d1f7a987b56e1937b3", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.1.2", GitCommit:"58e545f47002e36ca71ac5d1f7a987b56e1937b3", GitTreeState:"clean"}
Helm cuenta con otro componente que se llama Tiller, es un pod que actua como un agente dentro de Kubernetes. La forma más rápida de desplegar el agente es así:
$ helm init
Esto tomará los valores por defecto para conectar con el clúster y desplegar el agente. Vemos el agente desplegado como pod
$ kubectl --namespace=kube-system get pods --selector='name=tiller' NAME READY STATUS RESTARTS AGE tiller-deploy-3161388333-0lqd4 1/1 Running 8 6d
Estructura de un paquete para Kubernetes/Helm
Al igual que otros paquetes como los deb de Debian los paquetes de Helm se llaman Charts y tienen la siguiente estructura:
wordpress/ Chart.yaml # A YAML file containing information about the chart LICENSE # OPTIONAL: A plain text file containing the license for the chart README.md # OPTIONAL: A human-readable README file values.yaml # The default configuration values for this chart charts/ # OPTIONAL: A directory containing any charts upon which this chart depends. templates/ # OPTIONAL: A directory of templates that, when combined with values, # will generate valid Kubernetes manifest files. templates/NOTES.txt # OPTIONAL: A plain text file containing short usage notes
Todos nos interesan ahora mismo excepto el de charts/ porque nuestro Chart (de wordpress) no depende de ningún otro. Vamos a ir viendo cada uno al tiempo que vemos como lo hemos adaptado a nuestros yaml para wordpress
Nuestro Chart de WordPress
Chart.yaml
name: wp-helm description: An example of Helm and WordPress version: 0.1.0 keywords: - http - wordpress - www - web - cms home: "https://www.wordpress.org" sources: - "https://github.com/nordri/helm-wordpress" maintainers: - name: nordri email: nordri@gmail.com engine: gotpl
No hay mucho que contar, está bastante claro. La opción engine hace referencia al parseador que usaremos para las plantillas, la opción por defecto si no se indica es gotpl que es el que usa Golang, como Jinja2 para Python.
LICENSE
Es el texto de la Licencia Apache 2
README.md
La información relativa a nuestro Chart, como funciona y demás
Un ejemplo de WordPress con Helm y Kubernetes.........
values.yaml
Este fichero contiene los datos de nuestra instalación. Como por ejemplo el nombre del sitio. Puertos a usar, usuarios y contraseñas.
image: wordpress db_server: 192.168.1.43 root_db_password: root01 nfs_path: srvnfs nfs_server: 192.168.1.43 pv_size: 20Gi pvc_size: 2Gi hostname: wordpress resources: requests: memory: 128Mi cpu: 500m
Para este ejemplo hemos introducido dos nuevos parámetros que van a controlar el uso de los recursos por parte de nuestra aplicación. La memoria que hemos establecido a 128Mi y la cpu a 500m (500 milicores)
charts
Si usáramos dependencias de otros charts los incluiríamos en este directorio. Seguiría la misma estructura de directorios del padre, por ejemplo si nuestro chart depende del chart Apache y MySQL sería:
wordpress: Chart.yaml requirements.yaml # ... charts/ apache/ Chart.yaml # ... mysql/ Chart.yaml # ...
templates
Aquí es donde vamos a definir cada uno de los componentes que conforman nuestra aplicación. Cada fichero yaml que utilizamos en la entrada anterior aparece aquí parametrizado para que coja los valores del fichero de values.yaml. Por no alargar mucho la entrada vamos a ver los detalles más significativos:
Hay dos ficheros clave que son _helpers.tpl y NOTES.txt. El primero es donde definimos funciones que serán ejecutadas por el parseador y el segundo es el mensaje que presentaremos cuando la aplicación se instale, como la URL de acceso.
Una vez tenemos las funciones definidas podemos hacer uso de ellas dentro de nuestras plantillas. En nuestro caso usamos la función template con el parámetro “fullname” para obtener el nombre de la instalación. Esto es porque, al igual que con Docker, cada instalación recibe un nombre aleatorio dentro del clúster, así podemos definir por ejemplo para nuestro servicio la siguiente línea:
name: {{template "fullname" .}}-svc
Ese será el nombre del servicio y lo usaremos para relacionar cada componente de la aplicación dentro del cluster.
Lo siguiente será sacar valores del fichero values.yaml y usaríamos la siguiente sintaxis:
# Obtener el nombre del host que le pasaremos a ingress - host: {{ .Values.hostname }}
También podemos tener en la plantilla un nombre por defecto en caso que no se rellene ese valor en values.yaml
- host: {{ default "localhost" .Values.hostname }}
Los valores pueden hacer uso de pipelines al estilo Bash por ejemplo para cifrar una password y entrecomillarla. Lo vemos en el fichero de mysql-secrets.yaml.
mysql-root-password: {{.Values.root_db_password | b64enc | quote}}
Vemos que la contraseña está en plano en el fichero de values, la tomamos, la pasamos a base64 y la ponemos entre comillas.
Si queremos incluir trozos de values sin tener que referenciarlos uno a uno podemos hacer uso de toYaml que es una función para llamar a plantillas, tenemos que definir una plantilla dentro de values, nosotros hemos llamado resources y luego pasarla por la función de indentado, así si queremos incluir los resources que puede hacer uso el pod hacemos así:
{{ toYaml .Values.resources | indent 10 }}
Y tomará de values el trozo de plantilla que corresponda con resources y lo indentará 10 posiciones.
También se usa una lista de variables ya definidas que podemos consultar aquí
Instalando el paquete
Una vez tenemos todo instalamos el paquete. Si vemos la ayuda de Helm tenemos varias formas de instalar el paquete:
[...] 1. By chart reference: helm install stable/mariadb 2. By path to a packaged chart: helm install ./nginx-1.2.3.tgz 3. By path to an unpacked chart directory: helm install ./nginx 4. By absolute URL: helm install https://example.com/charts/nginx-1.2.3.tgz [...]
Si lo instalamos usando la opción 3 veremos algo parecido a esto:
NAME: winsome-tortoise LAST DEPLOYED: Thu Dec 29 12:19:26 2016 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Secret NAME TYPE DATA AGE winsome-tortoise-wordpress-secret Opaque 1 1s ==> v1/PersistentVolume NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE winsome-tortoise-wordpress-pv 20Gi RWX Retain Bound default/winsome-tortoise-wordpress-pvc 1s ==> v1/Service NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE winsome-tortoise-wordpress-svc 10.111.214.12380:32590/TCP 1s ==> extensions/Deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE winsome-tortoise-wordpress 1 1 1 0 1s ==> extensions/Ingress NAME HOSTS ADDRESS PORTS AGE winsome-tortoise-wordpress-ing wordpress 80 1s ==> v1/PersistentVolumeClaim NAME STATUS VOLUME CAPACITY ACCESSMODES AGE winsome-tortoise-wordpress-pvc Bound winsome-tortoise-wordpress-pv 20Gi RWX 1s NOTES: Los datos de acceso son los siguientes: Host: wordpress
Donde vemos un resumen de los componentes que han sido lanzados y la información que nos da el fichero NOTES.txt. Vemos las aplicaciones instaladas a través de helm, asi
$ helm list
NAME REVISION UPDATED STATUS CHART winsome-tortoise 1 Thu Dec 29 12:19:26 2016 DEPLOYED wp-helm-0.1.0
Si quisiéramos eliminar la aplicación hariamos:
$ helm delete winsome-tortoise
Repositorio
Aquí el repositorio en GitHub: aquí