Soy Oscar Mas y me gustaría enseñaros que es Helm y como montar el almacenamiento para que Helm funcione correctamente. Helm dicho rápidamente es el “apt-get” de Kubernetes, pero para que esto funcione de manera automática hay que realizar un par de procedimientos antes de empezar a usarlo.
Cuando vemos en GitHub como despliegan un helm, veremos que para hacerlo rápido (TL;DR;) lo lanzan de la siguiente forma:
$ helm install stable/dokuwiki
Pero si no procedemos de una forma correcta al montaje del almacenamiento, nos encontraremos que nos da errores, ya que el sistema no encontrará un storage por defecto para poder hacer el despliegue que indicamos en el comando de “helm install stable/paquete”.
En este post os explicaré como configurar un sistema de almacenamiento basado en GlusterFS, el cual se adaptará a las necesidades de los paquetes Helm. El almacenamiento se adaptará gracias a los StorageClass de Kubernetes y su Dynamic Provisioning, el cual pasó de ser Beta a Estable en la versión 1.6 de Kubernetes. Si queréis más información sobre el Dynamic Provisioning , os aconsejo que os leáis el siguiente artículo:
Es importante indicar que los paquetes Helm disponen de dos ramas:
- Stable – es la versión estable.
- Incubator – es la versión de prueba, las cuales están a la espera para pasar a ser estables.
Lo primero que hay que hacer es montar el StorageClass, el cual es un volumen con persistencia. El almacenamiento que usará el StorageClass, se puede definir con diferentes tecnologías de almacenamiento, como pueden ser: Ceph RBD, ScaleIO, GlusterFS, etc…. Este post se enfocará en GlusterFS.
Kubernetes por si solo no puede comunicarse con GlusterFS, ya que Kubernetes usa RESTful en sus comunicaciones. A consecuencia de esto necesitamos una herramienta intermedia con la cual se comunicará Kubernetes con GlusterFS. Esta herramienta intermedia es Heketi, que no es más que un RESTful para poder gestionar el almacenamiento de GlusterFS.
Para poder realizar este post, partimos de la base de una plataforma de Kubernetes desplegada, tal y como se muestra en mi anterior post:
En definitiva, los servidores necesarios son los siguientes:
Los servidores de ub-nodo0-sbd y ub-nodo1-sbd, son los que forman la infraestructura de Kubernetes.
El esquema lógico será el siguiente:
Cosas a tener en cuenta
Hay varios puntos que hay que tener en cuenta antes de realizar el montaje:
En los servidores de GlusterFS, les he añadido a cada uno un disco (sdb) de 50GB en el cual se almacenaran los datos.
Cabe destacar que este tipo de montajes, es necesario como mínimo tres servidores de GlusterFS para un correcto funcionamiento. Si usamos menos de tres servidores, podremos observar el siguiente error: “Error: No space”.
También es importante que entre los servidores de GlusterFS hay resolución entre ellos, ya sea por DNS o añadiendo las entradas en el fichero de hosts.
Montaje de GlusterFS
El primer paso que hemos de realizar es el montaje del sistema de GlusterFS en tres o más servidores. En estos servidores desplegaremos GlusterFS, pero no realizaremos ningún tipo de configuración, ya que para esto se encargará Kubernetes mediante el RESTful de Heketi. Así que procederemos a la instalación en los tres servidores de GlusterFS:
apt-get update && apt-get install -y apt-transport-https
apt-get install -y software-properties-common
add-apt-repository ppa:gluster/glusterfs-3.12
apt-get update && apt-get install -y glusterfs-server thin-provisioning-tools
mkdir -p /data/heketi/{db,.ssh} && chmod 700 /data/heketi/.ssh
Una vez instalados los paquetes necesarios en nuestros servidores de GlusterFS, instalaremos la parte cliente en todos los nodos que queramos que accedan a nuestro Storage. En mi caso al sólo tener un nodo de Kubernetes, lo instalaré en el nodo ub-nodo1-sbd. Recordar que el servidor ub-nodo0-sbd es donde está ubicado el servidor master de Kubernetes y en este servidor no se despliega nada por defecto.
apt-get update && apt-get install -y apt-transport-https
apt-get install -y software-properties-common
add-apt-repository ppa:gluster/glusterfs-3.12
apt-get update && apt-get install -y glusterfs-client thin-provisioning-tools
mkdir -p /data/heketi/{db,.ssh} && chmod 700 /data/heketi/.ssh
Fijaros que tanto en los servidores de GlusterFS como en los nodos de Kubernetes, hemos realizado es mismo procedimiento, pero en los servidores de GlusterFS hemos instalado el paquete: “glusterfs-server” y en los nodos de Kubernetes se ha de instalar el paquete: “glusterfs-client”.
Revisaremos que nuesto cluster de Kubernetes esté funcionando correctamente y le añadiremos el label: “glusterfs” a los nodos de nuestro Kubernetes que vayan a gestionar el storage y en los cuales se vaya a desplegar el Helm que hayamos decidido. Esto es a consecuencia, de que el deployment que usaremos más adelante, simplemente se desplegará en los servidores de Kubernetes que tengan el label “glusterfs”. En mi caso es el servidor ub-nodo1-sbd y lo haremos de la siguiente manera:
root@ub-nodo0-sbd:~# kubectl get nodes root@ub-nodo0-sbd:~# kubectl label node ub-nodo1-sbd storagenode=glusterfs
Instalación de Heketi
Heketi se conecta a nuestro sistema de GlusterFS mediante el protocolo SSH, por eso lo que haremos es crear una clave SSH, para que Heketi pueda conectarse al GlusterFS y así poder crear los storages de una forma transparente y automática. En el momento de descargar la versión de Heketi, es importante verificar que estamos usando la última versión en su web oficial: https://github.com/heketi/heketi/releases
root@ub-nodo0-sbd:~# wget https://github.com/heketi/heketi/releases/download/v6.0.0/heketi-client-v6.0.0.linux.amd64.tar.gz
root@ub-nodo0-sbd:~# tar xzvf heketi-client-v6.0.0.linux.amd64.tar.gz
root@ub-nodo0-sbd:~# cp heketi-client/bin/heketi-cli /usr/local/sbin/
root@ub-nodo0-sbd:~# heketi-cli -v
root@ub-nodo0-sbd:~# mkdir -p /data/heketi/.ssh && chmod 700 /data/heketi/.ssh
root@ub-nodo0-sbd:~# ssh-keygen -t rsa -b 2048 -f /data/heketi/.ssh/id_rsa
root@ub-nodo0-sbd:~# for NODE in 172.26.0.218 172.26.0.219 172.26.0.220; do scp -r /data/heketi/.ssh/ root@${NODE}:/data/heketi; done
root@ub-nodo0-sbd:~# for NODE in 172.26.0.218 172.26.0.219 172.26.0.220; do cat /data/heketi/.ssh/id_rsa.pub | ssh root@${NODE} "cat >> /root/.ssh/authorized_keys"; done
Ahora nos descargaremos el deployment y el secret del despliegue de Heketi. Podremos observar que el deployment (heketi-deployment.json), se desplegará en los servidores con el label “glusterfs” y modificaremos el fichero de secret, en el cual pondremos nuestro password en base64.
root@ub-nodo0-sbd:~# wget https://raw.githubusercontent.com/psyhomb/heketi/master/kubernetes/heketi-deployment.json root@ub-nodo0-sbd:~# wget https://raw.githubusercontent.com/psyhomb/heketi/master/kubernetes/heketi-secret.yaml root@ub-nodo0-sbd:~# cat heketi-deployment.json | grep storagenode root@ub-nodo0-sbd:~# echo -n "password" | base64 root@ub-nodo0-sbd:~# vim heketi-secret.yaml
Una vez realizados los cambios y antes de desplegar los ficheros que nos hemos descargado, copiaremos las claves SSH en nuestros servidores de Kubernetes que hayamos etiquetado con el label “glusterfs”, que es mi caso es el nodo 1 (ub-nodo1-sbd).
Ahora solamente nos queda esperar a se descarguen y se cree el deployment de Heketi. Hemos de verificar que todo está funcionando de manera correcta de la siguiente forma:
root@ub-nodo0-sbd:~# kubectl get pods root@ub-nodo0-sbd:~# kubectl get svc -l glusterfs=heketi-service root@ub-nodo0-sbd:~# curl -s http://172.26.0.217:30537/hello
Al desplegar el pod de Heketi, este nos dará un puerto de acceso aleatorio. En mi caso ha sido el puerto 30537, el cual usaremos para poder comunicarnos con Heketi durante el post.
En el último comando podremos observar que Heketi nos saluda: “Hello from Heketi”. Ahora ya tenemos instalado Heketi en nuestra plataforma, seguidamente precederemos a la configuración de Heketi.
Configuración de Heketi
Una vez realizada la instalación de Heketi, procederemos a indicarle la topología, donde le indicaremos la lista de los nodos que forman parte del GlusterFS y los discos.
root@ub-nodo0-sbd:~# vim heketi-topology.json
{
"clusters": [
{
"nodes": [
{
"node": {
"hostnames": {
"manage": [
"172.26.0.218"
],
"storage": [
"172.26.0.218"
]
},
"zone": 1
},
"devices": [
"/dev/sdb"
]
},
{
"node": {
"hostnames": {
"manage": [
"172.26.0.219"
],
"storage": [
"172.26.0.219"
]
},
"zone": 2
},
"devices": [
"/dev/sdb"
]
},
{
"node": {
"hostnames": {
"manage": [
"172.26.0.220"
],
"storage": [
"172.26.0.220"
]
},
"zone": 3
},
"devices": [
"/dev/sdb"
]
}
]
}
]
}
Una vez creado el fichero y adaptado a nuestras necesidades, lo aplicaremos:
root@ub-nodo0-sbd:~# heketi-cli --user admin --secret password --server http://172.26.0.217:30537 topology load --json heketi-topology.json
Una vez aplicada nuestra configuración, podremos observar el resultado:
root@ub-nodo0-sbd:~# heketi-cli --user admin --secret password--server http://172.26.0.217:30537 topology info
Seguidamente extraeremos la configuración del Heketi y la aplicaremos:
root@ub-nodo0-sbd:~# heketi-cli --user admin --secret password --server http://172.26.0.217:30537 setup-openshift-heketi-storage --listfile heketi-storage.json root@ub-nodo0-sbd:~# kubectl apply -f heketi-storage.json
Verificaremos que se ha creado todo correctamente y lo borraremos, ya que lo que hemos provocado es que nos añada la base de datos de Heketi en nuestro sistema de GlusterFS:
root@ub-nodo0-sbd:~# kubectl get job root@ub-nodo0-sbd:~# kubectl delete -f heketi-storage.json
Eliminaremos los datos locales de los servidores, ya que nos interesa que use los datos que se han almacenado en nuestrop storage de GlusterFS y verificaremos que nos los ha creado en nuestro GlusterFS:
root@ub-nodo1-sbd:~# ls -la /data/heketi/db/heketi.db root@ub-nodo1-sbd:~# rm -rf /data/heketi/db/heketi.db root@ub-nodo1-sbd:~# mount.glusterfs 172.26.0.218:/heketidbstorage /data/heketi/db root@ub-nodo1-sbd:~# ls -la /data/heketi/db/heketi.db
Nos descargaremos el strorageClass y modificaremos el resturl y el clusterid con nuestros valores para que el sistema pueda acceder a nuestro sistema de GlusterFS.
root@ub-nodo0-sbd:~# wget https://raw.githubusercontent.com/psyhomb/heketi/master/kubernetes/heketi-storageclass.yaml root@ub-nodo0-sbd:~# heketi-cli --user admin --secret password --server http://172.26.0.217:30537 cluster list root@ub-nodo0-sbd:~# vim heketi-storageclass.yaml resturl: "http://172.26.0.217:30537" clusterid: "bb14cc9ae7865f48b7b03d6ef5912736" root@ub-nodo0-sbd:~# kubectl apply -f heketi-storageclass.yaml
Ahora lo que nos queda es crear nuestro PVC y PV en nuestro sistema de Kubernetes.
root@ub-nodo0-sbd:~# wget https://raw.githubusercontent.com/psyhomb/heketi/master/kubernetes/heketi-pvc.yaml root@ub-nodo0-sbd:~# kubectl apply -f heketi-pvc.yaml root@ub-nodo0-sbd:~# kubectl get pvc test-claim root@ub-nodo0-sbd:~# kubectl get pv root@ub-nodo0-sbd:~# heketi-cli --user admin --secret password --server http://172.26.0.217:30537 volume list
Le indicaremos a Kubernetes que este storage que hemos creado es el default. De esta manera cuando despleguemos el helm, usará este storage de manera automática:
root@ub-nodo0-sbd:~# kubectl get sc
root@ub-nodo0-sbd:~# kubectl describe storageclass slow | grep IsDefaultClass
root@ub-nodo0-sbd:~# kubectl patch storageclass slow -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
root@ub-nodo0-sbd:~# kubectl get sc
root@ub-nodo0-sbd:~# kubectl describe storageclass slow | grep IsDefaultClass
Helm
Una vez realizado la configuración de nuestro storage por defecto, descargaremos helm y lo actualizaremos:
root@ub-nodo0-bcn:~# curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh root@ub-nodo0-bcn:~# chmod 700 get_helm.sh root@ub-nodo0-bcn:~# ./get_helm.sh root@ub-nodo0-bcn:~# helm init root@ub-nodo0-bcn:~# helm init –upgrade
Crearemos la cuenta de servicio y actualizaremos helm, para que se apliquen los cambios realizados:
root@ub-nodo0-bcn:~# kubectl create serviceaccount --namespace kube-system tiller
root@ub-nodo0-bcn:~# kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
root@ub-nodo0-bcn:~# kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
root@ub-nodo0-bcn:~# helm init --service-account tiller –upgrade
Una vez acabados todos los pasos, simplemente actualizaremos nuestro repositorio de helm e instalaremos nuestro paquete. En este caso he instalado la DokuWiki, pero podéis probar cualquier otro paquete.
root@ub-nodo0-bcn:~# helm repo update root@ub-nodo0-bcn:~# helm search dokuwiki root@ub-nodo0-sbd:~# helm install stable/dokuwiki
Ahora solamente nos falta crear el ingress y configurar nuestro traefik para poder acceder a nuestra dokuwiki desplegada desde helm, tal y como he mostrado en posts anteriores:
https://www.jorgedelacruz.es/2018/01/09/kubernetes-traefik/
https://www.jorgedelacruz.es/2018/01/16/kubernetes-systemd-con-traefik-y-proxy-de-kubernetes/
Espero que os sirva de ayuda.


Muy currado, thx dude.
Tengo creado este pv y este pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-2b54cf82-4365-11e9-97a8-8ae35e6569e3 1Gi RWO Delete Bound default/gluster1 slow 46h
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/gluster1 Bound pvc-2b54cf82-4365-11e9-97a8-8ae35e6569e3 1Gi RWO slow 46h
El cual es usado por un pod con nginx.
Si deseo instalar con helm la dokuwiki del ejemplo, se me queda el pod sin crear con el error:
pod has unbound immediate PersistentVolumeClaims
¿Debo de crear un pvc por cada ‘aplicaión’ que desee instalar?
Gracias.