Ceph & Rook - Kit de Supervivencia para K8s Admins
Conectando Cluster Externo CEPH w/Rook Operator en Kubernetes
Objetivo
Administrar un cluster Ceph externo a nuestro cluster de Kubernetes, utilizando Rook Operator y su csi-rbdplugin (RADOS)
Intro
En un cluster de Kubernetes los pods, o mejor dicho los contenedores dentro de nuestros pods, son stateless por definición, pero necesitamos almacenar y persistir información para disponibilizar a otros servicios/usuarios/APIs etc
La solución a este requerimiento es un objeto llamado Persistent Volume Claim o PVC, es lo que se recomienda en el mundo de Kubernetes para manejar aplicaciones stateful, con un PVC un pod puede pedir conectarse a storage (en forma de volúmenes) que existen, tienen un ciclo de vida y se gestionan de manera totalmente independiente al Pod que lo solicita.
Los PVC junto a las SC tienen la ventaja de desacoplar la complejidad de la implementación de storage de ciertas características y al mismo tiempo proveer una interface amigable para que el Dev team de cualquier compañía pueda consumir storage fácilmente, por ejemplo, los Cloud Engineers/SRE/Devops/Platform Engineers pueden aprovisionar volúmenes, y los developers pueden solicitar estos volúmenes y utilizarlos sin conocer detalles de la implementación de estos volúmenes y sus StorageClasses
Resumiendo PVC:
-
PVC: o PersistenVolumeClaim son solicitudes de almacenamiento por parte de un Pod, los PVC se montan en dichos pods y responden a una StorageClass.
-
PV: o PersistentVolume son los volúmenes propiamente dichos creados manualmente por los k8s admin o dinámicamente por un StorageClass asociado a un PVC.
-
StorageClass: son los objetos que tienen la configuración fina/detallada y agrupada de una clase de volumen específica, podemos crear varias, es común configurarlas por velocidad, así podemos tener una SC para volúmenes de alta velocidad de acceso y SC para realizar operaciones en donde no es necesario contar con alta velocidad de acceso de datos
Que es Ceph?
Ceph es un sistema de almacenamiento distribuido, escalable y de alto rendimiento sin SPOF (único punto de fallo), que significa todo esto? que es una muy buena opción a la hora de resolver el almacenamiento de aplicaciones stateful y además con HA (alta disponibilidad)
Ceph no es un solo objeto, es una familia de componentes:
-
Ceph Monitors (MON): son responsables de formar los QUÓRUM del Ceph cluster, todos los nodos del cluster informan y comparten información sobre sus cambios de estado.
-
Object Storage Daemon (OSD): son responsables de almacenar objetos en sistemas de archivo locales y proporcionar acceso a ellos a través de la red, por lo general un OSD está vinculado a un disco físico en el cluster; los Ceph Clients interactúan directamente con los OSD.
-
Ceph Manager (MGR): es el admin de todo, y a su vez nos ofrece soluciones de integración con otras tools de administración de storage.
-
RADOS: o Reliable Autonomic Distributed Object Store, es una solución de storage Open Source y es el núcleo de los clusters de almacenamiento Ceph, RADOS se asegura de que los datos almacenados sean consistentes, y también realiza replicación de datos, detección de errores, etc.
IMPORTANTE: para leer/escribir datos desde/hacia un Ceph cluster, un Ceph Client se debe comunicar en primer lugar con los MON de Ceph para obtener la copia más reciente del “clusterMap”, el cual contiene la topología del cluster, así como las ubicaciones de almacenamiento de datos, los CephClients utilizan el ClusterMap para determinar con qué OSD interactuar e iniciar una conexión
Que es Rook?
Rook es un Operator que administra Ceph clusters por vos, hace que todo sea más sencillo, lo hace mediante la instalación de varios CRDs y un Controller custom para implementar y administrar recursos personalizados como por ejemplo un CephCluster (literalmente pueden hacer k get cephcluster) una maravilla del mundo mundial
al igual que Ceph, Rook es una familia de componentes:
-
Rook Operator: es el corazón de Rook, este operator es un pod simple de un solo contenedor que arranca automáticamente los clusters de storage y supervisa los daemons de storage para garantizar la salud de dichos clusters.
-
Rook Agents: se ejecutan en los nodos de almacenamiento y configura un plugin que se integra con el CSI de nuestro Kubernetes
-
Rook Discover: escucha conexiones de los clientes hacia los nodos del ceph cluster
Instalación y Configuración
Colectar Información en el Cluster CEPH externo
El objetivo es conectar a nuestro cluster de Kubernetes con un cluster Ceph externo, es por esto que primero necesitamos recolectar información del cluster Ceph que nos va a servir para establecer la conexión.
Una vez dentro de uno de los nodos Ceph vamos a correr este script, de la siguiente manera:
python3 create-external-cluster-resources.py --rbd-data-pool-name <my-pool> --format <bash> --namespace <ns>
- rbd-data-pool-name: el nombre de nuestro pool Ceph
- format: el formato de salida de nuestro script
- namespace: el ns donde vamos a tener corriendo nuestro rook operator y el objeto cephcluster para administrar la conexión
Ejemplo de salida del script:
export NAMESPACE=ns
export ROOK_EXTERNAL_FSID=12345678-1111-2222-3333-5555566666
export ROOK_EXTERNAL_USERNAME=client.healthchecker
export ROOK_EXTERNAL_CEPH_MON_DATA=server=192.168.100.50:6789
export ROOK_EXTERNAL_USER_SECRET=jknwehnofuiyoiuewfqouiqouryouhuxeR36+A==
export CSI_RBD_NODE_SECRET=khqucqwtbybtybtyootceftbebtioetioM8/XKytDFe2A==
export CSI_RBD_NODE_SECRET_NAME=csi-rbd-node
export CSI_RBD_PROVISIONER_SECRET=hjknafbgcqbwebgyegbyrogeogoweiuglqweA7w==
export CSI_RBD_PROVISIONER_SECRET_NAME=csi-rbd-provisioner
export MONITORING_ENDPOINT=192.168.100.51
export MONITORING_ENDPOINT_PORT=9283
export RBD_POOL_NAME=mi-pool
export RGW_POOL_PREFIX=default
Instalar Rook en el Cluster de Kubernetes
Manifests Way
- Deployar Rook Commons
k apply -f common.yaml
- Deployar Rook Custom Resources
k apply -f crds.yaml
- Deployar Rook Operator
k apply -f operator.yaml
- Deployar Rook Common External
k apply -f common-external.yaml
- Deployar Rook Custer External
k apply -f cluster-external.yaml
Helm Way
Rook actualmente mantiene 2 charts, uno para la instalación del Rook Operator y otro con los CRDS, SC y demás objetos necesarios con los cuales el Operator va a interactuar dependiendo de lo que queramos hacer, ya que con Rook podemos deployar nuestro cluster Ceph dentro del cluster k8s o administrar uno pre-existente externo al cluster de k8s
-
Rook Ceph Operator:
helm repo add rook-release https://charts.rook.io/release helm install --create-namespace --namespace rook-ceph rook-ceph rook-release/rook-ceph -f values.yaml
-
Rook Ceph Cluster:
helm repo add rook-release https://charts.rook.io/release helm install --create-namespace --namespace rook-ceph rook-ceph-cluster \ --set operatorNamespace=rook-ceph rook-release/rook-ceph-cluster -f values-override.yaml
IMPORTANTE: crear el values-override basados en el archivo values.yaml
Conectamos Kubernetes a un Cluster Ceph Externo
En este punto ya tendremos varios pods en estado running, incluyendo el rook operator, los plugins y provisioners de rbd y cephfs, además de un objeto llamado cephcluster, es decir podemos hacer algo como:
k get cephcluster
Y veremos un objeto cephcluster integrado a nuestra API k8s gracias a la magia de los CRD’s
En este punto lo veremos en estado desconectado, ahora el siguiente paso es sincronizar nuestro objeto k8s cephcluster con nuestro cluster real de Ceph que se encuentra fuera del cluster k8s, para ello vamos a setear todas las variables que nos arrojó el script en el cluster de Ceph y luego vamos a correr un script de import.
- Copiar y pegar el resultado del script que corrimos en el cluster externo Ceph
- Correr el script de import de Rook
. import-external-cluster.sh
-
Ahora deberíamos ver nuestro cephcluster en k8s en estado conectado
$ k -n rook-ceph-external get CephCluster NAME DATADIRHOSTPATH MONCOUNT AGE STATE HEALTH rook-ceph-external /var/lib/rook 162m Connected HEALTH_OK
-
El script también creó un StorageClass para usarlo tanto para RBD (RADOS) o CEPHFS con sus nombres correspondientes
Probemos todo
Creamos un PVC basado en el SC RBD (RADOS) que creó el script de import con el siguiente manifest:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: ceph-rbd
Ahora creamos un Pod que consuma nuestro PVC creado anteriormente
apiVersion: v1
kind: Pod
metadata:
name: csirbd-demo-pod
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- name: mypvc
mountPath: /var/lib/www/html
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: rbd-pvc
readOnly: false
Veremos como el PVC crea un PV de forma dinámica utilizando el SC especificado
También podemos ahorrarnos la creación del pvc por separado y probar con un Pod efimero:
kind: Pod
apiVersion: v1
metadata:
name: csi-rbd-demo-ephemeral-pod
spec:
containers:
- name: web-server
image: docker.io/library/nginx:latest
volumeMounts:
- mountPath: "/myspace"
name: mypvc
volumes:
- name: mypvc
ephemeral:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "ceph-rbd"
resources:
requests:
storage: 1Gi
Este manifest va a crear un PVC usando el nombre del Pod con la diferencia que dicho PVC tendrá el mismo ciclo de vida que el Pod.
Fuente
Material Extra: Curso “Devops en 5 Pasos” Disponible en Udemy
Temas:
- Docker
- Kubernetes
- MultiCloud (AWS - Azure - GCP)
- IaC (Terraform, Cloud Formation, ARM Templates, Cloud Resource Manager)
- CI/CD Pipelines (GitlabCI, Azure Devops, CircleCI)
Descripción completa: Detalle y enlaces del curso