Lors de la mission Chez G.E Aviation , nous utilisons Cassandra base de données NoSQL pour certaines de nos solutions cloud hautement disponibles. Cassandra est une base de données NoSQL évolutive hautement disponible, hautement performante et véritablement horizontale. Cependant, le déploiement de Cassandra dans le cloud de manière hautement disponible est une tâche non triviale et nécessite une configuration appropriée. Heureusement, en raison de l’émergence de nouvelles technologies, le déploiement d’un cluster Cassandra dans AWS est plus facile de nos jours.
Cet article vous montrera comment déployer un cluster Cassandra dans AWS, à l’aide de kops (Kubernetes Operations). Il montrera également que la configuration est hautement disponible en testant certains scénarios de défaillance.
Cet article suppose des connaissances de base d’AWS, Kubernetes et Apache Cassandra.
Déploiement
L’image ci-dessous montre à quoi ressemble le déploiement final de Cassandra dans AWS :

Décrivons le déploiement en détail :
- Le déploiement utilise une région géographique : Europe (Paris) eu-west-3
- Dans cette région, trois zones de disponibilité sont utilisées. Une zone de disponibilité est une zone isolée dans une région, c’est-à-dire qu’une défaillance dans une zone de disponibilité n’a pas d’impact sur les opérations dans une autre zone de disponibilité. Par conséquent, la haute disponibilité est obtenue en répartissant le traitement et le stockage sur les zones de disponibilité.
- Il existe trois masters appelés maîtres Kubernetes, un dans chaque zone de disponibilité. Un maître Kubernete planifie les pods (conteneurs), c’est-à-dire qu’il détermine quel noeud Kubernetes exécute quel pod (conteneur). En ayant un maître dans chaque zone de disponibilité, les maîtres Kubernetes peuvent continuer à planifier des pods, même si une zone de disponibilité est en panne. Les machines principales sont déployées dans un groupe à mise à l’échelle automatique. Par conséquent, si une instance EC2 de ce groupe se termine, une nouvelle instance EC2 (et le maître Kubernetes) est démarrée automatiquement.
- Il existe six nœuds Kubernetes, deux dans chaque zone de disponibilité. Un nœud Kubernetes exécute vos modules d’application. Dans cette configuration, chaque nœud Kubernetes exécutera un module Cassandra. Si un pod échoue, un nouveau sera planifié par le maître Kubernetes. Les nœuds Kubernetes sont également déployés dans un groupe à mise à l’échelle automatique.
- Un état Kubernetes avec des volumes persistants est utilisé pour déployer Cassandra: chaque pod Cassandra a une identité connue (par exemple cassandra-0) et un volume connu (par exemple cassandra-storage-cassandra-0). L’identité du pod et l’identité du volume sont étroitement liées. Cela permet à un pod Cassandra de redémarrer sur un autre nœud et de transférer son état. Lorsqu’un pod Cassandra démarre, il attache le même volume EBS que précédemment et a donc le même état qu’auparavant. Les volumes EBS sont automatiquement créés au premier démarrage d’un pod Cassandra.
Voyons maintenant comment Cassandra doit être configuré pour répliquer les données dans plusieurs zones de disponibilité. Pour ce faire, définissez les propriétés suivantes :
- · Snitch. Il détermine à quel datacenter et rack appartient un nœud. Cassandra utilise les termes « datacenter » et «rack» pour identifier la topologie du réseau. EC2Snitch est utilisé. Lorsqu’un nœud Cassandra démarre, EC2Snitch récupère les informations de région et de zone de disponibilité à partir du point de terminaison de métadonnées EC2 : le datacenter est défini sur la région et le rack est défini sur la zone de disponibilité.
- · Facteur de réplication. Ceci détermine le nombre de copies de données. Un facteur de réplication de trois est utilisé, c’est-à-dire que trois copies sont stockées sur des nœuds différents.
- · Stratégie de réplication Cette propriété détermine quels nœuds stockent les répliques. La NetworkTopologyStrategy est utilisée. Avec cette stratégie, une réplique est stockée dans chaque zone de disponibilité. Comment cela est fait précisément, est discuté ensuite.
Configuration étape par étape
Ensuite, nous allons installer le déploiement décrit à partir de zéro. Pour suivre ces étapes, vous n’avez besoin que d’un compte AWS et d’une machine Linux pour exécuter les commandes. Nous utilisons les versions suivantes pour les différents composants :
- MacOs Pro Catalina 10.15.2
- Kops 1.15.0
- Kubernetes 1.7.16
- Cassandra 3.11.5
NB : Vous pouvez utiliser la même démarche en utilisant le système linux comme ubuntu.
Si vous voulez installer ubuntu sur virtualbox ou vmware ou encore récupérer une image déjà prête, vous avez les ressources ci-dessous :
Installation de Ubuntu sur VirtualBox: https://dmnbigdata.com/fr/installation-de-ubuntu-18-04-3-lts-sur-oracle-virtualbox-pour-installer-apache-cassandra Installation de Ubuntu sur VMWare ou VMWare Fusion: https://dmnbigdata.com/fr/installation-de-ubuntu-18-04-3-lts-sur-vmware-fusion-et-conditions-prealables-pour-linstallation-de-cassandraImage VMware : https://drive.google.com/open?id=1MZ1ilbZk-Sy7uNpSPSisrkswOiAiBUZd
Image VirtualBox : https://drive.google.com/open?id=1kaNJRYfwn2Xh4ktKr0mpl6zrjb9rsNx0
Configuration de Kubernetes
Premièrement, vous avez besoin de la commande kops, qui est utilisée pour configurer l’infrastructure dans AWS :
Commandes pour macOS :
· Téléchargez la version récente de kops avec la commande :
curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-darwin-amd64
· Mettre les binaires de kops en mode exécutable.
chmod +x kops-darwin-amd64
· Déplacez les binaires de kops dans le répertoire /usr/local/bin/kops.
sudo mv kops-darwin-amd64 /usr/local/bin/kops
Linux:
· Téléchargez la version récente avec la commande :
curl -LO https://github.com/kubernetes/kops/releases/download/1.15.0/kops-linux-amd64
· Mettre les binaires de kops en mode exécutable
sudo mv kops-linux-amd64 /usr/local/bin/kops && sudo chmod a+x /usr/local/bin/kops
Voir la version récente sur :
https://kubernetes.io/docs/setup/production-environment/tools/kops/
Vous avez besoin de la commande kubectl pour interagir avec le cluster Kubernetes dans AWS :
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.7.16/bin/linux/amd64/kubectl
chmod +x ./kubectl ;sudo mv kubectl /usr/local/bin/kubectl ;sudo chmod a+x /usr/local/bin/kubectl
Kops utilise la commande awscli pour interagir avec AWS. Sur Ubuntu, vous pouvez installer cet outil via :
apt-get install awscli
Commandes pour Linux :
curl "https://d1vvhvl2y92vvt.cloudfront.net/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install
Commandes pour macOS:
curl "https://d1vvhvl2y92vvt.cloudfront.net/awscli-exe-macos.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install
D’autres moyens d’installer awscli peuvent être trouvés ici :
https://docs.aws.amazon.com/fr_fr/cli/latest/userguide/aws-cli.pdf
https://docs.aws.amazon.com/cli/latest/userguide/installing.html
https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux-mac.html
Vous devez maintenant vous assurer qu’il existe un utilisateur IAM que kops peut utiliser pour installer les composants requis dans AWS. L’utilisateur IAM a besoin d’un accès par programmation (c’est-à-dire utiliser une clé d’accès (access-key) et une clé d’accès secrète (secret-access-key) pour se connecter). En outre, l’utilisateur IAM requiert les autorisations suivantes :
AmazonEC2FullAccess
AmazonRoute53FullAccess
AmazonS3FullAccess
IAMFullAccess
AmazonVPCFullAccess
Voici comment créer cet utilisateur. Pour notre cas, nous allons l’appeler dmnbigdata

Cliquez sur Utilisateurs et ensuite sur Ajouter un utilisateur

Ensuite cliquez sur Suivant : Autorisations après avoir rempli les points 1 et 2 :

Cliquez sur groupe pour créer un groupe et lui attribué les autorisations notées ci-dessous :

Une fois le groupe crée avec les bonnes autorisations, cliquez sur Créer un groupe et vous aurez l’image ci-dessous :

Cliquez sur Suivant : Balises

Cliquez sur Suivant : Vérification

Cliquez sur Créer un utilisateur

Surtout ne pas oublier de cliquer sur Télécharger.csv et le sauvegarder dans un endroit sécurisé sinon, vous ne pouvez plus le régénérer.
Maintenant, configurons AWS2 (aws2 parce que j’ai installé la version 2 de aws-cli) :
aws2 configure
Entrez les informations d’identification de l’utilisateur IAM créées à l’étape précédente. Nous utilisons Europe (Paris) eu-west-3 comme région. Acceptez le format de sortie par défaut. Vous devez ensuite créer un bucket S3. Kops stocke la configuration du déploiement dans ce bucket
aws2 s3api create-bucket --bucket kops-cassandra-dmnbigdata --region eu-west-3 --create-bucket-configuration LocationConstraint=eu-west-3
Pour voir les buckets crées dans s3, lancez la commande ci-dessous :
$ aws2 s3api list-buckets
Générez maintenant une paire de clés publique / privée :
ssh-keygen -f kops-cassandra-dmnbigdata
Cette paire de clés est utilisée pour accéder aux machines EC2. La commande suivante crée la définition de cluster :
kops create cluster \ --cloud=aws \ --name=kops-cassandra-dmnbigdata.k8s.local \ --zones=eu-west-3a,eu-west-3b,eu-west-3c \ --master-size="t2.small" \ --master-zones=eu-west-3a,eu-west-3b,eu-west-3c \ --node-size="t2.small" \ --ssh-public-key="kops-cassandra-dmnbigdata.pub" \ --state=s3://kops-cassandra-dmnbigdata \ --node-count=6
Appliquez maintenant la définition de cluster, c’est-à-dire créez les ressources actuelles dans AWS :
kops update cluster --name=kops-cassandra-dmnbigdata.k8s.local --state=s3://kops-cassandra-dmnbigdata --yes
Après quelques minutes, nous aurons un cluster Kubernetes hautement disponible dans AWS. Kops configure automatiquement kubectl. Utilisez la commande suivante pour vérifier les nœuds principaux de Kubernetes (l’argument -L affiche les étiquettes (labels), tandis que l’argument -l filtre sur les étiquettes (labels)):
kubectl get no -L failure-domain.beta.kubernetes.io/zone -l kubernetes.io/role=master
La sortie suivante est visible :
NAME STATUS ROLES AGE VERSION ZONE ip-172-20-117-22 Ready master 104s v1.15.7 eu-west-3c ip-172-20-43-100 Ready master 98s v1.15.7 eu-west-3a ip-172-20-81-84 Ready master 103s v1.15.7 eu-west-3b
En se connectant dans aws et en cliquant sur le Tableau de bord EC2, vous allez voir toutes les instances créées :
Comme on peut le voir, les trois maîtres Kubernetes résident chacun dans une zone de disponibilité distincte. Exécutez maintenant la même commande pour les nœuds Kubernetes :
$ kubectl get no -L failure-domain.beta.kubernetes.io/zone -l kubernetes.io/role=node
Comme on peut le voir dans la sortie, chaque zone de disponibilité a deux nœuds Kubernetes :
NAME STATUS ROLES AGE VERSION ZONE ip-172-20-100-27 Ready node 9m23s v1.15.7 eu-west-3c ip-172-20-108-191 Ready node 9m23s v1.15.7 eu-west-3c ip-172-20-51-2 Ready node 9m22s v1.15.7 eu-west-3a ip-172-20-59-252 Ready node 9m23s v1.15.7 eu-west-3a ip-172-20-71-148 Ready node 9m20s v1.15.7 eu-west-3b ip-172-20-73-128 Ready node 6m2s v1.15.7 eu-west-3b
Vous pouvez détruire l’environnement à tout moment en exécutant la commande suivante :
$ kops delete cluster --name=kops-cassandra-dmnbigdata.k8s.local --state=s3://kops-cassandra-dmnbigdata --yes
Configuration et Installation de Cassandra
Nous allons voir la classe de storage appelée storage class pour Cassandra :
$ kubectl get sc NAME PROVISIONER AGE default kubernetes.io/aws-ebs 4h37m gp2 (default) kubernetes.io/aws-ebs 4h37m
Déploiement de Cassandra StatefulSet sur AWS :
StatefulSet dans kubernates nécessite un service pour fournir une identité réseau aux pods qu’il crée. La commande suivante et la spécification vous aideront à créer un service pour votre installation Cassandra.
cat > px-cassandra-svc.yaml << EOF apiVersion: v1 kind: Service metadata: labels: app: cassandra name: cassandra spec: clusterIP: None ports: - port: 9042 selector: app: Cassandra EOF
$ kubectl create -f px-cassandra-svc.yaml $ service "cassandra" created
Maintenant, nous allons créer un cluster Cassandra avec statefulset en cours d’exécution basé sur les spécifications ci-dessous :
cat > px-cassandra-app.yaml << EOF apiVersion: apps/v1 kind: StatefulSet metadata: name: cassandra labels: app: cassandra spec: serviceName: cassandra replicas: 6 selector: matchLabels: app: cassandra template: metadata: labels: app: cassandra spec: containers: - name: cassandra image: cassandra:3 ports: - containerPort: 7000 name: intra-node - containerPort: 7001 name: tls-intra-node - containerPort: 7199 name: jmx - containerPort: 9042 name: cql resources: limits: cpu: "500m" memory: 1Gi requests: cpu: "500m" memory: 1Gi securityContext: capabilities: add: - IPC_LOCK lifecycle: preStop: exec: command: - /bin/sh - -c - nodetool drain env: - name: MAX_HEAP_SIZE value: 512M - name: HEAP_NEWSIZE value: 100M - name: CASSANDRA_SEEDS value: "cassandra-0.cassandra.default.svc.cluster.local" - name: CASSANDRA_CLUSTER_NAME value: "Cassandra" - name: CASSANDRA_DC value: "DC1" - name: CASSANDRA_RACK value: "Rack1" - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP readinessProbe: exec: command: - /bin/bash - -c - /ready-probe.sh initialDelaySeconds: 15 timeoutSeconds: 5 # Ces disques volumes montes sont persistants. volumeMounts: - name: cassandra-data mountPath: /var/lib/cassandra # Ceux-ci en été convertis en volume par le contrôleur contrôleur # et montes aux chemins mentionnes ci-dessus. # Ne pas les utiliser en production mais plutôt choisir les disques ssd volumeClaimTemplates: - metadata: name: cassandra-data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: fast resources: requests: storage: 1Gi # kind: StorageClass # apiVersion: storage.k8s.io/v1 # metadata: # name: fast # provisioner: k8s.io/minikube-hostpath # parameters: # type: pd-ssd EOF
$ kubectl apply -f px-cassandra-app.yaml
$ statefulset.apps "cassandra" created
Vérifiez que tous les pods sont en cours d’exécution avant de poursuivre :
$ kubectl get statefulset NAME READY AGE cassandra 6/6 63m
$ kubectl get pods NAME READY STATUS RESTARTS AGE cassandra-0 1/1 Running 0 64m cassandra-1 1/1 Running 0 63m cassandra-2 1/1 Running 1 63m cassandra-3 1/1 Running 1 62m cassandra-4 1/1 Running 1 62m cassandra-5 1/1 Running 2 61m
Vérifions également les volumes :
$ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE cassandra-data-cassandra-0 Bound pvc-132ebdf7-3855-4492-9cdd-4a3ac9141e89 1Gi RWO gp2 24m cassandra-data-cassandra-1 Bound pvc-73a14efd-f29b-4da6-b08a-6db462bd475a 1Gi RWO gp2 23m cassandra-data-cassandra-2 Bound pvc-fdff8d71-e6ae-444f-abf0-230231696710 1Gi RWO gp2 22m cassandra-data-cassandra-3 Bound pvc-2df3f2e5-4a5b-451c-93c0-89c04a5b8927 1Gi RWO gp2 18m cassandra-data-cassandra-4 Bound pvc-7cbaa701-ee67-4f61-bc07-7cfc9d163227 1Gi RWO gp2 17m cassandra-data-cassandra-5 Bound pvc-f21cbf71-394d-424d-8b5c-0afa87927474 1Gi RWO gp2 17m
Obtenez les pods et la connaissance des hôtes sur lesquels ils sont programmés :
$ kubectl get pods -l app=cassandra -o json
Nous pouvons également utiliser l’outil nodetool de Cassandra pour vérifier l’état du cluster :
$ kubectl exec cassandra-0 -- nodetool status Datacenter: DC1 =============== Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 100.96.6.2 80.27 KiB 256 50.2% af410846-5bcc-4434-8bfe-51c851d71956 Rack1 UN 100.96.8.2 91.85 KiB 256 52.6% 6c5f672a-56b6-45b5-826a-5b8fa31a7402 Rack1 UN 100.96.4.2 95.67 KiB 256 46.1% eb3a1c8c-c87b-4a5b-8955-c4d6a762b0de Rack1 UN 100.96.5.2 186.41 KiB 256 48.2% 4de4fe7e-880f-42b7-856e-76c40cd86102 Rack1 UN 100.96.7.3 186.67 KiB 256 48.7% 05e700a1-0343-45ad-b571-5c61be743e55 Rack1 UN 100.96.3.4 136.42 KiB 256 54.2% 1912d775-c8e7-4ca7-899d-3d38c48b2798 Rack1
Afin de se connecter au cluster Cassandra, nous utilisons la commande cqlsh qui est disponible sur chaque nœud :
$ kubectl exec -ti cassandra-0 cqlsh cassandra-0
Cela ouvre une invite de commande CQL et vous permet d’interagir avec le cluster à l’aide de CQL. La commande « cqlsh cassandra-0 » se connecte en fait au serveur répertorié dans le premier argument (cassandra-0). Donc, dans ce cas, il se connecte à lui-même.
Nous allons maintenant créer un keyspace, une table et 5 lignes. Définissez d’abord le niveau de cohérence :
CONSISTENCY QUORUM ;
Quorum signifie qu’une majorité des réplicas (2 dans notre cas) doivent être lues ou écrites pour que la commande de lecture ou d’écriture réussisse. Créez maintenant le keyspace:
CREATE KEYSPACE killrvideo WITH REPLICATION = {'class': 'NetworkTopologyStrategy', 'DC1': 3 };
Passer au keyspace de killrvideo:
USE killrvideo;
Créer une table videos:
CREATE TABLE videos (video_id timeuuid PRIMARY KEY, added_date timestamp,title text) ;
Exécutez maintenant les commandes suivantes pour insérer 5 lignes.
INSERT INTO videos (video_id ,added_date ,title ) VALUES (1645ea59-14bd-11e5-a993-8138354b7e31,'2014-01-29', 'Cassandra History'); INSERT INTO videos (video_id ,added_date ,title ) VALUES (245e8024-14bd-11e5-9743-8238356b7e32,'2012-04-03', ' Cassandra & SSDs '); INSERT INTO videos (video_id ,added_date ,title ) VALUES (3452f7de-14bd-11e5-855e-8738355b7e3a,'2013-03-17', ' Cassandra Intro '); INSERT INTO videos (video_id ,added_date ,title ) VALUES (4845ed97-14bd-11e5-8a40-8338255b7e33,'2013-10-16', ' DataStax DevCenter '); INSERT INTO videos (video_id ,added_date ,title ) VALUES (5645f8bd-14bd-11e5-af1a-8638355b8e3a,'2013-04-16', ' What is DataStax Enterprise?’);
Exécutez maintenant la commande suivante et assurez-vous que 5 lignes sont retournées :
SELECT * FROM videos;
cqlsh:killrvideo> SELECT * FROM videos;
video_id | added_date | title
--------------------------------------+-----------------------
245e8024-14bd-11e5-9743-8238356b7e32 | 2012-04-03 00:00:00.000000+0000 | Cassandra & SSDs
3452f7de-14bd-11e5-855e-8738355b7e3a | 2013-03-17 00:00:00.000000+0000 | Cassandra Intro
5645f8bd-14bd-11e5-af1a-8638355b8e3a|2013-04-16 00:00:00.000000+0000|What is DataStax Enterprise?
1645ea59-14bd-11e5-a993-8138354b7e31 | 2014-01-29 00:00:00.000000+0000 | Cassandra History
4845ed97-14bd-11e5-8a40-8338255b7e33 | 2013-10-16 00:00:00.000000+0000 | DataStax DevCenter
(5 rows)
Test de la haute disponibilité
Maintenant que nous avons un cluster Cassandra dans AWS avec des données à l’intérieur, nous pouvons tester la haute disponibilité. Notez que cette configuration n’est résiliente qu’aux défaillances dans une zone de disponibilité. Afin d’être résilient face à plusieurs défaillances simultanées de zone de disponibilité, il convient d’envisager d’utiliser un site de reprise après sinistre dans une autre région. Lors de l’exécution des scénarios d’échec dans les sections suivantes, la requête de sélection présentée plus haut doit toujours renvoyer 5 enregistrements, c’est-à-dire que Cassandra doit être en haute disponibilité (toutes les données doivent être disponibles) à tout moment.
Échec de l’instance EC2
Notez que nous ne testerons que la défaillance du nœud Kubernetes (pas la défaillance du maître Kubernetes). Terminons une instance EC2 via la console AWS. Nous ne devons pas terminer une instance EC2 exécutant le pod cassandra-0. Sinon, notre invite CQL se termine. Via les commandes suivantes :
$ kubectl get no -L failure-domain.beta.kubernetes.io/zone NAME STATUS ROLES AGE VERSION ZONE ip-172-20-107-251 Ready master 36m v1.15.7 eu-west-3c ip-172-20-115-221 Ready node 35m v1.15.7 eu-west-3c ip-172-20-38-248 Ready node 35m v1.15.7 eu-west-3a ip-172-20-45-107 Ready master 36m v1.15.7 eu-west-3a ip-172-20-79-12 Ready node 35m v1.15.7 eu-west-3b ip-172-20-92-62 Ready node 35m v1.15.7 eu-west-3b ip-172-20-93-178 Ready master 36m v1.15.7 eu-west-3b ip-172-20-99-226 Ready node 35m v1.15.7 eu-west-3c
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cassandra-0 1/1 Running 0 30m 100.96.6.2 ip-172-20-79-12
cassandra-1 1/1 Running 0 30m 100.96.8.2 ip-172-20-115-221
cassandra-2 1/1 Running 0 29m 100.96.4.2 ip-172-20-45-107
cassandra-3 1/1 Running 1 24m 100.96.3.4 ip-172-20-92-62
cassandra-4 1/1 Running 2 24m 100.96.7.3 ip-172-20-99-226
cassandra-5 1/1 Running 2 23m 100.96.5.2 ip-172-20-38-248
Nous pouvons construire le tableau suivant :
Cassandra-node EC2 instance Availability-zone —————————————————————————- cassandra-0 ip-172-20-79-12 eu-west-3b cassandra-1 ip-172-20-115-221 eu-west-3c cassandra-2 ip-172-20-45-107 eu-west-3a cassandra-3 ip-172-20-92-62 eu-west-3b cassandra-4 ip-172-20-99-226 eu-west-3c cassandra-5 ip-172-20-38-248 eu-west-3a
Pour ce test, nous terminerons l’instance ip-172-20-115-221 qui terminera cassandra-1. AWS tentera de lancer une nouvelle instance EC2 dans la zone de disponibilité avec le moins d’instances. Dans notre cas, le groupe de mise à l’échelle automatique appelé « nœuds » contient une instance pour la zone eu-west-3c, tandis qu’il en contient deux pour les autres zones. Par conséquent, la nouvelle instance est lancée dans eu-west-3c. Notez que c’est le meilleur effort ; si une zone de disponibilité entière est en panne pendant une période prolongée, une intervention manuelle est nécessaire pour récupérer. Cela sera discuté plus tard. Lors de la demande des pods, la sortie suivante est visible :
NAME READY STATUS RESTARTS AGE cassandra-0 1/1 Running 0 118m cassandra-1 1/1 Running 0 117m cassandra-2 1/1 Running 1 116m cassandra-3 1/1 Running 1 116m cassandra-4 1/1 Running 1 115m cassandra-5 1/1 Running 2 115m
Pendant le démarrage de l’instance EC2, l’état du pod est en attente. Comme prévu, la requête en lecture renvoie toujours 5 lignes. En effet, nous utilisons le niveau de consistance des lectures en quorum: nous avons besoin de deux des trois réplicas et puisque toutes les zones contiennent un réplica , la lecture réussit. Le pod cassandra-1 sera replanifié vers la nouvelle instance EC2. Les politiques suivantes s’appliquent lors de la reprogrammation :
Lorsqu’un nœud Kubernetes est démarré, il obtient automatiquement une étiquette avec des informations de zone de disponibilité. Lorsque Kubernetes planifie les pods d’un ensemble avec un état stateful, il essaie de les répartir sur les zones de disponibilité. Les volumes persistants (le volume EBS) d’un pod sont également situés dans une zone de disponibilité particulière. Lorsqu’un volume persistant est créé, il obtient également une étiquette contenant des informations sur la zone de disponibilité. Désormais, lorsqu’un pod est planifié et revendique un volume, Kubernetes s’assure que le pod est planifié sur un nœud dans la même zone de disponibilité que le volume. Dans notre cas, cassandra-1 doit être reprogrammé. Ce pod revendique (veut lier) le volume cassandra-stockage-cassandra-1. Étant donné que ce volume est situé dans la zone eu-west-3c, cassandra-1 sera programmé sur un nœud s’exécutant dans eu-west-3c.
Nous utilisons l’anti-pod-affinity pour nous assurer qu’un nœud Kubernetes exécute au maximum un pod Cassandra. Bien qu’il soit parfaitement viable de fonctionner sans cette stratégie, il présente deux avantages : Pendant le démarrage de la nouvelle instance EC2, le pod Cassandra n’est pas démarré sur les nœuds restants. Par conséquent, aucune replanification manuelle n’est requise par la suite (afin d’équilibrer les pods). Le deuxième avantage est que toutes les ressources du nœud sont disponibles pour le nœud Cassandra. Notez que la même chose peut être obtenue en utilisant d’autres moyens (par exemple en utilisant des quotas de ressources)
Échec de la zone de disponibilité
Afin de tester ce scénario, nous allons terminer les nœuds Cassandra fonctionnant dans la zone eu-west-3a: cassandra-2 (instance EC2 ip-172-20-45-107) cassandra-2 et cassandra-5 (instance EC2 ip-172-20-38-248) .La commande «get pods» n’affiche désormais que cinq nœuds, dont l’un est en attente:
$ kubectl get po -o wide cassandra-0 1/1 Running 0 60m 100.96.6.2 ip-172-20-79-12 cassandra-1 1/1 Running 0 60m 100.96.8.2 ip-172-20-115-221 cassandra-2 0/1 Pending 0 43s cassandra-3 1/1 Running 1 55m 100.96.3.4 ip-172-20-92-62 cassandra-4 1/1 Running 2 54m 100.96.7.3 ip-172-20-99-226
Étant donné que Cassandra réplique les données dans toutes les zones, toutes les données sont toujours disponibles. Cela peut être confirmé en exécutant la requête de lecture qui renvoie toujours 5 enregistrements.
Le processus de récupération pour ce scénario est fondamentalement le même que le scénario de défaillance d’une seule instance EC2 décrit dans le scénario précédent. Bien que très rare, une zone de disponibilité peut échouer de telle manière que les instances ne peuvent pas être redémarrées dans la zone défaillante, mais sont démarrées à la place dans une autre zone. Plus d’informations peuvent être trouvées ici:https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-add-availability-zone.html
Le scénario précédent décrivait la façon dont les modules pods contenant des revendications de volume sont planifiés. Parce qu’il y aura une incompatibilité entre les nouvelles informations de zone d’instance EC2 et les informations de zone de volume, les pods ne peuvent pas replanifier. Une intervention manuelle est requise. Lorsque la zone de disponibilité défaillante est à nouveau active, arrêtez toutes les machines qui ne pouvaient auparavant pas démarrer dans la zone de disponibilité défaillante et toutes devraient se rétablir automatiquement.
Destruction de l’environnement :
Une fois que vous avez fini de travailler afin d’éviter les coûts financiers en exécutant la commande suivante :$ kops delete cluster --name=kops-cassandra-dmnbigdata.k8s.local --state=s3://kops-cassandra-dmnbigdata --yesA la fin de l’exécution de la commande, vous devez avoir le message ci-dessous si tout s’est bien terminé :
Deleted kubectl config for kops-cassandra-dmnbigdata.k8s.local Deleted cluster: "kops-cassandra-dmnbigdata.k8s.local"Au niveau du tableau de bord EC2, toutes les instances seront en Etat de l’instance terminated, comme ci-dessous :

$ aws2 s3api delete-bucket --bucket kops-cassandra-dmnbigdata
Conclusion
Dans cet article, nous avons montré comment déployer un cluster Cassandra à haute disponibilité dans AWS. Nous avons également montré que le déploiement récupère automatiquement des défaillances de nœuds dans la même zone de disponibilité. Dans un prochain article, nous discuterons de la mise de l’évolutivité du cluster. Un autre sujet, non abordé ici, est la performance, qui pourrait également faire l’objet d’un futur article.