Corosync et Pacemaker
Mise à jour :
Je poursuis sur la haute disponibilité et, dans ce guide, je vais explorer les outils Corosync et Pacemaker. Corosync et Pacemaker sont des outils essentiels pour assurer une haute disponibilité (HA) et la continuité des services. Ensemble, ils permettent de gérer efficacement les défaillances et d’assurer une résilience optimale dans les clusters de serveurs. Ce guide explique leur fonctionnement et propose des conseils pratiques pour leur configuration et leur maintenance.
Historique
La genèse et le développement de Corosync et Pacemaker sont intrinsèquement liés à l’évolution des besoins en haute disponibilité et en gestion de clusters.
Corosync est issu du projet OpenAIS, qui avait pour objectif de développer une implémentation open source des standards de l’API de service d’interface d’application (API). Le but était de créer une infrastructure de communication pour les services de haute disponibilité. À mesure que le projet évoluait, le besoin de simplifier et de focaliser les fonctionnalités sur la communication en cluster est devenu évident. Corosync a ainsi été créé pour se concentrer exclusivement sur la couche de communication, laissant la gestion des ressources à d’autres outils, tels que Pacemaker.
Pacemaker a été développé initialement par la société Linux-HA (High-Availability Linux) pour étendre les capacités de l’outil Heartbeat, qui était alors limité à la gestion de deux nœuds seulement. Avec l’augmentation de la complexité des infrastructures IT et la nécessité de gérer des clusters plus grands et plus dynamiques, Pacemaker est devenu un gestionnaire de ressources complet capable de supporter des configurations de clusters étendues et complexes.
Au fil du temps, Corosync et Pacemaker ont été intégrés pour travailler conjointement, fournissant une solution complète pour la gestion de clusters haute disponibilité. Cette intégration a permis aux utilisateurs de bénéficier d’une communication efficace entre les nœuds avec Corosync, tout en utilisant Pacemaker pour la gestion fine et stratégique des ressources du cluster. Cette synergie a renforcé leur position comme la solution de référence pour les systèmes nécessitant une haute disponibilité.
Fonctionnalités principales
Fonctionnalités principales de Corosync
Corosync est responsable de la communication et de la synchronisation entre les nœuds d’un cluster. Voici ses points forts :
- Gestion du quorum : Il vérifie qu’un certain nombre de nœuds du cluster sont actifs pour garantir la cohérence des données et éviter des situations où plusieurs nœuds prennent des décisions contradictoires.
- Communication inter-nœuds : Corosync offre un mécanisme fiable et performant pour échanger des messages entre les nœuds d’un cluster. Il repose sur des protocoles comme Totem pour assurer la diffusion en anneau (ring).
- Détection des pannes : Si un nœud devient inactif ou ne répond plus, Corosync le détecte rapidement et notifie le cluster pour prendre des mesures correctives.
- Extension via plugins : Corosync peut être enrichi avec des modules supplémentaires pour répondre à des besoins spécifiques, comme la gestion d’événements ou le suivi des ressources.
Fonctionnalités principales de Pacemaker
Pacemaker gère les ressources du cluster et s’assure que les services critiques restent disponibles en tout temps. Ses atouts incluent :
- Gestion des ressources : Pacemaker permet de configurer, surveiller et relancer des ressources comme des services (ex : Apache, Nginx) ou des disques montés.
- Failover automatisé : En cas de défaillance d’un nœud, Pacemaker déplace automatiquement les ressources vers un autre nœud actif du cluster.
- Gestion des dépendances : Il prend en compte les relations entre ressources (par exemple, un service web doit attendre que le service de base de données soit actif).
- STONITH (Shoot The Other Node In The Head) : Pacemaker utilise des mécanismes de fencing pour couper complètement un nœud en panne ou isolé, afin de protéger les données.
- Flexibilité de configuration : Pacemaker prend en charge des profils complexes de règles (par exemple, redémarrer un service après 3 échecs ou ajuster les comportements selon l’heure ou la charge).
- Monitoring et alerte : Il surveille l’état des ressources et envoie des alertes si quelque chose ne va pas, tout en enregistrant des logs détaillés pour les diagnostics.
Fonctionnalités combinées Corosync + Pacemaker
Ensemble, Corosync et Pacemaker offrent une solution complète pour la haute disponibilité :
- Fiabilité des clusters grâce à la communication robuste de Corosync et la gestion intelligente des ressources de Pacemaker.
- Tolérance aux pannes : les services critiques restent disponibles même si un ou plusieurs nœuds tombent.
- Scalabilité : ils peuvent être utilisés dans des petits clusters (2 nœuds) ou des clusters plus larges pour des environnements complexes.
- Simplicité d’utilisation : bien que puissants, ces outils disposent d’interfaces claires et d’une documentation bien fournie pour faciliter leur prise en main.
Concepts clés
Pour comprendre pleinement comment Corosync et Pacemaker fonctionnent ensemble dans la gestion des clusters, il est indispensable de maîtriser certains concepts fondamentaux du clustering. Ces concepts sont essentiels pour configurer et maintenir un cluster de haute disponibilité.
-
Quorum : Le quorum est un concept clé dans la gestion des clusters, désignant la majorité nécessaire pour prendre des décisions opérationnelles. Dans un cluster, le quorum aide à éviter le problème de “split brain”, où le cluster pourrait être divisé en plusieurs sous-groupes qui fonctionnent de manière indépendante, ce qui peut entraîner des conflits de données. Corosync utilise des mécanismes de quorum pour s’assurer qu’un seul sous-ensemble de nœuds (ayant la majorité) peut opérer à un moment donné, améliorant ainsi l’intégrité et la cohérence des données.
-
Fencing (Isolation) : Le fencing est une stratégie de sécurité critique pour la gestion des clusters. Il s’agit de l’isolation d’un nœud qui semble défaillant ou instable, pour empêcher qu’il cause des dommages au reste du cluster, comme des corruptions de données. Pacemaker utilise le fencing pour garantir que seulement les nœuds sains et fiables participent au cluster, en éteignant ou en redémarrant les nœuds problématiques si nécessaire.
Les différents types de ressources Pacemaker
Dans le contexte de Pacemaker, une ressource représente un service ou un élément du système que le cluster doit gérer pour garantir une haute disponibilité. Ces ressources peuvent inclure des services comme une base de données, un serveur web, ou même des adresses IP flottantes. Pacemaker utilise différents types d’agents pour gérer ces ressources. Ces agents définissent comment démarrer, arrêter et surveiller une ressource spécifique. Les principaux types d’agents de ressources utilisés dans Pacemaker incluent OCF, systemd et lsb.
OCF (Open Cluster Framework)
Les scripts OCF sont un standard développé par le projet Linux-HA pour
uniformiser la manière dont les ressources sont gérées dans un cluster de haute
disponibilité. Les scripts OCF sont des scripts shell qui suivent une convention
spécifique et offrent des actions standardisées telles que start
, stop
,
monitor
, meta-data
, entre autres. Chaque script OCF doit être capable de :
- Démarrer une ressource
- Arrêter une ressource
- Surveiller l’état actuel de la ressource
- Fournir des métadonnées décrivant la ressource et ses paramètres
Un exemple de configuration d’une ressource OCF dans Pacemaker pourrait ressembler à ceci :
pcs resource create myResource ocf:heartbeat:Dummy op monitor interval=30s
Ici, heartbeat:Dummy
indique que le script OCF Dummy
du fournisseur
heartbeat
est utilisé.
Les scripts OCF sont généralement stockés dans des répertoires spécifiques au
fournisseur sous le dossier /usr/lib/ocf/resource.d/
. Chaque fournisseur, tel
que heartbeat ou pacemaker, a son propre sous-dossier dans ce répertoire.
Exemple de contenu du dossier /usr/lib/ocf/resource.d/heartbeat
:
root@node1:/usr/lib/ocf/resource.d# ls heartbeat/AoEtarget LVM SphinxSearchDaemon apache docker iface-bridge minio oralsnr rsyslogAudibleAlarm LVM-activate Squid asterisk docker-compose iface-vlan mpathpersist ovsmonitor scsi2reservationCTDB LinuxSCSI Stateful aws-vpc-move-ip dovecot ipsec mysql pgagent sfexClusterMon MailTo SysInfo aws-vpc-route53 dummypy iscsi mysql-proxy pgsql sg_persistDelay ManageRAID VIPArip awseip eDir88 jboss nagios pingd slapdDummy ManageVE VirtualDomain awsvip ethmonitor jira named podman sybaseASEEvmsSCC NodeUtilization WAS azure-events exportfs kamailio nfsnotify portblock symlinkEvmsd Pure-FTPd WAS6 azure-lb fio ldirectord nfsserver postfix syslog-ngFilesystem Raid1 WinPopup clvm galera lvmlockd nginx pound tomcatICP Route Xen conntrackd garbd lxc openstack-cinder-volume proftpd varnishIPaddr SAPDatabase Xinetd crypt gcp-vpc-move-ip lxd-info openstack-floating-ip rabbitmq-cluster vdo-volIPaddr2 SAPInstance ZFS db2 iSCSILogicalUnit machine-info openstack-info redis vmwareIPsrcaddr SendArp aliyun-vpc-move-ip dhcpd iSCSITarget mariadb oraasm rkt vsftpdIPv6addr ServeRAID anything dnsupdate ids mdraid oracle rsyncd zabbixserver
systemd
Les unités systemd sont des scripts de service pour le système
d’initialisation systemd
, utilisé par de nombreuses distributions Linux
modernes pour gérer les services système et les processus. Pacemaker peut
directement gérer ces services en tant que ressources, en utilisant les
commandes et fonctionnalités fournies par systemd
. Cela permet une intégration
étroite avec les composants système sous-jacents et simplifie la gestion des
services qui sont déjà configurés pour être gérés par systemd
.
Pour configurer une ressource systemd
dans Pacemaker, vous pouvez utiliser une
commande telle que :
pcs resource create myWebServer systemd:httpd.service op monitor interval=60s
Dans cet exemple, httpd.service
est le nom du service systemd
géré par
Pacemaker.
LSB (Linux Standard Base)
Les scripts LSB sont basés sur les standards de la Linux Standard Base, qui
définit les actions de service standard comme start
, stop
, status
, et
restart
. Pacemaker peut utiliser ces scripts pour gérer des services qui ne
sont pas encore intégrés à systemd
. Bien que moins fréquemment utilisés
aujourd’hui en raison de la prévalence de systemd
, ils sont toujours pris en
charge pour assurer la compatibilité avec les systèmes plus anciens.
Un exemple de commande pour configurer une ressource LSB pourrait être :
pcs resource create myOldService lsb:my-service op monitor interval=120s
Choix de l’agent de ressource
Le choix de l’agent de ressource dépend principalement du type de service à
gérer et de l’environnement système. Les agents OCF sont préférables pour leur
portabilité et leur extensibilité, tandis que les agents systemd
sont mieux
intégrés avec les systèmes qui utilisent systemd
pour la gestion des services.
Les agents LSB peuvent être utilisés pour les services plus anciens ou pour ceux
qui ne sont pas encore pris en charge par systemd
.
Stratégie de fencing de Pacemacker
Le fencing, également connu sous le terme de clôture, est une stratégie importante dans la gestion des clusters de haute disponibilité, comme ceux contrôlés par Pacemaker. Le but principal du fencing est de prévenir les scénarios de “cerveau divisé” (split-brain) où plusieurs nœuds du cluster croient être le coordinateur actif, conduisant potentiellement à des corruptions de données.
Le fencing est une méthode utilisée pour isoler un nœud défectueux ou non fiable d’un cluster, afin de garantir que ce nœud ne puisse pas causer de dommages aux données partagées ou aux services du cluster. Cela est souvent réalisé en coupant l’accès du nœud aux ressources partagées, telles que le stockage réseau ou l’adresse IP virtuelle. Il existe principalement deux types de fencing :
- Fencing actif : où le système prend des mesures actives pour isoler le nœud défectueux, comme redémarrer ou éteindre le nœud.
- Fencing passif : où le nœud défectueux est simplement ignoré par les autres nœuds du cluster sans prendre de mesures actives pour l’arrêter.
Les principaux agents de fencing de Pacemaker
Pacemaker supporte une variété d’agents de fencing (aussi appelés agents STONITH, pour “Shoot The Other Node In The Head”), qui sont essentiels pour assurer l’intégrité des données et la haute disponibilité dans un environnement de cluster. Ces agents permettent de garantir qu’un nœud défectueux est correctement isolé du cluster pour éviter les conflits et la corruption des données. Voici une liste de quelques agents de fencing communément utilisés avec Pacemaker :
- fence_aws : Conçu pour interagir avec les services Amazon Web Services (AWS). Cet agent peut arrêter, redémarrer ou isoler des instances EC2 via l’API AWS.
- fence_azure_arm : Utilisé pour les environnements Microsoft Azure. Cet agent fait appel à Azure Resource Manager pour gérer les instances virtuelles.
- fence_gce : Dédié aux environnements Google Cloud Platform (GCP). Il utilise l’API Google Compute Engine pour contrôler les instances virtuelles.
- fence_vmware_soap : Cet agent utilise l’API SOAP de VMware pour gérer les machines virtuelles sur des hôtes VMware ESXi ou vSphere.
- fence_ipmilan : Utilise l’interface de gestion à distance IPMI (Intelligent Platform Management Interface) pour contrôler le matériel serveur, permettant des actions telles que l’arrêt ou le redémarrage de la machine.
- fence_rhevm : Conçu pour les environnements Red Hat Enterprise Virtualization (RHEV), maintenant connu sous le nom de Red Hat Virtualization (RHV). Cet agent interagit avec l’API RHEV pour gérer les machines virtuelles.
- fence_xvm : Utilisé pour le fencing de machines virtuelles Xen à l’aide de commandes xm ou xl sur un hôte Xen.
- fence_scsi : Un agent de fencing qui utilise le SCSI persistent reservations pour contrôler l’accès aux périphériques de stockage partagé.
- fence_brocade : Permet le contrôle des switches Fibre Channel Brocade via telnet, ssh ou SNMP.
- fence_drac : Cible les serveurs Dell équipés de la carte de gestion à distance iDRAC, permettant diverses opérations de contrôle à distance.
Ces agents couvrent un large éventail de technologies et de plateformes, offrant ainsi des solutions de fencing flexibles et adaptées à divers environnements de datacenter et de cloud. Choisir l’agent approprié dépend des équipements et des services spécifiquement utilisés dans votre infrastructure.
Mise en place d’un LAB
Pour tester ces outils avec comme objectif de configurer un cluster HA avec Corosync et Pacemaker, je vais utiliser un environnement cloud, comme celui proposé par Outscale.
Pour cela, je vais modifier l’infrastructure du guide
suivant pour avoir un NET composé de
deux subnets provisionnés dans deux AZ différentes de la région SNC
cloudgouv-eu-west-1
.
Dans cette exemple, je vais provisionner un bastion et un cluster de deux nœuds, répartis sur les deux sous-réseaux. Le bastion sera accessible depuis mon IP et les nœuds seront accessibles seulement depuis le bastion. Les nœuds seront configurés avec Corosync et Pacemaker pour gérer une IP flottante servant les deux noeuds HAProxy. Si un nœud tombe, l’autre prendra le relais.
Provisionnement Terraform
Voici le code Terraform :
resource "outscale_security_group_rule" "security_group_rule01" { flow = "Inbound" security_group_id = outscale_security_group.sg-ssh-all.id from_port_range = "22" to_port_range = "22" ip_protocol = "tcp" ip_range = "46.231.144.178/32"}
resource "outscale_security_group_rule" "security_group_rule02" { flow = "Inbound" security_group_id = outscale_security_group.sg-all-all.security_group_id from_port_range = "2224" to_port_range = "2224" ip_protocol = "tcp" ip_range = "10.0.0.0/16"}
resource "outscale_security_group_rule" "security_group_rule03" { flow = "Inbound" security_group_id = outscale_security_group.sg-all-all.security_group_id from_port_range = "5404" to_port_range = "5405" ip_protocol = "udp" ip_range = "10.0.0.0/16"}
resource "outscale_security_group_rule" "security_group_rule04" { flow = "Inbound" security_group_id = outscale_security_group.sg-all-all.security_group_id from_port_range = "3121" to_port_range = "3121" ip_protocol = "tcp" ip_range = "10.0.0.0/16"}
resource "outscale_security_group_rule" "security_group_rule05" { flow = "Inbound" security_group_id = outscale_security_group.sg-all-all.security_group_id from_port_range = "80" to_port_range = "80" ip_protocol = "tcp" ip_range = "10.0.0.0/16"}
resource "outscale_security_group" "sg-ssh-all" { description = "Permit SSH from All" security_group_name = "seg-ssh-all" net_id = outscale_net.my_net.net_id}
resource "outscale_security_group" "sg-all-all" { description = "Permit All from All" security_group_name = "seg-all-all" net_id = outscale_net.my_net.net_id}
resource "outscale_route_table" "private_route_table" { net_id = outscale_net.my_net.net_id tags { key = "Name" value = "private_route_table-a" }}
resource "outscale_route_table" "private_route_table2" { net_id = outscale_net.my_net.net_id tags { key = "Name" value = "private_route_table-b" }}
resource "outscale_route_table" "public_route_table" { net_id = outscale_net.my_net.net_id tags { key = "Name" value = "public_route_table" }}
resource "outscale_route" "route-IGW" { destination_ip_range = "0.0.0.0/0" gateway_id = outscale_internet_service.internet_gateway.internet_service_id route_table_id = outscale_route_table.public_route_table.route_table_id}
resource "outscale_route" "to_nat_gateway" { nat_service_id = outscale_nat_service.public_nat_gateway.nat_service_id destination_ip_range = "0.0.0.0/0" route_table_id = outscale_route_table.private_route_table.route_table_id}
resource "outscale_route" "to_nat_gatewa2" { nat_service_id = outscale_nat_service.public_nat_gateway.nat_service_id destination_ip_range = "0.0.0.0/0" route_table_id = outscale_route_table.private_route_table2.route_table_id}
resource "outscale_route_table_link" "backend_subnet-a_private_route_table_link" { subnet_id = outscale_subnet.backend_subnet-a.subnet_id route_table_id = outscale_route_table.private_route_table.route_table_id}
resource "outscale_route_table_link" "backend_subnet-b_private_route_table_link" { subnet_id = outscale_subnet.backend_subnet-b.subnet_id route_table_id = outscale_route_table.private_route_table2.route_table_id}
resource "outscale_route_table_link" "public_subnet_public_route_table_link" { subnet_id = outscale_subnet.public_subnet.subnet_id route_table_id = outscale_route_table.public_route_table.route_table_id}
resource "outscale_public_ip" "public_nat_gateway_ip" {}
resource "outscale_nat_service" "public_nat_gateway" { subnet_id = outscale_subnet.public_subnet.subnet_id public_ip_id = outscale_public_ip.public_nat_gateway_ip.public_ip_id tags { key = "Name" value = "public_nat_gateway" }}
resource "outscale_subnet" "public_subnet" { subregion_name = "${var.region}a" ip_range = "10.0.1.0/24" net_id = outscale_net.my_net.net_id tags { key = "Name" value = "public_subnet" }}
resource "outscale_subnet" "backend_subnet-a" { subregion_name = "${var.region}a" ip_range = "10.0.2.0/24" net_id = outscale_net.my_net.net_id tags { key = "Name" value = "backend_subnet-a" }}
resource "outscale_subnet" "backend_subnet-b" { subregion_name = "${var.region}b" ip_range = "10.0.3.0/24" net_id = outscale_net.my_net.net_id tags { key = "Name" value = "backend_subnet-b" }}
resource "outscale_net" "my_net" { ip_range = "10.0.0.0/16" tags { key = "Name" value = "my_net" }}
resource "outscale_internet_service" "internet_gateway" {}
resource "outscale_internet_service_link" "internet_gateway_link" { internet_service_id = outscale_internet_service.internet_gateway.internet_service_id net_id = outscale_net.my_net.net_id}
Je provisionne deux nœuds, utilisant des OMI RHEL 8 et en les répartissant sur
les deux sous-réseaux (remplacer node1
par node2
et backend_subnet-a
par
backend_subnet-b
pour la seconde machine) :
data "outscale_images" "images" { filter { name = "image_name" values = ["RHEL-8-2024.01.29-0"] }}
data "outscale_keypair" "keypair01" { keypair_name = "bastion"}
data "outscale_subnet" "subnet" { filter { name = "tag_values" values = ["backend_subnet-a"] }}
data "outscale_security_group" "sg-all-all" { security_group_name = "seg-all-all"}
data "outscale_security_group" "sg-ssh-all" { security_group_name = "seg-ssh-all"}
resource "outscale_vm" "vm" { image_id = data.outscale_images.images.images[0].image_id vm_type = "tinav5.c4r8p1" keypair_name = data.outscale_keypair.keypair01.keypair_name security_group_ids = [ data.outscale_security_group.sg-all-all.security_group_id, data.outscale_security_group.sg-ssh-all.security_group_id ] subnet_id = data.outscale_subnet.subnet.id state = "running" block_device_mappings { device_name = "/dev/sda1" bsu { volume_size = 100 volume_type = "io1" iops = 2000 delete_on_vm_deletion = true } } tags { key = "Name" value = "node1" } tags { key = "Application" value = "cluster" } tags { key = "Group" value = "http" } tags { key = "Env" value = "test" }}
output "IP" { value = outscale_vm.vm.private_ip}
Configuration des noeuds
Un premier playbook Ansible pour configurer les noeuds :
---- name: First playbook hosts: aws_ec2 gather_facts: true pre_tasks: - name: Add IP address of all hosts to all hosts ansible.builtin.lineinfile: dest: /etc/hosts regexp: "^.*{{ hostvars[item].tags.Name }}.{{ hostvars[item].tags.Env }}.local" line: "{{ (hostvars[item].ansible_all_ipv4_addresses | select('match', '10.') | list)[0] }} {{ hostvars[item].tags.Name }}.{{ hostvars[item].tags.Env }}.local {{ hostvars[item].tags.Name }}" state: present when: hostvars[item].ansible_nodename is defined with_items: "{{ groups.aws_ec2 }}" become: true - name: Change Hostname ansible.builtin.hostname: name: "{{ hostvars[inventory_hostname].tags.Name }}.{{ hostvars[inventory_hostname].tags.Env }}.local" tags: name become: true - name: Add ./local/bin in path ansible.builtin.lineinfile: regexp: "^export PATH=${HOME}/local/bin.*" line: "export PATH=${HOME}/local/bin:${PATH}" path: /home/outscale/.bashrc - name: Install tools become: true ansible.builtin.dnf: name: - net-tools state: present - name: Register Outscale RHEL8 subscription become: true ansible.builtin.shell: > subscription-manager register --activationkey outscale-rhel8 --org Outscale --baseurl 'https://rhsatellite.outscale.internal:4888/pulp/repos' --serverurl 'rhsatellite.outscale.internal:4888' --force - name: Update all packages become: true ansible.builtin.dnf: update_cache: true state: latest name: "*"---
Ce playbook permet de :
- Ajouter les adresses IP des nœuds dans le fichier
/etc/hosts
. - Changer le nom des nœuds.
- Ajouter le répertoire
~/local/bin
dans lePATH
. - Installer les outils
net-tools
. - Enregistrer l’abonnement RHEL8.
- Mettre à jour tous les paquets.
Ensuite, je vais utiliser un playbook ansible nommé cluster.yml
qui ne sera
exécuté que sur les machines du cluster :
---- name: Create Corosync Pacemaker Cluster hosts: cluster gather_facts: true vars: cluster_name: my_cluster pacemaker_disable_stonith: true elastic_ip: 217.75.167.20 tasks: - name: Add High Availability Repo become: true community.general.rhsm_repository: name: rhel-8-for-x86_64-highavailability-rpms state: enabled - name: Install All packages become: true ansible.builtin.dnf: name: - haproxy - gtk2-devel - libqb-devel - pcs - pacemaker - corosync - fence-agents-all - resource-agents - '@Development tools' state: present - name: Install osc-cli become: true ansible.builtin.pip: name: osc-sdk state: present - name: Create osc-cli directory become: true ansible.builtin.file: path: /root/.osc state: directory owner: root group: root mode: "0755" - name: Configure osc-cli become: true ansible.builtin.copy: src: config.json dest: /root/.osc/config.json owner: root group: root mode: "0600" - name: Git ressource-agents repo become: true ansible.builtin.git: repo: "https://github.com/ClusterLabs/resource-agents.git" dest: "/tmp/resource-agents" - name: Create script become: true ansible.builtin.copy: content: | ./autogen.sh ./configure make make install dest: /tmp/resource-agents/build.sh mode: "0755" owner: root group: root - name: Build ressource-agents become: true ansible.builtin.shell: cmd: /tmp/resource-agents/build.sh creates: /usr/lib/ocf/resource.d/heartbeat/osceip args: chdir: "/tmp/resource-agents" - name: Configure haproxy become: true ansible.builtin.template: src: haproxy.cfg.j2 dest: /etc/haproxy/haproxy.cfg owner: root mode: "0644" - name: Set password of user hacluster ansible.builtin.user: name: hacluster state: present password: "{{ 'hacluster' | password_hash('sha512') }}" become: true - name: Create log diirectory become: true ansible.builtin.file: path: /var/log/corosync owner: root group: root mode: "0755" state: directory - name: Create corosync-config become: true ansible.builtin.template: src: corosync.conf.j2 dest: /etc/corosync/corosync.conf mode: "0644" notify: Restart corosync - name: Start pacemaker become: true ansible.builtin.service: name: pacemaker state: started enabled: true - name: Start pcsd become: true ansible.builtin.service: name: pcsd state: started enabled: true - name: Authorize pcs auth ansible.builtin.command: "pcs cluster auth -u hacluster -p hacluster" become: true changed_when: false run_once: true - name: Start pcsd ansible.builtin.service: name: pcsd state: started enabled: true - name: Capturing Cluster Resources ansible.builtin.command: "pcs resource show --full" become: true register: "_pcs_resource_show" changed_when: false - name: Setting Stonith ansible.builtin.command: pcs property set stonith-enabled=false become: true when: pacemaker_disable_stonith - name: Creating HAProxy Cluster Resource ansible.builtin.command: pcs resource create HAProxy systemd:haproxy become: true run_once: true when: "'HAProxy' not in _pcs_resource_show.stdout" - name: Creating ElasticIP Cluster Resources ansible.builtin.command: "pcs resource create ElasticIP ocf:heartbeat:osceip elastic_ip='{{ elastic_ip }}' op start timeout='60s' interval='0s' on-fail='restart' op monitor timeout='60s' interval='10s' on-fail='restart' op stop timeout='60s' interval='0s' on-fail='block'" become: true run_once: true when: "'ElasticIP' not in _pcs_resource_show.stdout" - name: Creating colocation constrainst ansible.builtin.command: "pcs constraint colocation add ElasticIP with HAProxy" become: true run_once: true
handlers: - name: Restart corosync become: true ansible.builtin.systemd: name: corosync state: restarted enabled: true
Ce playbook Ansible est conçu pour configurer un cluster Corosync et
Pacemaker sur un groupe d’hôtes désigné sous le nom cluster
. Il inclut
plusieurs tâches pour préparer les hôtes, installer les paquets nécessaires,
configurer les fichiers et gérer les ressources du cluster. Voici une
explication détaillée des différentes parties de ce playbook :
Structure et Variables Globales
- hosts: cluster : Le playbook cible les hôtes du groupe
cluster
. - gather_facts: true : Collecte les informations sur les hôtes avant d’exécuter les tâches.
- vars : Définit des variables utilisées dans le playbook :
cluster_name
: Nom du cluster.pacemaker_disable_stonith
: Une variable booléenne pour activer ou désactiver STONITH (fencing).elastic_ip
: Adresse IP élastique à utiliser pour le cluster.
Tâches
- Add IP address of all hosts : Met à jour le fichier
/etc/hosts
sur tous les hôtes du cluster pour inclure les adresses IP et noms d’hôte de chaque hôte, facilitant ainsi la résolution de noms au sein du cluster. - Set password of user hacluster : Définit le mot de passe pour
l’utilisateur
hacluster
, qui est utilisé pour l’authentification par les outils de cluster. Le commentaire suggère de stocker ce mot de passe dans un “vault” Ansible pour la sécurité. - Authorize pcs auth : Exécute l’authentification de cluster sur un seul noeud.
- Upgrade packages : Met à jour tous les paquets sur les hôtes du cluster pour s’assurer que les dernières mises à jour de sécurité et de logiciel sont appliquées.
- Install packages : Installe les paquets nécessaires pour le cluster, y
compris
pcs
,pacemaker
,corosync
, des agents de clôture et de ressources, ainsi que HAProxy et PHP. - Create corosync-config : Utilise un template Jinja2 pour configurer
Corosync à partir du fichier
corosync.conf.j2
et le place dans/etc/corosync/corosync.conf
. - Start pacemaker : Démarre le service Pacemaker.
- Create index.php et Remove index.html : Gère les fichiers dans le
répertoire web d’Apache, en s’assurant que
index.php
est en place et en supprimantindex.html
. - Capturing Cluster Resources : Capture la sortie de
pcs resource show --full
pour vérifier les ressources actuellement gérées par le cluster. - Setting Stonith : Désactive STONITH si
pacemaker_disable_stonith
est vrai. STONITH est une méthode de fencing critique pour la gestion de cluster. - Creating Cluster Resources : Crée les ressources de cluster.
Handlers
- Restart corosync : Redémarre le service Corosync si nécessaire, généralement après une modification de configuration.
Points Importants
- Le playbook utilise des conditions
when
pour s’assurer que certaines tâches ne s’exécutent que dans des circonstances appropriées. - Les tâches de configuration sont protégées par
become: true
pour exécuter les commandes avec des privilèges élevés. - La gestion des configurations de ressources est dynamique, permettant des modifications faciles via les variables définies au début du playbook.
Le template corosync.conf.j2
totem { version: 2 cluster_name: {{ cluster_name }} transport: udpu}
quorum { provider: corosync_votequorum{% if groups['cluster']|count == 2 %} two_node: 1{% else %} wait_for_all: 1 last_man_standing: 1{% endif %}}
nodelist {{% for node in groups['cluster']|sort %} node { ring0_addr: {{ hostvars[node]['ansible_default_ipv4']['address'] }} nodeid: {{ loop.index }} name: {{ hostvars[node]['ansible_fqdn'] }}
}{% endfor %}}
logging { to_logfile: yes logfile: /var/log/corosync/corosync.log to_syslog: yes timestamp: on}
Les principaux outils pour gérer des clusters
Il existe deux principaux outils en ligne de commande pour gérer les clusters :
crm
et pcs
.
Utilisation et commandes principales de crm
crm
est une interface en ligne de commande pour gérer les clusters qui
utilisent le moteur de haute disponibilité Pacemaker. Cet outil est
essentiel pour la configuration et la gestion du cluster, permettant aux
administrateurs de surveiller, de modifier et de maintenir les paramètres et les
ressources du cluster de manière interactive. crm
offre une interface complète
pour la gestion des clusters, ce qui en fait un choix privilégié pour les
configurations complexes et les ajustements fins.
crm status
Cette commande fournit un aperçu de l’état actuel du cluster, y compris l’état des nœuds, des ressources et des contraintes de groupe.
crm configure show
Utilisez cette commande pour afficher la configuration actuelle des ressources du cluster.
crm configure edit <resource_name>
Cette commande permet de modifier la configuration d’une ressource spécifique.
crm node status
Montre le statut de chaque nœud du cluster.
crm configure colocation add <constraint_name> <resource1> with <resource2>
Définit une contrainte de colocation pour que deux ressources soient placées sur le même nœud.
crm configure stonith
Permet de configurer et de gérer les dispositifs STONITH dans le cluster.
Utilisation et commandes principales de pcs
pcs
(Pacemaker/Corosync Configuration System) est un outil de gestion de
cluster qui simplifie le processus de configuration de clusters utilisant
Corosync et Pacemaker. Il fournit une interface de ligne de commande
unifiée pour configurer, gérer et visualiser tous les aspects du cluster.
pcs status
Cluster name: my_clusterCluster Summary: * Stack: corosync * Current DC: node2.test.local (version 2.1.2-ada5c3b36e2) - partition with quorum * Last updated: Tue May 14 08:37:39 2024 * Last change: Tue May 14 06:10:26 2024 by hacluster via crmd on node1.test.local * 2 nodes configured * 1 resource instance configured
Node List: * Online: [ node1.test.local node2.test.local ]
Full List of Resources: * HAProxy (systemd:haproxy): Started node2.test.local
Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
Cette commande donne une vue d’ensemble de l’état du cluster, incluant les nœuds, les ressources et les contraintes.
pcs resource create <resource_name> <agent> [options]
Crée une nouvelle ressource avec le type d’agent spécifié et des options configurables.
pcs cluster start --allpcs cluster stop --all
Ces commandes permettent de démarrer ou d’arrêter tous les nœuds du cluster.
pcs property set stonith-enabled=true
Active ou modifie une propriété du cluster, comme l’activation de STONITH.
pcs constraint colocation add <resource1> with <resource2> [score]
Ajoute une contrainte de colocation entre deux ressources.
Quel outil choisir : crm
ou pcs
?
Bien que crm
et pcs
accomplissent des fonctions similaires, pcs
est
souvent préféré pour sa simplicité et son approche plus directes.
pcs
est conçu pour être plus accessible et plus facile à utiliser pour les
nouveaux administrateurs de clusters, fournissant des commandes claires et des
options de configuration simplifiées. Cela en fait un outil idéal pour les
tâches courantes de gestion de clusters, rendant la configuration et la
surveillance plus intuitives et moins sujettes aux erreurs.
pcs
est conçu pour être plus accessible et plus facile à utiliser pour les
nouveaux administrateurs de clusters, fournissant des commandes claires et des
options de configuration simplifiées. Cela en fait un outil idéal pour les
tâches courantes de gestion de clusters, rendant la configuration et la
surveillance plus intuitives et moins sujettes aux erreurs.
Test du cluster provisionné par l’arrêt d’un nœud
Maintenant que notre cluster Corosync et Pacemaker est en place, il est important de tester sa robustesse et sa capacité à gérer les pannes de manière adéquate. Un test fréquent consiste à arrêter un nœud pour observer si le cluster réagit correctement en basculant les ressources comme prévu.
Assurez-vous que toutes vos configurations sont correctes et que toutes les ressources sont opérationnelles avant de commencer le test. Il est également important de s’assurer que toutes les données nécessaires sont sauvegardées pour éviter toute perte en cas de problème durant le test.
Arrêt d’un nœud
Choisissez un nœud à arrêter dans votre cluster (dans mon cas, je choisis le noeud 2). Cette action devrait simuler une panne et forcer le cluster à réagir. Vous pouvez arrêter un nœud de manière contrôlée via la commande suivante :
sudo pcs cluster stop node2.test.local
Vérification du statut du cluster
Après avoir arrêté le nœud, utilisez la commande pcs status
pour observer
comment le cluster réagit. Cette commande vous fournira une vue d’ensemble de
l’état du cluster, y compris le statut des nœuds et des ressources. Voici un
exemple de commande et de sortie typique :
pcs statusCluster name: my_clusterCluster Summary: * Stack: corosync * Current DC: node1.test.local (version 2.1.2-ada5c3b36e2) - partition with quorum * Last updated: Tue May 14 10:16:46 2024 * Last change: Tue May 14 09:23:11 2024 by hacluster via crmd on node1.test.local * 2 nodes configured * 1 resource instance configured
Node List: * Online: [ node1.test.local ] * OFFLINE: [ node2.test.local ]
Full List of Resources: * webserver (ocf:heartbeat:apache): Started node1.test.local
Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
Dans cet exemple, node2
est arrêté et vous pouvez voir que le nœud node1
est
en ligne et que la ressource WebServer
a basculé sur node1
.
Analyse des résultats
Lorsque vous vérifiez le résultat de la commande pcs status
, cherchez les
points suivants :
- Le nœud arrêté doit apparaître comme
OFFLINE
. - Les autres nœuds du cluster doivent être
Online
. - Toutes les ressources critiques qui fonctionnaient sur le nœud arrêté devraient maintenant être actives sur un autre nœud, indiquant un basculement réussi.
Conclusion du test
Ce test est indispensable pour valider la configuration de haute disponibilité de votre cluster. Il assure que le cluster est capable de gérer les défaillances de nœuds sans interruption du service. Des tests réguliers comme celui-ci aident à maintenir l’intégrité du cluster et à préparer l’équipe de gestion à répondre efficacement aux incidents réels.
Si le cluster ne réagit pas comme prévu, il peut être nécessaire de revoir les configurations des ressources, les politiques de basculement ou même les paramètres réseau du cluster.
Conclusion
Corosync et Pacemaker offrent une fondation solide pour la gestion des clusters de haute disponibilité, adaptée à une large gamme d’applications et de scénarios. En tirant parti de ces outils, les entreprises peuvent considérablement améliorer la résilience et la fiabilité de leurs infrastructures critiques. La mise en œuvre efficace de ces technologies est une compétence précieuse pour tout administrateur système cherchant à optimiser la disponibilité et la performance dans des environnements complexes et exigeants.
Conclusion
Corosync et Pacemaker offrent une fondation solide pour la gestion des clusters de haute disponibilité, adaptée à une large gamme d’applications et de scénarios. En tirant parti de ces outils, les entreprises peuvent considérablement améliorer la résilience et la fiabilité de leurs infrastructures critiques. La mise en œuvre efficace de ces technologies est une compétence précieuse pour tout administrateur système cherchant à optimiser la disponibilité et la performance dans des environnements complexes et exigeants.