Migración de Cassandra a Kubernetes: características e solucións

Migración de Cassandra a Kubernetes: características e solucións

Atopámonos regularmente coa base de datos Apache Cassandra e a necesidade de operala dentro dunha infraestrutura baseada en Kubernetes. Neste material, compartiremos a nosa visión dos pasos necesarios, criterios e solucións existentes (incluída unha visión xeral dos operadores) para migrar Cassandra a K8s.

"Quen pode gobernar unha muller tamén pode gobernar o Estado"

Quen é Cassandra? É un sistema de almacenamento distribuído deseñado para xestionar grandes volumes de datos ao tempo que se garante unha alta dispoñibilidade sen un único punto de falla. O proxecto dificilmente necesita unha introdución longa, polo que darei só as características principais de Cassandra que serán relevantes no contexto dun artigo específico:

  • Cassandra está escrita en Java.
  • A topoloxía Cassandra inclúe varios niveis:
    • Node: unha instancia de Cassandra despregada;
    • Rack é un grupo de instancias de Cassandra, unidas por algunha característica, situadas nun mesmo centro de datos;
    • Centro de datos: unha colección de todos os grupos de instancias de Cassandra situadas nun centro de datos;
    • Clúster é unha colección de todos os centros de datos.
  • Cassandra usa un enderezo IP para identificar un nodo.
  • Para acelerar as operacións de escritura e lectura, Cassandra almacena algúns dos datos na memoria RAM.

Agora, ao cambio potencial real a Kubernetes.

Lista de verificación para a transferencia

Falando da migración de Cassandra a Kubernetes, esperamos que coa mudanza sexa máis cómodo de xestionar. Que será necesario para iso, que vai axudar con isto?

1. Almacenamento de datos

Como xa se aclarou, Cassanda almacena parte dos datos na memoria RAM Memtable. Pero hai outra parte dos datos que se gardan no disco: no formulario SSTable. Engádese unha entidade a estes datos Rexistro de confirmación — rexistros de todas as transaccións, que tamén se gardan no disco.

Migración de Cassandra a Kubernetes: características e solucións
Escribe un diagrama de transacción en Cassandra

En Kubernetes, podemos usar PersistentVolume para almacenar datos. Grazas a mecanismos comprobados, traballar con datos en Kubernetes é cada vez máis sinxelo cada ano.

Migración de Cassandra a Kubernetes: características e solucións
Asignaremos o noso propio PersistentVolume a cada pod de Cassandra

É importante ter en conta que a propia Cassandra implica a replicación de datos, ofrecendo mecanismos integrados para iso. Polo tanto, se está a construír un clúster Cassandra a partir dun gran número de nodos, non é necesario utilizar sistemas distribuídos como Ceph ou GlusterFS para o almacenamento de datos. Neste caso, sería lóxico almacenar datos no disco host usando discos persistentes locais ou montaxe hostPath.

Outra pregunta é se queres crear un ambiente separado para os desenvolvedores para cada rama de funcións. Neste caso, o enfoque correcto sería levantar un nodo Cassandra e almacenar os datos nun almacenamento distribuído, é dicir. os mencionados Ceph e GlusterFS serán as túas opcións. Entón, o programador estará seguro de que non perderá os datos de proba aínda que se perda un dos nodos do clúster de Kuberntes.

2. Seguimento

A opción practicamente incontestada para implementar a monitorización en Kubernetes é Prometheus (falamos sobre isto en detalle en informe relacionado). Como está Cassandra cos exportadores de métricas para Prometheus? E, o que é aínda máis importante, con paneis coincidentes para Grafana?

Migración de Cassandra a Kubernetes: características e solucións
Un exemplo da aparición de gráficos en Grafana para Cassandra

Só hai dous exportadores: jmx_exporter и cassandra_exporter.

Escollemos o primeiro para nós porque:

  1. JMX Exporter está crecendo e desenvolvendo, mentres que Cassandra Exporter non puido obter o suficiente apoio da comunidade. Cassandra Exporter aínda non admite a maioría das versións de Cassandra.
  2. Pode executalo como un javaagent engadindo unha marca -javaagent:<plugin-dir-name>/cassandra-exporter.jar=--listen=:9180.
  3. Hai un para el cadro de mandos adecuado, que é incompatible con Cassandra Exporter.

3. Selección de primitivas de Kubernetes

Segundo a estrutura anterior do clúster Cassandra, intentemos traducir todo o que alí se describe á terminoloxía de Kubernetes:

  • Nodo Cassandra → Pod
  • Cassandra Rack → StatefulSet
  • Cassandra Datacenter → pool de StatefulSets
  • Clúster de Cassandra → ???

Resulta que falta algunha entidade adicional para xestionar todo o clúster de Cassandra á vez. Pero se algo non existe, podemos crealo! Kubernetes ten un mecanismo para definir os seus propios recursos para este fin: Definicións de recursos personalizados.

Migración de Cassandra a Kubernetes: características e solucións
Declaración de recursos adicionais para rexistros e alertas

Pero Custom Resource en si non significa nada: despois de todo, require controlador. Quizais necesites buscar axuda Operador de Kubernetes...

4. Identificación da vaina

No parágrafo anterior, acordamos que un nodo de Cassandra equivale a un pod en Kubernetes. Pero os enderezos IP dos pods serán diferentes cada vez. E a identificación dun nodo en Cassandra baséase no enderezo IP... Resulta que despois de cada eliminación dun pod, o clúster Cassandra engadirá un novo nodo.

Hai unha saída, e non só unha:

  1. Podemos manter rexistros por identificadores de host (UUID que identifican de forma única as instancias de Cassandra) ou por enderezos IP e almacenalo todo nalgunhas estruturas/táboas. O método ten dúas desvantaxes principais:
    • O risco de que se produza unha condición de carreira se dous nodos caen á vez. Despois do ascenso, os nodos de Cassandra solicitarán simultáneamente un enderezo IP da táboa e competirán polo mesmo recurso.
    • Se un nodo de Cassandra perdeu os seus datos, xa non poderemos identificalo.
  2. A segunda solución parece un pequeno truco, pero con todo: podemos crear un Servizo con ClusterIP para cada nodo de Cassandra. Problemas con esta implementación:
    • Se hai moitos nodos nun clúster de Cassandra, teremos que crear moitos Servizos.
    • A función ClusterIP implétase a través de iptables. Isto pode converterse nun problema se o clúster Cassandra ten moitos (1000... ou incluso 100?) nós. Aínda que balance baseado en IPVS pode resolver este problema.
  3. A terceira solución é usar unha rede de nodos para os nodos Cassandra en lugar dunha rede dedicada de pods activando a configuración hostNetwork: true. Este método impón certas limitacións:
    • Para substituír unidades. É necesario que o novo nodo teña o mesmo enderezo IP que o anterior (en nubes como AWS, GCP é case imposible de facer);
    • Usando unha rede de nodos de clúster, comezamos a competir polos recursos da rede. Polo tanto, colocar máis dun pod con Cassandra nun nodo do clúster será problemático.

5. Backups

Queremos gardar unha versión completa dos datos dun único nodo de Cassandra nunha programación. Kubernetes ofrece unha función cómoda CronJob, pero aquí a propia Casandra ponnos un raio nas rodas.

Permíteme lembrarche que Cassandra almacena algúns dos datos na memoria. Para facer unha copia de seguridade completa, necesitas datos da memoria (Memtables) mover ao disco (SSTables). Neste punto, o nodo Cassandra deixa de aceptar conexións, apagando completamente o clúster.

Despois diso, elimínase a copia de seguridade (instantáneo) e gárdase o esquema (espazo de teclas). E entón resulta que só unha copia de seguridade non nos dá nada: necesitamos gardar os identificadores de datos dos que foi responsable o nodo Cassandra: son fichas especiais.

Migración de Cassandra a Kubernetes: características e solucións
Distribución de tokens para identificar de que datos son responsables os nós de Cassandra

Pódese atopar un script de exemplo para facer unha copia de seguridade de Cassandra de Google en Kubernetes en este enlace. O único punto que o script non ten en conta é restablecer os datos no nodo antes de tomar a instantánea. É dicir, a copia de seguridade non se realiza para o estado actual, senón para un estado un pouco anterior. Pero isto axuda a non levar o nodo fóra de funcionamento, o que parece moi lóxico.

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 exemplo de script bash para facer unha copia de seguridade dun nodo Cassandra

Solucións listas para Cassandra en Kubernetes

Que se usa actualmente para implementar Cassandra en Kubernetes e cal destes se adapta mellor aos requisitos indicados?

1. Solucións baseadas en gráficos StatefulSet ou Helm

Usar as funcións básicas de StatefulSets para executar un clúster Cassandra é unha boa opción. Usando os modelos Helm Chart e Go, podes proporcionar ao usuario unha interface flexible para implementar Cassandra.

Isto normalmente funciona ben... ata que ocorre algo inesperado, como un fallo de nodo. As ferramentas estándar de Kubernetes simplemente non poden ter en conta todas as funcións descritas anteriormente. Ademais, este enfoque é moi limitado no canto se pode estender para usos máis complexos: substitución de nodos, copia de seguridade, recuperación, seguimento, etc.

Representantes:

Ambos os gráficos son igualmente bos, pero están suxeitos aos problemas descritos anteriormente.

2. Solucións baseadas en Kubernetes Operator

Tales opcións son máis interesantes porque ofrecen amplas oportunidades para xestionar o clúster. Para deseñar un operador Cassandra, como calquera outra base de datos, un bo patrón parece Sidecar <-> Controller <-> CRD:

Migración de Cassandra a Kubernetes: características e solucións
Esquema de xestión de nodos nun operador Cassandra ben deseñado

Vexamos os operadores existentes.

1. Cassandra-operador de instaclustr

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

Este é un proxecto moi prometedor e en desenvolvemento activo dunha empresa que ofrece implantacións xestionadas de Cassandra. Como se describe anteriormente, usa un contenedor sidecar que acepta comandos a través de HTTP. Escrito en Java, ás veces carece da funcionalidade máis avanzada da biblioteca client-go. Ademais, o operador non admite diferentes racks para un centro de datos.

Pero o operador ten vantaxes como soporte para a monitorización, xestión de clúster de alto nivel mediante CRD e mesmo documentación para facer copias de seguridade.

2. Navegador de Jetstack

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

Unha declaración deseñada para implementar DB-as-a-Service. Actualmente admite dúas bases de datos: Elasticsearch e Cassandra. Ten solucións tan interesantes como o control de acceso a bases de datos a través de RBAC (para iso ten o seu propio navegador-apiserver). Un proxecto interesante que pagaría a pena profundizar, pero que o último compromiso foi feito hai ano e medio, o que reduce claramente o seu potencial.

3. Cassandra-operador por vgkowski

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

Non o consideraron "en serio", xa que o último compromiso co repositorio foi hai máis dun ano. O desenvolvemento do operador está abandonado: a última versión de Kubernetes que se informa como compatible é a 1.9.

4. Cassandra-operador por Rook

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

Un operador cuxo desenvolvemento non avanza tan rápido como nos gustaría. Ten unha estrutura CRD ben pensada para a xestión de clúster, resolve o problema de identificar nodos usando Service with ClusterIP (o mesmo "hack")... pero iso é todo por agora. Actualmente non hai seguimento nin copias de seguranza listas (por certo, estamos para supervisar levámolo nós). Un punto interesante é que tamén pode implementar ScyllaDB usando este operador.

NB: Utilizamos este operador con pequenas modificacións nun dos nosos proxectos. Non se observaron problemas no traballo do operador durante todo o período de operación (~ 4 meses de operación).

5. CassKop de Orange

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

O operador máis novo da lista: o primeiro compromiso realizouse o 23 de maio de 2019. Xa ten no seu arsenal unha gran cantidade de funcións da nosa lista, das cales pódense atopar máis detalles no repositorio do proxecto. O operador está construído sobre a base do popular operador-sdk. Soporta monitorización fóra da caixa. A principal diferenza con outros operadores é o uso Complemento CassKop, implementado en Python e usado para a comunicación entre os nodos Cassandra.

Descubrimentos

O número de enfoques e opcións posibles para trasladar a Cassandra a Kubernetes fala por si só: o tema é demandado.

Nesta fase, podes probar calquera das anteriores baixo o teu propio risco e risco: ningún dos desenvolvedores garante o funcionamento do 100% da súa solución nun ambiente de produción. Pero xa, moitos produtos parecen prometedores para probalos en bancos de desenvolvemento.

Creo que no futuro esta muller no barco virá moi ben!

PS

Lea tamén no noso blog:

Fonte: www.habr.com

Engadir un comentario