Migração de Cassandra para Kubernetes: funcionalidades e soluções

Migração de Cassandra para Kubernetes: funcionalidades e soluções

Encontramos regularmente o banco de dados Apache Cassandra e a necessidade de operá-lo em uma infraestrutura baseada em Kubernetes. Neste material compartilharemos nossa visão sobre as etapas necessárias, critérios e soluções existentes (incluindo uma visão geral das operadoras) para migrar Cassandra para K8s.

“Quem pode governar uma mulher também pode governar o Estado”

Quem é Cassandra? É um sistema de armazenamento distribuído projetado para gerenciar grandes volumes de dados e, ao mesmo tempo, garantir alta disponibilidade sem um único ponto de falha. O projeto dificilmente precisa de uma longa introdução, então darei apenas as principais características do Cassandra que serão relevantes no contexto de um artigo específico:

  • Cassandra é escrita em Java.
  • A topologia Cassandra inclui vários níveis:
    • Nó - uma instância implantada do Cassandra;
    • Rack é um grupo de instâncias Cassandra, unidas por alguma característica, localizadas no mesmo data center;
    • Datacenter - uma coleção de todos os grupos de instâncias Cassandra localizadas em um data center;
    • Cluster é uma coleção de todos os data centers.
  • Cassandra usa um endereço IP para identificar um nó.
  • Para acelerar as operações de escrita e leitura, Cassandra armazena alguns dados na RAM.

Agora - para a mudança potencial real para o Kubernetes.

Lista de verificação para transferência

Falando sobre a migração do Cassandra para o Kubernetes, esperamos que com a mudança se torne mais conveniente de gerenciar. O que será necessário para isso, o que ajudará nisso?

1. Armazenamento de dados

Como já foi esclarecido, Cassanda armazena parte dos dados na RAM - em Tabela de memória. Mas há outra parte dos dados que é salva no disco - na forma SSTable. Uma entidade é adicionada a esses dados Registro de confirmação — registros de todas as transações, que também são salvos em disco.

Migração de Cassandra para Kubernetes: funcionalidades e soluções
Escreva o diagrama de transação no Cassandra

No Kubernetes, podemos usar PersistentVolume para armazenar dados. Graças a mecanismos comprovados, trabalhar com dados no Kubernetes está se tornando mais fácil a cada ano.

Migração de Cassandra para Kubernetes: funcionalidades e soluções
Alocaremos cada pod com Cassandra em seu próprio PersistentVolume

É importante notar que o próprio Cassandra implica replicação de dados, oferecendo mecanismos integrados para isso. Portanto, se você estiver construindo um cluster Cassandra a partir de um grande número de nós, não há necessidade de usar sistemas distribuídos como Ceph ou GlusterFS para armazenamento de dados. Neste caso, seria lógico armazenar dados no disco host usando discos permanentes locais ou montagem hostPath.

Outra questão é se você deseja criar um ambiente separado para desenvolvedores para cada ramificação de recursos. Neste caso, a abordagem correta seria criar um nó Cassandra e armazenar os dados em um armazenamento distribuído, ou seja, os mencionados Ceph e GlusterFS serão suas opções. Assim, o desenvolvedor terá certeza de que não perderá os dados de teste, mesmo se um dos nós do cluster Kuberntes for perdido.

2. Monitoramento

A escolha praticamente incontestada para implementação de monitoramento no Kubernetes é o Prometheus (falamos sobre isso em detalhes em relatório relacionado). Como está o desempenho de Cassandra com os exportadores de métricas do Prometheus? E o que é ainda mais importante, com painéis correspondentes para Grafana?

Migração de Cassandra para Kubernetes: funcionalidades e soluções
Um exemplo de aparecimento de gráficos no Grafana para Cassandra

Existem apenas dois exportadores: jmx_exportador и cassandra_exportador.

Escolhemos o primeiro para nós porque:

  1. O JMX Exporter está crescendo e se desenvolvendo, enquanto o Cassandra Exporter não conseguiu obter apoio suficiente da comunidade. O Cassandra Exporter ainda não oferece suporte à maioria das versões do Cassandra.
  2. Você pode executá-lo como um javaagent adicionando um sinalizador -javaagent:<plugin-dir-name>/cassandra-exporter.jar=--listen=:9180.
  3. Existe um para ele painel adequado, que é incompatível com o Cassandra Exporter.

3. Selecionando primitivas do Kubernetes

De acordo com a estrutura do cluster Cassandra acima, vamos tentar traduzir tudo o que está descrito lá para a terminologia do Kubernetes:

  • Nodo Cassandra → Pod
  • Rack Cassandra → StatefulSet
  • Cassandra Datacenter → pool de StatefulSets
  • Aglomerado de Cassandra → ???

Acontece que falta alguma entidade adicional para gerenciar todo o cluster Cassandra de uma só vez. Mas se algo não existe, podemos criá-lo! O Kubernetes possui um mecanismo para definir recursos próprios para essa finalidade - Definições de recursos personalizados.

Migração de Cassandra para Kubernetes: funcionalidades e soluções
Declarando recursos adicionais para logs e alertas

Mas o recurso personalizado em si não significa nada: afinal, requer controlador. Você pode precisar procurar ajuda Operador Kubernetes...

4. Identificação de frutos

No parágrafo acima, concordamos que um nó Cassandra será igual a um pod no Kubernetes. Mas os endereços IP dos pods serão diferentes a cada vez. E a identificação de um nó no Cassandra é baseada no endereço IP... Acontece que após cada remoção de um pod, o cluster Cassandra irá adicionar um novo nó.

Existe uma saída, e não apenas uma:

  1. Podemos manter registros por identificadores de host (UUIDs que identificam exclusivamente instâncias do Cassandra) ou por endereços IP e armazenar tudo em algumas estruturas/tabelas. O método tem duas desvantagens principais:
    • O risco de ocorrência de uma condição de corrida se dois nós caírem ao mesmo tempo. Após a ascensão, os nós Cassandra solicitarão simultaneamente um endereço IP da tabela e competirão pelo mesmo recurso.
    • Se um nó Cassandra perder seus dados, não poderemos mais identificá-lo.
  2. A segunda solução parece um pequeno hack, mas mesmo assim: podemos criar um serviço com ClusterIP para cada nó Cassandra. Problemas com esta implementação:
    • Se houver muitos nós em um cluster Cassandra, teremos que criar muitos serviços.
    • O recurso ClusterIP é implementado via iptables. Isso pode se tornar um problema se o cluster Cassandra tiver muitos (1000... ou mesmo 100?) Nós. Embora balanceamento baseado em IPVS pode resolver este problema.
  3. A terceira solução é usar uma rede de nós para nós Cassandra em vez de uma rede dedicada de pods, habilitando a configuração hostNetwork: true. Este método impõe certas restrições:
    • Para substituir unidades. É necessário que o novo nó tenha o mesmo endereço IP do anterior (em nuvens como AWS, GCP isso é quase impossível de fazer);
    • Usando uma rede de nós de cluster, começamos a competir pelos recursos da rede. Portanto, colocar mais de um pod com Cassandra em um nó de cluster será problemático.

5. Cópias de segurança

Queremos salvar uma versão completa dos dados de um único nó Cassandra em uma programação. Kubernetes oferece um recurso conveniente usando CronJobGenericName, mas aqui a própria Cassandra coloca um raio em nossas rodas.

Deixe-me lembrá-lo de que Cassandra armazena alguns dados na memória. Para fazer um backup completo, você precisa de dados da memória (Tabelas de memória) mover para o disco (Tabelas SS). Neste ponto, o nó Cassandra para de aceitar conexões, desligando completamente o cluster.

Depois disso, o backup é removido (instantâneo) e o esquema é salvo (espaço de chave). E então acontece que apenas um backup não nos dá nada: precisamos salvar os identificadores de dados pelos quais o nó Cassandra foi responsável - esses são tokens especiais.

Migração de Cassandra para Kubernetes: funcionalidades e soluções
Distribuição de tokens para identificar quais dados os nós do Cassandra são responsáveis

Um exemplo de script para fazer um backup do Cassandra do Google no Kubernetes pode ser encontrado em este link. O único ponto que o script não leva em consideração é a redefinição dos dados para o nó antes de tirar o snapshot. Ou seja, o backup não é realizado para o estado atual, mas para um estado um pouco anterior. Mas isso ajuda a não tirar o nó de operação, o que parece muito 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}"

Um exemplo de script bash para fazer backup de um nó Cassandra

Soluções prontas para Cassandra no Kubernetes

O que é usado atualmente para implantar Cassandra no Kubernetes e qual deles melhor atende aos requisitos fornecidos?

1. Soluções baseadas em gráficos StatefulSet ou Helm

Usar as funções básicas do StatefulSets para executar um cluster Cassandra é uma boa opção. Usando o gráfico Helm e os modelos Go, você pode fornecer ao usuário uma interface flexível para implantar o Cassandra.

Isso geralmente funciona bem... até que algo inesperado aconteça, como uma falha de nó. As ferramentas padrão do Kubernetes simplesmente não podem levar em consideração todos os recursos descritos acima. Além disso, esta abordagem é muito limitada na medida em que pode ser estendida para usos mais complexos: substituição de nós, backup, recuperação, monitoramento, etc.

Representantes:

Ambos os gráficos são igualmente bons, mas estão sujeitos aos problemas descritos acima.

2. Soluções baseadas no Operador Kubernetes

Essas opções são mais interessantes porque oferecem amplas oportunidades de gerenciamento do cluster. Para projetar um operador Cassandra, como qualquer outro banco de dados, um bom padrão se parece com Sidecar <-> Controller <-> CRD:

Migração de Cassandra para Kubernetes: funcionalidades e soluções
Esquema de gerenciamento de nós em um operador Cassandra bem projetado

Vejamos os operadores existentes.

1. Operador Cassandra do instaclustr

  • GitHub
  • Prontidão: Alfa
  • Licença: Apache 2.0
  • Implementado em: Java

Este é realmente um projeto muito promissor e em desenvolvimento ativo de uma empresa que oferece implantações gerenciadas do Cassandra. Ele, conforme descrito acima, usa um contêiner secundário que aceita comandos via HTTP. Escrito em Java, às vezes falta a funcionalidade mais avançada da biblioteca client-go. Além disso, a operadora não suporta Racks diferentes para um Datacenter.

Mas a operadora tem vantagens como suporte para monitoramento, gerenciamento de cluster de alto nível usando CRD e até documentação para fazer backups.

2. Navegador do Jetstack

  • GitHub
  • Prontidão: Alfa
  • Licença: Apache 2.0
  • Implementado em: Golang

Uma instrução projetada para implantar o banco de dados como serviço. Atualmente suporta dois bancos de dados: Elasticsearch e Cassandra. Possui soluções interessantes como controle de acesso ao banco de dados via RBAC (para isso possui seu próprio navegador-apiserver separado). Um projeto interessante que valeria a pena olhar mais de perto, mas o último compromisso foi feito há um ano e meio, o que reduz claramente o seu potencial.

3. Operador Cassandra por vgkowski

  • GitHub
  • Prontidão: Alfa
  • Licença: Apache 2.0
  • Implementado em: Golang

Eles não levaram isso “a sério”, já que o último commit no repositório foi há mais de um ano. O desenvolvimento do operador foi abandonado: a versão mais recente do Kubernetes relatada como suportada é 1.9.

4. Operadora Cassandra por Rook

  • GitHub
  • Prontidão: Alfa
  • Licença: Apache 2.0
  • Implementado em: Golang

Um operador cujo desenvolvimento não avança tão rapidamente como gostaríamos. Possui uma estrutura CRD bem pensada para gerenciamento de cluster, resolve o problema de identificação de nós usando Serviço com ClusterIP (o mesmo “hack”)... mas por enquanto é tudo. Atualmente não há monitoramento ou backups prontos para uso (aliás, somos a favor do monitoramento pegamos nós mesmos). Um ponto interessante é que você também pode implantar o ScyllaDB usando este operador.

NB: Utilizamos este operador com pequenas modificações em um de nossos projetos. Não foram notados problemas no trabalho do operador durante todo o período de operação (~4 meses de operação).

5. CassKop de Laranja

  • GitHub
  • Prontidão: Alfa
  • Licença: Apache 2.0
  • Implementado em: Golang

A operadora mais jovem da lista: o primeiro commit foi feito em 23 de maio de 2019. Já possui em seu arsenal um grande número de recursos de nossa lista, mais detalhes dos quais podem ser encontrados no repositório do projeto. O operador é construído com base no popular operador-sdk. Suporta monitoramento pronto para uso. A principal diferença de outras operadoras é o uso Plug-in CassKop, implementado em Python e usado para comunicação entre nós Cassandra.

Descobertas

A quantidade de abordagens e opções possíveis para portar Cassandra para Kubernetes fala por si: o tema está em alta.

Neste estágio, você pode tentar qualquer uma das opções acima por sua própria conta e risco: nenhum dos desenvolvedores garante 100% de operação de sua solução em um ambiente de produção. Mas muitos produtos já parecem promissores para serem usados ​​em bancadas de desenvolvimento.

Acho que no futuro essa mulher no navio será útil!

PS

Leia também em nosso blog:

Fonte: habr.com

Adicionar um comentário