Kubernetes Persistent Storage: Volumes and Storage Classes
Al implementar una aplicación que necesita retener datos, deberá crear un almacenamiento persistente. El almacenamiento persistente le permite almacenar datos de aplicaciones fuera del pod que ejecuta su aplicación. Esta práctica de almacenamiento le permite mantener los datos de la aplicación, incluso si falla la aplicación o se elimina.
Un volumen persistente (PV) es una pieza de almacenamiento en el clúster de Kubernetes, mientras que una reclamación de volumen persistente (PVC) es una solicitud de almacenamiento.
Hay dos formas de usar el almacenamiento persistente en Kubernetes:
- Usar un volumen persistente existente
- Aprovisionar dinámicamente nuevos volúmenes persistentes
Para usar un PV existente, su aplicación deberá usar un PVC que esté vinculado a un PV, y el PV debe incluir los recursos mínimos que requiere el PVC.
Para el aprovisionamiento de almacenamiento dinámico, su aplicación deberá usar un PVC que esté vinculado a un Storage Class. El Storage Class contiene la autorización para aprovisionar nuevos volúmenes persistentes.
Storage Class
Un PV puede especificar un StorageClass para vincular dinámicamente el PV y el PVC, donde el StorageClass específico se define a través de la propiedad storageClassName. Si no se especifica ningún PV con esta propiedad, solo se puede vincular a un PVC que no requiera una clase específica.
Volume Mode:
Kubernetes admite dos modos de volumen de volúmenes persistentes. Un valor válido para el modo de volumen puede ser Filesystemo Block. Filesystemes el modo predeterminado si el modo de volumen no está definido.
Access Mode:
ReadOnlyMany(ROX): permite ser montado por múltiples nodos en modo de solo lectura. ReadWriteOnce(RWO): permite ser montado por un solo nodo en modo lectura-escritura. ReadWriteMany(RWX): permite montar múltiples nodos en modo lectura-escritura.
Reclaim Policy:
Cuando el nodo ya no necesita almacenamiento persistente, las estrategias de recuperación que se pueden usar incluyen:
- Retain: lo que significa que el PV, hasta que se elimine, se mantiene vivo.
- Recycle: lo que significa que que el volumen se recicla para ser utilizado posteriormente.
- Delete: se eliminan los activos de almacenamiento asociados (como volúmenes de AWS EBS, GCE PD, Azure Disk y OpenStack Cinder).
Longhorn es un sistema de almacenamiento de bloques distribuido ligero, confiable y fácil de usar para Kubernetes.
Longhorn es un software gratuito de código abierto. Originalmente desarrollado por Rancher Labs, ahora se está desarrollando como un proyecto sandbox de Cloud Native Computing Foundation. Se puede instalar en cualquier clúster de Kubernetes con Helm, con kubectl o con la interfaz de usuario de Rancher.

Laboratorio: Kubernetes Horizontal Pod Autoscaling
Descripción
La presente guía ayuda a realizar la solución de almacenamiento persistente proporcionada por Rancher, a la vez que muestra como hacer uso de volumenes desde las aplicaciones.
Objetivos
- Realizar la instalación de Rancher Longhorn
- Crear una carga de trabajo con almacenamiento persistente
Antes de comenzar
- Contar con el acceso al ambiente del laboratorio
- Haber realizado la guía de Instalación Rancher Kubernetes Engine (RKE)
- Haber realizado la guía de Acceso a rancher y kubernetes cluster
- Instalar en los servidores los requerimientos de software:
# Ingrese al CLI del sistema operativo del servidor usado como **Bastion** con el usuario y la contraseña proporcionados.
ssh student-X-master -i student-X-private_key.pem
sudo yum install iscsi-initiator-utils -y
# Ingrese al CLI del sistema operativo del servidor usado como worker con el usuario y la contraseña proporcionados.
ssh student-X-worker -i student-X-private_key.pem
sudo yum install iscsi-initiator-utils -y
Laboratorio: Instalación de Rancher Longhorn, creación y asignación de volúmenes a un Deployment desde la Web Console
- Ingrese a a la Web Console de Rancher Server con las credenciales utilizadas durante la instalación
- Haga clic en ☰ luego en Cluster Management
- Vaya al clúster que creó cluster-users y haga clic en Explorar
- Haga clic en Cluster Tools (esquina inferior izquierda)
- Haga clic en el botón Install del recuadro de Longhorn
- Haga clic en el botón Next
- Explorar las diferentes opciones del formulario
- Explorar la personalización de la instalación mediante YAML, NO haga ningún cambio
- Haga clic en el botón Install
- Esperar a que finalice la instalación de Rancher Longhorn y que se muestre el siguiente mensaje: SUCCESS: helm upgrade --install=true --namespace=longhorn-system --timeout=10m0 .....
- Ingrese al menú Longhorn
- Explorar Longhorn - Manage storage system via UI
- Dirijase a Node, luego al menú del Nodo student-0-worker, después Edit Node and Disk
- Cambie a 5 el valor de Storage Reserved
- Presione el boton Save
- Regrese a Web Console de Rancher Server y haga clic en ☰ luego en Cluster Management
- Vaya al clúster que creó cluster-users y haga clic en Explorar
- Dirijase a Storage y luego a StorageClass
- Dar clic sobre el StorageClass llamado longhorn y explore las opciones de configuración
- Dirijase a Projects/Namespaces
- Dar clic en el botón Create Project
- En Name colocar project-storage
- Dar clic en el botón Create
- Dirijase a Projects/Namespaces
- Buscar el proyecto recien creado y dar clic en el botón Create Namespace
- En Name colocar example-storage
- Dar clic en el botón Create
- Verifique que el nuevo Namespace aparece listado dentro del proyecto project-storage
- Dar clic sobre example-storage
- vaya al menú Storage, luego a Persistent Volume Claims
- Dar clic en el botón Create
- En Namespace elejir el Namespace recien creado example-storage
- En Name colocar pvc-example
- En Request Storage colocar 1
- Dar clic en el botón Create y esperar a que el nuevo PVC aparezca en estado Bound
- Explorar los recursos PV y PVC creados
- Dirijase a Workloads
- Dar clic en el botón Create
- Elejir la opción Deployment
- En Namespace elejir el Namespace recien creado example-storage
- En Name colocar deployment-storage
- En General > Image > Conatiner Image colocar nginx:latest
- Dirijase a las opciones de Storage, luego en Add Volume elija Persistent Volume Claim
- En Persistent Volume Claim y luego Persistent Volume Claim elija pvc-example
- En Mount Point colocar /usr/share/nginx/html/
- Dar clic en el botón Create
- Verificar que el Deployment aparece en estado Active
- Dar clic en el Deployment deployment-storage
- Verificar que el Pod aparece en estado Running
- Dar clic en los tres puntos
- Elegir la opción Execute Shell
- Ejecutar comandos dentro del contenedor
df -h echo 'Kubernetes Persistent Storage: Volumes and Storage Classes' > /usr/share/nginx/html/index.html curl http://localhost/ - Dirijase a Pods y filtre la búsqueda por ** deployment-storage**
- Dar clic en los tres puntos
- Elegir la opción Delete
- Esperar a que el Pod se encuentre nuevamente en estado Running
- Dar clic en los tres puntos
- Elegir la opción Execute Shell
- Ejecutar los siguientes comandos dentro del contenedor para verificar que la información persiste:
df -h curl http://localhost/
Laboratorio: Creación y asignación de volúmenes a un Deployment de forma declarativa
Este laboratorio muestra cómo implementar un sitio de WordPress y una base de datos MySQL usando Kubernetes. Ambas aplicaciones usan PersistentVolumes y PersistentVolumeClaims para almacenar datos.
También haremos uso de Kustomize, en otros módulos se revisa a profundidad el uso de esta herramienta.
Kustomize es una utilidad independiente para personalizar objetos de Kubernetes a través de un archivo de personalización. Desde la versión 1.14, Kubectl también admite la gestión de objetos de Kubernetes mediante un archivo de personalización.
-
Ingresar al ambiente de laboratorio en el servidor student-#-aio al cluster de usuarios de Kubernetes, exportar la variable de ambiente KUBECONFIG
export KUBECONFIG=~/rke-cluster-users/kube_config_cluster.yml -
Examinar el recurso StorageClass llamado longhorn, el cual fue creado durante el proceso de instalación de Rancher Longhorn, este recurso permite la creación dinámica de volúmenes persistentes.
kubectl get storageclasskubectl describe storageclass longhorn -
Verifique la estructura en formato YAML del recurso StorageClass llamado Longhorn
kubectl get storageclass longhorn -o yaml -
Crear un directorio de trabajo e ingresar al mismo, en este directorio se crearan todos los archivos necesarios
mkdir example-persistentappcd example-persistentapp -
Crear un nuevo namespace llamado example-persistentapp
kubectl create ns example-persistentapp -
Establcer el nuevo namespace por defecto en el contexto actual:
kubectl config set-context --current --namespace=example-persistentapp -
Ejecutar el siguiente comando para crear un nuevo archivo llamado kustomization.yaml, la herramienta Kustomize hará uso de él para crear un recurso tipo Secret que contendrá una contraseña de la base de datos MYSQL. En otros módulos se revisa a profundidad el uso de esta herramienta.
cat <<EOF >./kustomization.yaml secretGenerator: - name: mysql-pass literals: - password=P3rsist3ntAbb EOF -
Crear el siguiente manifiesto con nombre mysql-deployment.yaml, el cual describe un Deployment de MySQL de instancia única. El contenedor de MySQL monta PersistentVolume en /var/lib/mysql. La variable de entorno MYSQL_ROOT_PASSWORD establece la contraseña de la base de datos, valor proporcionado por el Secret.
apiVersion: v1 kind: Service metadata: name: wordpress-mysql labels: app: wordpress spec: ports: - port: 3306 selector: app: wordpress tier: mysql clusterIP: None --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim labels: app: wordpress spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: wordpress-mysql labels: app: wordpress spec: selector: matchLabels: app: wordpress tier: mysql strategy: type: Recreate template: metadata: labels: app: wordpress tier: mysql spec: containers: - image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pv-claim -
Crear el siguiente manifiesto con nombre wordpress-deployment.yaml, el cual describe un Deployment de WordPress de instancia única. El contenedor de WordPress monta PersistentVolume en /var/www/html los archivos de datos del sitio web. La variable de entorno WORDPRESS_DB_HOST establece el nombre del Servicio MySQL definido anteriormente, y WordPress accederá a la base de datos por Servicio. La variable de entorno WORDPRESS_DB_PASSWORD establece la contraseña de la base de datos a partir del Secret generado con Kustomize.
apiVersion: v1 kind: Service metadata: name: wordpress labels: app: wordpress spec: ports: - port: 80 selector: app: wordpress tier: frontend type: ClusterIP --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wp-pv-claim labels: app: wordpress spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: selector: matchLabels: app: wordpress tier: frontend strategy: type: Recreate template: metadata: labels: app: wordpress tier: frontend spec: containers: - image: wordpress:4.8-apache name: wordpress env: - name: WORDPRESS_DB_HOST value: wordpress-mysql - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password ports: - containerPort: 80 name: wordpress volumeMounts: - name: wordpress-persistent-storage mountPath: /var/www/html volumes: - name: wordpress-persistent-storage persistentVolumeClaim: claimName: wp-pv-claim -
Ejecutar el siguiente comando para agregar los archivos anteriores a kustomization.yaml. En otros módulos se revisa a profundidad el uso de esta herramienta.
El archivo completo debe verse de la siguiente manera:cat <<EOF >>./kustomization.yaml resources: - mysql-deployment.yaml - wordpress-deployment.yaml EOFsecretGenerator: - name: mysql-pass literals: - password=P3rsist3ntAbb resources: - mysql-deployment.yaml - wordpress-deployment.yaml -
Ahora el archivo kustomization.yaml ya contiene todos los recursos para implementar un sitio de WordPress y una base de datos MySQL. Realizar la creación de todos los recursos utilizando el siguente comando:
La salida del comando anterior debe ser similar a la siguiente:kubectl apply -k ./secret/mysql-pass-h9kd89h556 created service/wordpress created service/wordpress-mysql created persistentvolumeclaim/mysql-pv-claim created persistentvolumeclaim/wp-pv-claim created deployment.apps/wordpress created deployment.apps/wordpress-mysql created -
Revisar la creación del recurso tipo secret
kubectl get secrets -
Revisar la creación del recurso tipo PV y PVC
kubectl get pvLa respuesta debería ser así:kubectl get pvcNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mysql-pv-claim Bound pvc-8cbd7b2e-4044-11e9-b2bb-42010a800002 1Gi RWO standard 77s wp-pv-claim Bound pvc-8cd0df54-4044-11e9-b2bb-42010a800002 1Gi RWO standard 77s - Verifique que los Pode se estén ejecutando con el siguiente comando:
La respuesta debería ser así:
kubectl get podsNAME READY STATUS RESTARTS AGE wordpress-9f9cd7c76-wppqh 1/1 Running 0 24s wordpress-mysql-67497dc7c8-7tcmd 1/1 Running 0 24s - Verificar la creación de los recursos tipo Services
kubectl get svc - Extraer el Wildcard Domain para las aplicaciones en el nodo Worker, con la información obtenida se podrá exponer el servicio de Wordpress
# Ingresar al Nodo Worker ssh student-X-worker -i ~/student-X-private_key.pem # Establecer el Wildcard Domain: CLUSTER_WILDCARD=$(curl http://showip.net|tr '.' '-').nip.io # Ejecutar el siguiente comando y copiar la URL resultado para utilizarla mas adelante: echo http://wordpress.$CLUSTER_WILDCARD # Salir del servidor Worker exit[student@student-X-worker ~]$ exit logout Connection to student-X-worker closed. -
Crear el Ingress con la información extraida del Worker, este paso debe ejecutarse en el servidor student-#-aio, crear un archivo llamado wordpress-ingress.yaml con el siguiente contenido:
Asegurese de reemplazar la variable $CLUSTER_WILDCARD según corresponda con la información obtenida.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wordpress-ingress namespace: example-persistentapp spec: rules: - host: wordpress.$CLUSTER_WILDCARD http: paths: - backend: service: name: wordpress port: number: 80 path: / pathType: Prefix -
Crear el recurso tipo Ingress para exponer el servicio de Wordpress creado anteriormente
kubectl apply -f wordpress-ingress.yaml -
Verificar el Ingress creado correctamente con el siguiente comando
kubectl get ingress -
Abrir una nueva ventana del Navegador Web y dirigirse a la siguiente URL:
Deberá mostrarse la página inicial para comenzar con la instalación de Wordpress. Cuando Wordpress haya sido instalado y este funcionando correctamente, aunque se eliminen los Pods, la información no se pederá porque se encuentra en volúmenes persistentes. La instalación y configuración de Wordpress esta fuera de alcance en esta práctica.# Reemplazar el valor de $CLUSTER_WILDCARD http://example-ingress.$CLUSTER_WILDCARD -
Limpiar al ambiente, podemos realizarlo eliminando el Namespace complementamente y esperando unos minutos a que finalice.
kubectl delete ns example-persistentapp