Migration de Cassandra vers Kubernetes : fonctionnalités et solutions

Migration de Cassandra vers Kubernetes : fonctionnalités et solutions

Nous sommes régulièrement confrontés à la base de données Apache Cassandra et à la nécessité de l'exploiter au sein d'une infrastructure basée sur Kubernetes. Dans ce document, nous partagerons notre vision des étapes nécessaires, des critères et des solutions existantes (y compris un aperçu des opérateurs) pour migrer Cassandra vers K8.

« Celui qui peut diriger une femme peut aussi diriger l’État »

Qui est Cassandre ? Il s'agit d'un système de stockage distribué conçu pour gérer de gros volumes de données tout en garantissant une haute disponibilité sans aucun point de défaillance. Le projet n'a guère besoin d'une longue introduction, je ne donnerai donc que les principales caractéristiques de Cassandra qui seront pertinentes dans le cadre d'un article spécifique :

  • Cassandra est écrite en Java.
  • La topologie Cassandra comprend plusieurs niveaux :
    • Nœud - une instance Cassandra déployée ;
    • Rack est un groupe d'instances Cassandra, unies par certaines caractéristiques, situées dans le même centre de données ;
    • Centre de données - une collection de tous les groupes d'instances Cassandra situés dans un centre de données ;
    • Le cluster est une collection de tous les centres de données.
  • Cassandra utilise une adresse IP pour identifier un nœud.
  • Pour accélérer les opérations d'écriture et de lecture, Cassandra stocke une partie des données dans la RAM.

Passons maintenant au passage potentiel réel à Kubernetes.

Check-list pour le transfert

En parlant de la migration de Cassandra vers Kubernetes, nous espérons qu'avec ce déménagement, elle deviendra plus pratique à gérer. Que faudra-t-il pour cela, qu'est-ce qui y aidera ?

1. Stockage des données

Comme cela a déjà été précisé, Cassanda stocke une partie des données dans la RAM - dans Mémorisable. Mais il existe une autre partie des données qui est enregistrée sur le disque - sous la forme SSTable. Une entité est ajoutée à ces données Journal de validation — des enregistrements de toutes les transactions, qui sont également enregistrés sur le disque.

Migration de Cassandra vers Kubernetes : fonctionnalités et solutions
Écrire un diagramme de transaction dans Cassandra

Dans Kubernetes, nous pouvons utiliser PersistentVolume pour stocker des données. Grâce à des mécanismes éprouvés, travailler avec des données dans Kubernetes devient chaque année plus facile.

Migration de Cassandra vers Kubernetes : fonctionnalités et solutions
Nous allouerons notre propre PersistentVolume à chaque pod Cassandra

Il est important de noter que Cassandra elle-même implique la réplication des données, offrant des mécanismes intégrés pour cela. Par conséquent, si vous créez un cluster Cassandra à partir d'un grand nombre de nœuds, il n'est pas nécessaire d'utiliser des systèmes distribués comme Ceph ou GlusterFS pour le stockage des données. Dans ce cas, il serait logique de stocker les données sur le disque hôte en utilisant disques persistants locaux ou montage hostPath.

Une autre question est de savoir si vous souhaitez créer un environnement distinct pour les développeurs pour chaque branche de fonctionnalités. Dans ce cas, l'approche correcte serait d'augmenter un nœud Cassandra et de stocker les données dans un stockage distribué, c'est-à-dire les Ceph et GlusterFS mentionnés seront vos options. Le développeur sera alors sûr qu'il ne perdra pas les données de test même si l'un des nœuds du cluster Kuberntes est perdu.

2. Surveillance

Le choix pratiquement incontesté pour mettre en œuvre la surveillance dans Kubernetes est Prometheus (nous en avons parlé en détail dans rapport connexe). Comment Cassandra s’en sort-elle avec les exportateurs de métriques pour Prometheus ? Et qu’est-ce qui est encore plus important, avec des tableaux de bord correspondants pour Grafana ?

Migration de Cassandra vers Kubernetes : fonctionnalités et solutions
Un exemple d'apparition de graphiques dans Grafana pour Cassandra

Il n'y a que deux exportateurs : jmx_exportateur и cassandra_exportateur.

Nous avons choisi le premier pour nous-mêmes car :

  1. JMX Exporter grandit et se développe, tandis que Cassandra Exporter n'a pas réussi à obtenir suffisamment de soutien de la communauté. Cassandra Exporter ne prend toujours pas en charge la plupart des versions de Cassandra.
  2. Vous pouvez l'exécuter en tant que javaagent en ajoutant un indicateur -javaagent:<plugin-dir-name>/cassandra-exporter.jar=--listen=:9180.
  3. Il y en a un pour lui tableau de bord adéquat, qui est incompatible avec Cassandra Exporter.

3. Sélection des primitives Kubernetes

Selon la structure ci-dessus du cluster Cassandra, essayons de traduire tout ce qui y est décrit dans la terminologie Kubernetes :

  • Nœud Cassandra → Pod
  • Cassandra Rack → StatefulSet
  • Cassandra Datacenter → pool de StatefulSets
  • Amas Cassandra → ???

Il s'avère qu'il manque une entité supplémentaire pour gérer l'ensemble du cluster Cassandra en même temps. Mais si quelque chose n’existe pas, nous pouvons le créer ! Kubernetes dispose d'un mécanisme pour définir ses propres ressources à cet effet - Définitions de ressources personnalisées.

Migration de Cassandra vers Kubernetes : fonctionnalités et solutions
Déclarer des ressources supplémentaires pour les journaux et les alertes

Mais la ressource personnalisée en elle-même ne veut rien dire : après tout, elle nécessite contrôleur. Vous devrez peut-être demander de l'aide Opérateur Kubernetes...

4. Identification des cabosses

Dans le paragraphe ci-dessus, nous avons convenu qu'un nœud Cassandra équivaudrait à un pod dans Kubernetes. Mais les adresses IP des pods seront différentes à chaque fois. Et l'identification d'un nœud dans Cassandra se base sur l'adresse IP... Il s'avère qu'après chaque suppression d'un pod, le cluster Cassandra ajoutera un nouveau nœud.

Il existe une issue, et pas une seule :

  1. Nous pouvons conserver des enregistrements par identifiants d'hôte (UUID qui identifient de manière unique les instances Cassandra) ou par adresses IP et tout stocker dans certaines structures/tables. La méthode présente deux inconvénients principaux :
    • Le risque qu'une situation de concurrence critique se produise si deux nœuds tombent en même temps. Après la montée, les nœuds Cassandra demanderont simultanément une adresse IP à la table et se disputeront la même ressource.
    • Si un nœud Cassandra a perdu ses données, nous ne pourrons plus l'identifier.
  2. La deuxième solution semble être un petit hack, mais néanmoins : on peut créer un Service avec ClusterIP pour chaque nœud Cassandra. Problèmes avec cette implémentation :
    • S'il y a beaucoup de nœuds dans un cluster Cassandra, nous devrons créer beaucoup de services.
    • La fonctionnalité ClusterIP est implémentée via iptables. Cela peut devenir un problème si le cluster Cassandra comporte de nombreux nœuds (1000 100... voire XNUMX ?). Bien que équilibrage basé sur IPVS peut résoudre ce problème.
  3. La troisième solution consiste à utiliser un réseau de nœuds pour les nœuds Cassandra au lieu d'un réseau dédié de pods en activant le paramètre hostNetwork: true. Cette méthode impose certaines limites :
    • Pour remplacer des unités. Il faut que le nouveau nœud ait la même adresse IP que le précédent (dans les cloud comme AWS, GCP c'est presque impossible à faire) ;
    • En utilisant un réseau de nœuds de cluster, nous commençons à rivaliser pour les ressources réseau. Par conséquent, placer plusieurs pods avec Cassandra sur un nœud de cluster sera problématique.

5. Sauvegardes

Nous souhaitons enregistrer une version complète des données d'un seul nœud Cassandra selon un calendrier. Kubernetes fournit une fonctionnalité pratique utilisant Tâche planifiée, mais ici, Cassandra elle-même met des bâtons dans les roues.

Permettez-moi de vous rappeler que Cassandra stocke certaines données en mémoire. Pour effectuer une sauvegarde complète, vous avez besoin des données de la mémoire (Tableaux mémorables) déplacer vers le disque (Tables SS). À ce stade, le nœud Cassandra cesse d'accepter les connexions et se ferme complètement du cluster.

Après cela, la sauvegarde est supprimée (instantané) et le schéma est enregistré (espace de clés). Et puis il s'avère qu'une simple sauvegarde ne nous donne rien : nous devons sauvegarder les identifiants de données dont le nœud Cassandra était responsable - ce sont des jetons spéciaux.

Migration de Cassandra vers Kubernetes : fonctionnalités et solutions
Distribution de jetons pour identifier les données dont les nœuds Cassandra sont responsables

Un exemple de script pour effectuer une sauvegarde Cassandra de Google dans Kubernetes peut être trouvé à l'adresse ce lien. Le seul point que le script ne prend pas en compte est la réinitialisation des données sur le nœud avant de prendre l'instantané. Autrement dit, la sauvegarde n'est pas effectuée pour l'état actuel, mais pour un état légèrement antérieur. Mais cela permet de ne pas mettre le nœud hors service, ce qui semble très logique.

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 exemple de script bash pour effectuer une sauvegarde à partir d'un nœud Cassandra

Solutions prêtes pour Cassandra dans Kubernetes

Qu'est-ce qui est actuellement utilisé pour déployer Cassandra dans Kubernetes et lequel de ces éléments répond le mieux aux exigences données ?

1. Solutions basées sur des chartes StatefulSet ou Helm

Utiliser les fonctions de base StatefulSets pour exécuter un cluster Cassandra est une bonne option. À l'aide du graphique Helm et des modèles Go, vous pouvez fournir à l'utilisateur une interface flexible pour déployer Cassandra.

Cela fonctionne généralement bien... jusqu'à ce que quelque chose d'inattendu se produise, comme une panne de nœud. Les outils Kubernetes standards ne peuvent tout simplement pas prendre en compte toutes les fonctionnalités décrites ci-dessus. De plus, cette approche est très limitée dans la mesure où elle peut être étendue à des utilisations plus complexes : remplacement de nœuds, sauvegarde, restauration, surveillance, etc.

Représentants:

Les deux graphiques sont tout aussi bons, mais sont sujets aux problèmes décrits ci-dessus.

2. Solutions basées sur l'opérateur Kubernetes

De telles options sont plus intéressantes car elles offrent de nombreuses possibilités de gestion du cluster. Pour concevoir un opérateur Cassandra, comme toute autre base de données, un bon modèle ressemble à Sidecar <-> Controller <-> CRD :

Migration de Cassandra vers Kubernetes : fonctionnalités et solutions
Schéma de gestion des nœuds dans un opérateur Cassandra bien conçu

Regardons les opérateurs existants.

1. Cassandra-opérateur d'instaclustr

  • GitHub
  • Préparation : Alpha
  • Licence : Apache 2.0
  • Implémenté en : Java

Il s'agit en effet d'un projet très prometteur et en développement actif d'une entreprise qui propose des déploiements Cassandra gérés. Comme décrit ci-dessus, il utilise un conteneur side-car qui accepte les commandes via HTTP. Écrit en Java, il lui manque parfois les fonctionnalités les plus avancées de la bibliothèque client-go. De plus, l'opérateur ne prend pas en charge différents racks pour un centre de données.

Mais l'opérateur présente des avantages tels que la prise en charge de la surveillance, la gestion de cluster de haut niveau à l'aide de CRD et même la documentation pour effectuer des sauvegardes.

2. Navigateur de Jetstack

  • GitHub
  • Préparation : Alpha
  • Licence : Apache 2.0
  • Implémenté dans : Golang

Une instruction conçue pour déployer DB-as-a-Service. Prend actuellement en charge deux bases de données : Elasticsearch et Cassandra. Il propose des solutions aussi intéressantes que le contrôle d'accès aux bases de données via RBAC (pour cela, il dispose de son propre navigateur-apiserver séparé). Un projet intéressant qui mériterait d'être examiné de plus près, mais le dernier engagement date d'il y a un an et demi, ce qui réduit clairement son potentiel.

3. Cassandra-opérateur par vgkowski

  • GitHub
  • Préparation : Alpha
  • Licence : Apache 2.0
  • Implémenté dans : Golang

Ils ne l’ont pas considéré « sérieusement », puisque le dernier commit dans le référentiel remonte à plus d’un an. Le développement des opérateurs est abandonné : la dernière version de Kubernetes signalée comme prise en charge est la 1.9.

4. Cassandra-opérateur par Rook

  • GitHub
  • Préparation : Alpha
  • Licence : Apache 2.0
  • Implémenté dans : Golang

Un opérateur dont le développement n’avance pas aussi vite qu’on le souhaiterait. Il dispose d'une structure CRD bien pensée pour la gestion des clusters, résout le problème de l'identification des nœuds utilisant Service avec ClusterIP (le même « hack »)... mais c'est tout pour l'instant. Il n'y a actuellement aucune surveillance ni sauvegarde prête à l'emploi (d'ailleurs, nous sommes pour la surveillance nous l'avons pris nous-mêmes). Un point intéressant est que vous pouvez également déployer ScyllaDB en utilisant cet opérateur.

NB : Nous avons utilisé cet opérateur avec des modifications mineures dans un de nos projets. Aucun problème n’a été constaté dans le travail de l’opérateur pendant toute la période d’exploitation (~4 mois d’exploitation).

5. CassKop d'Orange

  • GitHub
  • Préparation : Alpha
  • Licence : Apache 2.0
  • Implémenté dans : Golang

Le plus jeune opérateur de la liste : le premier commit a été réalisé le 23 mai 2019. Il dispose déjà dans son arsenal d'un grand nombre de fonctionnalités de notre liste, dont plus de détails peuvent être trouvés dans le référentiel du projet. L'opérateur est construit sur la base du populaire opérateur-sdk. Prend en charge la surveillance prête à l'emploi. La principale différence avec les autres opérateurs est l'utilisation Plugin CassKop, implémenté en Python et utilisé pour la communication entre les nœuds Cassandra.

résultats

Le nombre d'approches et d'options possibles pour porter Cassandra sur Kubernetes parle de lui-même : le sujet est très demandé.

À ce stade, vous pouvez essayer l'une des solutions ci-dessus à vos risques et périls : aucun des développeurs ne garantit le fonctionnement à 100 % de sa solution dans un environnement de production. Mais déjà, de nombreux produits semblent prometteurs et pourraient être utilisés dans des bancs de développement.

Je pense qu'à l'avenir, cette femme sur le navire sera utile !

PS

A lire aussi sur notre blog :

Source: habr.com

Ajouter un commentaire