Skip to content

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.

Rancher Storage

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

  1. Ingrese a a la Web Console de Rancher Server con las credenciales utilizadas durante la instalación
  2. Haga clic en luego en Cluster Management
  3. Vaya al clúster que creó cluster-users y haga clic en Explorar
  4. Haga clic en Cluster Tools (esquina inferior izquierda)
  5. Haga clic en el botón Install del recuadro de Longhorn
  6. Haga clic en el botón Next
  7. Explorar las diferentes opciones del formulario
  8. Explorar la personalización de la instalación mediante YAML, NO haga ningún cambio
  9. Haga clic en el botón Install
  10. 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 .....
  11. Ingrese al menú Longhorn
  12. Explorar Longhorn - Manage storage system via UI
  13. Dirijase a Node, luego al menú del Nodo student-0-worker, después Edit Node and Disk
  14. Cambie a 5 el valor de Storage Reserved
  15. Presione el boton Save
  16. Regrese a Web Console de Rancher Server y haga clic en luego en Cluster Management
  17. Vaya al clúster que creó cluster-users y haga clic en Explorar
  18. Dirijase a Storage y luego a StorageClass
  19. Dar clic sobre el StorageClass llamado longhorn y explore las opciones de configuración
  20. Dirijase a Projects/Namespaces
  21. Dar clic en el botón Create Project
  22. En Name colocar project-storage
  23. Dar clic en el botón Create
  24. Dirijase a Projects/Namespaces
  25. Buscar el proyecto recien creado y dar clic en el botón Create Namespace
  26. En Name colocar example-storage
  27. Dar clic en el botón Create
  28. Verifique que el nuevo Namespace aparece listado dentro del proyecto project-storage
  29. Dar clic sobre example-storage
  30. vaya al menú Storage, luego a Persistent Volume Claims
  31. Dar clic en el botón Create
  32. En Namespace elejir el Namespace recien creado example-storage
  33. En Name colocar pvc-example
  34. En Request Storage colocar 1
  35. Dar clic en el botón Create y esperar a que el nuevo PVC aparezca en estado Bound
  36. Explorar los recursos PV y PVC creados
  37. Dirijase a Workloads
  38. Dar clic en el botón Create
  39. Elejir la opción Deployment
  40. En Namespace elejir el Namespace recien creado example-storage
  41. En Name colocar deployment-storage
  42. En General > Image > Conatiner Image colocar nginx:latest
  43. Dirijase a las opciones de Storage, luego en Add Volume elija Persistent Volume Claim
  44. En Persistent Volume Claim y luego Persistent Volume Claim elija pvc-example
  45. En Mount Point colocar /usr/share/nginx/html/
  46. Dar clic en el botón Create
  47. Verificar que el Deployment aparece en estado Active
  48. Dar clic en el Deployment deployment-storage
  49. Verificar que el Pod aparece en estado Running
  50. Dar clic en los tres puntos
  51. Elegir la opción Execute Shell
  52. Ejecutar comandos dentro del contenedor
    df -h
    echo 'Kubernetes Persistent Storage: Volumes and Storage Classes' > /usr/share/nginx/html/index.html
    curl http://localhost/
    
  53. Dirijase a Pods y filtre la búsqueda por ** deployment-storage**
  54. Dar clic en los tres puntos
  55. Elegir la opción Delete
  56. Esperar a que el Pod se encuentre nuevamente en estado Running
  57. Dar clic en los tres puntos
  58. Elegir la opción Execute Shell
  59. 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.

  1. 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
    

  2. 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 storageclass
    
    kubectl describe storageclass longhorn
    

  3. Verifique la estructura en formato YAML del recurso StorageClass llamado Longhorn

    kubectl get storageclass longhorn -o yaml
    

  4. Crear un directorio de trabajo e ingresar al mismo, en este directorio se crearan todos los archivos necesarios

    mkdir example-persistentapp
    
    cd example-persistentapp
    

  5. Crear un nuevo namespace llamado example-persistentapp

    kubectl create ns example-persistentapp
    

  6. Establcer el nuevo namespace por defecto en el contexto actual:

    kubectl config set-context --current --namespace=example-persistentapp
    

  7. 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
    

  8. 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
    

  9. 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
    

  10. 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.

    cat <<EOF >>./kustomization.yaml
    resources:
      - mysql-deployment.yaml
      - wordpress-deployment.yaml
    EOF
    
    El archivo completo debe verse de la siguiente manera:
    secretGenerator:
    - name: mysql-pass
      literals:
      - password=P3rsist3ntAbb
    resources:
      - mysql-deployment.yaml
      - wordpress-deployment.yaml
    

  11. 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:

    kubectl apply -k ./
    
    La salida del comando anterior debe ser similar a la siguiente:
    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
    

  12. Revisar la creación del recurso tipo secret

    kubectl get secrets
    

  13. Revisar la creación del recurso tipo PV y PVC

    kubectl get pv
    
    kubectl get pvc
    
    La respuesta debería ser así:
    NAME             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
    

  14. Verifique que los Pode se estén ejecutando con el siguiente comando:
    kubectl get pods
    
    La respuesta debería ser así:
    NAME                               READY   STATUS    RESTARTS   AGE
    wordpress-9f9cd7c76-wppqh          1/1     Running   0          24s
    wordpress-mysql-67497dc7c8-7tcmd   1/1     Running   0          24s
    
  15. Verificar la creación de los recursos tipo Services
    kubectl get svc
    
  16. 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.
    
  17. 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:

    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
    
    Asegurese de reemplazar la variable $CLUSTER_WILDCARD según corresponda con la información obtenida.

  18. Crear el recurso tipo Ingress para exponer el servicio de Wordpress creado anteriormente

    kubectl apply -f wordpress-ingress.yaml
    

  19. Verificar el Ingress creado correctamente con el siguiente comando

    kubectl get ingress
    

  20. Abrir una nueva ventana del Navegador Web y dirigirse a la siguiente URL:

    # Reemplazar el valor de $CLUSTER_WILDCARD
    http://example-ingress.$CLUSTER_WILDCARD
    
    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.

  21. Limpiar al ambiente, podemos realizarlo eliminando el Namespace complementamente y esperando unos minutos a que finalice.

    kubectl delete ns example-persistentapp