Migración de Cassandra a Kubernetes: características y soluciones

Migración de Cassandra a Kubernetes: características y soluciones

Regularmente nos encontramos con la base de datos Apache Cassandra y la necesidad de operarla dentro de una infraestructura basada en Kubernetes. En este material, compartiremos nuestra visión de los pasos necesarios, los criterios y las soluciones existentes (incluida una descripción general de los operadores) para migrar Cassandra a K8.

“Quien puede gobernar a una mujer también puede gobernar el Estado”

¿Quién es Casandra? Es un sistema de almacenamiento distribuido diseñado para gestionar grandes volúmenes de datos garantizando al mismo tiempo una alta disponibilidad sin un único punto de falla. El proyecto apenas necesita una larga introducción, por lo que solo daré las características principales de Cassandra que serán relevantes en el contexto de un artículo específico:

  • Cassandra está escrita en Java.
  • La topología de Cassandra incluye varios niveles:
    • Nodo: una instancia de Cassandra implementada;
    • Rack es un grupo de instancias de Cassandra, unidas por alguna característica, ubicadas en un mismo centro de datos;
    • Centro de datos: una colección de todos los grupos de instancias de Cassandra ubicadas en un centro de datos;
    • Un clúster es una colección de todos los centros de datos.
  • Cassandra usa una dirección IP para identificar un nodo.
  • Para acelerar las operaciones de escritura y lectura, Cassandra almacena algunos de los datos en la RAM.

Ahora, pasemos al posible paso real a Kubernetes.

Lista de verificación para la transferencia

Hablando de la migración de Cassandra a Kubernetes, esperamos que con la mudanza sea más conveniente de administrar. ¿Qué se necesitará para esto, qué ayudará con esto?

1. Almacenamiento de datos

Como ya se ha aclarado, Cassanda almacena parte de los datos en la RAM - en Tabla de memoria. Pero hay otra parte de los datos que se guarda en el disco, en el formulario SSTable. Se agrega una entidad a estos datos. Registro de confirmación — registros de todas las transacciones, que también se guardan en el disco.

Migración de Cassandra a Kubernetes: características y soluciones
Escribir diagrama de transacciones en Cassandra

En Kubernetes, podemos usar PersistentVolume para almacenar datos. Gracias a mecanismos probados, trabajar con datos en Kubernetes es cada año más fácil.

Migración de Cassandra a Kubernetes: características y soluciones
Asignaremos nuestro propio PersistentVolume a cada pod de Cassandra.

Es importante señalar que Cassandra en sí implica la replicación de datos y ofrece mecanismos integrados para ello. Por lo tanto, si está creando un clúster de Cassandra a partir de una gran cantidad de nodos, no es necesario utilizar sistemas distribuidos como Ceph o GlusterFS para el almacenamiento de datos. En este caso, sería lógico almacenar datos en el disco host usando discos persistentes locales o montaje hostPath.

Otra pregunta es si desea crear un entorno separado para desarrolladores para cada rama de funciones. En este caso, el enfoque correcto sería generar un nodo Cassandra y almacenar los datos en un almacenamiento distribuido, es decir. los mencionados Ceph y GlusterFS serán sus opciones. Entonces, el desarrollador estará seguro de que no perderá datos de prueba incluso si se pierde uno de los nodos del clúster de Kuberntes.

2. Supervisión

La opción prácticamente indiscutible para implementar la monitorización en Kubernetes es Prometheus (hablamos de esto en detalle en informe relacionado). ¿Cómo le va a Cassandra con los exportadores de métricas para Prometheus? Y, lo que es aún más importante, ¿con paneles de control compatibles con Grafana?

Migración de Cassandra a Kubernetes: características y soluciones
Un ejemplo de la aparición de gráficos en Grafana para Cassandra.

Sólo hay dos exportadores: jmx_exportador и casandra_exportadora.

Elegimos el primero para nosotros porque:

  1. JMX Exporter está creciendo y desarrollándose, mientras que Cassandra Exporter no ha podido obtener suficiente apoyo de la comunidad. Cassandra Exporter todavía no es compatible con la mayoría de las versiones de Cassandra.
  2. Puedes ejecutarlo como un agente java agregando una bandera -javaagent:<plugin-dir-name>/cassandra-exporter.jar=--listen=:9180.
  3. Hay uno para el tablero adecuado, que es incompatible con Cassandra Exporter.

3. Seleccionar primitivas de Kubernetes

De acuerdo con la estructura anterior del clúster Cassandra, intentemos traducir todo lo que se describe allí a la terminología de Kubernetes:

  • Nodo Cassandra → Cápsula
  • Cassandra Rack → Conjunto con estado
  • Cassandra Datacenter → grupo de StatefulSets
  • Casandra Clúster → ???

Resulta que falta alguna entidad adicional para administrar todo el clúster de Cassandra a la vez. Pero si algo no existe, ¡podemos crearlo! Kubernetes tiene un mecanismo para definir sus propios recursos para este propósito: Definiciones de recursos personalizados.

Migración de Cassandra a Kubernetes: características y soluciones
Declarar recursos adicionales para registros y alertas

Pero el recurso personalizado en sí no significa nada: después de todo, requiere controlador. Es posible que necesites buscar ayuda. Operador Kubernetes...

4. Identificación de vainas

En el párrafo anterior, acordamos que un nodo de Cassandra equivaldrá a un pod en Kubernetes. Pero las direcciones IP de los pods serán diferentes cada vez. Y la identificación de un nodo en Cassandra se basa en la dirección IP... Resulta que después de cada eliminación de un pod, el clúster de Cassandra agregará un nuevo nodo.

Hay una salida, y no sólo una:

  1. Podemos mantener registros por identificadores de host (UUID que identifican de forma única las instancias de Cassandra) o por direcciones IP y almacenarlos todos en algunas estructuras/tablas. El método tiene dos desventajas principales:
    • El riesgo de que se produzca una condición de carrera si dos nodos caen a la vez. Después del aumento, los nodos de Cassandra solicitarán simultáneamente una dirección IP de la mesa y competirán por el mismo recurso.
    • Si un nodo Cassandra ha perdido sus datos, ya no podremos identificarlo.
  2. La segunda solución parece un pequeño truco, sin embargo: podemos crear un Servicio con ClusterIP para cada nodo de Cassandra. Problemas con esta implementación:
    • Si hay muchos nodos en un clúster de Cassandra, tendremos que crear muchos Servicios.
    • La función ClusterIP se implementa a través de iptables. Esto puede convertirse en un problema si el clúster de Cassandra tiene muchos (1000... ¿o incluso 100?) nodos. A pesar de equilibrio basado en IPVS puede resolver este problema.
  3. La tercera solución es utilizar una red de nodos para los nodos de Cassandra en lugar de una red dedicada de pods habilitando la configuración hostNetwork: true. Este método impone ciertas restricciones:
    • Para reponer unidades. Es necesario que el nuevo nodo tenga la misma dirección IP que el anterior (en nubes como AWS, GCP esto es casi imposible de hacer);
    • Utilizando una red de nodos de clúster, comenzamos a competir por los recursos de la red. Por lo tanto, será problemático colocar más de un pod con Cassandra en un nodo del clúster.

5. Copias de seguridad

Queremos guardar una versión completa de los datos de un único nodo de Cassandra según un cronograma. Kubernetes proporciona una característica conveniente usando CronJob, pero aquí la propia Cassandra pone un freno a nuestras ruedas.

Déjame recordarte que Cassandra almacena algunos de los datos en la memoria. Para realizar una copia de seguridad completa, necesita datos de la memoria (Memtables) pasar al disco (SSMesas). En este punto, el nodo Cassandra deja de aceptar conexiones y se cierra por completo del clúster.

Después de esto, se elimina la copia de seguridad (instantánea) y el esquema se guarda (espacio de teclas). Y luego resulta que simplemente una copia de seguridad no nos proporciona nada: necesitamos guardar los identificadores de datos de los cuales era responsable el nodo Cassandra; estos son tokens especiales.

Migración de Cassandra a Kubernetes: características y soluciones
Distribución de tokens para identificar de qué datos son responsables los nodos de Cassandra

Puede encontrar un script de ejemplo para realizar una copia de seguridad de Cassandra de Google en Kubernetes en este enlace. El único punto que el script no tiene en cuenta es restablecer los datos en el nodo antes de tomar la instantánea. Es decir, la copia de seguridad no se realiza para el estado actual, sino para un estado un poco anterior. Pero esto ayuda a no dejar el nodo fuera de funcionamiento, lo que parece muy lógico.

set -eu

if [[ -z "$1" ]]; then
  info "Please provide a keyspace"
  exit 1
fi

KEYSPACE="$1"

result=$(nodetool snapshot "${KEYSPACE}")

if [[ $? -ne 0 ]]; then
  echo "Error while making snapshot"
  exit 1
fi

timestamp=$(echo "$result" | awk '/Snapshot directory: / { print $3 }')

mkdir -p /tmp/backup

for path in $(find "/var/lib/cassandra/data/${KEYSPACE}" -name $timestamp); do
  table=$(echo "${path}" | awk -F "[/-]" '{print $7}')
  mkdir /tmp/backup/$table
  mv $path /tmp/backup/$table
done


tar -zcf /tmp/backup.tar.gz -C /tmp/backup .

nodetool clearsnapshot "${KEYSPACE}"

Un ejemplo de un script bash para realizar una copia de seguridad de un nodo Cassandra

Soluciones listas para Cassandra en Kubernetes

¿Qué se utiliza actualmente para implementar Cassandra en Kubernetes y cuál de ellos se adapta mejor a los requisitos establecidos?

1. Soluciones basadas en gráficos StatefulSet o Helm

Usar las funciones básicas de StatefulSets para ejecutar un clúster de Cassandra es una buena opción. Utilizando el gráfico Helm y las plantillas Go, puede proporcionar al usuario una interfaz flexible para implementar Cassandra.

Esto normalmente funciona bien... hasta que sucede algo inesperado, como una falla en el nodo. Las herramientas estándar de Kubernetes simplemente no pueden tener en cuenta todas las funciones descritas anteriormente. Además, este enfoque es muy limitado en cuanto a su extensión para usos más complejos: reemplazo de nodos, respaldo, recuperación, monitoreo, etc.

Representantes:

Ambos gráficos son igualmente buenos, pero están sujetos a los problemas descritos anteriormente.

2. Soluciones basadas en Kubernetes Operador

Estas opciones son más interesantes porque brindan amplias oportunidades para gestionar el clúster. Para diseñar un operador Cassandra, como cualquier otra base de datos, un buen patrón es Sidecar <-> Controlador <-> CRD:

Migración de Cassandra a Kubernetes: características y soluciones
Esquema de gestión de nodos en un operador Cassandra bien diseñado

Echemos un vistazo a los operadores existentes.

1. Cassandra-operadora de instaclustr

  • GitHub
  • Preparación: Alfa
  • Licencia: Apache 2.0
  • Implementado en: Java

De hecho, este es un proyecto muy prometedor y en desarrollo activo de una empresa que ofrece implementaciones administradas de Cassandra. Como se describió anteriormente, utiliza un contenedor complementario que acepta comandos a través de HTTP. Escrito en Java, a veces carece de la funcionalidad más avanzada de la biblioteca client-go. Además, el operador no admite diferentes Racks para un mismo centro de datos.

Pero el operador tiene ventajas como soporte para monitoreo, administración de clústeres de alto nivel mediante CRD e incluso documentación para realizar copias de seguridad.

2. Navegador de Jetstack

  • GitHub
  • Preparación: Alfa
  • Licencia: Apache 2.0
  • Implementado en: Golang

Una declaración diseñada para implementar DB-as-a-Service. Actualmente admite dos bases de datos: Elasticsearch y Cassandra. Dispone de soluciones tan interesantes como el control de acceso a bases de datos vía RBAC (para ello dispone de su propio navegador-apiserver independiente). Un proyecto interesante que merecería la pena estudiar más de cerca, pero el último compromiso se hizo hace año y medio, lo que claramente reduce su potencial.

3. Cassandra-operadora de vgkowski

  • GitHub
  • Preparación: Alfa
  • Licencia: Apache 2.0
  • Implementado en: Golang

No lo consideraron “en serio”, ya que el último compromiso con el repositorio fue hace más de un año. Se abandona el desarrollo del operador: la última versión de Kubernetes reportada como compatible es la 1.9.

4. Cassandra-operadora de Rook

  • GitHub
  • Preparación: Alfa
  • Licencia: Apache 2.0
  • Implementado en: Golang

Un operador cuyo desarrollo no avanza tan rápido como nos gustaría. Tiene una estructura CRD bien pensada para la gestión de clústeres, resuelve el problema de identificar nodos usando Service con ClusterIP (el mismo "truco")... pero eso es todo por ahora. Actualmente no hay monitoreo ni copias de seguridad listas para usar (por cierto, estamos para monitorear lo tomamos nosotros mismos). Un punto interesante es que también puedes implementar ScyllaDB usando este operador.

NB: Utilizamos este operador con modificaciones menores en uno de nuestros proyectos. No se observaron problemas en el trabajo del operador durante todo el período de operación (~4 meses de operación).

5. CassKop de Orange

  • GitHub
  • Preparación: Alfa
  • Licencia: Apache 2.0
  • Implementado en: Golang

El operador más joven de la lista: el primer compromiso se realizó el 23 de mayo de 2019. Ya tiene en su arsenal una gran cantidad de funciones de nuestra lista, cuyos detalles se pueden encontrar en el repositorio del proyecto. El operador está construido sobre la base del popular operador-sdk. Admite monitoreo listo para usar. La principal diferencia con otros operadores es el uso. Complemento CassKop, implementado en Python y utilizado para la comunicación entre nodos de Cassandra.

Hallazgos

La cantidad de enfoques y posibles opciones para migrar Cassandra a Kubernetes habla por sí sola: el tema tiene demanda.

En esta etapa, puede probar cualquiera de los anteriores bajo su propia responsabilidad y riesgo: ninguno de los desarrolladores garantiza el 100% de funcionamiento de su solución en un entorno de producción. Pero ya muchos productos parecen prometedores para intentar utilizarlos en bancos de desarrollo.

¡Creo que en el futuro esta mujer en el barco será útil!

PS

Lea también en nuestro blog:

Fuente: habr.com

Añadir un comentario