Nueva entrada sobre la gestión automática de despliegues vía Kubernetes. Vamos a explicar la gestión de almacenamiento y vamos a montar nuestro primer contenedor de aplicaciones para la base de datos.
El objetivo de esta entrada es crear un Persistent Volume, reclamar una parte vía Persistent Volume Claim y asociarlo a un pod, el cual contendrá la base de datos MongoDB. Hasta ahora los despliegues que habíamos hecho no hemos tocado los fichero yaml de configuración, puesto que no lo hemos necesitado, ahora vamos a crear nosotros cuatro para gestionar este volumen y que la base de datos se almacene en el volumen indicado.
Para la reserva de espacio la hemos hecho en un sistema de archivos montado en red y por esta razón tuvimos que generar la imagen de Hyperkube con el paquete nfs-common , para que el cluster tuviera acceso al disco duro de red.
Recomendamos, instalar el paquete nfs-common en cada nodo (incluido el master) para poder ver desde cada nodo el disco de red.
$ apt-get install nfs-common $ showmount -e ip_NFS
Primero vemos la creación del PV (Persistent Volume), con este vamos a darle al cluster un sitio donde guardar información:
apiVersion: v1 kind: PersistentVolume metadata: name: pv0001 spec: capacity: storage: 10Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Recycle nfs: path: /volume2/kubernetes server: ip_NFS
Aquí le estamos diciendo que necesitamos un PV de 10Gigas, que pueda ser accedido por varios a la vez y en el path del servidor NFS indicado vía dirección IP. Es importante señalar que en el gestor de servidor de NFS el path debe ser accesible y con los permisos NFS necesarios.
Ahora vamos a crear el PVC (Persistent Volume Claim), un anclaje para que MongoDB guarde sus datos:
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: claim-mongo spec: accessModes: - ReadWriteMany resources: requests: storage: 2Gi
Al punto claim-mongo , le estamos pidiendo que guarde 2Gigas para los datos.
Para introducirlos en el sistema Kubernetes, lo podemos hacer con el «+» de la esquina superior derecha o con la siguiente pantalla
En el botón DEPLOY AN APP:
Sobre los tres puntos «···», seleccionamos primero el pv.yaml y luego el pvc.yaml .
Con la siguiente instrucción, revisamos que todo haya ido correctamente:
$ kubectl get pv,pvc -o wide NAME CAPACITY ACCESSMODES STATUS CLAIM REASON AGE pv0001 10Gi RWX Bound default/claim-mongo 4d NAME STATUS VOLUME CAPACITY ACCESSMODES AGE claim-mongo Bound pv0001 2Gi RWX 4d
Tenemos el PV y el PVC asociado, el STATUS es Bound, que significado que están alineados.
Ahora mismo, desde los contenedores podemos acceder al sistema externo de ficheros, como si estuvieran dentro de los contenedores. Vamos a verlo con un ejemplo para MongoDB.
apiVersion: v1 kind: ReplicationController metadata: labels: name: mongo name: mongo-controller spec: replicas: 1 template: metadata: labels: name: mongo spec: containers: - image: mangoraft/mongodb-arm name: mongo ports: - name: mongo containerPort: 27017 hostPort: 27017 env: - name: "AUTH" value: "no" volumeMounts: - name: mongo-persistent-storage mountPath: /data/db volumes: - name: mongo-persistent-storage persistentVolumeClaim: claimName: claim-mongo
Por partes, como decía el otro, aquí tenemos un RC (Replication Controller), esto es un gestionador de contenedores que nos va a permitir escalar y soportar fallos de MongoDB de forma sencilla. Por ahora, le estoy diciendo que tenga solo una replica, por tanto desplegará solo un pod, con nombre mongo .
El contenedor monta la imagen para procesadores arm de mongodb, generada por mangoraft , que esta publicada en Docker Hub. Dicho contenedor va a exponer el puesto 27017 al resto del clúster para el acceso a la base de datos. Le indicamos que dichas conexiones sean sin autorización, para facilitar la tarea.
¿Dónde va a guardar los datos mongo? Lo va a hacer en el directorio /data/db del contenedor, del pequeño linux que genera la imagen de mangoraft . Dicho directorio esta ubicado en el PVC claim-mongo. El cual, a su vez, esta en el recurso NFS que le hemos indicado antes. De esta manera, conseguimos guardar en un recurso de red los datos de la base de datos del contenedor, que ahora mismo solo tiene una replica pero que podría escalarse a 2, 4 o 15 replicas y se almacenarían los datos igual.
Ahora tenemos el RC, con una imagen de MongoDB corriendo pero ¿eso lo ve el resto del clúster? La respuesta es NO. Para ello necesitamos asignarle un servicio con el que pueda interactuar el resto del clúster.
apiVersion: v1 kind: Service metadata: labels: name: mongo name: mongo spec: ports: - port: 27017 targetPort: 27017 selector: name: mongo
El proceso de carga es el mismo que anteriormente, desde la pantalla de despliegue, subir y cargar primero el db-controller.yaml y luego el db-service.yaml . En este caso el orden es importante.
Vamos a consultar el estado de los RC y los servicios expuestos en el clúster:
$ kubectl get rc,svc -o wide NAME DESIRED CURRENT AGE CONTAINER(S) IMAGE(S) SELECTOR mongo-controller 1 1 1d mongo mangoraft/mongodb-arm name=mongo NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR mongo 10.0.0.158 <none> 27017/TCP 1d name=mongo
¿Incidencias? Puede haber, en algunos casos si el contenedor se reinicia, y al intentar hacer «reconnect» falla, es un fallo que aún estamos buscando si es por la imagen, o por el NFS. Pero la solución es eliminar a mano los ficheros de la BD en el NFS. Es una solución ahora, no si existen datos que quieras conservar.
Contadnos vuestras experiencias en los comentarios, y volvemos a dar las gracias a Diego Barrio (@guili) por su ayuda en el camino.