diff --git a/docs/workshop/en/README.md b/docs/workshop/en/README.md new file mode 100644 index 0000000..227ec59 --- /dev/null +++ b/docs/workshop/en/README.md @@ -0,0 +1,36 @@ +# How to build the workshop + +## Flat HTML output with pandoc + +~~~ +pandoc -s -o /tmp/workshop-PAF.html workshop-PAF.md +~~~ + +## Slide output with reveal and pandoc + +Download and extract reveal.js to /tmp/reveal.js: + +~~~ +cd /tmp +wget https://github.com/hakimel/reveal.js/archive/master.zip +unzip master.zip +mv reveal.js-master reveal.js +~~~ + +Now you can build a self-contained html file: + +~~~ +pandoc -t revealjs --variable=revealjs-url:/tmp/reveal.js workshop-PAF.md --self-contained --standalone -o /tmp/paf.html +~~~ + +Note: if you have an internet access you can build html files without downloading and extracting reveal.js (but speaker notes will not work): + +~~~ +pandoc -t revealjs --variable=revealjs-url:http://lab.hakim.se/reveal-js workshop-PAF.md --self-contained --standalone -o /tmp/paf.html +~~~ + +## PDF output with pandoc + +~~~ +pandoc workshop-PAF.md -o /tmp/paf.pdf +~~~ diff --git a/docs/workshop/en/medias/Makefile b/docs/workshop/en/medias/Makefile new file mode 100644 index 0000000..63c1f99 --- /dev/null +++ b/docs/workshop/en/medias/Makefile @@ -0,0 +1,72 @@ +# export png: +# make DRAWIO_HOME=/home/ioguix/git/drawio-desktop + +DRAWIO_HOME=/change/me +DRAWIO=npm start --prefix "$(DRAWIO_HOME)" -- --no-sandbox -x -f png --border=30 --height=800 + +ALLPNG=pcmk-archi-all.png pcmk-archi-cib.png pcmk-archi-crmd.png +ALLPNG+=pcmk-archi-fencing.png pcmk-archi-pengine.png pcmk-archi-resource.png +ALLPNG+=pcmk-archi-dc.png pcmk-archi-transition.png pcmk-archi-paf-overview.png +ALLPNG+=paf-ms-roles.png paf-ms-roles-notify.png paf-election.png +ALLPNG+=paf-standby-recover.png paf-primary-recover.png + + +all: $(ALLPNG) + +clean: + rm -f $(ALLPNG) + +pcmk-archi-all.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=0 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-cib.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=1 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-crmd.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=2 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-dc.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=3 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-fencing.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=4 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-pengine.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=5 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-resource.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=6 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-paf-overview.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=7 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +pcmk-archi-transition.png: $(CURDIR)/pcmk-archi.xml + $(DRAWIO) --page-index=8 -o "$(CURDIR)/$@" $(CURDIR)/pcmk-archi.xml + +paf-ms-roles.png: $(CURDIR)/paf-mecha.xml + $(DRAWIO) --page-index=0 -o "$(CURDIR)/$@" $(CURDIR)/paf-mecha.xml + +paf-ms-roles-notify.png: $(CURDIR)/paf-mecha.xml + $(DRAWIO) --page-index=1 -o "$(CURDIR)/$@" $(CURDIR)/paf-mecha.xml + +paf-standby-recover.png: $(CURDIR)/paf-mecha.xml + $(DRAWIO) --page-index=2 -o "$(CURDIR)/$@" $(CURDIR)/paf-mecha.xml + +paf-primary-recover.png: $(CURDIR)/paf-mecha.xml + $(DRAWIO) --page-index=3 -o "$(CURDIR)/$@" $(CURDIR)/paf-mecha.xml + +paf-election.png: $(CURDIR)/paf-mecha.xml + $(DRAWIO) --page-index=4 -o "$(CURDIR)/$@" $(CURDIR)/paf-mecha.xml + +# paf-mecha.xml +# pcmk-archi.xml +# pcmk-archi-cib.png +# pcmk-archi-crmd.png +# pcmk-archi-dc.png +# pcmk-archi-fencing.png +# pcmk-archi-pengine.png +# pcmk-archi.png +# pcmk-archi-resource.png +# pcmk-archi.png +# pcmk-archi.xml +# Policy-Engine-big.png diff --git a/docs/workshop/en/medias/Policy-Engine-big.png b/docs/workshop/en/medias/Policy-Engine-big.png new file mode 100644 index 0000000..e6e66ee Binary files /dev/null and b/docs/workshop/en/medias/Policy-Engine-big.png differ diff --git a/docs/workshop/en/medias/README b/docs/workshop/en/medias/README new file mode 100644 index 0000000..6d81e7c --- /dev/null +++ b/docs/workshop/en/medias/README @@ -0,0 +1,14 @@ +Diagrams have been generated using draw.io from https://www.draw.io/. + +To modify it, go to the website and "Open Existing Diagram" or install draw.io +localy. + +Select the .xml source file. + +Do your modification and Save. + +To generate the png and svg files, select "Export as" or use the Makefile. +Eg.: + + make DRAWIO_HOME=$HOME/git/drawio-desktop all + diff --git a/docs/workshop/en/medias/paf-election.png b/docs/workshop/en/medias/paf-election.png new file mode 100644 index 0000000..9e40dc6 Binary files /dev/null and b/docs/workshop/en/medias/paf-election.png differ diff --git a/docs/workshop/en/medias/paf-mecha.xml b/docs/workshop/en/medias/paf-mecha.xml new file mode 100644 index 0000000..3ce451a --- /dev/null +++ b/docs/workshop/en/medias/paf-mecha.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/workshop/en/medias/paf-ms-roles-notify.png b/docs/workshop/en/medias/paf-ms-roles-notify.png new file mode 100644 index 0000000..e1658c2 Binary files /dev/null and b/docs/workshop/en/medias/paf-ms-roles-notify.png differ diff --git a/docs/workshop/en/medias/paf-ms-roles.png b/docs/workshop/en/medias/paf-ms-roles.png new file mode 100644 index 0000000..5b0a665 Binary files /dev/null and b/docs/workshop/en/medias/paf-ms-roles.png differ diff --git a/docs/workshop/en/medias/paf-primary-recover.png b/docs/workshop/en/medias/paf-primary-recover.png new file mode 100644 index 0000000..cb23a88 Binary files /dev/null and b/docs/workshop/en/medias/paf-primary-recover.png differ diff --git a/docs/workshop/en/medias/paf-standby-recover.png b/docs/workshop/en/medias/paf-standby-recover.png new file mode 100644 index 0000000..510a3a1 Binary files /dev/null and b/docs/workshop/en/medias/paf-standby-recover.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-all.png b/docs/workshop/en/medias/pcmk-archi-all.png new file mode 100644 index 0000000..171f776 Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-all.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-cib.png b/docs/workshop/en/medias/pcmk-archi-cib.png new file mode 100644 index 0000000..0261649 Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-cib.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-crmd.png b/docs/workshop/en/medias/pcmk-archi-crmd.png new file mode 100644 index 0000000..b6190cc Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-crmd.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-dc.png b/docs/workshop/en/medias/pcmk-archi-dc.png new file mode 100644 index 0000000..cae44a5 Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-dc.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-fencing.png b/docs/workshop/en/medias/pcmk-archi-fencing.png new file mode 100644 index 0000000..016bf1f Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-fencing.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-paf-overview.png b/docs/workshop/en/medias/pcmk-archi-paf-overview.png new file mode 100644 index 0000000..4ffa9ac Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-paf-overview.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-pengine.png b/docs/workshop/en/medias/pcmk-archi-pengine.png new file mode 100644 index 0000000..14806bb Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-pengine.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-resource.png b/docs/workshop/en/medias/pcmk-archi-resource.png new file mode 100644 index 0000000..5a7c9a5 Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-resource.png differ diff --git a/docs/workshop/en/medias/pcmk-archi-transition.png b/docs/workshop/en/medias/pcmk-archi-transition.png new file mode 100644 index 0000000..f27fd45 Binary files /dev/null and b/docs/workshop/en/medias/pcmk-archi-transition.png differ diff --git a/docs/workshop/en/medias/pcmk-archi.xml b/docs/workshop/en/medias/pcmk-archi.xml new file mode 100644 index 0000000..3ce7d49 --- /dev/null +++ b/docs/workshop/en/medias/pcmk-archi.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/workshop/en/prerequisites.md b/docs/workshop/en/prerequisites.md new file mode 100644 index 0000000..e5c1d9b --- /dev/null +++ b/docs/workshop/en/prerequisites.md @@ -0,0 +1,49 @@ +# Prerequisites + +Before attending to this workshop, attendees should have prepared their +computer with the following: + +* libvirtd +* virt-manager +* 3 VM running CentOS 7 +* SSH authentication between the VM -> user@hypervisor +* the VM should be able to ping each other + +## Preparation of the VM + +* Exchange SSH keys between the root users on the VM and the hypervisor user: + + ~~~ + ssh-keygen + ssh-copy-id @ + ~~~ + +* The VM should be able to communicate between each other using their node + names, e.g.: + + ~~~ + cat >> /etc/hosts <. +In this case some data has not been replicated from the old primary to the new +one before the switchover. As a result, several days were needed to restore the +lost data in the newly build cluster. + +Never underestimate the innovative nature of incidents, and the likelihood that +they will partition your cluster. Here are some more examples: +. + +Note that PAF is build with fencing enabled clusters in mind. Should a +failure occurs, no failover will occur if your cluster is not able to fence the +relevant resource. + +::: + +----- + +## Quorum + +* which part of the cluster should keep operating during a network partition? + * each cluster member has one vote + * the cluster keeps running only if it has the majority of the votes + +::: notes + +The quorum is the minimum number of votes requiered for a distributed +transaction to be authorized to execute an operation on the system. It's goal +is to guaranty the coherence of the distributed system. + +To achieve this goal, each node is granted some votes. A minimum of `(N / 2) + +1` votes are required to grant the quorum, `N` being the maximum number +of vote possible). The cluster will be able to operate only if the majority +of node is available. + +After a network partition, the cluster relies on the quorum information to +decide on which partition the services must runs, and which partition must stop +all of them. Fencing operation can be started if necessary. + +In addition to stopping all local services, a cluster partition who doesn't meet +the quorum cannot use fencing operation against remote nodes. + + + +This mecanism is paramount for the cluster to operate correctly. + +::: + +----- + +## KISS + +* a complex architecture brings its own complex problems: + * to build (avoid a _SPOF_) + * to maintain + * to document +* it's advised to aim for simplicity first and foremost + + +::: notes + +Increasing the complexity of a cluster also increases the number of failures +scenarios. Given two cluster implementations, the simplest one will usually be +the best and most sustainable. + +The outage described by Grocardless in the following hyperlink is a good +example of this. The article describes how automation erodes the knowledge of +the architecture and how it's difficult ot keep the documentation up to date +and the team trained: + +[Incident review: API and Dashboard outage on 10 October +2017](https://gocardless.com/blog/incident-review-api-and-dashboard-outage-on-10th-october/) + +> **Automation erodes knowledge** +> +> It turns out that when your automation successfully handles failures for two +years, your skills in manually controlling the infrastructure below it atrophy. +There's no "one size fits all" here. It's easy to say "just write a runbook", +but if multiple years go by before you next need it, it's almost guaranteed to +be out-of-date. + +::: + +----- + +## History + +----- + +### History of Pacemaker + +* several projects on different platforms + * Linux HA project led by SUSE + * "Cluster Services" by Red Hat +* 2007: Pacemaker appears + * originated from Linux-HA + * first projects convergence + +::: notes + +The complete history is available +[here](https://www.alteeve.com/w/High-Availability_Clustering_in_the_Open_Source_Ecosystem). + +Several companies have build a long standing experience in the field of high +availability and provide solution dedicated to it. + +SUSE is one of them with the project Linux-HA. Red Hat is also known for their +"Cluster Services". + +In 2007, a first collaborative work leads to the birth of Pacemaker. This +solution is designed to operate clusters over the different communication +layers avaiable at that time: OpenAIS (Reh Hat) or Heartbeat (SUSE). + +::: + +----- + +### Historique de Pacemaker - suite + +* 2009 : Corosync appears + * based on OpenAIS + * 2nd convergence +* 2014 : harmonisation starts + +::: notes + +In 2009, an effort to standarize the communication layers leads to the birth of +Corosync. + +A strong collaboration is born, Pacemaker and Corosync are becoming the +reference for Linux high availability and all the Linux distributions start to +include these tools in their packaging. + +::: + +----- + +### History of Pacemaker - future + +* 2017: the main distribution have converged + * Corosync 2.x and Pacemaker 1.1.x +* 2018: corosync 3 and Pacemaker 2.0.x + +::: notes + +In 2017, the latest versions of the main Linux distributions are done +converging to Corosync 2.x and Pacemaker 1.1.x. The last difference between +them is the chosen cluster administration tool: `crmsh` or `pcs`. + +Early 2018, Pacemaker 2.0 and Corosync 3.0 are release. On the Pacemaker side, +the main changes are : + +* the removal of a lot of code dedicated to old architectures: OpenAIS, CMAN, + Corosync 1.x and Heartbeat compatibility is dropped. +* several configuration parameters have been removed or replaced with others in + an effort to make the configuration more consistent. + +More information is available here: + +In regard with Corosync, the main novelty is the availability of "Kronosnet" as +communication protocol. This library allows for more flexibility, adds more +functionality, ease the supervision of Corosync and decreases the +latency. Some of the novelties are listed below : + +* support for up to 8 network links +* support for the addition of network without restart +* support for multiple protocols in different links +* several algorithm to manage links (active/passive or active/active) +* support for compression and encryption + +More information is available here: [Kronosnet:The new face of Corosync communications](http://build.clusterlabs.org/corosync/presentations/2017-Kronosnet-The-new-face-of-corosync-communications.pdf) + +::: + +----- + +## Administration tools + +* `crmsh` + * original tool + * management and configuration of the cluster + * rely on ssh +* `pcs` + * introduced by Red Hat + * management and configuration of the cluster + * rely on its own communication daemons `pcsd` + * used in this workshop + +::: notes + +The tool `cmrsh` originates to the beginning of the Pacemaker project. This +tool is designed to managed and configure the cluster without requiering to +modify the configuration files. It's mostly maintained by SUSE, and sometimes +presents incompatibilities with other distribution in the creation, starting +and stopping process of the cluster. Nevertheless, the tool evolves quickly and +several incompatibilities have been fixed. + +When Red Hat adopted Pacemaker, a new tool was created: `pcs`. It regroups all +the Pacemaker commands along with those for Corosync (and CMAN in the versions +for EL 6). It includes an HTTP service to configure and maintain the cluster +via a web browser. + +`crmsh` uses SSH and csync2 to execute commands on the remote servers (via the +`parallax` python library) and manage the configuration across all servers. + +To archive the same tasks, the `pcsd` daemons exchange commands via their web +services. The `pcsd` daemon manages the communication for the HTTP API +dedicated to inter-server commands and the HTTP administrator frontend. + +When a command requiers a system operation (outside of Pacemaker), the `pcsd` +daemons communicate and exchange the commands to execute using the HTTP API. +The command that use this API range from the cluster creation or destruction, +starting or stopping process and the addition or removal a node, etc. + +In 2018, `pcs` is fully integrated into Debian. `crmsh` is still used in +piority in SUSE, it's also often used in Debian and Ubuntu since it's the +historic choice for thoses platforms. It remains a good choise as long as the +administrator doesn't need to interact with the system itself. + +**This workshop is based on Centos 7 and uses the `pcs` tool.** + +::: + +----- + +## Available versions + +* RHEL 7 and Debian 9: + * Corosync 2.x + * Pacemaker 1.1.x + +* RHEL 8 and Debian 10: + * Corosync 3.x + * Pacemaker 2.0.x + + +::: notes + +The recommended (and supported) version depending on the distribution are: + +| OS | Corosync | Pacemaker | Administration tool | +|:---------:|:--------:|:---------:|------------------------------| +| EL 7 | 2.x | 1.1.x | pcsd 0.9 | +| EL 8 | 3.x | 2.0.x | pcsd 0.10 | +| Debian 9 | 2.4 | 1.1.x | pcs 0.9 or crmsh 2.3 | +| Debian 10 | 3.0 | 2.0.x | pcs 0.10 or crmsh 4.0 | +| Debian 11 | 3.1 | 2.0.x | pcs 0.10 or crmsh 4.2 | + +By the time of Debian 9, the cluster initialization with `crmsh` 2.x was not +working with Debian. The 3.x version of `crmsh` supported the cluster +initialization with some manual intervention and integration errors. The main +branch of the project is now 4.x, but authors of this workshop never tested it. + +Despite `crmsh` is the historical administration tool for Debian based OS, the +use of `pcsd` and `pcs` is fully operational since Debian 9. See: + + +::: + +----- + +# First steps with Pacemaker + +This chapter takes up the installation and start-up of Pacemaker. The objective +is to quickly create an empty cluster that we will populate and learn from +during this workshop. + +----- + +## Installation + +Mandatory packages: + +* `corosync`: messaging layer +* `pacemaker`: cluster orchestration +* `pcs`: administration tool + +:::notes + +The installation of Pacemaker is made simple by using the `pacemaker` package +available from the CentOS 7 official repositories. Note that the `corosync` and +the `resource-agents` packages are also installed as dependencies. + +More details about the packages: + +* `corosync`: manages the communication between nodes, the group membership and + the quorum +* `pacemaker`: orchestrates the cluster, reacts to events, takes decisions and + performs actions +* `resource-agents` (_RA_): are a collection of scripts that share a common API + and allow Pacemaker to control and monitor different kind of resources. + +The `corosync` package installs several tools common to all Linux distributions. +We will describe them later on: + +* `corosync-cfgtool` +* `corosync-cmapctl` +* `corosync-cpgtool` +* `corosync-keygen` +* `corosync-quorumtool` + +Pacemaker also installs it's share of binaries that are common across all Linux +distributions. Some of them are listed below we might use them in this workshop +or are commonly discussed in Pacemaler related topics: + +* `crm_attribute` +* `crm_node` +* `attrd_updater` +* `cibadmin` +* `crm_mon` +* `crm_report` +* `crm_resource` +* `crm_shadow` +* `crm_simulate` +* `crm_verify` +* `stonith_admin` + +A lots of other tools are installed on all distributions, but their use cases +are limited to some debug activities or used only by the agents. + +The administration tools `pcs` and `crm` rely heavily on these tools and create +a unified interface to manage the cluster. Even thought cluster admnistration +tasks can be performed without these tools, they are very usefull and ease +cluster management to a great degree. Moreover, they carry a fair amount of best +practices for the supported commands. + +During this workshop, we will be using `pcs` to simplify the deployment and +administration of the cluster. In addition to it's simplicity, the tool works +the same on all Linux distributions, most notably Debian, EL and their +derivatives. + +The packages install both the CLI `pcs` and the daemon `pcsd`. The latter is +responsible for the configuration and commands propagation across the nodes. + +::: + +----- + +### Practical work: Installation of Pacemaker + +::: notes + +1. install the required packages +2. verify which dependencies were installed + +::: + +----- + +### Correction: Installation of Pacemaker + +::: notes + +1. Install the required packages + +~~~console +# yum install -y pacemaker +~~~ + +2. verify which dependencies were installed + +Check the output of the previous command: + +~~~ +Dependency Installed: +[...] + corosync.x86_64 0:2.4.3-6.el7_7.1 + pacemaker-cli.x86_64 0:1.1.20-5.el7_7.2 + resource-agents.x86_64 0:4.1.1-30.el7_7.4 +~~~ + +The `corosync`, `resource-agents` and `pacemaker-cli` packages have been +installed as dependencies of `pacemaker`. + +All the required tools to manage a Pacemaker cluster are installer. Most +notably: + +~~~console +# ls /sbin/crm* /sbin/corosync* + +/sbin/corosync /sbin/corosync-cfgtool /sbin/corosync-cmapctl +/sbin/corosync-cpgtool /sbin/corosync-keygen /sbin/corosync-notifyd +/sbin/corosync-quorumtool + +/sbin/crmadmin /sbin/crm_attribute /sbin/crm_diff +/sbin/crm_error /sbin/crm_failcount /sbin/crm_master +/sbin/crm_mon /sbin/crm_node /sbin/crm_report +/sbin/crm_resource /sbin/crm_shadow /sbin/crm_simulate +/sbin/crm_standby /sbin/crm_ticket /sbin/crm_verify +~~~ + +::: + +----- + +### Practical work: Installation of `pcs` + +::: notes + +1. install the `pcs` package +2. enable the `pcsd` daemon so that it starts on server boots, and start it. + +::: +----- + +### Correction: Installation of `pcs` + +::: notes + +1. install the `pcs` package + +~~~console +# yum install -y pcs +~~~ + +2. enable the `pcsd` daemon so that it starts on server boots, and start it. + +~~~console +# systemctl enable --now pcsd +~~~ + +or + +~~~console +# systemctl enable pcsd +# systemctl start pcsd +~~~ + +::: + +----- + +## Cluster creation + +* authenticate all `pcsd` daemons with each others +* create the cluster using `pcs` + - this creates the corosync configuration on all servers +* configures the behavior of Pacemaker's processes + +::: notes + +Cluster creation is done by creating the same Corosync configuration file on all +nodes, then starting Pacemaker on them. + +Using `pcs` simplifies this process since it creates the configuration files +everywhere itself. However, this magical step requires that all `pcsd` dameons +are authenticated with each other so they can exchange of commands using the +HTTP API. This can be done with the command `pcs cluster auth [...]`. + +Once this is done, it's easy to create the cluster using `pcs cluster setup +[...]`. + +The Pacemaker configuration file deals with the behavior of Pacemaker's +processes, not the cluster management. Information such as where are the traces +and what is logged can be found there. On the EL familly, the file is stored in +the `/etc/sysconfig/pacemaker` directory. On Debian, it's located in +`/etc/default/pacemaker`. This file is relevant only for the local instance of +Pacemaker. Unlike Corosync's configuration, each node can have a different +file, but this practice is not recommended. + +::: + +----- + +### Practical work: pcs authentication + +::: notes + +1. create a password for the `hacluster` user on each node. + +The `pcs` tool uses the `hacluster` system user for the authentication with +`pcsd`. Since the cluster management commands can be executed from any member +of the cluster, it is advised to configure the same password on all node to +avoid mixing them up. + +2. authenticate all cluster members with each other + +Note: since Pacemaker 2, the command must be executed on each node of the +cluster. + +::: + +----- + +### Correction: pcs authentiation + +::: notes + +1. create a password for the `hacluster` user on each node. + +~~~console +# passwd hacluster +~~~ + +2. authenticate all cluster members with each other + +~~~console +# pcs cluster auth hanode1 hanode2 hanode3 -u hacluster +~~~ + +::: + +----- + +### Practical work: Cluster creation with pcs + +::: notes + +The `pcs` commands can be executed from any node. + +1. create a cluster called `cluster_tp` with three node `hanode1`, `hanode2` and + `hanode3` +2. find the corosync configuration file on all three nodes +3. check that the configuration file is identical on all three nodes +4. enable the debug mode in Pacemaker for the `crmd`, `pengine`, `attrd` and + `lrmd` sub processes. + +We activate the debug mode for the `crmd`, `pengine`, `attrd` and `lrmd` in +order to have an easier time studying Pacemaker. This will be very useful during +the workshop. + +::: + +----- + +### Correction: Cluster creation with pcs + +::: notes + +The `pcs` commands can be executed from any node. + +1. create a cluster called `cluster_tp` with three node `hanode1`, `hanode2` and + `hanode3` + +~~~console +# pcs cluster setup --name cluster_tp hanode1 hanode2 hanode3 +~~~ + +2. find the corosync configuration file on all three nodes + +Corosync's configuration file is located here: `/etc/corosync/corosync.conf`. + +3. check that the configuration file is identical on all three nodes + +~~~console +root@hanode1# md5sum /etc/corosync/corosync.conf +564b9964bc03baecf42e5fa8a344e489 /etc/corosync/corosync.conf + +root@hanode2# md5sum /etc/corosync/corosync.conf +564b9964bc03baecf42e5fa8a344e489 /etc/corosync/corosync.conf + +root@hanode3# md5sum /etc/corosync/corosync.conf +564b9964bc03baecf42e5fa8a344e489 /etc/corosync/corosync.conf +~~~ + +4. enable the debug mode in Pacemaker for the `crmd`, `pengine`, `attrd` and + `lrmd` sub processes. + +Edit the `PCMK_debug` variable in the configuration file +`/etc/sysconfig/pacemaker`: + +~~~console +PCMK_debug=crmd,pengine,lrmd,attrd +~~~ + +You can trace all the debug messages from all processes by setting this +parameter to `yes`. + +::: + +----- + +## Cluster startup + +FR * cluster créé mais pas démarré +FR * désactiver Pacemaker au démarrage des serveurs +FR * utilisation de `pcs` pour démarrer le cluster +FR +* the cluster is created but not started +* disable Pacemaker on server startup +* use `pcs` to start the cluster + +::: notes + +FR Une fois le cluster créé, ce dernier n'est pas démarré automatiquement. Il est +FR déconseillé de démarrer Pacemaker automatiquement au démarrage des serveurs. En +FR cas d'incident et de fencing, un nœud toujours défaillant pourrait déstabiliser +FR le cluster et provoquer des interruptions de services suite à un retour +FR automatique prématuré. En forçant l'administrateur à devoir démarrer Pacemaker +FR manuellement, celui-ci a alors tout le loisir d'intervenir, d'analyser +FR l'origine du problème et éventuellement d'effectuer des actions correctives +FR avant de réintégrer le nœud, sain, dans le cluster. +FR +The cluster is not automatically started once it's creation. It's discouraged +to enable Pacemaker's startup at boot time. In case of outage or fencing, a +failing node could destabilize the cluster and provoque a downtime because +it joined the cluster prematurely. By forcing the administrator to start +Pacemaker manually, we give him time to intervene, analyze the origin of the +problem and conduct corrective mesure if necessary, before reintroducing the +node into the cluster. + +FR Le démarrage du cluster nécessite la présence des deux services Corosync et +FR Pacemaker sur tous les nœuds. Démarrer d'abord les services Corosync puis +FR Pacemaker. À noter que démarrer Pacemaker suffit souvent sur de nombreuses +FR distributions Linux, Corosync étant démarré automatiquement comme dépendance. +FR +Cluster startup requires the presence of the Corosync and Pacemaker services on +all nodes. Corosync should be started first then Pacemaker. On most Linux +distribution, starting Pacemaker is enough, since Corosync will be started +automatically as a dependency. + +FR Plutôt que de lancer manuellement Pacemaker sur chaque nœud, il est possible +FR de sous traiter cette tâche aux daemons `pcsd` avec une unique commande `pcs`. +FR +Instead of starting Pacemaker manually on each node, it's possible to delagate +this task to the `pcsd` daemons thanks to a single `pcs` command. + +::: + +----- + +### Practical work: Starting the cluster + +::: notes + +FR 1. désactiver Pacemaker et Corosync au démarrage du serveur +FR 2. démarrer Pacemaker et Corosync sur tous les nœuds à l'aide de `pcs` +FR 3. vérifier l'état de Pacemaker et Corosync +FR +1. deactivate Pacemaker and Corosync at server startup +2. start Pacemaker and Corosync on all nodes using `pcs` +3. verify the state of Pacemaker and Corosync + +::: + +----- + +### Correction: Starting the cluster + +::: notes + +FR 1. désactiver Pacemaker et Corosync au démarrage du serveur +FR +FR Sur tous les serveurs: +FR +1. deactivate Pacemaker and Corosync at server startup + +On all servers: + +~~~console +# systemctl disable corosync pacemaker +~~~ + +FR Ou, depuis un seul des serveurs: +FR +Or from one of the servers: + +~~~console +# pcs cluster disable --all +~~~ + +FR 2. démarrer Pacemaker et Corosync sur tous les nœuds à l'aide de `pcs` +FR +2. start Pacemaker and Corosync on all nodes using `pcs` + +~~~console +# pcs cluster start --all +~~~ + +FR 3. vérifier l'état de Pacemaker et Corosync +FR +FR Sur chaque serveur, exécuter: +FR +3. verify the state of Pacemaker and Corosync + +On each server, execute: + +~~~ +# systemctl status pacemaker corosync +~~~ + +Or: + +~~~ +# pcs status +~~~ + +FR Nous observons que les deux services sont désactivés au démarrage des +FR serveurs et actuellement démarrés. +FR +We can see that both services are running and have been disabled at server +startup. + +::: + +----- + +## Visualize the cluster state + +FR Pour visualiser l'état du cluster : +FR +FR * `crm_mon`: commande livrée avec Pacemaker +FR * `pcs` +FR +To visualize the cluster state: + +* `crm_mon`: a command provided with Pacemaker +* `pcs` + +::: notes + +FR L'outil `crm_mon` permet de visualiser l'état complet du cluster et des +FR ressources. Voici le détail des arguments disponibles : +FR +FR * `-1`: affiche l'état du cluster et quitte +FR * `-n`: regroupe les ressources par nœuds +FR * `-r`: affiche les ressources non actives +FR * `-f`: affiche le nombre fail count pour chaque ressource +FR * `-t`: affiche les dates des événements +FR * `-c`: affiche les tickets du cluster (utile pour les cluster étendus sur réseau WAN) +FR * `-L`: affiche les contraintes de location négatives +FR * `-A`: affiche les attributs des nœuds +FR * `-R`: affiche plus de détails (node IDs, individual clone instances) +FR * `-D`: cache l'entête +FR +FR Voici des exemples d'utilisation: +FR +The `crm_mon` tool is geared to the visualisation of the state of the cluster +as a whole, including it's resources. Here is the detail of the available +arguments: + +* `-1`: displays the state of the cluster and exits +* `-n`: gathers resources on a per node basis +* `-r`: displays the active resources +* `-f`: displays the fail count for each node +* `-t`: displays the dates of the events +* `-c`: displays the tickets of the cluster (useful for extended clusters on WAN networks) +* `-L`: displays the negative location constraints +* `-A`: displays the node attributes +* `-R`: displays mode detailed information (node IDs, individual clone instances) +* `-D`: hide the header + +Here are some examples: + +~~~console +# crm_mon -DnA +# crm_mon -fronA +# crm_mon -1frntcLAR +~~~ + +FR À noter que ces différents arguments peuvent être aussi activés ou désactivés +FR dans le mode interactif. +FR +FR L'outil `pcs` contient quelques commandes utiles pour consulter l'état d'un +FR cluster, mais n'a pas de mode interactif. Voici quelques exemples +FR d'utilisation: +FR + +Please note that these arguments can also be toggle on and off in interactive +mode. + +The `pcs` tool comes equiped with several commands that are useful to display +the cluster state, but it doesn't have an interactive mode. Here are few +examples of their usage: + +~~~console +# pcs cluster status +# pcs status +# pcs cluster cib +# pcs constraint show +~~~ + +::: + +----- + +### Practical work: Cluster state visualization + +::: notes + +FR Expérimenter avec les commandes vues précédemment et leurs arguments. +FR +Experiment with the commands listed before and their arguments. + +::: + +----- + +# Corosync + +FR Rapide tour d'horizon sur Corosync. +FR +A Quick overview of Corosync. + +----- + +## Presentation + +FR * couche de communication bas niveau du cluster +FR * créé en 2004 +FR * dérivé de OpenAIS +FR * avec des morceaux de CMAN dedans ensuite (à vérifier) +FR +* communication layer of the clusterware +* created in 2004 +* derived from OpenAIS +* with some components from CMAN + + +::: notes + +FR Corosync est un système de communication de groupe (`GCS`). Il fournit +FR l'infrastructure nécessaire au fonctionnement du cluster en mettant à +FR disposition des APIs permettant la communication et d'adhésion des membres au +FR sein du cluster. Corosync fournit notamment des notifications de gain ou de +FR perte du quorum qui sont utilisés pour mettre en place la haute disponibilité. +FR +Corosync is a group communication system (_GCS_). It provides the +infrastructure necessary for the cluster to operate by providing API for +communication and cluster membership. Among other features, it also provides +notification for the gain or loss of quorum which is important to archive high +availability. + +FR Son fichier de configuration se trouve à l'emplacement +FR `/etc/corosync/corosync.conf`. En cas de modification manuelle, il faut +FR __ABSOLUMENT__ veiller à conserver une configuration identique sur tous les +FR nœuds. Cela peut être fait manuellement ou avec la commande `pcs cluster sync`. +FR +It's configuration is located in `/etc/corosync/corosync.conf`. In case of +manual update, it is paramount to propagate the modifications on all nodes and +ensure that all nodes have the same configuration. This can be done manually +or with the command `pcs cluster sync`. + +FR La configuration de corosync est décrite dans la page de manuel +FR `corosync.conf`. Ses fonctionnalités liées au quorum sont décrites dans le +FR manuel nommé `votequorum`. +FR +The Corosync configuration is described in length in the man page for +`corosync.conf`. The parameters describing quorum are described in the man page +for `votequorum`. + +::: + +----- + +## Architecture + +FR * corosync expose ses fonctionnalités sous forme de services, eg. : +FR * `cgp` : API de gestion de groupe de processus ; +FR * `cmap` : API de gestion de configuration ; +FR * `votequorum` : API de gestion du quorum. +FR +* corosync exposes it's functionnalities as servises, e.g.: + * `cpg` (closed process group): process group & membership management API; + * `cmap`: configuration management API; + * `votequorum`: quorum managment API. + + +::: notes + +FR Corosync s'appuie sur une ensemble de services internes pour proposer plusieurs APIs aux applications +FR qui l'utilisent. +FR +FR Corosync expose notamment l'api `cpg` dont l'objet est d'assurer le moyen de +FR communication d'une applications distribuées. Cette api permet de gérer : +FR +FR * l'entrée et la sortie des membres dans un ou plusieurs groupes ; +FR * la propagation des messages à l'ensemble des membres des groupes ; +FR * la propagation des changements de configuration ; +FR * l'ordre de délivrance des messages. +FR +Corosync relies on a set of internal services to propose several API to its +client applications. + +One of those API is `cpg` whose role is to provide means of communication for +distributed applications. This API can manage: + +* the entry or exit of members in one or more groups; +* the propagation of messages to all members of said groups; +* the propagation of configuration changes; +* the order of delivery of messages. + +FR Corosync utilise `cmap` pour gérer et stocker sa configuration sous forme de stockage +FR clé-valeur. Cette API est également mise à disposition des applications qui utilisent corosync. +FR Pacemaker s'en sert notamment pour récupérer certaines informations sur le cluster et +FR ses membres. +FR +Corosync uses `cmap` to manage and store it's configuration in the form of a +key value store. This API is also available for the client applications of +Corosync. For example, Pacemaker uses it to fetch some information from the +cluster and it's members. + +FR Le service `votequorum` permet à corosync de fournir des notifications sur la gain ou la +FR perte du quorum dans le cluster, le nombre de vote courant, etc. +FR +The `votequorum` service is designed to provide notification when quorum is +archived or lost in the cluster, about the number of nodes in the cluster, +etc. + +::: + +----- + +## Corosync 3 features + +FR Nouvelle librairie `kronosnet` (`knet`): +FR +FR * évolution du chiffrement +FR * redondance des canaux de communications +FR * compression +FR + +New library `kronosnet` (`knet`): + +* cryptography +* redundancy of channels +* compression + +::: notes + +FR Corosync3 utilise la librairie kronosnet (`knet`). Cette libraire : +FR +FR * remplace les modes de transport `multicast` et `unicast` ; +FR * remplace le protocole `RRP` (_Redundant Ring Protocole_). +FR +Corosync 3 uses the `kronosnet` (`knet`) library, which: + +* replaces the `multicast` and `unicast` method, +* replaces the `RRP` protocol (_Redundant Ring Protocol_) + +FR Corosync implémente le protocole _Totem Single Ring Ordering and Membership_ pour la gestion +FR des messages et des groupes. Il est possible de redonder les canaux de communications ou liens +FR en créant plusieurs interfaces (option `totem` > `interface` > `linknumber`) qui seront +FR utilisés comme support des rings (option `nodelist` > `node` > `ringX_addr`). `knet` permet +FR de créer jusqu'à 8 liens avec des protocoles et des priorités différentes. +FR +FR Le chiffrement peut être configuré soit avec l'option `totem` > `secauth` soit avec les +FR paramètres `totem` > `crypto_model`, `totem` > `crypto_cipher` et `totem` > `crypto_hash`. +FR +FR Il est également possible d'utiliser la compression. +FR +Corosync implements the _Totem Single Ring Ordering and Membership_ protocol +for its message and group management. It's possible to add redundancy for +communication channels and network links by creating several interfaces +(`totem` > `interface` > `linknumer` option) which will be used by the rings +(`nodelist` > `node` > `ringX_addr`). `knet` allows for the creation of +up to 8 links with different protocols and priorities. + +Cryptography can be configured either with the option `totem` > `secauth` or +the parameters `totem` > `crypto_model`, `totem` > `crypto_cipher` and `totem` +> `crypto_hash`. + +It's also possible to use compression. + +::: + +----- + +## Two node clusters + +FR * paramètre dédié : `two_node: 1` +FR * option héritée de CMAN +FR * requiers `expected-votes: 2` +FR * implique `wait_for_all: 1` +FR * requiers un fencing hardware configuré sur la même interface que le heartbeat +FR +* dedicated parameter: `two_node: 1` +* inherited from CMAN +* requires: `expected-votes: 2` +* implies: `wait_for_all: 1` +* requiers a fencing hardware configured on the same interface as the + heartbeat. + +::: notes + +FR Considérons un cluster à deux nœuds avec un vote par nœud. Le nombre de vote +FR attendu est 2 (`expected-votes`), il n'est donc pas possible d'avoir une +FR majorité en cas de partition du cluster. La configuration `two_node` permet de +FR fixer artificiellement le quorum à 1 et de résoudre ce problème. +FR +Given a two cluster node with one vote per node, the number of expected vote is +2 (`expected-votes`). Therefore, it's not possible to have a majority in case +of cluster partition. The `two_node` parameter fixes this problem by fixing the +quorum at a value of 1. + +CR Ce paramétrage, implique `wait_for_all : 1` qui empêche le cluster d'établir +CR une majorité tant que l'ensemble des nœuds n'est pas présent. Ce qui évite une +CR partition au démarrage du cluster. +CR +This configuration implies the usage of `wait_for_all: 1`, which forbids the +cluster from establishing a majority unless all members of the cluster are +present. This restriction is designed to avoid a partition during cluster +startup. + +CR En cas de partition réseau, les deux nœuds font la course pour fencer l'autre. +CR Le nœud vainqueur conserve alors le quorum grâce au paramètre `two_node: 1`. +CR Quand au second nœud, après redémarrage de Pacemaker, si la partition réseau +CR existe toujours, ce dernier n'obtient donc pas le quorum grâce au paramètre +CR `wait_for_all: 1` et en conséquence ne peut démarrer aucune ressource. +CR +In case of network partition, both nodes race to fence the other node. The +winner keeps the quorum thanks to the parameter `two_node: 1`. If the second +node is restarted while the partition is still present, it will not be able to +archive the quorum thanks to the parameter `wait_for_all: 1`. As a result it +will bot be able to start any ressource. + +FR Même si elle fonctionne, ce genre de configuration n'est cependant pas +FR optimale. Comme en témoigne +FR [cet article du blog de clusterlabs](http://blog.clusterlabs.org/blog/2018/two-node-problems). +FR +Even though this kind of configuration works, it's not optimal as explained in +[this clusterlab blog +post](http://blog.clusterlabs.org/blog/2018/two-node-problems). + +::: + +----- + +## Tools + +FR Corosync installe plusieurs outils: +FR +FR * `corosync-cfgtool` : administration, paramétrage +FR * `corosync-cpgtool` : visualisation des différents groupes CPG +FR * `corosync-cmapctl` : administration de la base d'objets +FR * `corosync-quorumtool` : gestion du quorum +FR +Corosync installs several tools: + +* `corosync-cfgtool` : administration, configuration +* `corosync-cpgtool` : cpg group visualization +* `corosync-cmapctl` : administration of the cmap key value store +* `corosync-quorumtool` : quorum managment + + +::: notes + +FR `corosync-cfgtool` permet de : +FR +FR * arrêter corosync sur le serveur ; +FR * récupérer l'IP d'un nœud ; +FR * tuer un nœud ; +FR * récupérer des informations sur les rings et réinitialiser leur statut ; +FR * demander à l'ensemble des nœuds de recharger leur configuration. +FR +`corosync-cfgtool` can be used to: + +* stop corosync on the server; +* retrieve the IP of a node; +* kill a node; +* retrieve information about rings and reinitialize their status; +* ask all nodes to reload their configuration. + +FR `corosync-cpgtool` permet d'afficher les groupes cpg et leurs membres. +FR +`corosync-cpgtool` can be used to display cpg groups and members. + +FR `corosync-cmapctl` permet de manipuler et consulter la base d'objet de corosync, +FR les actions possibles sont : +FR +FR * lister les valeurs associées aux clés : directement (ex: totem.secauth), par +FR préfix(ex: totem.) ou sans filtre ; +FR * définir ou supprimer des valeurs ; +FR * changer la configuration depuis un fichier externe ; +FR * suivre les modifications des clés stockées dans `cmap` en temps réel en filtrant +FR sur un préfix ou directement sur un clé. +FR +`corosync-cmapctl` can be used to read and modify data in the key value store +of corosync, possible actions are: + +* list the values for given keys: directrly (e.g.: totem.secauth), using a + prefix (e.g.: totem.) or without filters; +* define or delete values; +* change the configuration using an external file; +* follow the modification of keys sorted in `cmap` in realtime. + +FR `corosync-quorumtool` permet d'accéder au service de quorum pour par exemple: +FR +FR * modifier la configuration des votes (nombre, nombre attendu) ; +FR * suivre les modifications de quorum ; +FR * lister les nœuds avec leurs nom, id et IPs . +FR +`corosync-quorumtool` can be used to access the quorum service in order to: + +* modify the configuration of votes (number & avaited number); +* follow quorum evolution; +* list nodes with their name, id and ips. + +::: + +----- + +## Practice work: Corosync utilisation + +::: notes + +FR 1. afficher le statut du ring local avec `corosync-cfgtool` +FR 2. afficher l'IP de chaque nœud avec `corosync-cfgtool` +FR 3. afficher les groupes CPG et leurs membres avec `corosync-cpgtool` +FR 4. afficher la configuration des nœuds dans la base CMAP avec +FR `corosync-cmapctl` (clé `nodelist`) +FR 5. afficher l'état du quorum avec `corosync-quorumtool` +FR +1. display the local ring status with `corosync-cfgtool` +2. display the IP of each node with `corosync-cfgtool` +3. display CPG groups and members with `corosync-cpgtool` +4. display the configuration of each node from the CMAP base with + `corosync-cmapctl` (key: `nodelist`) +5. display the state of the quorum with `corosync-quorumtool` + +::: + +----- + +## Correction: Corosync utilisation + +::: notes + +FR 1. afficher le statut du ring local avec `corosync-cfgtool` +FR +1. display the local ring status with `corosync-cfgtool` + +~~~console +# corosync-cfgtool -s +Printing ring status. +Local node ID 1 +RING ID 0 + id = 10.20.30.6 + status = ring 0 active with no faults +~~~ + +FR 2. afficher l'IP de chaque nœud avec `corosync-cfgtool` +FR +2. display the IP of each node with `corosync-cfgtool` + +~~~console +# corosync-cfgtool -a 1 +10.20.30.6 + +# corosync-cfgtool -a 2 +10.20.30.7 + +# corosync-cfgtool -a 3 +10.20.30.8 +~~~ + +FR 3. afficher les groupes CPG et leurs membres avec `corosync-cpgtool` +FR +3. display CPG groups and members with `corosync-cpgtool` + +~~~console +# corosync-cpgtool -e +Group Name PID Node ID +crmd + 6912 1 (10.20.30.6) + 6647 3 (10.20.30.8) + 6727 2 (10.20.30.7) +attrd + 6910 1 (10.20.30.6) + 6645 3 (10.20.30.8) + 6725 2 (10.20.30.7) +stonith-ng + 6908 1 (10.20.30.6) + 6643 3 (10.20.30.8) + 6723 2 (10.20.30.7) +cib + 6907 1 (10.20.30.6) + 6642 3 (10.20.30.8) + 6722 2 (10.20.30.7) +pacemakerd + 6906 1 (10.20.30.6) + 6641 3 (10.20.30.8) + 6721 2 (10.20.30.7) +~~~ + +FR Chaque sous-processus de pacemaker est associé à un groupe de communication +FR avec leur équivalents sur les autres nœuds du cluster. +FR +Each sub process of pacemaker is part of a communication group with it's +counterpart on the other nodes. + +FR 4. afficher la configuration des nœuds dans la base CMAP avec +FR `corosync-cmapctl` (clé `nodelist`) +FR +4. display the configuration of each node from the CMAP base with + `corosync-cmapctl` (key: `nodelist`) + +~~~console +# corosync-cmapctl -b nodelist +nodelist.local_node_pos (u32) = 0 +nodelist.node.0.nodeid (u32) = 1 +nodelist.node.0.ring0_addr (str) = hanode1 +nodelist.node.1.nodeid (u32) = 2 +nodelist.node.1.ring0_addr (str) = hanode2 +nodelist.node.2.nodeid (u32) = 3 +nodelist.node.2.ring0_addr (str) = hanode3 +~~~ + +FR 5. afficher l'état du quorum avec `corosync-quorumtool` +FR +5. display the state of the quorum with `corosync-quorumtool` + +~~~console +# corosync-quorumtool +Quorum information +------------------ +Date: ... +Quorum provider: corosync_votequorum +Nodes: 3 +Node ID: 1 +Ring ID: 3/8 +Quorate: Yes + +Votequorum information +---------------------- +Expected votes: 3 +Highest expected: 3 +Total votes: 3 +Quorum: 2 +Flags: Quorate + +Membership information +---------------------- + Nodeid Votes Name + 3 1 hanode3 + 2 1 hanode2 + 1 1 hanode1 (local) +~~~ + +::: + +----- + + +# Components of the cluster + +![Diagramme complet](medias/pcmk-archi-all.png) + +::: notes + +FR Dans ce chapitre, nous abordons rapidement l'architecture de Pacemaker en détaillant ses +FR sous processus. Le but est de comprendre le rôle de chaque brique et ainsi mieux +FR diagnostiquer l'état du cluster, son paramétrage et savoir interpréter les messages de +FR log correctement. Voici les différents processus tel que démarrés par Pacemaker: +FR +In this chapter, we will do an overview of Pacemaker's architecture and focus +on it's sub processes. The objective is to understand the role of each part in +order to have an easier time diagnosing the cluster state, understanding it's +configuration and interpreting the log messages correctly. + +~~~ +/usr/sbin/pacemakerd -f +\_ /usr/libexec/pacemaker/cib +\_ /usr/libexec/pacemaker/stonithd +\_ /usr/libexec/pacemaker/lrmd +\_ /usr/libexec/pacemaker/attrd +\_ /usr/libexec/pacemaker/pengine +\_ /usr/libexec/pacemaker/crmd +~~~ + +FR Le diagramme présente les différents éléments de Pacemaker au sein d'un cluster à trois +FR nœuds. Une vue plus détaillée mais centrée sur un seul nœud est présenté dans la +FR documentation de Pacemaker. Voir: +FR +FR [Schémas de l'architecture interne de Pacemaker](http://clusterlabs.org/pacemaker/doc/en-US/Pacemaker/2.0/html/Pacemaker_Explained/_pacemaker_architecture.html#_internal_components) +FR +This diagram shows the different components of Pacemaker in a three node +cluster. A more detailed view, focused on a single node is present in +Pacemaker's documentation. See: + +[Schemas of the internal architecture of Pacemaker](http://clusterlabs.org/pacemaker/doc/en-US/Pacemaker/2.0/html/Pacemaker_Explained/_pacemaker_architecture.html#_internal_components) + +FR Cette architecture et le paramétrage de Pacemaker permet de supporter différents types de +FR scénario de cluster dont certains (vieux) exemples sont présentés dans le wiki de +FR Pacemaker: +FR +FR [Schémas des différentes configuration de nœuds possibles avec Pacemaker](https://wiki.clusterlabs.org/wiki/Pacemaker#Example_Configurations) +FR +This architecture is designed to support different types of clusters. Some +(old) example are present in the Pacemaker wiki: + +[Schemas of different cluster configuration in pacemaker](https://wiki.clusterlabs.org/wiki/Pacemaker#Example_Configurations) + +::: + + +----- + +## Cluster Information Base (CIB) + +FR * détient la configuration du cluster +FR * l'état des différentes ressources +FR * un historique des actions exécutées +FR * stockage fichier au format XML +FR * synchronisé automatiquement entre les nœuds +FR * historisé +FR * géré par le processus `cib` +FR * renommé `pacemaker-based` depuis la version 2.0 +FR +* contains: + - the cluster configuration + - the state of the resources + - an history of the latest actions +* stored in XML format +* automatically synchronized between nodes +* archived +* managed by the `cib` process + - renamed `pacemaker-based` since version 2.0 + +::: notes + +FR La CIB est la représentation interne de la configuration et de l'état des composantes du +FR cluster. C'est un fichier XML, créée par Pacemaker à l'initialisation du cluster et qui +FR évolue ensuite au fil des configurations et évènements du cluster. +FR +The CIB is a internal representation of the configuration and state of the +cluster's components and resources. It's an XML file, created by Pacemaker +during cluster initialization. It evolves as the cluster configuration changes +and events takes place in the cluster. + +FR En fonction de cet ensemble d'états et du paramétrage fourni, le cluster détermine l'état +FR idéal de chaque ressource qu'il gère (démarré/arrêté/promu et sur quel serveur) et +FR calcule les transitions permettant d'atteindre cet état. +FR +From the component states and configuration, the cluster determines the ideal +state for each managed resource (started/stopped/promoted and on which server) +and computes the transitions necessary to reach this state. + +FR Le processus `cib` est chargé d'appliquer les modifications dans la CIB, de +FR conserver les information transitoires en mémoire (statuts, certains scores, etc) et de +FR notifier les autres processus de ces modifications si nécessaire. +FR +The `cib` process (`pacemaker-based`) is tasked to apply the modification +inside the CIB, keep track of transient information (status, some scores, etc.) +ad notify the other processes of the changes if it's necessary. + +FR Le contenu de la CIB est historisé puis systématiquement synchronisé entre les nœuds à +FR chaque modification. Ces fichiers sont stockés dans `/var/lib/pacemaker/cib` : +FR +The content of the CIB is archived and synchronized between all nodes after +each modification. These files are stored in `/var/lib/pacemaker/cib`. + +~~~ +ls /var/lib/pacemaker/cib/ -alh +total 68K +drwxr-x--- 2 hacluster haclient 4.0K Feb 7 16:46 . +drwxr-x--- 6 hacluster haclient 4.0K Feb 7 12:16 .. +-rw------- 1 hacluster haclient 258 Feb 7 16:43 cib-1.raw +-rw------- 1 hacluster haclient 32 Feb 7 16:43 cib-1.raw.sig +-rw------- 1 hacluster haclient 442 Feb 7 16:43 cib-2.raw +-rw------- 1 hacluster haclient 32 Feb 7 16:43 cib-2.raw.sig +-rw------- 1 hacluster haclient 639 Feb 7 16:43 cib-3.raw +-rw------- 1 hacluster haclient 32 Feb 7 16:43 cib-3.raw.sig +-rw------- 1 hacluster haclient 959 Feb 7 16:43 cib-4.raw +-rw------- 1 hacluster haclient 32 Feb 7 16:43 cib-4.raw.sig +-rw------- 1 hacluster haclient 959 Feb 7 16:43 cib-5.raw +-rw------- 1 hacluster haclient 32 Feb 7 16:43 cib-5.raw.sig +-rw------- 1 hacluster haclient 959 Feb 7 16:46 cib-6.raw +-rw------- 1 hacluster haclient 32 Feb 7 16:46 cib-6.raw.sig +-rw-r----- 1 hacluster haclient 1 Feb 7 16:46 cib.last +-rw------- 1 hacluster haclient 959 Feb 7 16:46 cib.xml +-rw------- 1 hacluster haclient 32 Feb 7 16:46 cib.xml.sig +~~~ + +FR `cib.xml` correspond à la version courante de la CIB, les autres fichiers `cib-*.raw`, +FR aux versions précédentes. +FR +`cib.xml` is the current version of the CIB, the `cib-*.raw` files are older +versions of it. + +FR Par défaut, Pacemaker conserve toutes les versions de la CIB depuis la création du +FR cluster. Il est recommandé de limiter ce nombre de fichier grâce aux paramètres +FR `pe-error-series-max`, `pe-warn-series-max` et `pe-input-series-max`. +FR +By default, Pacemaker keep all the versions of the CIB since cluster creation. +It's advised to limit the amount of files kept with the parameters: +`pe-error-series-max`, `pe-warn-series-max` and `pe-input-series-max`. + +FR Il n'est pas recommandé d'éditer la CIB directement en XML. Préférez toujours utiliser +FR les commandes de haut niveau proposées par `pcs` ou `crm`. En dernier recours, utilisez +FR l'outil `cibadmin`. +FR +Making modification by editing the CIB directly is not recommanded. A better +practice is to used the high level commands available in `pcs` or `crm`. As a +last resort, the `cibadmin` tool is available. + +::: + +----- + +### Practice work: CIB + +::: notes + +FR 1. consulter le contenu de ce répertoire où est stockée la CIB +FR 2. identifier la dernière version de la CIB +FR 3. comparer avec `cibadmin --query` et `pcs cluster cib` +FR +1. check the content of the directory where the CIB is stored +2. identify the last version of the CIB +3. compare the output of the commands `cibadmin --query` and `pcs cluster cib` + +::: + +----- + +### Correction: CIB + +::: notes + +FR 1. consulter le contenu de ce répertoire où est stockée la CIB +FR +1. check the content of the directory where the CIB is stored + +~~~ +# ls /var/lib/pacemaker/cib +~~~ + +FR 2. identifier la dernière version de la CIB +FR +FR La version courante de la CIB est stockée dans +FR `/var/lib/pacemaker/cib/cib.xml`. Sa version est stockée dans +FR `/var/lib/pacemaker/cib/cib.last`. +FR +2. identify the last version of the CIB + +The current version of the CIB is stored in `/var/lib/pacemaker/cib/cib.xml`. +It's version is stored in `/var/lib/pacemaker/cib/cib.last`. + +FR 3. comparer avec `cibadmin --query` et `pcs cluster cib` +FR +FR Vous observez une section `` supplémentaire dans le document +FR XML présenté par `cibadmin`. Cette section contient l'état du cluster et est +FR uniquement conservée en mémoire. +FR + +3. compare the output of the commands `cibadmin --query` and `pcs cluster cib` + +There is a additional `` section in the XML document presented by +`cibadmin`. This section contains the cluster state and is only kept in +memory which explains why it's onlu visible with `cibadmin`. + +::: + +----- + +### Designated Controler (DC) - Global diagram + +![DC diagram](medias/pcmk-archi-dc.png) + +----- + +## Designated Controler (DC) + +FR * daemon `CRMd` désigné pilote principal sur un nœud uniquement +FR * lit et écrit dans la CIB +FR * invoque PEngine pour générer les éventuelles transitions +FR * contrôle le déroulement des transitions +FR * envoie les actions à réaliser aux daemons `CRMd` des autres nœuds +FR * possède les journaux applicatifs les plus complets +FR + +* a `CRMd` daemon appointed as the manager of the cluster + - present only on one node +* read and write from/to the CIB +* calls the PEngine to generate the necessary transitions +* control the proceeding of transitions +* sends the actions to the daemons`CRMd` of other nodes +* has the most complete traces of all nodes + +::: notes + +FR Le *Designated Controler* est élu au sein du cluster une fois le groupe de communication +FR établi au niveau de Corosync. Il pilote l'ensemble du cluster. +FR +FR Il est responsable de: +FR +FR * lire l'état courant dans la CIB +FR * invoquer le `PEngine` en cas d'écart avec l'état +FR stable (changement d'état d'un service, changement de configuration, évolution des +FR scores ou des attributs, etc) +FR * mettre à jour la CIB (mises à jour propagée aux autres nœuds) +FR * transmettre aux `CRMd` distants une à une les actions à réaliser sur leur nœud +FR +FR C'est le DC qui maintient l'état primaire de la CIB ("master copy"). +FR + + +The *Designated Controler* is elected once a communication group is established +by Corosync. It manages the whole cluster. + +It's responsible for: + +* reading the current state in the CIB +* invoking the `PEngine` if the state of the cluster is different from it's + expected state (service state change, configuration change, evolution of + scores or attributes, etc.) +* updates the CIB (the updates sent to all nodes) +* dictate the actions that have to be executed to the relevant remote `CRMd` + processes, theses changes are send one at a time + +The DC is responsible for the _master copy_ of the CIB. + + +::: + +----- + +### PEngine - Global Diagram + +![PEngine diagram](medias/pcmk-archi-pengine.png) + +----- + +## Policy Engine (PEngine) + +FR * reçoit en entrée les informations d'état des ressources et le paramétrage +FR * décide de l'état idéal du cluster +FR * génère un graphe de transition pour atteindre cet état +FR * renommé `Scheduler` depuis la version 2.0 +FR * peut être consulté grâce à la commande `crm_simulate` +FR +FR ![Diagramme Scheduler - calcul graphe de transition](medias/pcmk-archi-transition.png) + +* receives information about the state of resources and configuration +* decides the ideal state for the cluster +* creates a transition graph to reach the ideal state +* renamed `Scheduler` in version 2.0 +* can be leveraged with the `crm_simulate` command + +![Diagramme Scheduler - transition graph calculation](medias/pcmk-archi-transition.png) + +::: notes + +FR Le `PEngine` est la brique de Pacemaker qui calcule les transitions nécessaires pour +FR passer d'un état à l'autre. +FR +FR Il reçoit en entrée des informations d'état et de paramétrage au format XML (extrait de +FR la CIB), détermine si un nouvel état est disponible pour les ressources du cluster, et +FR calcule toutes les actions à mettre en œuvre pour l'atteindre. +FR +FR Toutes ces actions sont regroupées au sein d'un graph de transition que le +FR `Designated Controller`, qui pilote le cluster, devra ensuite mettre en œuvre. +FR +The `PEngine` is the Pacemaker component responsible for the computation of the +transition necessary to go from one state to another. + +It receives information about states and configuration in XML format (from the +CIB), decides if a new state is available and computes all the actions +necessary to reach it. + +All theses actions are gathered in a transition graph which will be applied by +the component responsible for decision making: the `Designated Controller`. + +FR Voici un exemple de transition complexe présentant une bascule maître-esclave DRBD: +FR ![Diagramme exemple de transition complexe](medias/Policy-Engine-big.png) +FR +FR Ce diagramme vient de la documentation de Pacemaker. L'original est disponible à cette +FR adresse: +FR +FR +FR Les explications sur les codes couleurs sont disponibles à cette adresse: +FR +FR +This is an example of complex transition graph involving a master slave DRBD +switchover. +![example diagram for a complex transition](medias/Policy-Engine-big.png) + +This diagram comes from the Pacemaker documentation. The original is available +at: + + +The explanation of the color code is available at this address: + + +FR Dans cet exemple chaque flèche impose une dépendance et un ordre entre les actions. Pour +FR qu'une action soit déclenchée, toutes les actions précédentes doivent être exécutées et +FR réussies. Les textes en jaune sont des "actions virtuelles", simples points de passage +FR permettant de synchroniser les actions entre elles avant de poursuivre les suivantes. Les +FR textes en noir représentent des actions à exécuter sur l'un des nœuds du cluster. +FR +FR Le format des textes est le suivant: `__` +FR +FR Une action avec un intervalle à 0 est une action ponctuelle (`start`, `stop`, etc). Une +FR action avec un intervalle supérieur à 0 est une action récurrente, tel que `monitor`. +FR +In this example each arrow represents a dependancy and forces an order of +execution between actions. In an order for an action to be triggered, all the +preceding actions must have been executed and have succeded. The yellow texts +represent virtual actions, they act as synchronisation points when several +actions are required before starting another one. The black texts represent +actions that must be executed on a cluster node. + +The format of the text is the following: `__`. + +An action with an interval of zero is a one off action (`start`, `stop`, etc.). +Actions with intervals superior to zero are recurring action such as `monitor`. + +FR Dans cet exemple: +FR +FR * les actions 1 à 4 concernent l'exécution des actions `notify pre-demote` sur les nœuds +FR "frigg" et "odin" du cluster +FR * l'action 1 déclenche en parallèle les deux actions 2 et 3 +FR * l'action 4 est réalisée une fois que les actions 1, 2 et 3 sont validées +FR * l'action 5 est exécutée n'importe quand +FR * l'action 5 interrompt l'exécution récurrente de l'action `monitor` sur la ressource +FR "drbd0:0" du serveur "frigg" +FR * l'action 7 est exécutée après que 5 et 6 soient validées +FR * l'action 7 effectue un `demote` de la ressource "drbd0:0" sur "frigg" (qui n'est donc +FR plus supervisée) +FR * la pseudo action 8 est réalisée une fois que l'action `demote` est terminée +FR * la pseudo action 9 initialise le déclenchement des actions `notify post-demote` et +FR dépend de la réalisation précédente de la notification "pre-demote" et de l'action +FR `demote` elle même +FR * les actions 9 à 12 représentent l'exécution des notifications `post-demote` dans tout +FR le cluster +FR * les actions 13 à 24 représentent les actions de `notify pre-promote`, `promote` de +FR drbd sur "odin" et `notify post-promote` au sein du cluster +FR * les actions 25 et 27 peuvent alors être exécutées et redémarrent les actions de +FR monitoring récurrentes de drbd sur "odin" et "frigg" +FR * les actions 26, 28 à 30 démarrent un groupe de ressource dépendant de la ressource +FR drbd +FR +In this example: + +* action 1 to 4 are `notify pre-demote` actions executed on the nodes "frigg" + and "odin" + - action 1 is used to start action 2 and 3 in parallel + - action 4 is done after action 1, 2 and 3 are completed sucessfully +* action 5 is executed at any time +* action 5 cancels the recurring execution of the `monitor` action on ressource + "drbd0:0" of server "frigg" +* action 7 is executed after action 5 and 6 are deemed valid +* action 7 `demotes` the ressource "drbd0:0" on server "frigg" (it is therefore + no longer monitored) +* action 8 is a pseudo action triggered once the `demote` is finished +* action 9 is a pseudo action responsible for starting the the two `notify + post-demote` actions. It requires the `pre-demote` notification and the + `demote` action +* action 9 to 12 represent the execution of the `post-demote` actions in the + whole cluster +* action 13 to 24 represent the execution of the `notify-pre-demote` and + `demote` action on the drbd resource of "odin". `notify post-demote` is a + cluster wide action +* action 25 to 27 can then be executed and restart the recurring monitoring + actions of drbd on "odin" and "frigg" +* action 26, 28 and 29 start the group of resource which depends on the drbd + resource + + +FR Enfin, il est possible de consulter les transitions proposées par le PEngine +FR grâce à la commande `crm_simulate`. Cette commande est aussi parfois utile +FR pour en extraire des informations disponibles nulles par ailleurs, comme les +FR [scores de localisation][Contraintes de localisation]. +FR +Finally, it's possible to check the transitions proposed by PEngine with the +command `crm_simulate`. This command is also sometimes useful to get +information that are not accessible elsewhere like the [location +scores][Localisation constraints]. + +::: + +----- + +### Practical work: PEngine + +::: notes + +FR 1. identifier sur quels nœuds est lancé le processus `pengine` +FR 2. identifier où se trouvent les logs de `pengine` +FR 3. identifier le DC +FR 4. observer la différence de contenu des log de `pengine` entre nœuds +FR 5. afficher la vision de PEngine sur l'état du cluster (`crm_simulate`) +FR +1. identify on which node the processus `pengine` is started. +2. identify where are the logs of the `pengine` +3. identify the DC +4. check the difference between the content of the `pengine` logs across nodes +5. display the PEngine point of view of the cluster state (`¢rm_simulate`) + +::: + +----- + +### Correction: PEngine + +::: notes + +FR 1. identifier sur quels nœuds est lancé le processus `pengine` +FR +FR Sur tous les nœuds. +FR +1. identify on which node the processus `pengine` is started. + +On all nodes + +FR 2. identifier où se trouvent les logs de `pengine` +FR +FR Les messages de `pengine` se situent dans `/var/log/cluster/corosync.log`, +FR mélangés avec ceux des autres sous processus. +FR +FR Il est aussi possible de les retrouver dans `/var/log/messages` ou ailleurs en +FR fonction de la configuration de corosync, syslog, etc. +FR +2. identify where are the logs of the `pengine` + +The `pengine` logs is located in `/var/log/cluster/corosync.log`, it's mixed +with the other processus logs. + +It's also possible to find these messages in `/var/log/messages` or wherever +the configuration of corosync, syslog, etc. dictates it. + +FR 3. identifier le DC +FR +FR Utiliser `crm_mon`, `pcs status` ou `crmadmin`: +FR +3. identify the DC + +Use `crm_mon`, `pcs status` or `crmadmin`: + +~~~console +# crmadmin -D +Designated Controller is: hanode3 +~~~ + +FR 4. observer la différence de contenu des log de `pengine` entre nœuds +FR +FR Seuls le DC possède les messages relatifs au calcul de transitions effectués +FR par le sous-processus `pengine`. +FR +4. check the difference between the content of the `pengine` logs across nodes + +The message related to the transition calculation done by the `pengine` sub +process are only available on the DC. + +FR 5. afficher la vision de PEngine sur l'état du cluster (`crm_simulate`) +FR +5. display the PEngine point of view of the cluster state (`¢rm_simulate`) + +~~~console +# crm_simulate --live-check + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + +~~~ + +::: + +----- + +### Cluster Resource Manager (CRM) - Global diagram + +![CRM Diagram](medias/pcmk-archi-crmd.png) + +----- + +## Cluster Resource Manager (CRM) + +FR * daemon `CRMd` local à chaque nœud +FR * chargé du pilotage des événements +FR * reçoit des instructions du `PEngine` s'il est DC ou du `CRMd` DC distant +FR * transmet les actions à réaliser au sein des transitions +FR * au daemon `LRMd` local +FR * au daemon `STONITHd` local +FR * récupère les codes retours des actions +FR * transmets les codes retours de chaque action au `CRMd` DC +FR * renommé `controller` depuis la version 2.0 +FR +* local daemon `CRMd` on each node +* tasked with event management +* receives instructions from `PEngine` if it's the DC or from a remote `CRMd` + otherwise (the DC) +* transmits the actions + * to the local `LRMd` daemon + * to the local `STONITHd` daemon +* fetches the return code of the actions +* resends these return code to `CRMDd` on the DC +* renamed `controller` in version 2.0 + +::: notes + + +FR Le daemon `CRMd` est local à chaque nœud qui pilote les événements. Il peut soit être +FR actif (DC), et donc être chargé de l'ensemble du pilotage du cluster, soit passif, et +FR attendre que le `CRMd` DC lui fournisse des instructions. +FR +FR Lorsque des instructions lui sont transmises, il les communique aux daemons `LRMd` et/ou +FR `STONITHd` locaux pour qu'ils exécutent les actions appropriées auprès des _ressources +FR agents_ et _fencing agents_. +FR +FR Une fois l'action réalisée, le `CRMd` récupère le statut de l'action (via +FR son code retour) et le transmet au `CRMd` DC qui en valide la cohérence +FR avec ce qui est attendu au sein de la transition. +FR +FR En cas de code retour différent de celui attendu, le `CRMd` DC décide d'annuler la +FR transition en cours. Il demande alors une nouvelle transition au `PEngine`. +FR +The `CRMd` daemon is local to each nodes and manages events. It can be active +(DC) in which case it's in charge of managing the whole cluster, or passive in +which case it recieves instructions from the `CRMd` DC. + +When instructions are fed to `CRMd`, it communicates with the local `LRMd` +and/or local `STONITHd` so that the appropriate actions can be executed by +the _resource agents_ and _fencing agents_. + +Once the action is finished, `CRMd` fetches the status of the action (via the +return code) and transmits it to the `CRMd` DC. The DC validates the coherence +of the result with what was expected in the transition. + +If the return code is different from the expected one, the `CRMd` DC decides to +cancel the current transaction and asks for a new transition from the +`PEngine`. + +::: + +----- + +### Practical work: Cluster Resource Manager + +::: notes + +FR 1. trouver comment sont désignés les messages du `CRMd` dans les log +FR 2. identifier dans les log qui est le DC +FR +1. find how the `CRMd` messages are tagged in the logs +2. identify which server is the DC in the logs + +::: + +----- + +### Correction: Cluster Resource Manager + +Study of the `CRMd` daemon. + +::: notes + +FR 1. trouver comment sont désignés les messages du `CRMd` dans les log +FR +FR Les messages de ce sous-processus sont identifiés par `crmd:`. +FR +1. find how the `CRMd` messages are tagged in the logs + +The messages from this sub process are identified with `crmd:` + +FR 2. identifier dans les log qui est le DC +FR +2. identify which server is the DC in the logs +~~~ +crmd: info: update_dc: Set DC to hanode1 (3.0.14) +~~~ + +FR À noter que le retrait d'un DC est aussi visible: +FR +When a DC is demoted, it's also visible: + +~~~ +crmd: info: update_dc: Unset DC. Was hanode2 +~~~ + +::: + +----- + +## `STONITHd` and _Fencing Agent_ + +![Fencing diagram](medias/pcmk-archi-fencing.png) + +----- + +### `STONITHd` + + +FR * daemon `STONITHd` +FR * gestionnaire des agents de fencing (_FA_) +FR * utilise l'API des fencing agent pour exécuter les actions demandées +FR * reçoit des commandes du `CRMd` et les passe aux _FA_ +FR * renvoie le code de retour de l'action au `CRMd` +FR * support de plusieurs niveau de fencing avec ordre de priorité +FR * outil `stonith-admin` +FR * renommé `fenced` depuis la version 2.0 +FR +* `STONITHd` daemon +* fencing agent manager (_FA_) +* uses the fencing agent API to execute the requiered actions +* recieves the commands from `CRMd` and feeds them to the _FA_ +* resends the return code of the actions to `CRMd` +* supports several level of fencing with a priority order +* `stonith-admin` tool +* renamed `fencer` since version 2.0 + +::: notes + + + +FR Le daemon `STONITHd` joue sensiblement un rôle identique à celui du `LRMd` vis-à-vis des +FR agents de fencing (_FA_). + +FR +FR L'outil `stonith-admin` permet d'interagir avec le daemon `STONITHd`, notamment: +FR +FR * `stonith_admin -V --list-registered` : liste les agents configurés +FR * `stonith_admin -V --list-installed` : liste tous les agents disponibles +FR * `stonith_admin -V -l ` : liste les agents contrôlant le nœud spécifié. +FR * `stonith_admin -V -Q ` : contrôle l'état d'un nœud. +FR +The `STONITHd` daemon is for the fencing agents (_FA_) what `LRMd` is for +resource agents (_RA_). + +The `stonith-admin` tool can be used to interact with the `STONITHd` daemon, +for example: + +* `stonith_admin -V --list-registered` : list the configured agents +* `stonith_admin -V --list-installed` : list the available agents +* `stonith_admin -V -l ` : list the agents that can terminate the + specified node +* `stonith_admin -V -Q ` : controls the state of a device on a node + +::: + +----- + +### _Fencing Agent_ (_FA_) + +FR * script permettant de traduire les instructions du _fencer_ vers l'outil de fencing +FR * doit assurer que le nœud cible est bien complètement isolé du cluster +FR * doit renvoyer des codes retours définis dans l'API des _FA_ en fonction des résultats +FR * dix actions disponibles dans l'API, toutes ne sont pas obligatoires +FR +* script designed to translate `fencer`'s instruction to the fencing device +* must guaranty that the target node is isolated from the reste of the cluster +* must return the approriate return codes as defined in the fencing agent API +* ten actions are availagble in the API, the are not all mandatory + +::: notes + +FR Attention aux _FA_ qui dépendent du nœud cible ! +FR +FR Exemple classique : la carte IPMI. Si le serveur a une coupure électrique le +FR _FA_ (la carte IPMI donc) n'est plus joignable. Pacemaker ne reçoit donc +FR aucune réponse et ne peut pas savoir si le fencing a fonctionné, ce qui +FR empêche toute bascule. +FR +FR Il est conseillé de chaîner plusieurs _FA_ si la méthode de fencing présente +FR un _SPoF_: IPMI, rack d'alimentation, switch réseau ou SAN, ... +FR +Be wary of _FA_ that depend on the node state ! + + +Example: the IPMI card. If the server as an electrical outage, the _FA_ (the +IPMI card) is no longer reachable. Pacemaker can't receive feedback from it +therefore it cannot know if the fencing was successful, which can prevent a +failover. + +In such cases, where the fencing is a _SPoF_ (IMPI, rack power supply, network +switch or SAN ..), it's a good practice to chaine several _FA_. + + +FR Voici les actions disponibles de l'API des FA: +FR +FR * `off`: implémentation obligatoire. Permet d'isoler la ressource ou le serveur +FR * `on`: libère la ressource ou démarre le serveur +FR * `reboot`: isoler et libérer la ressource. Si non implémentée, le daemon +FR exécute les actions off et on. +FR * `status`: permet de vérifier la disponibilité de l'agent de fencing et le +FR statut du dispositif concerné: on ou off +FR * `monitor`: permet de vérifier la disponibilité de l'agent de fencing +FR * `list`: permet de vérifier la disponibilité de l'agent de fencing et de +FR lister l'ensemble des dispositifs que l'agent est capable d'isoler (cas d'un +FR hyperviseur, d'un PDU, etc) +FR * `list-status`: comme l'action `list`, mais ajoute le statut de chaque dispositif +FR * `validate-all`: valide la configuration de la ressource +FR * `meta-data`: présente les capacités de l'agent au cluster +FR * `manpage`: nom de la page de manuelle de l'agent de fencing +FR + +The following action are available in the _FA_ API: + +* `off`: mandatory action, enables the isolation of a resource of server +* `on`: frees a resource or start a server +* `reboot`: isolate and restart a resource. If the action is not available the + daemon will execute the off and on actions +* `status`: check to see if a local stonith device's port is reachable +* `monitor`: check to see if a local stonith device is reachable +* `list`: listing hosts and port assignments from a local stonith device and + the fencing agent availability +* `list-status`: same as `list` but with the status of each assignement +* `validate-all`: validate the configuration of the resource +* `meta-data`: displays the capabilities of the agent for the cluster +* `manpage`: displays the name of the man page for this fencing agent + +::: + +----- + +### Practical work: Fencing + +::: notes + +FR Au cours de workshop, nous utilisons l'agent de fencing `fence_virsh`. Il ne +FR fait pas parti des agents de fencing distribués par défaut et s'installe via le +FR paquet `fence-agents-virsh`. Cet agent de fencing est basé sur SSH et la +FR commande `virsh`. +FR +FR 1. installer tous les _FA_ ainsi que `fence_virsh` +FR 2. lister les FA à l'aide de `pcs resource` ou `stonith_admin` +FR +FR Nous abordons la création d'une ressource de fencing plus loin dans le workshop. +FR +During this worshop, we will use the fencing agent `fence_virsh`. it's not part +of the default fencing agent package and can be installed via the package +`fence-agent-virsh`. This fencing agent is based on SSH and the `virsh` +command. + +1. install all the _FA_ including `fence_virsh` +2. list the _FA_ with `pcs resource` and `stonith_admin` + +We will delve into fencing resource creation later on. + +::: + +----- + +### Correction: Fencing + +::: notes + +FR 1. installer tous les _FA_ ainsi que `fence_virsh` +FR +1. install all the _FA_ including `fence_virsh` + +~~~console +# yum install -y fence-agents-all fence-agents-virsh +~~~ + +FR 2. lister les FA à l'aide de `pcs resource` ou `stonith_admin` +FR +2. list the _FA_ with `pcs resource` and `stonith_admin` + +~~~ +# pcs resource agents stonith +fence_amt_ws +fence_apc +fence_apc_snmp +[...] + +# stonith_admin --list-installed + fence_xvm + fence_wti + fence_vmware_soap +[...] +~~~ + +::: + +----- + +## `LRMd` et _Resources Agent_ - Global diagram + +![LRM and it's resources diagram](medias/pcmk-archi-resource.png) + +----- + +### Local Resource Manager (LRM) + +FR * daemon `lrmd` +FR * interface entre le `CRMd` et les _resource agents_ (_RA_) +FR * capable d'exécuter les différents types de _RA_ supportés (OCF, systemd, +FR LSF, etc) et d'en comprendre la réponse +FR * reçoit des commandes du `CRMd` et les passe aux _RA_ +FR * renvoie le résultat de l'action au `CRMd` de façon homogène, quelque +FR soit le type de _RA_ utilisé +FR * est responsable d'exécuter les actions récurrentes en toute autonomie et de +FR prévenir le `CRMd` en cas d'écart avec le résultat attendu +FR * renommé _local executor_ depuis la version 2.0 +FR +* `LRMd` daemon +* interface between `CRMd` and the _resource agent_ (_RA_) +* can inteface with all the available _RA_ types (OCF, systemd, LSF, etc.) and + understand their answers +* receives `CRMd` commands and feeds them to _RA_ +* resends the result of the action to `CRMd` in a homogenous fashion despite + the _RA_ type +* is responsible for the execution of recurring actions and must warn `CRMd` in + case the result of the action is different from the expected one (e.g. + monitor) +* renamed 'local executor' in version 2.0 + +::: notes + + +FR Lorsqu'une instruction doit être transmise à un agent, le `CRMd` passe +FR cette information au `LRMd`, qui se charge de faire exécuter l'action +FR appropriée par le _RA_. +FR +FR Le daemon `LRMd` reçoit un code de retour de l'agent, qu'il transmet au +FR `CRMd`, lequel mettra à jour la CIB pour que cette information soit +FR partagée au niveau du cluster. +FR +FR Pour les actions dont le paramètre `interval` est supérieur à 0, le +FR `LRMd` est responsable d'exécuter les actions de façon récurrente +FR à la période indiquée dans la configuration. Le `LRMd` ne +FR reviendra vers le `CRMd` que si le code retour de l'action varie. +FR +When an instruction must be sent to an agent, `CRMd` sends the information to +`LRMd` which execute the appropriate action on the _RA_. + +The `LRMd` daemon receives the return code from the agent and transmits it to +`CRMd` which is tasked with updating the CIB so that the whole cluster is aware +of the result. + +For action where the `interval` parameter is superior to 0, `LRMd` is +responsible for their recurring execution once the period specified in the +configuration has ended. `LRMd` will get back to `CRMd` in case the return code +is not the expected one. + +::: + +----- + +### _Ressource Agent_ (_RA_) + +FR * applique les instructions du `LRMd` sur la ressource qu'il gère +FR * renvoie des codes retours stricts reflétant le statut de sa ressource +FR * plusieurs types/API de _ressource agent_ supportés +FR * la spécification "OCF" est la plus complète +FR * l'API OCF présente au `CRMd` les actions supportées par l'agent +FR * `action` et `operation` sont deux termes synonymes +FR * chaque opérations a un timeout propre et éventuellement une récurrence +FR +* applies the instruction sent by `LRMd` on the resource it manages +* resends the return code according to the API specification, in accordance to + the resource status +* several kinds of _resource agent_ supported (with different API) +* the _OCF_ specification is the most exhaustive +* the _OCF_ API present the action supported by the agent to `CRMd` +* `action` and `operation` as synonyms +* each operation has a specific timeout and might have an inteval for recuring + operations + +::: notes + +FR Il est possible d'utiliser plusieurs types de _RA_ différents au sein d'un même cluster: +FR +FR * OCF (Open Cluster Framework, type préconisé) +FR * SYSV +FR * systemd... +FR +FR Vous trouverez la liste des types supportés à l'adresse suivante: +FR +It's possible to use several kinfs of _RA_ in the same cluster: + +* OCF (Open ClusterFramework, the advised type) +* SYSV +* Systemd +* etc.. + +A list of all available types of _RA_ is available here: + + +FR Dans les spécifications du type OCF, un agent a le choix parmi dix codes retours +FR différents pour communiquer l'état de son opération à `LRMd`: +FR + +In the _OCF_ specification, ten different return codes are available for the +_RA_ to communicate the state of the action it was tasked with by `LMRd`. + +* `OCF_SUCCESS` (0, soft) +* `OCF_ERR_GENERIC` (1, soft) +* `OCF_ERR_ARGS` (2, hard) +* `OCF_ERR_UNIMPLEMENTED` (3, hard) +* `OCF_ERR_PERM` (4, hard) +* `OCF_ERR_INSTALLED` (5, hard) +* `OCF_ERR_CONFIGURED` (6, fatal) +* `OCF_NOT_RUNNING` (7) +* `OCF_RUNNING_MASTER` (8, soft) +* `OCF_FAILED_MASTER` (9, soft) + +FR Chaque code retour est associé à un niveau de criticité s'il ne correspond +FR à celui attendu par le cluster: +FR +FR * `soft`: le cluster tente une action corrective sur le même nœud ou déplace +FR la ressource ailleurs +FR * `hard`: la ressource doit être déplacée et ne pas revenir sur l'ancien nœud +FR sans intervention humaine +FR * `fatal`: le cluster ne peut gérer la ressource sur aucun nœud +FR +Each return code as a corresponding criticity, which is used when the return +code is different from the one expected by the cluster: + +* `soft`: the cluster will try to make a corrective action on the same node or + move the resource elsewhere; +* `hard`: the resource must be move and cannot return to the old node without + human intervention; +* `fatal`: the cluster cannot manage the resource on any node. + +FR Voici les opérations disponibles aux agents implémentant la specification OCF: +FR +FR * `start`: démarre la ressource +FR * `stop`: arrête la ressource +FR * `monitor`: vérifie l'état de la ressource +FR * `validate-all`: valide la configuration de la ressource +FR * `meta-data`: présente les capacités de l'agent au cluster +FR * `promote`: promote la ressource slave en master +FR * `demote`: démote la ressource master en slave +FR * `migrate_to`: actions à réaliser pour déplacer une ressource vers un autre nœud +FR * `migrate_from`: actions à réaliser pour déplacer une ressource vers le nœud local +FR * `notify`: action à exécuter lorsque le cluster notifie l'agent des actions +FR le concernant au sein du cluster +FR +These are the available operations for the agent who implement the _OCF_ +specification: + +* `start`: start the resource +* `stop`: stop resource +* `monitor`: check the state resource +* `validate-all`: validate the configuration of the resource +* `meta-data`: displays the capabilities of the _RA_ +* `promote`: promote the slave resource into a master +* `demote`: demote a master resource to a slave +* `migrate_to`: required action in order to move the resource to another node +* `migrate_from`: required action in order to move the resource to the local + node +* `notify`: action to execute when the cluster notifies the _RA_ of the actions + it must execute + +FR L'opération `meta-data` permet à l'agent de documenter ses paramètres et +FR d'exposer ses capacités au cluster qui adapte donc ses décisions en fonction +FR des actions possibles. Par exemple, si les actions `migrate_*` ne sont pas +FR disponibles, le cluster utilise les actions `stop` et `start` pour déplacer +FR une ressource. +FR +The `meta-data` operation is used by the agent to document it's configuration +and expose it's capabilities to the cluster. The cluster will then adapt it's +decision according to the available actions. For example, if the `migrate_*` +action are not available, the cluster will use the `stop` and `start` actions +to move a resource. + +FR Les agents systemd ou sysV sont limités aux seules actions `start`, `stop`, +FR `monitor`. Dans ces deux cas, les codes retours sont interprétés par `LRMd` +FR comme étant ceux définis par la spécification LSB: +FR +FR +The systemd and sysV agent are limited to three actions `start`, `stop` and +`monitor`. With these agents `LRMd` interprets the return codes as described in +the LSB specification: + + +FR Un ressource peut gérer un service seul (eg. une vIP) au sein du cluster, un +FR ensemble de service cloné (eg. Nginx) ou un ensemble de clone _multi-state_ +FR pour lesquels un statut `master` et `slave` est géré par le cluster et le _RA_. +FR +A resource can manage a single service (e.g. a VIP), or a group of cloned +services (e.g. Nginx) or even a group of _multi-state_ clones where the +`master` and `slave` state is managed by the cluster and the _RA_. + +FR Les _RA_ qui pilotent des ressources _multi-state_ implémentent obligatoirement +FR les actions `promote` et `demote` : une ressource est clonée sur autant de +FR nœuds que demandé, démarrée en tant que slave, puis le cluster promeut un ou +FR plusieurs `master` parmi les `slave`. +FR +The _RA_ designed to control _multi-state_ resources must implement the +`promote` and `demote` actions: the resource will be cloned on as many nodes as +requested, started as a slave, then the cluster will promote one or several +`masters` amongst the `slaves`. + +FR Le _resource agent_ PAF utilise intensément toutes ces actions, sauf +FR `migrate_to` et `migrate_from` qui ne sont disponibles qu'aux _RA_ non +FR _multi-state_ (non implémenté dans Pacemaker pour les ressources multistate). +FR +The _resource agent_ PAF uses all theses actions except for `migrate_to` and +`migrate_from` which are available only for non _multi-state_ _RA_ (it's not +implemented in Pacemaker for multi state resources). + +::: + +----- + +### Practical work: _Resource Agents_ + +::: notes + +FR 1. installer les _resource agents_ +FR 2. lister les RA installés à l'aide de `pcs` +FR 3. afficher les informations relatives à l'agent `dummy` à l'aide de `pcs` +FR 4. afficher les informations relatives à l'agent `pgsql` à l'aide de `pcs` +FR +1. install the _resource agents_ +2. list the available _RA_ with `pcs` +3. display the information about the `dummy` _RA_ with `pcs` +4. display the information about the `pgsql` _RA_ with `pcs` + +::: + +----- + +### Correction: _Resource Agents_ + +::: notes + +FR 1. installer les _resource agents_ +FR +FR Il est normalement déjà installé comme dépendance de pacemaker. +FR +1. install the _resource agents_ + +This package is usually installed as a dependency of Pacemaker. + +~~~ +yum install -y resource-agents +~~~ + +FR 2. lister les RA installés à l'aide de `pcs` +FR +2. list the available _RA_ with `pcs` + +~~~ +pcs resource agents +~~~ + +FR 3. afficher les informations relatives à l'agent `dummy` à l'aide de `pcs` +FR +FR Chaque agent embarque sa propre documentation. +FR +3. display the information about the `dummy` _RA_ with `pcs` + +Each _RA_ contains it's own documentation. + +~~~ +pcs resource describe dummy +~~~ + +FR 4. afficher les informations relatives à l'agent `pgsql` à l'aide de `pcs` +FR +FR Le RA `pgsql` livré avec le paquet `resource-agents` n'est **pas** celui de PAF. Vous +FR pouvez lister l'ensemble de ses options grâce à la commande: +FR + +4. display the information about the `pgsql` _RA_ with `pcs` + +The `pgsql` _RA_ is deployed with the `resource_agents` package is the one +deployed with PAF. + +You can list all it's options with the command : + +~~~ +pcs resource describe pgsql +~~~ + +::: + +----- + +## PostgreSQL Automatic Failover (PAF) + +FR * _RA_ spécifique à PostgreSQL pour Pacemaker +FR * alternative à l'agent existant +FR * moins complexe et moins intrusif +FR * compatible avec PostgreSQL 9.3 et supérieur +FR * Voir: +FR +* _RA_ dedicated to PostgreSQL +* an alternative to the existing one + - less complex and intrusive + - compatible with PostgreSQL 9.3 and up +* see: + +::: notes + +FR PAF se situe entre Pacemaker et PostgreSQL. C'est un _resource agent_ +FR qui permet au cluster d'administrer pleinement une instance PostgreSQL locale. +FR +FR Un chapitre entier est dédié à son installation, son fonctionnement et sa +FR configuration plus loin dans ce workshop. +FR +FR ![Schema](medias/pcmk-archi-paf-overview.png) +FR +PAF is a component placed between Pacemaker and PostgreSQL. It's a _resource +agent_ which enables the cluster to administer a local PostgreSQL instance. + +A chapter dedicated to it's installation, inner working and configuration can +be found later in this workshop. + +![Schema](medias/pcmk-archi-paf-overview.png) +::: + +------ + +# Cluster configuration + +FR Attention: +FR +FR * les paramètres de Pacemaker sont tous sensibles à la casse +FR * aucune erreur n'est levée en cas de création d'un paramètre inexistant +FR * les paramètres inconnus sont simplement ignorés par Pacemaker +FR +Warning: + +* Pacemaker's parameters are all case sensitive +* no error is returned when a non existant parameter is created +* unknown parameters are juste ignored by Pacemaker + +----- + +## Quorum support + +FR Paramètre `no-quorum-policy` +FR +FR * `ignore`: désactive la gestion du quorum (déconseillé !) +FR * `stop`: (par défaut) arrête toutes les ressources +FR * `freeze`: préserve les ressources encore disponible dans la partition +FR * `suicide`: fencing des nœuds de la partition +FR +The `no-quorum-policy` parameter + +* `ignore`: disables quorum management (not recommanded) +* `stop`: stop the resources (default) +* `freeze`: keeps the resources that are still available in the partition +* `suicide`: fence the nodes of the partition + +:::notes + +FR Il est fortement déconseillé de désactiver le quorum. +FR +FR La valeur par défaut est le plus souvent la plus adaptée. +FR +FR Le cas du `freeze` peut être utile afin de conserver les ressources actives au +FR sein d'un cluster où il n'y a aucun risque de split brain en cas de partition +FR réseau, eg. un serveur httpd. +FR + +It's strongly advised not to disable quorum. + +Most of the time, the default value is the most suitable. + +The `freeze` value can be useful in order to keep resources active in a cluster +where there is no risk of split brain in case of network partition (e.g. an +httpd server). + +::: + +----- + +## Stonith support + +FR Paramètre `stonith-enabled` +FR +FR * `false` : désactive la gestion du fencing (déconseillé !) +FR * activé par défaut +FR * aucune ressource ne démarre sans présence de FA +FR +The `stonith-enabled` parameter + +* `false`: disables the fencing (not recommanded) +* enabled by default + - no ressource can start without _FA_ + +:::notes + +FR Ce paramètre contrôle la gestion du fencing au sein du cluster. Ce dernier +FR est activé et il est vivement recommandé de ne pas le désactiver. +FR +FR Effectivement, il est possible de désactiver le fencing au cas par cas, +FR ressource par ressource, grâce à leur méta-attribut `requires` (voir +FR chapitre [Configuration des ressources][]), positionné par défaut à `fencing`. +FR +This parameter controls fencing management inside the cluster. It's enabled by +default. It's not recommanded to disable it. + +If need be, it's possible to disable fencing peacemeal, one resource at a +time with their meta attribute `requires` (see the [Resource configuration][] +chapter). It's default value is `fencing`. + +FR Il est techniquement possible de désactiver le [quorum][] ou [fencing][]. +FR +FR Comme dit précédemment c'est à proscrire hors d'un environnement de test. Sans +FR ces fonctionnalités, le comportement du cluster est imprévisible en cas de +FR panne et sa cohérence en péril. +FR +FR Dans le cas d'un cluster qui gère une base de donnée cela signifie que l'on encourt le +FR risque d'avoir plusieurs ressources PostgreSQL disponibles en écriture sur plusieurs +FR nœuds (conséquence d'un `split brain`). +FR +It's possible to disable [quorum][] or [fencing][]. + +As explained before, this is not recommanded outside of a test environement. +Without these mechanisms, the cluster behavior is unpredictable in case of +outage and it's consistency is at risk. + +In case of clusters that manage databases, this means we risk a `split brain` +situation in case of network partition. Which will result in the same database +being opened in read/write mode on different nodes. + +::: + +----- + +## Symetric and asymetric clusters + +FR Paramètre `symmetric-cluster`: +FR +FR * change l'effet des scores de préférence des ressources +FR * `true`: (par défaut) cluster symétrique ou _Opt-Out_. Les ressources +FR peuvent démarrer sur tous les nœuds à moins d'y avoir un score déclaré +FR inférieur à `0` +FR * `false`: cluster asymétrique ou _Opt-In_. Les ressources ne peuvent +FR démarrer sur un nœud à moins d'y avoir un score déclaré supérieur ou +FR égal à `0` +FR +The `symetric-cluster` parameter + +* changes the effect of preference scores on resources +* `true`: the cluster is symetric or _Opt-Out_, this is the default. The + resources can start on all nodes except if there is a negative score placed + on the node. +* `false`: the cluster is asymetric or _Opt-In_. The resources cannot start on + a node unless a positive score as been placed on the node. + +::: notes + +FR Le paramètre `symetric-cluster` permet de changer la façon dont pacemaker choisit +FR où démarrer les ressources. +FR +FR Configuré à `true` (defaut), le cluster est dit symétrique. Les ressources +FR peuvent être démarrées sur n'importe quel nœud. Le choix se fait par ordre +FR décroissant des valeurs des [contraintes de localisation][Scores etlocalisation]. +FR Une contrainte de localisation négative empêchera la ressource de démarrer +FR sur un nœud. +FR +FR Configuré à `false`, le cluster est dit asymétrique. Les ressources ne peuvent +FR démarrer nulle part. La définition des contraintes de localisation doit définir +FR sur quels nœuds les ressources peuvent être démarrées. +FR +FR La notion de contraintes de localisation est définie dans le chapitre +FR [Contraintes de localisation][] +FR +The `symetric-cluster` parameter changes the way pacemaker choses where to +start resources. + +The default value is `true`, in this case the cluster is called symetric. The +resources can start on any node. The choice of the node is made in decreasing +order of the [location constraints][Scores and location constraints]. A negative location +constraint prevents a resource to start on the node. + +When it is set to `false`, the cluster is said to be `asymetric`. The resource +cannot start anywhere. Location constraints must be set to define where the +resource can start. + +The notion of [location constraints][] is defined in it's own chapter. + +::: + +----- + +## Maintenance mode + +FR Paramètre `maintenance-mode`: +FR +FR * désactive tout contrôle du cluster +FR * plus aucun opération n'est exécutée +FR * plus de monitoring des ressources +FR * les ressources démarrée sont laissée dans leur état courant (elles ne +FR sont pas arrêtées) +FR * toujours tester les transitions avec `crm_simulate` avant de sortir de la +FR maintenance +FR +The `maintenace-mode` parameter + +* disables all control on the cluster +* no more action will be executed + - no monitoring will be done on resources +* the started resources will be left in their current state +* always test the transition with `crm_simulate` when leaving maintenance mode + +::: notes + +FR Le paramètre `maintenance_mode` est utile pour réaliser des opérations de +FR maintenance globales à tous les nœuds du cluster. Toutes les opérations +FR `monitor` sont désactivées et le cluster ne réagit plus aucun événements. +FR +FR Ce paramètre, comme tous les autres, est préservé lors du redémarrage de +FR Pacemaker, sur un ou tous les nœuds. Il est donc possible de redémarrer tout +FR le cluster tout en conservant le mode maintenance actif. +FR +The `maintenance mode` parameter is useful to conduct maintenace operations +that impact all the nodes of the cluster. All the `monitor` action are disables +and the cluster doesn't react to any event. + +This parameter, like all others, is kept during Pacemaker restarts. It's +therefore possible to restart all the cluster while keeping the maintenance +mode active. + +FR Attention toutefois aux scores de localisation. D'autant plus que ceux-ci +FR peuvent être mis à jour lors du démarrage du cluster sur un nœud par exemple. +FR Vérifiez toujours que les ressources sont bien dans l'état attendu sur chaque +FR nœud avant de sortir du mode de maintenance afin d'éviter une intervention du +FR cluster. Lorsque ce dernier reprend la main, il lance l'action `probe` sur +FR toutes les ressources sur tous les nœuds pour détecter leur présence et +FR comparer la réalité avec l'état de sa CIB. +FR +Be careful to the location scores, they can be updated during cluster restart. +It's important to verify that all resources are in the correct state on all +nodes before leaving maintenance mode in order to avoid changes in the cluster +state. When the cluster is back in control, it starts a `probe` action on all +resources of all nodes in order to detect their presence and compare reality +with the state recorded in the CIB. + +::: + +----- + +## Other usefull parameters + +FR * `stop-all-resources=false`: toutes les ressources sont arrêtées si +FR positionné à `true` +FR * `stonith-watchdog-timeout`: temps d'attente avant qu'un nœud disparu est +FR considéré comme "auto-fencé" par son watchdog si le cluster est configuré +FR avec +FR * `cluster-recheck-interval=15min`: intervalle entre deux réveils forcé du +FR `PEngine` pour vérifier l +FR 'état du cluster +FR +* `stop-all-resources=false`: all resources are stopped if this parameter is + set to `true` +* `stonith-watchdog-timeout`: elapsed time before a failed node is considered + "self fenced" by it's watchdog if the cluster has one. +* `cluster-recheck-interval=15min`: interval between two forced awakening of + the `PEngine` in order to check the cluster state + +::: notes + +FR Pour la liste complète des paramètres globaux du cluster, voir: +FR +A compehensive list of cluster global parameters is available here: + + + +::: + +----- + +## Practical work: Cluster parameters + +::: notes + +FR 1. afficher les valeurs par défaut des paramètres suivants à l'aide de `pcs property`: +FR +1. display the default values of the following parameters with `pcs property`: + + * `no-quorum-policy` + * `stonith-enabled` + * `symmetric-cluster` + * `maintenance-mode` + +::: + +----- + +## Correction: Cluster parameters + +::: notes + +FR 1. afficher les valeurs par défaut des paramètres suivants à l'aide de `pcs property`: +FR +1. display the default values of the following parameters with `pcs property`: + + * `no-quorum-policy` + * `stonith-enabled` + * `symmetric-cluster` + * `maintenance-mode` + + +~~~console +# pcs property list --defaults|grep -E "(no-quorum-policy|stonith-enabled|symmetric-cluster|maintenance-mode)" + maintenance-mode: false + no-quorum-policy: stop + stonith-enabled: true + symmetric-cluster: true +~~~ + +::: + +----- + +# Node attributes + +## General information about node attributes + +FR * attributs propres à chaque nœud +FR * peut être persistant après reboot ou non +FR * peut stocker n'importe quelle valeur sous n'importe quel nom +FR * eg. `kernel=4.19.0-8-amd64` +FR +* node specific attributes +* can be persistent (survive a reboot or not) +* can store any value under any name + - eg. `kernel=4.19.0-8-amd64` + +::: notes + +FR Il est possible de créer vos propres attributs avec l'outil `crm_attribute`. +FR +FR La persistance de vos attributs se contrôle avec l'argument `--lifetime`: +FR +FR * valeur réinitialisée au redémarrage (non persistant) : `--lifetime reboot` +FR * note : `--type status` est également accepté. Mentionné dans la +FR documentation mais pas dans le manuel de la commande +FR * valeur conservée au redémarrage (persistant) : `--lifetime forever` +FR * note : `--type nodes` est également accepté. Mentionnée dans la +FR documentation mais pas dans le manuel de la commande +FR + +It's possible to create your own attributes with the tool `crm_attribute`. + +The lifetime of you attribute is control with the `--lifetime` argument of the +command: + +* `--lifetime reboot`: the value is reset during a restart of the cluster (it's + not pesistent) + - note: `--type status` is also accepted. It's mentionned in the + documentation but not in the command's manual. +* `--lifetime forever`: the value is persistant across cluster restarts + - note: `--type nodes` is also accepted. It's mentionned in the documentation + but not in the command's manual. + +FR Exemple pour stocker dans un attribut du nœud nommé `kernel` la version du +FR noyau système : +FR +This example shows how to create a `kernel` attribute with the kernel version +as a value: + +~~~ +crm_attribute -l forever --node hanode1 --name kernel --update $(uname -r) +~~~ + +FR Exemple de l'utilisation d'une rule basée sur un attribut de ce type: +The following link shows an example of how to setup rules based on attributes: + + +FR Le _RA_ PAF utilise également les attributs non persistants et très +FR transitoires. À l'annonce d'une promotion, chaque esclave renseigne son LSN +FR dans un attribut transient. Lors de la promotion, le nœud "élu" compare son LSN +FR avec celui des autres nœuds en consultant leur attribut `lsn_location` pour +FR s'assurer qu'il est bien le plus avancé. Ces attributs sont détruits une fois +FR l'élection terminée. +FR +The PAF _RA_ also uses non persistant attributes. During a promotion, each +slave announces it's LSN using a transient attribute. During the promotion, the +elected node compares it's LSN with the `lsn_location` attribute of the +resource on each node in order to verify that it's the most up to date. These +attributes are destroyed once the election is finished. + +::: + +----- + +## Spetial node attributes + +FR * plusieurs attributs font office de paramètres de configuration +FR * `maintenance`: mode maintenance au niveau du nœud +FR * `standby`: migrer toutes les ressources hors du nœud +FR +* several attributes are used as configuration parameters +* `maintenance`: is the node in maintenance mode +* `standby`: migrate resource outside of the node + +::: notes + +FR Il existe plusieurs attributs de nœuds spéciaux qui font offices de +FR paramétrage. Les deux plus utiles sont `maintenance` et `standby`. +FR +FR L'attribut `maintenance` a le même effet que le `maintenance_mode` au niveau +FR du cluster, mais localisé au seul nœud sur lequel il est activé. +FR +FR Lorsque l'attribut `standby` est activé, il indique que le nœud ne doit plus +FR héberger aucune ressource. Elle sont alors migré vers d'autres nœuds ou +FR arrêté le cas échéant. +FR +FR Vous trouverez la liste complète de ces attributs de nœud spéciaux à +FR l'adresse suivante: +FR +Several special node attributes are used as configuration parameters. The two +most useful are `maintenance` and `standby`. + +The `maintenance` attribute as the same effect as the `maintenance_mode` cluster +wide parameter, except that it's limited only to the node it's placed on. + +When the `standby` attribute is activated, it indicates that the node cannot +host resource anymore. They will be migrated to other nodes ou stopped. + +A more compehensive list of special node attribute is available a the folling +address: + + +::: + +----- + +## Other node attribute of interest + +FR Quelques autres attributs particuliers: +FR +FR * `fail-count-*`: nombre d'incident par ressource sur le nœud +FR * `master-*`: _master score_ de la ressource sur le nœud +FR +Some other node attributes of interest + +* `fail-count-*`: number of incident for a resource on a node +* `master-*`: the _master score_ of a resouce on a node + +::: notes + +FR Un attribut `fail-count-*` de type non persistant est utilisés pour +FR mémoriser le nombre d'erreur de chaque ressources sur chaque nœud. Préférez +FR utiliser `crm_failcount` ou `pcs resource failcount` pour accéder à ces +FR informations. +FR +Non persistent `fail-count-*` attributes are used to memorize the amount of +errors for each resource on a node. It's a good practice to use `crm_failcount` +or `pcs resource failcount` to access this information instead of accessible +the attributes directly. + +FR Enfin, il existe des _master score_ pour les ressources de type _multi-state_ +FR (primaire/secondaire), permettant d'indiquer où l'instance primaire peut ou +FR doit se trouver dans le cluster. Il sont préfixé par `master-*`. PAF positionne +FR ces scores comme attributs persistants des nœuds. La position de l'instance +FR primaire est ainsi préservée lors du redémarrage du cluster. +FR +FR Vous pouvez consulter ou modifier les _master score_ à l'aide de l'outil +FR `crm_master`. Attention toutefois, ces scores sont positionnés habituellement +FR par le _RA_ lui même. À moins de vous trouver dans une situation où le +FR cluster ne nomme aucune ressource primaire, vous ne devriez pas vous même +FR positionner un _maser score_. +FR + +Finally, a _master score_ attribute exists for _multi-state_ resources +(primary/secondary), it's used to specify where the primary instance can/must +be placed in the cluster. They are prefixed with `master-*`. PAF uses theses +scores as persistent attributes on each node. Unless you want the cluster to be +unable to chose a primary resource, you shouldn't specify a _maaster score_ +yourself. + +::: + +----- + +# Resource configuration + +FR * mécanique interne +FR * __tout__ dépend des scores ! +FR * chapitre organisé dans l'ordre des besoins de configuration +FR +* internal mechanics +* __everything__ depends on scores ! +* this chapter's organization is based on the order of configuration needs + +----- + +## Resource meta-attributes + +FR * un ensemble de _meta-attributes_ s'appliquent à n'importe quelle ressource: +FR * il est possible de leur positionner une valeur par défaut qui s'applique +FR à toutes les ressources +FR * il est possible de surcharger les valeurs par défaut pour chaque ressource +FR * quelques exemple de méta-attributs: +FR * `target-role`: rôle attendu: `Started`, `Stopped`, `Slave`, ou `Master` +FR * `migration-threshold` : combien d'erreurs "soft" avant de déclencher un failover +FR * `failure-timeout` : durée à partir de laquelle les erreurs "soft" sont réinitialisées +FR * `resource-stickiness` : score de maintien d'une ressource sur le nœud courant +FR * `is-managed`: le cluster doit-il agir en cas d'événement ? +FR +* a set of _meta-attributes_ can be applied to any resource: + - it's possible to set a default value which will be applied to all resources + - it's possible to overload all the default values +* some example of meta attributes: + - `target-role`: expected role among: `Started`, `Stopped`, `Slave or + `Master` + - `migration-threshold`: how many "soft" errors before we start a failover + - `failure-timeout`: amount of time elapsed before the "soft" errors are + reset + - `resource-stickiness`: controls how much a service prefers to stay running + where it is + - `is-managed`: does the cluster react in case of event ? + +::: notes + +FR Les _meta-attributes_ est un ensemble d'attributs commun à n'importe quelle +FR type de ressource. Ils se positionnent ressource par ressource. Il est possible +FR de leur créer une valeur par défaut qui sera appliquée automatiquement à toute +FR ressource présente dans le cluster. +FR +FR Par exemple avec `pcs`: +FR +_Meta-attributes_ are a set of attributes shared by all types of resources. +They can be set on a resource per resource basis. It's possible to change their +default value so that it's applied to all the resources in the cluster. + +Exemple using `pcs`: + +~~~ +pcs resource defaults =valeur +~~~ + +FR Le même exemple avec l'outil standard `crm_attribute`: +FR + +The same example using `crm_attribute`: + +~~~ +crm_attribute --type rsc_defaults --name --update valeur +~~~ + +FR La valeur d'un méta attribut positionné au niveau de la ressource elle même +FR surcharge la valeur par défaut positionné précédemment. +FR +FR La liste complète des méta-attributs et leur valeur par défaut est disponible à +FR cette adresse: +FR +The value of a meta attribute positionned at the resource level takes priority +over default values configures at a higher level. + +A comprehensive list of meta-attributes and their default value is available +here: + + +::: + +----- + +### Practical work: resource default parameters + +::: notes + +FR 1. trouver la valeur par défaut du paramètre `migration-threshold` +FR 2. positionner sa valeur à dix +FR 3. supprimer la valeur par défaut du paramètre `is-managed` +FR 4. contrôler que les modifications sont prise en compte avec `pcs config show` +FR 5. observer les modifications de la CIB dans les logs +FR +FR Remarque: il existe une propriété du cluster `default-resource-stickiness`. +FR Cette propriété est dépréciée, il faut utiliser les valeurs par defaut des +FR ressources à la place. +FR +1. find the default value of the parameter `migration-threshold` +2. set it to a value of 10 +3. remove the default value for the parameter `is-managed` +4. check that the modification where taken into account with `pcs config show` +5. look for the CIB modification in the logs + +Note: the property `default-resource-stickiness` is deprecated. The per +resource default value should be used instead. + +~~~ +pcs property list --defaults |grep -E "resource-stickiness" + default-resource-stickiness: 0 +~~~ + +::: + +----- + +### Correction: resource default parameters + +::: notes + +FR 1. trouver la valeur par défaut du paramètre `migration-threshold` +FR +FR La valeur par défaut est `INFINITY`. Voir: +FR +1. find the default value of the parameter `migration-threshold` + +The default value is set to `INFINITY`. See: + + + +2. positionner sa valeur à dix + +FR 2. set it to a value of 10 +FR +~~~console +# pcs resource defaults migration-threshold=10 +Warning: Defaults do not apply to resources which override them with their own defined values +# pcs resource defaults +migration-threshold: 10 +~~~ + +3. supprimer la valeur par défaut du paramètre `is-managed` + +FR 3. remove the default value for the parameter `is-managed` +FR +~~~console +# pcs resource defaults is-managed= +Warning: Defaults do not apply to resources which override them with their own defined values +~~~ + +FR 4. contrôler que les modifications sont prise en compte avec `pcs config show` +FR +4. check that the modification where taken into account with `pcs config show` + +~~~ +# pcs config show +[...] +Resources Defaults: + migration-threshold=10 +[...] +~~~ + +FR 5. observer les modifications de la CIB dans les logs +FR +FR NB: les log ont ici été remis en forme. +FR +5. look for the CIB modification in the logs + +Note: the logs where reformatted to fit the workshop. + +~~~ +cib: info: Forwarding cib_apply_diff operation for section 'all' to all +cib: info: Diff: --- 0.5.5 2 +cib: info: Diff: +++ 0.6.0 2edcd42b63c34c8c39f2ab281d0c09b8 +cib: info: + /cib: @epoch=6, @num_updates=0 +cib: info: ++ /cib/configuration: +cib: info: ++ +cib: info: ++ +cib: info: ++ +cib: info: ++ +cib: info: ++ +cib: info: Completed cib_apply_diff operation for section 'all': OK +~~~ + +::: + +----- + +## Fencing configuration + +FR * les _FA_ sont gérés comme des ressources classiques +FR * les _FA_ ont un certain nombre de paramètres en commun: `pcmk_*` +FR * les autres paramètres sont propres à chaque _FA_, eg. `port`, `identity_file`, `username`, ... +FR * chaque _FA_ configuré peut être appelé de n'importe quel nœud +FR +* _FA_ are handled like regular resources +* _FA_ have a bunch of: `pcmk_*` parameters +* other parameters exist and are _FA_ specific, eg. `port`, `identity_file`, + `username`, ... +* each configured _FA_ can be called from any node + +::: notes + +FR Pour chaque agent de fencing configuré, un certain nombre de méta attributs +FR définissent les capacités de l'agent auprès du cluster. Quelque exemples +FR notables: +FR +FR * `pcmk_reboot_action`: détermine quelle action exécuter pour isoler un nœud. +FR Par exemple `reboot` ou `off`. L'action indiquée dépend de ce que supporte +FR l'agent +FR * `pcmk_host_check`: détermine si l'agent doit interroger l'équipement pour +FR établir la liste des nœuds qu'il peut isoler, ou s'il doit se reposer sur +FR le paramètre `pcmk_host_list` +FR * `pcmk_host_list`: liste des nœuds que peut isoler l'agent de fencing +FR * `pcmk_delay_base`: temps d'attente minimum avant de lancer l'action de +FR fencing. Pratique dans les cluster à deux nœuds pour privilégier un des +FR nœuds +FR +FR Vous trouverez la liste complète à l'adresse suivante: + +For each configured fencing agent, a few meta attributes define the +capabilities of the agent to the cluster. Some notable examples: + +* `pcmk_reboot_action`: determines which action to execute in order to isolate + a node. For example `reboot` or `off`. the action provided depends upon what + the agent supports. +* `pcmk_host_check`: determines if the agent must ask the equipment for a list + of nodes it can isolate, or if it must rely on the `pcmk_host_list` + parameter. +* `pcmk_host_list`: list the nodes that the _FA_ can isolate +* `pcmk_delay_base`: minimum elapsed time before starting the fencing action. + It's useful in two node cluster to favor one node over the other. + +The full list can be found here: + + +FR Tous les paramètres ne débutants pas par `pcmk_*` sont propres à chaque +FR _fencing agent_. Dans le cadre de notre workshop, nous utiliserons l'agent +FR `fence_virsh` qui nécessite des paramètres de connexion SSH ainsi que le nom +FR de la machine virtuelle à interrompre. +FR +All the parameters who dont start with `pcmk_*` are specific to each _fencing +agent_. In this workshop, we will use the fencing agent `fence_virsh`. It +requires several specific parameters for the SSH connexion like the name of the +virtual machine to stop. + +FR Une fois paramétrés, Pacemaker s'assure que les _FA_ restent disponibles en +FR exécutant à intervalle régulier l'action `monitor`, positionnée par défaut +FR à une minute. À cause de cette action récurrente, les _FA_ apparaissent au +FR sein du cluster au même titre que les autres ressources. Mais notez qu'une +FR ressource de fencing ne démarre pas sur les nœud du cluster, ces équipement +FR sont actifs _ailleurs_ dans votre architecture. +FR +Once configured, Pacemaker will make sure the _FA_ are available at all times +with the execution of a regular `monitor` action. The default interval is set +to a minute. Because of the recuring actions, the _FA_ appear in the cluster +the same way as other resources do. Please note that the fencing resource is +not started on the cluster nodes, it's equipments are active somewhere else in +the architecture. + +FR Lorsqu'une action de fencing commandée par Pacemaker, celle-ci sera déclenchée +FR en priorité depuis le nœud d'où la ressource est supervisée. Si le nœud ou +FR la ressource de fencing sont devenus indisponibles depuis la dernière action de +FR monitor, n'importe quel autre nœud du cluster peut être utilisé pour +FR exécuter la commande. +FR +When a fencing action is requested by Pacemaker, it will be executed in +priority on the node where the resource is supervised. If the node or the +fencing resource are unavailable since the last monitor, any other node of the +cluster can be used to execute the command. + +::: + +----- + +### Practical work: Fencing Agent + +::: notes + +FR Rappel: par défaut le cluster refuse de prendre en charge des ressources en HA sans +FR fencing configuré. +FR +Reminder: the default behavior for the cluster is to refuse to start any +resource if there is no fencing configured. + +~~~console +# crm_verify --verbose --live-check +~~~ + +FR 1. afficher la description de l'agent de fencing `fence_virsh` +FR +FR Nous allons utiliser les paramètres suivants: +FR +FR * `ipaddr`: adresse de l'hyperviseur sur lequel se connecter en SSH +FR * `login`: utilisateur SSH pour se connecter à l'hyperviseur +FR * `identity_file`: chemin vers la clé privée SSH à utiliser pour l'authentification +FR * `login_timeout`: timeout du login SSH +FR * `port`: nom de la VM à isoler dans libvirtd +FR +FR Les autres paramètres sont décrits dans le slide précédent. +FR +FR Bien s'assurer que chaque nœud peut se connecter en SSH sans mot de passe à +FR l'hyperviseur. +FR +1. display the desciption of the _FA_ `fence_virsh` + +We will use the following parameters: + +* `ipaddr`: address of the hypervisor on which we will connect with SSH +* `login`: user for the SSH connection to the hypervisor +* `identity_file`: path to the SSH private key used for authentication +* `login_timeout`: timeout for the SSH login +* `port`: name of the VM to isolate in libvirtd + +The other parameters are described in the previous slides. + +It's important to check that passwordless authentication is configured between +the nodes and the hypervisor. + +FR 2. créer une ressource de fencing pour chaque nœud du cluster +FR +FR Les agents de fencing sont des ressources en HA prises en charge par le +FR cluster. Dans le cadre de ce TP, nous créons une ressource par nœud, +FR chacune responsable d'isoler un nœud. +FR +2. create a fencing resource for each node in the cluster + +The fencing agents are HA resources managed by the cluster. In this exercise, +we will create one resource per node each one will be responsible for fencing a +node. + +FR 3. vérifier que le cluster ne présente plus d'erreur +FR 4. vérifier que ces ressources ont bien été créées et démarrées +FR 5. afficher la configuration des agents de fencing +FR 6. vérifier dans les log que ces ressources sont bien surveillée par `LRMd` +FR +3. verify that the cluster doesn't have any error +4. verify that the resources have been created and started +5. display the configuration of the fencing agents +6. verify that the resources are supervized by `LRMd` in the logs + +::: + +----- + +### Correction: Fencing Agent + +::: notes + +FR Rappel: par défaut le cluster refuse de prendre en charge des ressources en HA sans +FR fencing configuré. +FR +Reminder: the default behavior for the cluster is to refuse to start any +resource if there is no fencing configured. + +~~~console +# crm_verify --verbose --live-check + error: unpack_resources: Resource start-up disabled since no STONITH resources have been defined + error: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option + error: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity +Errors found during check: config not valid +~~~ + +FR 1. afficher la description de l'agent de fencing `fence_virsh` +FR +1. display the desciption of the _FA_ `fence_virsh` + +~~~ +# pcs resource describe stonith:fence_virsh +~~~ + +FR 2. créer une ressource de fencing pour chaque nœud du cluster +FR +FRAdapter `pcmk_host_list`, `ipaddr`, `login` et `port` à votre environnement. +FR +2. create a fencing resource for each node in the cluster + +Adapt `pcmk_host_list`, `ipaddr`, `login` and `port` to your environnment. + +~~~console +# pcs stonith create fence_vm_hanode1 fence_virsh pcmk_host_check="static-list" \ +pcmk_host_list="hanode1" ipaddr="10.20.30.1" login="user" \ +port="centos7_hanode1" pcmk_reboot_action="reboot" \ +identity_file="/root/.ssh/id_rsa" login_timeout=15 + +# pcs stonith create fence_vm_hanode2 fence_virsh pcmk_host_check="static-list" \ +pcmk_host_list="hanode2" ipaddr="10.20.30.1" login="user" \ +port="centos7_hanode2" pcmk_reboot_action="reboot" \ +identity_file="/root/.ssh/id_rsa" login_timeout=15 + +# pcs stonith create fence_vm_hanode3 fence_virsh pcmk_host_check="static-list" \ +pcmk_host_list="hanode3" ipaddr="10.20.30.1" login="user" \ +port="centos7_hanode3" pcmk_reboot_action="reboot" \ +identity_file="/root/.ssh/id_rsa" login_timeout=15 +~~~ + +FR 3. vérifier que le cluster ne présente plus d'erreur +FR +3. verify that the cluster doesn't have any error + +~~~console +# crm_verify -VL +# echo $? +0 +~~~ + +FR 4. vérifier que ces ressources ont bien été créées et démarrées +FR +4. verify that the resources have been created and started + +~~~console +# pcs status +[...] +3 nodes configured +3 resources configured + +Online: [ hanode1 hanode2 hanode3 ] + +Full list of resources: + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode3 +[...] +~~~ + +FR 5. afficher la configuration des agents de fencing +FR +5. display the configuration of the fencing agents + +~~~ +# pcs stonith show --full + Resource: fence_vm_hanode1 (class=stonith type=fence_virsh) + Attributes: identity_file=/root/.ssh/id_rsa ipaddr=10.20.30.1 login=ioguix login_timeout=15 pcmk_host_check=static-list pcmk_host_list=hanode1 pcmk_reboot_action=reboot port=paf_3n-vip_hanode1 + Operations: monitor interval=60s (fence_vm_hanode1-monitor-interval-60s) + Resource: fence_vm_hanode2 (class=stonith type=fence_virsh) + Attributes: identity_file=/root/.ssh/id_rsa ipaddr=10.20.30.1 login=ioguix login_timeout=15 pcmk_host_check=static-list pcmk_host_list=hanode2 pcmk_reboot_action=reboot port=paf_3n-vip_hanode2 + Operations: monitor interval=60s (fence_vm_hanode2-monitor-interval-60s) + Resource: fence_vm_hanode3 (class=stonith type=fence_virsh) + Attributes: identity_file=/root/.ssh/id_rsa ipaddr=10.20.30.1 login=ioguix login_timeout=15 pcmk_host_check=static-list pcmk_host_list=hanode3 pcmk_reboot_action=reboot port=paf_3n-vip_hanode3 + Operations: monitor interval=60s (fence_vm_hanode3-monitor-interval-60s) +~~~ + +FR 6. vérifier dans les log que ces ressources sont bien surveillée par `LRMd` +FR +FR Les log ont été remis en forme. +FR +6. verify that the resources are supervized by `LRMd` in the logs + +Note: These logs have been reformatted. + +~~~ +lrmd: debug: executing - rsc:fence_vm_hanode1 action:monitor call_id:7 +lrmd: debug: finished - rsc:fence_vm_hanode1 action:monitor call_id:7 exit-code:0 +crmd: info: Result of monitor operation for fence_vm_hanode1 on hanode1: 0 (ok) +~~~ + +::: + +----- + +## Scores and location constraints + +FR * pondération interne d'une ressource sur un nœud +FR * peut définir une exclusion si le score est négatif +FR * `stickiness` : score de maintien en place d'une ressource sur son nœud +FR actuel +FR * éviter d'exclure un agent de fencing de son propre nœud définitivement +FR * scores accessibles grâce à `crm_simulate` +FR +* internal weighting of a resource on a node +* can be used to define an exclusion if the score is negative +* `stickiness`: controls how much a service prefers to stay running + where it is +* avoid the definitive exclusion of a fencing agent from it's own node +* scores are accessible via `crm_simulate` + +::: notes + +FR Pacemaker se base sur la configuration et les scores des ressources pour +FR calculer l'état idéal du cluster. Le cluster choisi le nœud où une ressource à +FR le score le plus haut pour l'y placer. +FR +Pacemaker uses the configuration and the scores of the resources to infer the +ideal state of the cluster. The cluster choses the node where the resource has +the hightest score to host it. + +FR Les scores peuvent être positionnés comme: +FR +FR * contraintes de localisation ; +FR * [contraintes de colocation][Contraintes de colocation] ; +FR * attributs: +FR * [`resource-stickiness`][Méta-attributs des ressources] du cluster ou des +FR ressources ; +FR * [`symetric-cluster`][Cluster symétrique et asymétrique] du cluster ; +FR +The score can be positionned as: + +* location constraints; +* [colocation constraints][Colocation constraints]; +* attributes: + - ['resource-stickiness`][Resource meta-attributes] of the cluster or + resources; + - [`symetric-clustre`][Symetric and asymetric clusters] of the cluster. + +FR Ils sont aussi être manipulés tout au long de la vie du cluster. Eg.: +FR +FR * [bascule][Détail d'un switchover] effectuée par l'administrateur : +FR * ban : place un score de localisation de `-INFINITY` sur le nœud courant ; +FR * move : place un score de localisation de `+INFINITY` sur le nœud cible ; +FR * les ressources agents pour désigner l'instance primaire grâce à un score de +FR localisation du rôle `master`. +FR +They are also changed during the cluster normal operation: + +* [switchover][Details of a switchover]: + - `ban`: places a `-INFINITY` location score on the current node; + - `move`: places a `+INFINITY` location score on the target node; +* multi-state resource agent chose the primary instance thanks to a location + score for the `master` role. + +FR Si pacemaker n'a pas d'instruction ou si les contraintes de localisation ont le +FR même score alors pacemaker tente de répartir équitablement les ressources parmi +FR les nœuds candidats. Ce comportement peut placer vos ressource de façon plus ou +FR moins aléatoire. Un score négatif empêche le placement d'une ressource sur un nœud. +FR +If pacemaker as no instruction or if the location constraints have the same +score then Pacemaker tries to allocate the resource equally between the +candidate nodes. A negative score prevents the placement of a resource on a +node. + +FR Les scores `+INFINITY` et `-INFINITY` permettent de forcer une ressource à +FR rejoindre ou quitter un nœud de manière inconditionnelle. Voici l'arithmétique +FR utilisée avec `INFINITY`: +FR +The `+INFINITY` and `-INFINITY` scores are used to force a resource to join or +quit a node unconditionnally. The arithmetic rules for score involving +`INFINITY` are: + +~~~ +INFINITY =< 1000000 +Any value + INFINITY = INFINITY +Any value - INFINITY = -INFINITY +INFINITY - INFINITY = -INFINITY +~~~ + +FR Si un nœud est sorti momentanément du cluster, par défaut ses ressources sont +FR déplacées vers d'autres nœuds. Lors de sa réintroduction, les contraintes de +FR localisation définies peuvent provoquer une nouvelle bascule des ressources si +FR les scores y sont supérieurs ou égaux à ceux présents sur les autres nœuds. La +FR plus part du temps, il est préférable d'éviter de déplacer des ressources qui +FR fonctionnent correctement. C'est particulièrement vrai pour les base de données +FR dont le temps de bascule peut prendre plusieurs secondes. +FR +If a node is momentarily excluded from a cluster, by default it's resource are +moved to nother node. During it's reintroduction, the location contraints of +the node can provoque another switchover of the resources if they are higher or +equal to those present on the other nodes. Most of the time, it's preferable to +avoid moving resources who are in are working properly. It's especially true +for databases where the switchover can last for several seconds. + +FR Le paramètre `stickiness` permet d'indiquer à pacemaker à quel point une +FR ressource en bonne santé préfère rester où elle se trouve. Pour cela la valeur +FR du paramètre `stickiness` est additionnée au score de localisation de la +FR ressource sur le nœud courant et comparé aux scores sur les autres nœuds pour +FR déterminer le nœud "idéal". Ce paramètre peut être défini globalement ou par +FR ressource. +FR +The `stickiness` parameter is designed to tell Pacemaker how much a resource in +good health prefers to stay where she is running. To archive this effect, the +valeur of the `stickiness` parameter is added to the location score of the +resource on the current node and compared to the scores og the other nodes to +infer the ideal node. This parameter can be set cluster wide or for a per +resource + +FR Les scores de localisation sont aussi utilisés pour positionner les ressources +FR de fencing. Vous pouvez les empêcher d'être exécutées depuis un nœud en +FR utilisant un score d'exclusion de `-INFINITY`. Cette ressource ne sera alors ni +FR supervisée, ni exécutée depuis ce nœud. Une telle configuration est souvent +FR utilisée pour empêcher une ressource de fencing d'être priorisée ou déclenchée +FR depuis le nœud qu'elle doit isoler. Néanmoins, il n'est pas recommandé +FR d'empêcher ce comporter à tout prix. Un score négatif reste une bonne +FR pratique, mais il est préférable d'autoriser le fencing d'un nœud depuis lui +FR même, en dernier recours. +FR +FR Enfin, les scores sont consultables grâce à l'outil `crm_simulate`. +FR + +The location constraints are also used to position the fencing resources. It's +possible to forbid them from being executed from a node with an exclusion score +of `-INFINITY`. In that case the resource will no be supervised or executed on +the node. Such a configuration is often used to prevent a fencing resource +from being chosen or used from the node it's supposed to isolate. Nevertheless, +it's not recommended to forbid this behavior at all cost. A negative score is +still an accepted practice, event if it's advise to let a fencing agent run on +the node it's tasked to fence. + +Finally, these scores are visible thanks to the `crm_simulate` tool. + +::: + +----- + +### Practical work: Location constraint creation + +::: notes + +FR 1. afficher les scores au sein du cluster +FR +FR Noter quel nœud est responsable de chaque ressource de fencing +FR +FR 2. positionner les stickiness de toutes les ressources à `1` +FR 3. comparer l'évolution des scores +FR 4. ajouter des contraintes d'exclusion pour que chaque ressource de fencing +FR évite le nœud dont il est responsable. Utiliser un poids de 100 pour ces +FR contraintes. +FR 5. observer les changements de placement et de score par rapport à l'état +FR précédent +FR 6. afficher les contraintes existantes à l'aide de `pcs` +FR +1. display the score + +Check which node is responsible for each fencing resource. + +2. configure the stickiness of all resources to value of `1` +3. compare the evolution of the scores +4. add exclusion constraits to prevent each fencing resource from running on + the node it's tasked to fence. Use a weight of 100 for these constraints. +5. watch out for the modification of the placement and score compared to the + previous state +6. display the existing constraints with `pcs` + +::: + +----- + +### Correction: Location constraint creation + +::: notes + +FR 1. afficher les scores au sein du cluster +FR +1. display the score + +~~~console +# crm_simulate --show-scores --live-check + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode3 + +Allocation scores: +native_color: fence_vm_hanode1 allocation score on hanode1: 0 +native_color: fence_vm_hanode1 allocation score on hanode2: 0 +native_color: fence_vm_hanode1 allocation score on hanode3: 0 +native_color: fence_vm_hanode2 allocation score on hanode1: 0 +native_color: fence_vm_hanode2 allocation score on hanode2: 0 +native_color: fence_vm_hanode2 allocation score on hanode3: 0 +native_color: fence_vm_hanode3 allocation score on hanode1: 0 +native_color: fence_vm_hanode3 allocation score on hanode2: 0 +native_color: fence_vm_hanode3 allocation score on hanode3: 0 + +Transition Summary: +~~~ + +FR Ici, `fence_vm_hanode1` est surveillé depuis `hanode1`, `fence_vm_hanode2` +FR depuis `hanode2` et `fence_vm_hanode3` depuis `hanode3`. +FR +Here, `fence_vm_hanode1` is monitored from `hanode1`, `fence_vm_hanode2` from +`hanode2` and `fence_vm_hanode3` from `hanode3`. + +FR 2. positionner les stickiness de toutes les ressources à `1` +FR +2. configure the stickiness of all resources to value of `1` + +~~~console +# pcs resource defaults resource-stickiness=1 +~~~ + +FR 3. comparer l'évolution des scores +FR +3. compare the evolution of the scores +~~~console +# crm_simulate -sL +[...] +Allocation scores: +native_color: fence_vm_hanode1 allocation score on hanode1: 1 +native_color: fence_vm_hanode1 allocation score on hanode2: 0 +native_color: fence_vm_hanode1 allocation score on hanode3: 0 +native_color: fence_vm_hanode2 allocation score on hanode1: 0 +native_color: fence_vm_hanode2 allocation score on hanode2: 1 +native_color: fence_vm_hanode2 allocation score on hanode3: 0 +native_color: fence_vm_hanode3 allocation score on hanode1: 0 +native_color: fence_vm_hanode3 allocation score on hanode2: 0 +native_color: fence_vm_hanode3 allocation score on hanode3: 1 +~~~ + +FR Le score de chaque ressource a augmenté de `1` pour le nœud sur lequel +FR elle est "démarrée". +FR +The score for each resource is increased by `1` on the node where it's started. + +FR 4. ajouter des contraintes d'exclusion pour que chaque ressource de fencing +FR évite le nœud dont il est responsable. Utiliser un poids de 100 pour ces +FR contraintes. +FR +4. add exclusion constraits to prevent each fencing resource from running on + the node it's tasked to fence. Use a weight of 100 for these constraints. + +~~~console +# pcs constraint location fence_vm_hanode1 avoids hanode1=100 +# pcs constraint location fence_vm_hanode2 prefers hanode2=-100 +# pcs constraint location fence_vm_hanode3 avoids hanode3=100 +~~~ + +FR Notez que les deux syntaxes proposées sont équivalentes du point de vue du +FR résultat dans la CIB. +FR +Note that the two syntaxes are equivalent from the point of view of the result +in the CIB. + +~~~ +# cibadmin -Q --xpath='//rsc_location' +~~~ + +FR 5. observer les changements de placement et de score par rapport à l'état +FR précédent +FR +5. watch out for the modification of the placement and score compared to the + previous state + +~~~console +# crm_simulate -sL + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + +Allocation scores: +native_color: fence_vm_hanode1 allocation score on hanode1: -100 +native_color: fence_vm_hanode1 allocation score on hanode2: 1 +native_color: fence_vm_hanode1 allocation score on hanode3: 0 +native_color: fence_vm_hanode2 allocation score on hanode1: 1 +native_color: fence_vm_hanode2 allocation score on hanode2: -100 +native_color: fence_vm_hanode2 allocation score on hanode3: 0 +native_color: fence_vm_hanode3 allocation score on hanode1: 1 +native_color: fence_vm_hanode3 allocation score on hanode2: 0 +native_color: fence_vm_hanode3 allocation score on hanode3: -100 + +Transition Summary: +~~~ + +FR Chaque ressource a changé de nœud afin de ne plus résider sur celui qu'elle +FR doit éventuellement isoler. +FR +FR Un score négatif de `-100` correspondant à la contrainte créée est positionné +FR pour chaque ressource sur le nœud qu'elle doit éventuellement isoler. +FR + +Each resource has changed node in order to avoid being hosted on the node they are +tasked to isolate. A negative score of `-100` corresponding to the constraint +is positionned for each resource on the relevant node. + +FR 6. afficher les contraintes existantes à l'aide de `pcs` +FR +6. display the existing constraints with `pcs` + +~~~console +# pcs constraint location show +Location Constraints: + Resource: fence_vm_hanode1 + Disabled on: hanode1 (score:-100) + Resource: fence_vm_hanode2 + Disabled on: hanode2 (score:-100) + Resource: fence_vm_hanode3 + Disabled on: hanode3 (score:-100) + +# pcs constraint location show nodes +Location Constraints: + Node: hanode1 + Not allowed to run: + Resource: fence_vm_hanode1 (location-fence_vm_hanode1-hanode1--100) Score: -100 + Node: hanode2 + Not allowed to run: + Resource: fence_vm_hanode2 (location-fence_vm_hanode2-hanode2--100) Score: -100 + Node: hanode3 + Not allowed to run: + Resource: fence_vm_hanode3 (location-fence_vm_hanode3-hanode3--100) Score: -100 + +# pcs constraint location show resources fence_vm_hanode1 +Location Constraints: + Resource: fence_vm_hanode1 + Disabled on: hanode1 (score:-100) +~~~ + +::: + +----- + +## Création d'une ressource + +* nécessite: + * un identifiant + * le type/fournisseur/_RA_ à utiliser +* et éventuellement: + * les paramètres propres à l'agent + * le paramétrage de [Méta-attributs des ressources] + * une configuration propre à chaque opérations +* détails sur les timeouts + +::: notes + +Chaque ressource créée au sein du cluster doit avoir un identifiant unique à +de votre choix. + +Vous devez ensuite indiquer le _resource agent_ adapté à la ressource que vous +souhaitez intégrer dans votre cluster. Ce dernier est indiqué dans le format +`type:nom` ou `type:fournisseur:nom`, par exemple: `systemd:pgbouncer` +ou `ocf:heartbeat:Dummy`. La liste complète est disponible grâce à la commande +`pcs resource list`. + +Voici un exemple simple de création d'une ressource avec `pcs`: + +~~~console +# pcs resource create identifiant_resource type:fournisseur:nom +~~~ + +Ensuite Chaque _resource agent_ peut avoir des paramètres de configuration +propre à sa ressource, un nom d'utilisateur par exemple. Avec `pcs`, ces +paramètres sont à préciser librement à la suite de la commande de base, par +exemple: + +~~~console +# pcs resource create identifiant_resource type:fournisseur:nom \ + user=nom_user_resource +~~~ + +Pour rappel, la liste des paramètres supportés par un _resource agent_ est +disponible grâce à la commande suivante: + +~~~console +# pcs resource describe +~~~ + +Comme détaillé dans le chapitre [Méta-attributs des ressources][], les +ressources ont en commun un certain nombre de méta-attributs qui peuvent être +modifiés pour chaque ressource. La commande `pcs` utilise le mot clé `meta` +pour les distinguer sur la ligne de commande des autres paramètres. Par +exemple, nous pouvons positionner `migration-threshold=1` sur une ressource +afin qu'elle soit migrée sur un autre nœud dès la première erreur: + +~~~console +# pcs resource create identifiant_resource type:fournisseur:nom \ + user=nom_user_resource \ + meta migration-threshold=1 +~~~ + +Enfin, un certain nombre de paramètres peuvent être modifiés pour chaque +opération supportée par le _RA_. Les plus fréquents sont `timeout`et +`interval`. Vous trouverez la liste complète à l'adresse suivante: + + +Concernant le timeout par exemple, ce dernier est de 20 secondes par défaut +pour toutes les opérations. Cette valeur par défaut peut être modifiée dans la +section `op_defaults` de la CIB, avec l'une ou l'autre de ces commandes: + +~~~ +crm_attribute --type op_defaults --name timeout --update 20s +pcs resource op defaults timeout=20s +~~~ + +Avec la commande `pcs` nous utilisons le mot clé `op ` pour définir +le paramétrage des différentes opérations. Le paramétrage pour ces actions +surcharge alors les valeurs par défaut. Voici un exemple: + +~~~ +# pcs resource create identifiant_resource type:fournisseur:nom \ + user=nom_user_resource \ + meta migration-threshold=1 \ + op start timeout=60s + op monitor timeout=10s interval=10s +~~~ + +__ATTENTION__: les valeurs par défaut exposées par les _RA_ sont des valeurs +__recommandées__. Elles ne sont pas appliquées automatiquement. Préciser les +timeouts de chaque action lors de la définition d'une ressource est recommandé +même s'ils sont identiques à la valeur par défaut. Cette pratique aide à la +compréhension rapide de la configuration d'un cluster. + +Les _resource agent_ n'ont pas à se préoccuper des timeout de leurs actions. +Tout au plus, ces agents peuvent indiquer des timeout par défaut à titre de +recommandation seulement. Il reste à la charge de l'administrateur de définir +les différents timeout en tenant compte de cette recommandation. + +Le daemon `execd`, qui exécute l'action, se charge d'interrompre une action dès +que son timeout est atteint. Habituellement, le cluster planifie alors des +actions palliatives à cette erreur (eg. _recovery_ ou _failover_). + +::: + +----- + +### TP: création d'une ressource dans le cluster + +::: notes + +Création d'une première ressource "Dummy". Ce _resource agent_ existe +seulement à titre de démonstration et d'expérimentation. + +1. afficher les détails de l'agent Dummy +2. créer le sous-répertoire `/opt/sub` sur les 3 nœuds. +3. créer une ressource `dummy1` utilisant le _RA_ Dummy + +Il est possible de travailler sur un fichier XML offline en précisant +l'argument `-f /chemin/vers/xml` à la commande `pcs`. Utiliser un fichier +`dummy1.xml` pour créer la ressource et ses contraintes en une seule +transition. + +* positionner le paramètre `state` à la valeur `/opt/sub/dummy1.state` +* vérifier son état toutes les 10 secondes +* positionner son attribut `migration-threshold` à `3` +* positionner son attribut `failure-timeout` à `4h` +* positionner un `stickiness` faible de `1` +* ajouter une forte préférence de `100` pour le nœud hanode1 + +Tout ce paramétrage doit être en surcharge des éventuelles valeurs par +défaut du cluster. + +4. contrôler le contenu du fichier `dummy1.xml` et simuler son application + avec `crm_simulate` +5. publier les modifications dans le cluster +6. consulter les logs du DC +7. observer les changements opérés + +::: + +----- + +### Correction: création d'une ressource dans le cluster + +::: notes + + +1. afficher les détails de l'agent Dummy + +~~~console +# pcs resource describe ocf:pacemaker:Dummy +~~~ + +2. créer le sous-répertoire `/opt/sub` sur les 3 nœuds. + +Sur chaque nœud: + +~~~console +# mkdir -p /opt/sub +~~~ + +3. créer une ressource `dummy1` utilisant le _RA_ Dummy + +~~~console +# pcs cluster cib dummy1.xml + +# pcs -f dummy1.xml resource create dummy1 ocf:pacemaker:Dummy \ + state=/opt/sub/dummy1.state \ + op monitor interval=10s \ + meta migration-threshold=3 \ + meta failure-timeout=4h \ + meta resource-stickiness=1 + +# pcs -f dummy1.xml constraint location dummy1 prefers hanode1=100 +~~~ + +4. contrôler le contenu du fichier `dummy1.xml` et simuler son application +avec `crm_simulate` + +Contrôle de la syntaxe: + +~~~console +# crm_verify -V --xml-file dummy1.xml +# pcs cluster verify -V dummy1.xml # alternative avec pcs +~~~ + +Simuler ces modifications: + +~~~ +# crm_simulate --simulate --xml-file dummy1.xml + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + dummy1 (ocf::pacemaker:Dummy): Stopped + +Transition Summary: + * Start dummy1 ( hanode1 ) + +Executing cluster transition: + * Resource action: dummy1 monitor on hanode3 + * Resource action: dummy1 monitor on hanode2 + * Resource action: dummy1 monitor on hanode1 + * Resource action: dummy1 start on hanode1 + * Resource action: dummy1 monitor=10000 on hanode1 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + dummy1 (ocf::pacemaker:Dummy): Started hanode1 +~~~ + +Nous observons dans cette sortie: + +* l'état du cluster avant la transition (`Current cluster status`) +* les actions à réaliser (`Transition Summary` et `Executing cluster transition`) +* l'état attendu du cluster après transition (`Revised cluster status`) + +5. publier les modifications dans le cluster + +~~~ +# pcs cluster cib-push dummy1.xml +~~~ + +6. consulter les logs du DC + +Les log ont été remis en forme. + +Actions prévues par `pengine`: + +~~~ +pengine: info: RecurringOp: Start recurring monitor (10s) for dummy1 on hanode1 +pengine: info: LogActions: Leave fence_vm_hanode1 (Started hanode2) +pengine: info: LogActions: Leave fence_vm_hanode2 (Started hanode1) +pengine: info: LogActions: Leave fence_vm_hanode3 (Started hanode1) +pengine: notice: LogAction: * Start dummy1 ( hanode1) +pengine: notice: Calculated transition 21, saving in /.../pengine/pe-input-11.bz2 +~~~ + +Actions initiées par `crmd`: + +~~~ +crmd: info: Processing graph 21 derived from /var/.../pengine/pe-input-11.bz2 +crmd: notice: Initiating monitor operation dummy1_monitor_0 on hanode3 | action 6 +crmd: notice: Initiating monitor operation dummy1_monitor_0 on hanode2 | action 5 +crmd: notice: Initiating monitor operation dummy1_monitor_0 locally on hanode1 | action 4 +crmd: info: Action dummy1_monitor_0 (5) confirmed on hanode2 (rc=7) +crmd: info: Action dummy1_monitor_0 (6) confirmed on hanode3 (rc=7) +crmd: info: Action dummy1_monitor_0 (4) confirmed on hanode1 (rc=7) +crmd: notice: Result of probe operation for dummy1 on hanode1: 7 (not running) + +crmd: notice: Initiating start operation dummy1_start_0 locally on hanode1 +lrmd: info: executing - rsc:dummy1 action:start call_id:26 +lrmd: info: finished - rsc:dummy1 action:start call_id:26 exit-code:0 +crmd: notice: Result of start operation for dummy1 on hanode1: 0 (ok) + +crmd: notice: Initiating monitor operation dummy1_monitor_10000 locally on hanode1 +lrmd: debug: executing - rsc:dummy1 action:monitor call_id:27 +~~~ + +Les actions `dummy1_monitor_0` vérifient que la ressource n'est démarrée pas +démarrée sur le nœud concerné. Ensuite, la ressource est démarrée sur +`hanode1` avec l'opération `dummy1_start_0`. Puis l'action de surveillance +`dummy1_monitor_10000` récurrente toutes les 10 secondes (`10000`ms) est +démarrée. + +7. observer les changements + +~~~console +# pcs status +# pcs config show +~~~ + +::: + +----- + +## Contraintes de colocation + +* définit un lien entre plusieurs ressources +* la force du lien est définie par un score qui s'ajoute aux scores existant +* peut être un lien de colocalisation ou d'exclusion + * Par exemple une VIP là où la ressource doit être démarrée +* attention à l'ordre de déclaration ! + +::: notes + +Les contraintes de colocation servent à indiquer à Pacemaker où une ressource _A_ doit +être placée par rapport à une ressource _B_. Elles permettent de localiser deux ressources +au même endroit ou à des endroits différents (exclusion). + +L'ordre des déclarations est important car cela implique que la ressource _A_ sera +assignée à un nœud après la ressource _B_. Cela implique que la contrainte de +localisation placée sur la ressource _B_ décide du placement de la ressource _A_. + +Ces contraintes n'ont pas d'impact sur l'[ordre de démarrage][Contraintes d'ordre]. + +Dans le cas de PAF, il faut utiliser une contrainte de colocation pour que la VIP +soit montée sur le même nœud que le master. + +[Explication](http://clusterlabs.org/doc/Colocation_Explained.pdf) + +::: + +----- + +### TP: création des _RA_ (dummy2) dans le cluster + + +::: notes + +1. ajouter une ressource `dummy2` + +Utiliser un fichier `dummy2.xml` pour préparer les actions. + +* positionner le paramètre `state` à la valeur `/opt/sub/dummy2.state` +* vérifier son état toutes les 10 secondes +* positionner son attribut `migration-threshold` à `3` +* positionner son attribut `failure-timeout` à `4h` +* positionner un `stickiness` élevé de `100` +* interdire la ressource de démarrer sur le même nœud que `dummy1` +* ajouter une faible préférence de `10` pour le nœud hanode2 + +Note : il est important d'utiliser un fichier xml pour appliquer les contraintes de localisation avant de démarrer la +ressource + +4. contrôler le contenu du fichier `dummy2.xml` et simuler son application +5. publier les modifications dans le cluster +6. observer les changements + +::: + +----- + +### Correction: création des _RA_ (dummy2) dans le cluster + +::: notes + + +1. ajouter une ressource `dummy2` + +~~~console +# pcs cluster cib dummy2.xml + +# pcs -f dummy2.xml resource create dummy2 ocf:pacemaker:Dummy \ + state=/opt/sub/dummy2.state \ + op monitor interval=10s \ + meta migration-threshold=3 \ + meta failure-timeout=4h \ + meta resource-stickiness=100 + +# pcs -f dummy2.xml constraint location dummy2 prefers hanode2=10 + +# pcs -f dummy2.xml constraint colocation add dummy2 with dummy1 -INFINITY +~~~ + +4. contrôler le contenu du fichier `dummy2.xml` et simuler son application + +~~~console +# pcs cluster verify -V dummy2.xml +# crm_simulate -S -x dummy2.xml + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + dummy1 (ocf::pacemaker:Dummy): Started hanode1 + dummy2 (ocf::pacemaker:Dummy): Stopped + +Transition Summary: + * Start dummy2 ( hanode3 ) + +Executing cluster transition: + * Resource action: dummy2 monitor on hanode3 + * Resource action: dummy2 monitor on hanode2 + * Resource action: dummy2 monitor on hanode1 + * Resource action: dummy2 start on hanode3 + * Resource action: dummy2 monitor=10000 on hanode3 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + dummy1 (ocf::pacemaker:Dummy): Started hanode1 + dummy2 (ocf::pacemaker:Dummy): Started hanode3 +~~~ + +Ici, `pengine` a prévu de démarrer `dummy2` sur `hanode3`. + +5. publier les modifications dans le cluster + +~~~console +# pcs cluster cib-push dummy2.xml +~~~ + +6. observer les changements opérés + +~~~console +# crm_mon -Dn +# pcs status +# pcs config show +~~~ + +::: + +----- + +## Contraintes d'ordre + +* concerne des ressources liées +* déclaration de l'ordre de déclenchement des actions + * `stop` + * `start` + * `promote` + * `demote` +* ordre obligatoire, optionnel ou sérialisé +* symétrique ou asymétrique + +::: notes + +Ce type de contrainte peut être nécessaire pour spécifier l'ordre de +déclenchement des actions. Par exemple, le déplacement d'une IP virtuelle une +fois que le service a été déplacé sur un autre nœud. + +Il existe trois type différents, précisé par l'attribut `kind` : + +* `Mandatory`: la seconde action n'est pas exécutée tant que la première + action n'a pas réussi +* `Optional`: les deux actions peuvent être exécutées indépendamment, mais +respecterons l'ordre imposé si elles doivent l'être dans la même transition +* `Serialize`: les actions ne doivent pas être exécutées en même temps par + le cluster. L'ordre importe peu ici. + +Si une contrainte d'ordre est symétrique (attribut `symmetrical`), elle +s'applique aussi pour les actions opposées, mais dans l'ordre inverse. + +::: + + +----- + +### TP: Contrainte d'ordre + +::: notes + +Il est recommandé de conserver un terminal avec un `crm_mon` actif tout au long +de ce TP. + +1. créer une contrainte d'ordre non symétrique qui force le démarrage de +`dummy1` avant celui de `dummy2` +2. arrêter la ressource `dummy1` et observer l'influence sur `dummy2` +3. arrêter la ressource `dummy2`, puis démarrer `dummy2` +4. démarrer `dummy1` +5. vérifiez dans les log __du DC__ l'ordre des actions + +::: + +----- + +### Correction: Contrainte d'ordre + +::: notes + +Il est recommandé de conserver un terminal avec un `crm_mon` actif tout au long +de ce TP. + +1. créer une contrainte d'ordre non symétrique qui force le démarrage de + `dummy1` avant celui de `dummy2` + +~~~console +# pcs constraint order start dummy1 then start dummy2 symmetrical=false kind=Mandatory +Adding dummy1 dummy2 (kind: Mandatory) (Options: first-action=start then-action=start symmetrical=false) +~~~ + +2. arrêter la ressource `dummy1` et observer l'influence sur `dummy2` + +~~~console +# pcs resource disable dummy1 +~~~ + +La ressource `dummy2` ne s'arrête pas. La contrainte ne concerne que le +démarrage des deux ressources. + +3. arrêter la ressource `dummy2`, puis démarrer `dummy2` + +~~~console +# pcs resource disable --wait dummy2 +# pcs resource enable dummy2 +~~~ + +La ressource `dummy2` ne démarre pas. Cette dernière ne peut démarrer +qu'après le démarrage de `dummy1`, mais cette dernière est arrêtée. + +4. démarrer `dummy1` + +~~~console +# pcs resource enable dummy1 +~~~ + +Les deux ressources démarrent. + +5. vérifiez dans les log __du DC__ l'ordre des actions + +Les log ont été remis en forme. + +~~~console +# grep 'dummy._start.*confirmed' /var/log/cluster/corosync.log +crmd: info: Action dummy1_start_0 (48) confirmed on hanode1 (rc=0) +crmd: info: Action dummy2_start_0 (50) confirmed on hanode3 (rc=0) +~~~ + +L'ordre des action est précisé par leur ID, ici 48 et 50. Il est possible +d'aller plus loin avec `crm_simulate` et ses options `-S`, `-G` et `-x` en +indiquant la transition produite par `pengine` dans le répertoire +`/var/lib/pacemaker/pengine`. Cette commande et analyse est laissée à +l'exercice du lecteur. + +::: + + +----- + +## Regroupement de ressources + +* "group" : regroupement de ressources liées ("primitives") +* simplification de déclaration de contraintes de "colocation" +* sont démarrées dans l'ordre de déclaration +* sont arrêtées dans l'ordre inverse de déclaration +* une impossibilité de démarrer une ressource affecte les ressources + suivantes dans le groupe + +::: notes + +La notion de groupe est un raccourcis syntaxique qui permet de simplifier les +déclarations en regroupant les contraintes d'un ensemble de ressources. + +Les attributs d'un groupe permettent notamment de définir la priorité et le +rôle du group ou encore de mettre l'ensemble du groupe en maintenance. + +La `stickiness` d'un groupe correspond à la somme des `stickiness` des ressources +présentes dans ce groupe. + +Dans le cas de PAF, on utilise un groupe pour rassembler la ressource PostgreSQL +master et la VIP. + +::: + +----- + +### TP: groupe de ressource + +::: notes + +1. créer une ressource `dummy3` + +Utiliser un fichier `dummy3.xml` pour préparer les actions. + +* positionner le paramètre `state` à la valeur `/opt/sub/dummy3.state` +* vérifier son état toutes les 10 secondes +* positionner son attribut `migration-threshold` à `3` +* positionner son attribut `failure-timeout` à `4h` +* positionner un `stickiness` élevé de `100` + +2. créer un group `dummygroup` qui regroupe les ressources `dummy3` et + `dummy2` dans cet ordre +3. créer une contrainte d'ordre qui impose de démarrer `dummy1` avant `dummy3` +4. créer une contrainte d'exclusion entre `dummygroup` et `dummy1` d'un score + de `-1000` +5. appliquer les modifications au cluster +6. désactiver les ressources `dummy1`, `dummy2` et `dummy3`, puis les + réactiver en même temps +7. observer l'ordre choisi par pengine pour le démarrage de l'ensemble des ressources + +::: + +----- + +### Correction: groupe de ressource + +::: notes + +1. créer une ressource `dummy3` + +~~~console +# pcs cluster cib dummy3.xml + +# pcs -f dummy3.xml resource create dummy3 ocf:pacemaker:Dummy \ + state=/opt/sub/dummy3.state \ + op monitor interval=10s \ + meta migration-threshold=3 \ + meta failure-timeout=4h \ + meta resource-stickiness=100 +~~~ + +2. créer un group `dummygroup` qui regroupe les ressources `dummy3` et `dummy2` dans cet ordre + +~~~console +# pcs -f dummy3.xml resource group add dummygroup dummy3 dummy2 +~~~ + +3. créer une contrainte d'ordre qui impose de démarrer `dummy1` avant `dummy3` + +~~~console +# pcs -f dummy3.xml constraint order start dummy1 then start dummy3 symmetrical=false kind=Mandatory +Adding dummy1 dummy3 (kind: Mandatory) (Options: first-action=start then-action=start symmetrical=false) +~~~ + +4. créer une contrainte d'exclusion entre `dummygroup` et `dummy1` d'un score + de `-1000` + +~~~console +# pcs -f dummy3.xml constraint colocation add dummygroup with dummy1 -1000 +~~~ + +5. appliquer les modifications au cluster + +~~~console +# pcs cluster verify -V dummy3.xml +# crm_simulate -S -x dummy3.xml + +# pcs cluster cib-push dummy3.xml +CIB updated +~~~ + +6. désactiver les ressources `dummy1`, `dummy2` et `dummy3`, puis les + réactiver en même temps + +~~~ +# pcs resource disable --wait dummy1 dummy2 dummy3 +# pcs resource enable dummy1 dummy2 dummy3 +~~~ + +7. observer l'ordre choisi par pengine pour le démarrage de l'ensemble des ressources + +Les ressources sont démarrés dans l'ordre suivant: `dummy1`, `dummy3` puis +`dummy2`. Les log ont été remis en forme. + +~~~ +# grep 'dummy._start.*confirmed' /var/log/cluster/corosync.log +crmd: info: Action dummy1_start_0 (10) confirmed on hanode1 (rc=0) +crmd: info: Action dummy3_start_0 (12) confirmed on hanode3 (rc=0) +crmd: info: Action dummy2_start_0 (14) confirmed on hanode3 (rc=0) +~~~ + +::: + +----- + +### TP: failcounts + +::: notes + +Nous provoquons dans ce TP une défaillance pour travailler dessus. + +1. renommer `/opt/sub` en `/opt/sub2` sur le nœud hébergeant `dummy1` + +Attendre que le cluster réagisse à la défaillance. + +2. observer le failcount de `dummy1` avec `crm_failcount` ou `pcs` +3. chercher dans les log les causes de cette valeur +4. réparer le problème sur `hanode1` et réinitialiser le failcount avec `pcs` +5. expliquer le comportement de `dummy1` + +Conseil: observer les scores. + +::: + +----- + +### Correction: failcounts + +::: notes + +1. renommer `/opt/sub` en `/opt/sub2` sur le nœud hébergeant `dummy1` + +Observer le cluster et ses réactions dans un terminal à l'aide de `crm_mon`: + +~~~console +# crm_mon -Dnf +~~~ + +Renommer le répertoire pour provoquer une défaillance: + +~~~console +# mv /opt/sub /opt/sub2 +~~~ + +Attendre que le cluster réagisse à la défaillance. + +2. observer le failcount de `dummy1` avec `crm_failcount` ou `pcs` + +~~~console +# crm_failcount -r dummy1 -N hanode1 -G +scope=status name=fail-count-dummy1 value=INFINITY + +# crm_failcount -r dummy1 -N hanode3 -G +scope=status name=fail-count-dummy1 value=0 + +# pcs resource failcount show dummy1 +Failcounts for dummy1 +hanode1: INFINITY +~~~ + +3. chercher dans les log les causes de cette valeur + +Rechercher dans les log du DC les mots clé `failcount` et `dummy1` pour +identifier les messages relatifs à cette activité. Ci-après une explication +des log remis en forme. + +Détection de l'erreur lors d'une opération `monitor` et incrément du +failcount pour la ressource sur le nœud où elle se situe: + +~~~ +crmd: info: Updating failcount for dummy1 on hanode1 after failed monitor: rc=7 (update=value++) +attrd: info: Expanded fail-count-dummy1#monitor_10000=value++ to 1 +attrd: info: Setting fail-count-dummy1#monitor_10000[hanode1]: (null) -> 1 +~~~ + +Calcul d'une transition afin de rétablir un état stable du cluster. Le +sous-processus `pengine` prévoit de redémarrer `dummy1` sur son nœud courant: + +~~~ +pengine: info: Start recurring monitor (10s) for dummy1 on hanode1 +pengine: notice: * Recover dummy1 ( hanode1) +pengine: info: Leave dummy3 (Started hanode2) +pengine: info: Leave dummy2 (Started hanode2) +~~~ + +Ce choix dépend de la propriété `on-fail` de l'opération, à `restart` par +défaut. Pour plus de détail, voir: + + +L'action `recovery` consiste a arrêter et démarrer la ressource concernée. +Une fois l'opération `stop` réalisée, nous observons que le `start` échoue. + +~~~ +crmd: notice: te_rsc_command: Initiating stop operation dummy1_stop_0 on hanode1 +crmd: info: match_graph_event: Action dummy1_stop_0 (6) confirmed on hanode1 (rc=0) +crmd: notice: te_rsc_command: Initiating start operation dummy1_start_0 on hanode1 +crmd: warning: status_from_rc: Action 14 (dummy1_start_0) on hanode1 failed (target: 0 vs. rc: 1): Error +crmd: notice: abort_transition_graph: Transition aborted by operation dummy1_start_0 'modify' on hanode1: Event failed +crmd: info: update_failcount: Updating failcount for dummy1 on hanode1 after failed start: rc=1 (update=INFINITY) +attrd: info: attrd_peer_update: Setting fail-count-dummy1#start_0[hanode1]: (null) -> INFINITY +~~~ + +Si une opération `start` échoue, la décision du cluster dépend de deux +paramètres: `on-fail` que nous avons vu précédemment et le paramètre du +cluster `start-failure-is-fatal`, positionné à `true` par défaut. + +Ici, l'opération `start` ayant échoué, le cluster décide donc de +positionner un failcount à INFINITY à cause de `start-failure-is-fatal`. + +La ressource `dummy1` ayant un failcount infini sur `hanode1`, `pengine` +décide de déplacer la ressource sur `hanode3`: + +~~~ +pengine: info: Start recurring monitor (10s) for dummy1 on hanode3 +pengine: notice: * Recover dummy1 (hanode1 -> hanode3) +pengine: info: Leave dummy3 (Started hanode2) +pengine: info: Leave dummy2 (Started hanode2) +~~~ + +Les opérations sont réalisées sans erreurs: + +~~~ +crmd: debug: Unpacked transition 22: 3 actions in 3 synapses +[...] +crmd: notice: Initiating stop operation dummy1_stop_0 on hanode1 +crmd: info: Action dummy1_stop_0 confirmed on hanode1 (rc=0) +[...] +crmd: notice: Initiating start operation dummy1_start_0 on hanode3 +crmd: info: Action dummy1_start_0 confirmed on hanode3 (rc=0) +[...] +crmd: notice: Initiating monitor operation dummy1_monitor_10000 on hanode3 +crmd: info: Action dummy1_monitor_10000 confirmed on hanode3 (rc=0) +[...] +crmd: debug: Transition 22 is now complete +~~~ + +4. réparer le problème sur `hanode1` et réinitialiser le failcount avec `pcs` + +~~~console +# mv /opt/sub2 /opt/sub +# pcs resource failcount reset dummy1 hanode1 +~~~ + +5. expliquer le comportement de `dummy1` + +La ressource `dummy1` retourne sur le nœud `hanode1` dès que nous y +supprimons son ancien failcount. + +Effectivement, `dummy1` a été créé avec un `stickiness` à `1` et une +contrainte de location sur `hanode1` de `100`. + +~~~ +# pcs constraint location show dummy1 +Location Constraints: + Resource: dummy1 + Enabled on: hanode1 (score:100) +[...] + +# pcs resource show dummy1 + Resource: dummy1 (class=ocf provider=pacemaker type=Dummy) + Attributes: state=/opt/sub/dummy1.state + Meta Attrs: failure-timeout=4h migration-threshold=3 resource-stickiness=1 +[...] +~~~ + +Avant de retirer son failcount sur `hanode1`, ses scores étaient les suivants: + +~~~ +native_color: dummy1 allocation score on hanode1: -INFINITY +native_color: dummy1 allocation score on hanode2: -220 +native_color: dummy1 allocation score on hanode3: 1 +~~~ + +Sur `hanode1`, `dummy1` cumulait le score de location de `100` et le failcount de +`-INFINITY`, soit un total de `-INFINITY`. Le score de `1` correspondant au +stickiness sur `hanode3`. + +Après la suppression du failcount de -INFINITY, les scores sont donc devenus: + +* `100` pour `dummy1` sur `hanode1` (score de location) +* `1` pour `dummy1` sur `hanode3` (score de stickiness) + +Par conséquent `pengine` décide de déplacer `dummy1` sur le nœud où il a +le plus gros score: `hanode1`. Après migration, les scores deviennent alors: + +~~~ +native_color: dummy1 allocation score on hanode1: 101 +native_color: dummy1 allocation score on hanode2: -220 +native_color: dummy1 allocation score on hanode3: 0 +~~~ + +::: + +----- + +## Édition des ressources + +* la modification d'un paramètre provoque une réaction du cluster +* soit le redémarrage de la ressource +* soit son rechargement à chaud +* dépend de la ressource et du paramètre + +::: notes + +La configuration des ressources peut être faite avec `pcs resource update` ou +avec l'outil `crm_resource` et l'option `-s / --set-parameter` ou `-d / +--delete-parameter`. + +On distingue les paramètres de : + +* configuration propre à la ressource, les paramètres propres à chaque RA +* configuration du RA, les paramètres communs à tous les RA (modifiable avec l'option --meta) +* configuration des opérations. + +Un paramètre propre à la ressource est modifiable à chaud si: + +* l'agent supporte l'action `reload` +* ce paramètre n'est pas marqué comme étant `unique` + +::: + +----- + +### TP: modification paramètre avec reload ou restart + +::: notes + +1. afficher la description du RA `ocf:pacemaker:Dummy` +2. identifier dans la description le paramètre `fake` +3. afficher la valeur actuelle du paramètre `fake` +4. modifier la valeur de `fake` avec `test` +5. vérifier le comportement dans les traces + +Notes: utilisez `crm_resource` ou `pcs resource` + +::: + +----- + +### Correction: modification paramètre avec reload ou restart + +::: notes + +1. afficher la description du RA `ocf:pacemaker:Dummy` + +~~~console +# pcs resource describe ocf:pacemaker:Dummy +~~~ + +2. identifier dans la description le paramètre `fake` + +~~~ +[...] + fake: Fake attribute that can be changed to cause a reload +[...] +~~~ + +3. afficher la valeur actuelle du paramètre `fake` + +~~~console +# crm_resource -r dummy1 -g fake +Attribute 'fake' not found for 'dummy1' +~~~ + +4. modifier la valeur de `fake` avec `test` + +~~~console +# crm_resource -r dummy1 -p fake -v test +~~~ + +ou + +~~~console +# pcs resource update dummy1 fake=test +~~~ + +5. vérifier le comportement dans les traces + +Log du DC remis en forme: + +~~~ +pengine: info: Start recurring monitor (10s) for dummy1 on hanode1 +pengine: notice: * Reload dummy1 (hanode1) +[...] +crmd: debug: Unpacked transition 34: 2 actions in 2 synapses +[...] +crmd: notice: Initiating reload operation dummy1_reload_0 on hanode1 +crmd: info: Action dummy1_start_0 confirmed on hanode1 +[...] +crmd: notice: Initiating monitor operation dummy1_monitor_10000 on hanode1 +crmd: info: Action dummy1_monitor_10000 confirmed on hanode1 +[...] +crmd: notice: Transition 34 (Complete=2): Complete +~~~ + +Log de `hanode1`: + +~~~ +crmd: debug: Cancelling op 55 for dummy1 +lrmd: info: Cancelling ocf operation dummy1_monitor_10000 +lrmd: debug: finished - rsc:dummy1 action:monitor call_id:55 exit-code:0 +crmd: debug: Op 55 for dummy1 (dummy1:55): cancelled +[...] +crmd: info: Performing key=7:34:0:cc37b9f1-860c-4a1f-bbac-db48f7cd080a op=dummy1_reload_0 +lrmd: info: executing - rsc:dummy1 action:reload call_id:57 +lrmd: info: finished - rsc:dummy1 action:reload call_id:57 pid:13714 exit-code:0 exec-time:69ms queue-time:0ms +crmd: notice: Result of reload operation for dummy1 on hanode1: 0 (ok) +[...] +crmd: info: Performing key=3:34:0:cc37b9f1-860c-4a1f-bbac-db48f7cd080a op=dummy1_monitor_10000 +lrmd: debug: executing - rsc:dummy1 action:monitor call_id:58 +lrmd: debug: finished - rsc:dummy1 action:monitor call_id:58 pid:13722 exit-code:0 exec-time:30ms queue-time +crmd: info: Result of monitor operation for dummy1 on hanode1: 0 (ok) +~~~ + +::: + + +----- + +## Ressources _Multi-State_ + +* les ressource multi-state sont des clones avec des rôles différents +* nécessite de configurer un `monitor` distinct par rôle +* une ressource supplémentaire dédiée à la gestion des clones et leurs rôles +* nombre de clones modifiable +* les clones démarrent toujours d'abord en `Slave` +* les master score permettent de désigner le ou les clones à promouvoir + +::: notes + +Comme expliqué dans le chapitre [_Ressource Agent_ (_RA_)] il existe +plusieurs type de ressources, dont les ressources clones ou les ressources +_multi-state_. Ces derniers héritent de toutes les propriétés des ressources +clones et ajoute une notion supplémentaire de rôle primaire et secondaire +appelés respectivement `Master` et `Slave`. + +Une ressource _multi-state_ se crée en deux étapes: + +* création d'une ressource type utilisant le RA voulu +* création d'une ressource _multi-state_ qui administre la ressource précédemment + créée, la clone en fonction de sa configuration et gère les rôles parmi + ces clones. + +Particularité des ressources géré en _muti-state_, ces dernières doivent +comporter une opération `monitor` différente pour les rôles `Slave` et +`Master`, chacune avec une récurrence différente. Ce dernier point est lié à un +détail d'implémentation de Pacemaker qui identifie les opérations par un +identifiant composé: du nom de la ressource, de l'opération, de sa récurrence. +Ainsi, `pgsqld_monitor_15000` désigne l'opération `monitor` sur la ressource +`pgsqld` exécutée toute les 15 secondes. Voir: + + + +Les différents paramètres utiles à une ressource _multi-state_ sont définis dans +la documentation de Pacemaker à ces pages: + +* liés aux clones: +* liés aux _multi-state_: + +Les paramètres intéressants dans le cadre de cette formation sont: + +* `clone-max`: nombre de clones dans tous le cluster, par défaut le nombre de + nœud du cluster +* `clone-node-max`: nombre de clone maximum sur chaque nœud, par défaut à `1` +* `master-max`: nombre maximum de clone promu au sein du cluster, par défaut + à `1` +* `master-node-max`: nombre maximum de clone promu sur chaque nœud, par + défaut à `1` +* `notify`: activer les opérations `notify` si le RA le supporte, par défaut + à `false` + +Nous constatons que la plupart des valeurs par défaut sont correcte pour PAF. +Seule le paramètre `notify` doit être __obligatoire__ activé dans le cadre +de PAF. + +Enfin, tous les clones d'une ressource multi-state sont __toujours__ démarrés +avec le rôle `Slave`. Ensuite, les clones avec les _master scores_ les plus +élevés sont sélectionnés pour être promus en `Master` (voir aussi à ce propos +[Attributs de nœuds particuliers] ). + +![Diagramme démarrage ressource multi-state](medias/paf-ms-roles.png) + +Ces master scores sont positionnés le plus souvent par le RA, mais peuvent +aussi être manipulés par l'administrateur si besoin. + +::: + +----- + +::: notes + +### TP: création d'une ressource _multi-state_ + +Utiliser un fichier `dummy-ms.xml` pour effectuer vos modifications. + +1. créer une ressource `Dummyd` avec le RA `ocf:pacemaker:Stateful` + +* surveiller le rôle `Master` toutes les 5 secondes +* surveiller le rôle `slave` toutes les 6 secondes + +2. créer la ressource multi-state `Dummyd-clone` clonant `Dummyd` + +* activer les notifications +* dix clones autorisés +* deux rôles `Master` autorisés + +3. appliquer vos modifications sur le cluster +4. expliquer le nombre de clone de `Dummyd` démarrés +5. observer combien de clones ont été promus en `Master` + +::: + +----- + +### Correction: création d'une ressource _multi-state_ + +::: notes + +Utiliser un fichier `dummy-ms.xml` pour effectuer vos modifications. + +~~~console +# pcs cluster cib dummy-ms.xml +~~~ + +1. créer une ressource `Dummyd` avec le RA `ocf:pacemaker:Stateful` + +~~~console +# pcs -f dummy-ms.xml resource create Dummyd ocf:pacemaker:Stateful \ + op monitor interval=5s role="Master" \ + op monitor interval=6s role="Slave" +~~~ + +2. créer la ressource multi-state `Dummyd-clone` clonant `Dummyd` + +* activer les notifications +* dix clones autorisés +* deux rôles `Master` autorisés + +Ou, en tenant compte des valeurs par défaut: + +~~~console +# pcs -f dummy-ms.xml resource master Dummyd-clone Dummyd \ + notify=true clone-max=10 master-max=2 +~~~ + +3. appliquer vos modifications sur le cluster + +~~~console +# pcs cluster verify -V dummy-ms.xml +# crm_simulate -S -x dummy-ms.xml +# pcs cluster cib-push dummy-ms.xml +~~~ + +4. expliquer le nombre de clone de `Dummyd` démarrés + +Trois clones ont été démarrés dans le cluster. Malgré la valeur de +`clone-max=10`, le paramètre `clone-node-max` par défaut à `1` empêche d'en +démarrer plus d'un par nœud. + +~~~ +pengine: debug: Allocating up to 10 Dummyd-clone instances to a possible 3 nodes (at most 1 per host, 3 optimal) +pengine: debug: Assigning hanode3 to Dummyd:0 +pengine: debug: Assigning hanode2 to Dummyd:1 +pengine: debug: Assigning hanode1 to Dummyd:2 +pengine: debug: All nodes for resource Dummyd:3 are unavailable, unclean or shutting down +pengine: debug: Could not allocate a node for Dummyd:3 +pengine: info: Resource Dummyd:3 cannot run anywhere +[...] +pengine: debug: All nodes for resource Dummyd:9 are unavailable, unclean or shutting down +pengine: debug: Could not allocate a node for Dummyd:9 +pengine: info: Resource Dummyd:9 cannot run anywhere +pengine: debug: Allocated 3 Dummyd-clone instances of a possible 10 +~~~ + +5. observer combien de clones ont été promus en `Master` + +Deux clones ont été promus. + +Lors du démarrage des instances `Dummyd`, l'agent positionne le master score +de sa ressource à `5`. Voir la fonction `stateful_start` dans le code source +de l'agent à l'emplacement `/usr/lib/ocf/resource.d/pacemaker/Stateful`. + +Le paramètre `master-max` étant positionné à `2`, le cluster choisi deux +clones à promouvoir parmis les trois disponibles. + +::: + +----- + +## Suppression des ressources + +* `pcs resource delete` supprime une ressource ou un groupe +* deux étapes : + * stopper la ressource + * supprimer la ressource + +::: notes + +La supression de ressource peut être réalisée par `pcs resource delete +`. + +La supression d'un groupe supprime non seulement ce groupe mais aussi les +ressources qu'il contient. + +::: + +----- + +### TP: supprimer les dummy + +::: notes + +1. lister les ressources du cluster +2. supprimer les ressources `dummy1` et `dummy2` +3. afficher l'état du cluster +4. supprimer le groupe `dummygroup` +5. afficher l'état du cluster +6. supprimer la ressource `Dummyd-clone` +7. afficher l'état du cluster + +::: + +----- + +### Correction: supprimer les dummy + +::: notes + +1. lister les ressources du cluster + +~~~console +# pcs resource show + Master/Slave Set: Dummyd-clone [Dummyd] + Masters: [ hanode1 hanode2 ] + Slaves: [ hanode3 ] + dummy1 (ocf::pacemaker:Dummy): Started hanode1 + Resource Group: dummygroup + dummy3 (ocf::pacemaker:Dummy): Started hanode2 + dummy2 (ocf::pacemaker:Dummy): Started hanode2 + + +~~~ + +2. supprimer les ressources `dummy1` et `dummy2` + +~~~console +# pcs resource delete dummy1 +Attempting to stop: dummy1... Stopped +# pcs resource delete dummy2 +Attempting to stop: dummy2... Stopped +~~~ + +3. afficher l'état du cluster + +~~~console +# pcs resource show + Master/Slave Set: Dummyd-clone [Dummyd] + Masters: [ hanode1 hanode2 ] + Slaves: [ hanode3 ] + Resource Group: dummygroup + dummy3 (ocf::pacemaker:Dummy): Started hanode2 + +~~~ + +4. supprimer le groupe dummygroup + +~~~console +# pcs resource delete dummygroup +Removing group: dummygroup (and all resources within group) +Stopping all resources in group: dummygroup... +Deleting Resource (and group) - dummy3 +~~~ + +5. afficher l'état du cluster + +~~~console +# pcs resource show + Master/Slave Set: Dummyd-clone [Dummyd] + Masters: [ hanode1 hanode2 ] + Slaves: [ hanode3 ] +~~~ + +6. supprimer la ressource `Dummyd-clone` + +~~~console +# pcs resource delete Dummyd-clone +Attempting to stop: Dummyd... Stopped +~~~ + +7. afficher l'état du cluster + +~~~console +# pcs resource show +NO resources configured +~~~ + +::: + +----- + +## Règles + +* possibilité de modifier les contraintes selon des conditions + * par exemple une plage horaire + +::: notes + +Les règles permettent de définir : + +* les contraintes de localisation , +* les options et attributs d'instance d'une ressource , +* les options du cluster , + +en fonction : + +* des attributs d'un nœud , +* de l'heure, de la date ou de la périodicité (à la manière d'une crontab) , +* d'une durée. + +Pacemaker recalcule l'état du cluster sur la base d'évènements. Il est possible +qu'aucun évènement ne se produise pendant une période, ce qui empêcherait le +déclenchement d'une modification de configuration lié à une règle temporelle. +Il faut donc configurer le paramètre `cluster-recheck-interval` a une valeur adaptée +pour s'assurer que les règles basées sur le temps soient exécutées. + +Les versions récentes de Pacemaker (à partir de la version 2.0.3) sont plus +fines à ce propos. Le `cluster-recheck-interval` est calculé dynamiquement en +fonction des contraintes, règles et différents timeout existants, à une +exception près. Voir à ce propos: + + +Les règles peuvent être utilisées pour favoriser l'utilisation d'un nœud plus +puissant en fonction de la périodes de la journée ou du nombre de CPU. + +Il faut cependant garder à l'esprit que la bascule d'une ressource PostgreSQL n'est +pas transparente et que la [simplicité][KISS] doit rester de mise. + +::: + + +----- + +# PAF + +Configuration et Mécanique de PAF + +----- + +## Historique PAF + +* agent officiel `pgsql` fastidieux et vieillissant +* premier agent stateless `pgsql-resource-agent` +* PAF est la seconde génération en mode stateful +* développé en bash, puis porté en perl + +::: notes + +Il existe déjà un agent `pgsql` distribué par le projet `resource-agents`. +Cependant, cet agent accumule plusieurs défauts: + +* très fastidieux à mettre en œuvre +* plusieurs objectifs: supporte les architectures _shared disk_ ou _shared nothing_ +* difficile à maintenir: code complexe, en bash +* procédures lourdes: pas de switchover, procédures lourdes, fichier de lock, etc +* configuration complexe: 31 paramètres disponibles +* détails d'implémentation visibles dans le paramétrage +* ne supporte pas le `demote` officieusement + +Pour les besoins d'un projet où cet agent était peu adapté à l'environnement, +un premier agent stateless nommé `pgsqlsr` a été développé. C'est le projet +`pgsql-resource-agent`, toujours disponible aujourd'hui mais plus maintenu. Ce +projet avait l'avantage d'être très simple. Cependant, il imposait des limites +importantes: un seul secondaire possible, un seul failover automatique +autorisé, pas de switchover. + +Suite à cette expérience, les auteurs ont créés le projet PAF, un nouvel agent +_multi-state_ exploitant au maximum les fonctionnalités de Pacemaker. Il a d'abord +été développé en bash, puis porté en perl, langage plus bas niveau, plus +lisible, plus efficace, plus fonctionnel. + +::: + +----- + +## Limitations + +* version de PostgreSQL supportée 9.3+ +* le demote de l'instance primaire nécessite un arrêt +* trop strict sur l'arrêt brutal d'une instance +* pas de reconstruction automatique de l'ancien primaire après failover +* pas de gestion des slots de réplication + +::: notes + +Une incohérence entre l'état de l'instance et le controldata provoque une +erreur fatale ! Ne __jamais__ utiliser `pg_ctl -m immediate stop` ! + +Limitations levées: + +* ne gère pas plusieurs instances PostgreSQL sur un seul nœud. Corrigé dans le commit 1a7d375. +* n'exclut pas une instance secondaire quel que soit son retard. Ajout du parametre maxlag dans le commit a3bbfa3. + +Fonctionnalités manquantes dans PostgreSQL pour améliorer la situation: + +* valider sur l'esclave ce qu'il a reçu du maître (cas du switchover) +* demote «à chaud» + +::: + +----- + +## Installation PAF + +* disponible directement depuis les dépôts PGDG RPM ou DEB +* paquets disponibles depuis github +* possibilité de l'installer à la main + +::: notes + +PAF peut être installé manuellement ou via les paquets mis à disposition sur +les dépôts communautaires PGDG ou encore ceux de Debian. + +Les paquets sont aussi mis à disposition depuis le dépôt github du projet: + + +::: + +----- + +### TP: installation de PAF + +::: notes + +1. installer le dépôt PGDG pour CentOS 7 sur tous les nœuds +2. installer PostgreSQL 12 sur sur tous les nœuds +3. chercher puis installer le paquet de PAF sur tous les nœuds + +::: + +----- + +### Correction: installation de PAF + +::: notes + +1. installer le dépôt PGDG pour CentOS 7 sur tous les nœuds + +~~~console +# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm +~~~ + +2. installer PostgreSQL 12 sur sur tous les nœuds + +~~~console +# yum install -y postgresql12 postgresql12-contrib postgresql12-server +~~~ + +3. chercher puis installer le paquet de PAF sur tous les nœuds + +~~~console +# yum search paf +Loaded plugins: fastestmirror +Loading mirror speeds from cached hostfile + * base: centos.mirrors.proxad.net + * extras: centos.mirror.fr.planethoster.net + * updates: centos.crazyfrogs.org +=============================== N/S matched: paf =============================== +resource-agents-paf.noarch : PostgreSQL resource agent for Pacemaker + + Name and summary matches only, use "search all" for everything. + +# yum install -y resource-agents-paf +~~~ + +::: + +----- + +## Pré-requis de PAF + +* supporte PostgreSQL à partir de la version 9.3 et supérieure +* _hot standby_ actif: doit pouvoir se connecter aux secondaires +* réplication streaming active entre les nœuds + * nécessite: + * `application_name` égal au nom du nœud + * `recovery_target_timeline = 'latest'` + * configurée dans : + * pg11 et avant : modèle de fichier de configuration `recovery.conf.pcmk` + * pg12 et après : fichier de configuration de PostgreSQL +* le cluster PostgreSQL doit être prêt avant le premier démarrage +* PostgreSQL doit être désactivé au démarrage du serveur +* empêcher le _wal receiver_ de se connecter sur sa propre instance + * eg. ajout d'une règle `reject` dans `pg_hba.conf` + +::: notes + +L'agent PAF a peu de pré-requis. + +Il supporte toutes les version de PostgreSQL supérieure ou égale à la version +9.3. + +Le `recovery.conf` a disparu avec la version 12 de PostgreSQL, les paramètres +qu'il contenait sont désormais renseignés dans le fichier de configuration de +l'instance. + +Le contrôleur du cluster à besoin de connaître le statut de chaque instance: +primaire ou secondaire. Ainsi, l'action `monitor` est exécutée à intervalle +régulier autant sur le primaire que sur les secondaires. Il est donc essentiel +que le paramètre `hot standby` soit activé sur toutes les instances, même sur +un primaire qui démarre toujours en secondaire d'abord ou qui peut être +repositionné en secondaire sur décision du cluster ou sur commande. + +Au tout premier démarrage du cluster, PAF recherche parmi les instances +configurées quel est l'instance principale. Il est donc essentiel d'avoir créé +le cluster PostgreSQL avant la création de la ressource dans Pacemaker et +que ce dernier soit fonctionnel dès son démarrage. + +Afin de permettre à PAF de faire le lien entre des connexions de réplication +et le nom des nœuds du cluster, il faut donner le nom du nœud où se trouve +l'instance dans la chaine de connexion (`primary_conninfo`) en utilisant le +paramètre `application_name`. + +Lors de la création de la ressource, Pacemaker s'attend à la trouver éteinte. +Il n'est pas vital que les instances soient éteintes, mais cela reste +préférable afin d'éviter une légère perte de temps et des erreurs inutiles +dans les log et les événements du cluster. + +Étant donné que Pacemaker contrôle entièrement le cluster PostgreSQL, ce +dernier doit être désactivé au démarrage du serveur. + +Il est recommandé d'empêcher activement chaque instance de pouvoir se +connecter en réplication avec elle même. La bascule étant automatique, un +ancien primaire rétrogradé en secondaire pourrait se connecter à lui même si +la mécanique d'aiguillage des connexions vers le nouveau primaire n'a pas +encore convergé. + +La _timeline_ à l'intérieur des journaux de transaction est mise à jour par le +serveur primaire suite à une promotion de l'instance. Pour que les instances +secondaires se raccrochent à la primaire, il faut leur indiquer d'utiliser la +dernière _timeline_ des journaux de transactions. C'est le rôle du +paramètre `recovery_target_timeline` que l'on doit positionner à `latest`. + +::: + +----- + +### TP: création du cluster PostgreSQL + +::: notes + +Ce TP a pour but de créer les instances PostgreSQL. Il ne comporte pas de +question, seulement des étapes à suivre. + +La configuration de PostgreSQL réalisée ci-dessous est une version simple et +rapide. Elle convient au cadre de ce TP dont le sujet principal est Pacemaker +et PAF, mais ne convient pas pour une utilisation en production. + +Dans ce cluster, l'adresse IP virtuelle `10.20.30.5` est associée au +serveur hébergeant l'instance principale. + +Créer l'instance primaire sur le nœuds `hanode1` : + +~~~console +# /usr/pgsql-12/bin/postgresql-12-setup initdb +Initializing database ... OK +~~~ + +Configuration de l'instance: + +~~~console +# su - postgres + +$ cat <> ~postgres/12/data/postgresql.conf +listen_addresses = '*' +wal_keep_segments = 32 +hba_file = '/var/lib/pgsql/12/pg_hba.conf' +include = '../standby.conf' +EOF + +$ cat < ~postgres/12/standby.conf +primary_conninfo = 'host=10.20.30.5 application_name=$(hostname -s)' +EOF +~~~ + +NB: depuis postgres 10, la mise en place de la réplication a été facilitée par +de nouvelles valeurs par défaut pour `wal_level`, `hot_standby`, `max_wal_sender`, +et `max_replication_slots` + +NB: avant la version 12, ces paramètres étaient à placer dans un modèle de +configuration (eg. `recovery.conf.pcmk`) nécessaire à PAF. + +NB: avant la version 12, il est nécessaire de positionner +`recovery_target_timeline = 'latest'` + +Notez que chaque fichier est différent sur chaque nœud grâce à l'utilisation du +hostname local pour l'attribut `application_name`. Ce point fait parti de +pré-requis, est essentiel et doit toujours être vérifié. + +Enfin, nous empêchons chaque instance de pouvoir entrer en réplication avec +elle même dans le fichier `pg_hba.conf`. La dernière règle autorise toute autre +connexion de réplication entrante: + +~~~console +$ rm ~postgres/12/data/pg_hba.conf +$ cat < ~postgres/12/pg_hba.conf +local all all trust +host all all 0.0.0.0/0 trust +host all all ::/0 trust + +# forbid self-replication from vIP +host replication postgres 10.20.30.5/32 reject +# forbid self-replication its own IP +host replication all $(hostname -s) reject +local replication all reject +host replication all 127.0.0.0/8 reject +host replication all ::1/128 reject + +# allow any standby connection +host replication postgres 0.0.0.0/0 trust +EOF + +$ exit +~~~ + +NB: les fichiers de configuration propres à chaque instance sont positionnés +hors du `PGDATA`. Ils sont ainsi conservés en cas de reconstruction de +l'instance, ce qui évite des étapes supplémentaires pour les adapter +systématiquement lors de cette procédure. + +Suite à cette configuration, nous pouvons démarrer l'instance principale et y +associer l'adresse IP virtuelle choisie pour le primaire: + +~~~console +# systemctl start postgresql-12 +# ip addr add 10.20.30.5/24 dev eth0 +~~~ + +Cloner l'instance sur les serveurs secondaires `hanode2` et `hanode3`: + +~~~console +# su - postgres +$ /usr/pgsql-12/bin/pg_basebackup -h 10.20.30.5 -D ~postgres/12/data/ -P +~~~ + +Corriger le paramètre `primary_conninfo` sur chaque nœud: + +~~~console +$ cat < ~postgres/12/standby.conf +primary_conninfo = 'host=10.20.30.5 application_name=$(hostname -s)' +EOF +~~~ + +Adapter les règles de rejet de la réplication du nœud avec lui même dans `pg_hba.conf`: + +~~~console +$ cat < ~postgres/12/pg_hba.conf +local all all trust +host all all 0.0.0.0/0 trust +host all all ::/0 trust + +# forbid self-replication from vIP +host replication postgres 10.20.30.5/32 reject +# forbid self-replication its own IP +host replication all $(hostname -s) reject +local replication all reject +host replication all 127.0.0.0/8 reject +host replication all ::1/128 reject + +# allow any standby connection +host replication postgres 0.0.0.0/0 trust +EOF +~~~ + +Démarrer les instances secondaires: + +~~~console +$ touch ~postgres/12/data/standby.signal +$ exit +# systemctl start postgresql-12 +~~~ + +NB: avant la version 12 de PostgreSQL, il faut copier le modèle template de +`recovery.conf` (eg. `recovery.conf.pcmk`) dans le `PGDATA` au lieu de créer +le fichier `standby.signal`. + +Vérifier le statut de la réplication depuis le serveur primaire : + +~~~console +postgres=# TABLE pg_stat_replication; +~~~ + +Enfin, éteindre tous les services PostgreSQL et les désactiver, comme indiqué +dans les pré-requis. Commencer par le primaire sur `hanode1`. + +~~~console +# systemctl disable --now postgresql-12 +~~~ + +Supprimer également l'adresse ip virtuelle ajoutée précédemment, celle-ci est +également contrôlée par Pacemaker par la suite : + +~~~console +# ip addr del 10.20.30.5/24 dev eth0 +~~~ + +::: + +----- + +## Configuration de PAF + +* Obligatoire: `PGDATA` +* Paramétrage avant la version 12 : `recovery_template` +* nécessite l'activation des opération `notify` +* Rappel : préciser tous les timeout des opérations +* Rappel : configurer deux opérations `monitor` + +::: notes + +La configuration de la ressource PostgreSQL est faite avec les paramètres : + +* `bindir` : localisation des binaires de PostgreSQL (défaut: `/usr/bin`) +* `pgdata` : localisation du PGDATA de l'instance (défaut: `/var/lib/pgsql/data`) +* `datadir` : chemin du répertoire data_directory si il est différent de `PGDATA` +* `pghost` : le répertoire de socket ou l'adresse IP pour se connecter à l'instance + locale (défaut: `/tmp` ou `/var/run/postgresql` pour Debian et dérivés) +* `pgport` : le port de l'instance locale (défaut: `5432`) +* `recovery_template` : un template local pour le fichier `PGDATA/recovery.conf` +(défaut: `$PGDATA/recovery.conf.pcmk`) + * avant PG12 : Ce fichier __doit__ exister sur tous les nœuds ; + * à partir de PG12 : Ce fichier ne doit exister sur aucun nœuds. +* `start_opts` : Argument supplémentaire à donner au processus PostgreSQL au démarrage + de PostgreSQL (vide pas défaut). +* `system_user` : l'utilisateur système du propriétaire de l'instance (défaut: `postgres`) +* `maxlag` : lag maximal autorisé pour une standby avant d'y placer un score négatif. + La différence est calculée entre la position actuelle dans le journal de transaction + sur le master et la postion écrite sur la standby (défaut: `0`, désactive la + fonction) + +Concernant la configuration des opérations, il est important de rappeler que +les timeout des opérations sont pas défaut de 20 secondes. Voir à ce propos le +chapitre [Création d'une ressource]. Les timeouts précisés dans la description +de l'agent `pgsqlms` ne sont __que__ des valeurs recommandées. Il __faut__ +préciser ce timeout en s'inspirant des valeurs conseillées pour __chaque__ +opération. + +Comme expliqué dans le chapitre [Ressources _Multi-State_], il faut +configurer deux opérations `monitor` distinctes: une pour le rôle `Slave`, +l'autre pour le rôle `Master`. Rappelez-vous que ces opérations doivent avoir +des périodes d'exécution différentes. + +Concernant la ressource multi-state prenant en charge les clones, il est +essentiel d'activer les opérations `notify` qui sont désactivées par défaut. +Effectivement, l'agent `pgsqlms` utilise intensément cette opération pour +détecter les cas de _switchover_, de _recovery_, gérer l'élection du +secondaire à promouvoir, etc. + +Les différentes opérations pour passer d'un état à l'autre sont deviennent +alors les suivantes: + +![Diagramme opérations multi-state avec notify](medias/paf-ms-roles-notify.png) + +::: + +----- + +### TP: création ressource PAF + +::: notes + +Effectuer les modifications dans un fichier `pgsqld.xml` avant de les appliquer +au cluster. + +1. créer une ressource `pgsqld` en précisant: + +* les paramètres `bindir` et `pgdata` +* les timeout de toutes les actions. Utiliser les timeout recommandé par + l'agent +* surveiller le rôle `Master` toutes les 15 secondes +* surveiller le rôle `Slave` toutes les 16 secondes + +2. créer la ressource `pgsqld-clone` responsable des clones de `pgsqld` +3. créer la ressource `pgsql-master-ip` gérant l'adresse `10.20.30.5` +4. ajouter une colocation obligatoire entre l'instance primaire de `pgsqld-clone` + et `pgsql-master-ip` +5. ajouter une contrainte asymétrique pour promouvoir `pgsqld-clone` avant de + démarrer `pgsql-master-ip` +6. ajouter une contrainte asymétrique pour rétrograder `pgsqld-clone` avant + d'arrêter `pgsql-master-ip` +7. vérifier la configuration créée puis appliquer la au cluster +8. observer le score `master-pgsqld` des clones `pgsqld` + +::: + +----- + +### Correction: ressource PAF + +::: notes + +Effectuer les modifications dans un fichier `pgsqld.xml` avant de les appliquer +au cluster. + +~~~console +# pcs cluster cib pgsqld.xml +~~~ + +1. créer une ressource `pgsqld` + +~~~console +# pcs -f pgsqld.xml resource create pgsqld ocf:heartbeat:pgsqlms \ + bindir=/usr/pgsql-12/bin pgdata=/var/lib/pgsql/12/data \ + op start timeout=60s \ + op stop timeout=60s \ + op promote timeout=30s \ + op demote timeout=120s \ + op monitor interval=15s timeout=10s role="Master" \ + op monitor interval=16s timeout=10s role="Slave" \ + op notify timeout=60s +~~~ + +2. créer la ressource `pgsqld-clone` responsable des clones de `pgsqld` + +~~~console +# pcs -f pgsqld.xml resource master pgsqld-clone pgsqld notify=true +~~~ + +Nous ne précisons ici la seule option `notify` qui est __essentielle__ à PAF +et qui est par défaut à `false`. Elle permet d'activer les action `notify` +avant et après chaque action sur la ressource. Nous laissons les autres +options à leur valeur par défaut. + +3. créer la ressource `pgsql-master-ip` gérant l'adresse `10.20.30.5` + +~~~console +# pcs -f pgsqld.xml resource create pgsql-master-ip ocf:heartbeat:IPaddr2 \ + ip=10.20.30.5 cidr_netmask=24 \ + op monitor interval=10s +~~~ + +4. ajouter une colocation obligatoire entre l'instance primaire de `pgsqld-clone` + et `pgsql-master-ip` + +~~~console +# pcs -f pgsqld.xml constraint \ + colocation add pgsql-master-ip with master pgsqld-clone INFINITY +~~~ + +5. ajouter une contrainte asymétrique pour promouvoir `pgsqld-clone` avant de + démarrer `pgsql-master-ip` + +~~~console +# pcs -f pgsqld.xml constraint order promote pgsqld-clone \ + then start pgsql-master-ip symmetrical=false kind=Mandatory +~~~ + +6. ajouter une contrainte asymétrique pour rétrograder `pgsqld-clone` + avant d'arrêter `pgsql-master-ip` + +~~~console +# pcs -f pgsqld.xml constraint order demote pgsqld-clone \ + then stop pgsql-master-ip symmetrical=false kind=Mandatory +~~~ + +7. vérifier la configuration créée puis appliquer la au cluster + +~~~console +# pcs cluster verify -V pgsqld.xml + +# crm_simulate -S -x pgsqld.xml + +# pcs cluster cib-push pgsqld.xml +~~~ + +::: + +----- + +## Master scores de PAF + +* mécanique des master scores de PAF +* `1001` pour le primaire +* `1000 - 10 x n` pour les secondaires +* score négatif en cas de décrochage ou retard +* cas du premier démarrage + +::: notes + +PAF positionne des _master scores_ permanents, qui sont conservés entre les +redémarrage du cluster. Le dernier emplacement du primaire est donc toujours +maintenu au sein du cluster. Il n'est pas recommandé de manipuler soit même +ces scores, nous étudions plus loin les commandes d'administration permettant +d'agir sur l'emplacement du primaire. + +Lors du démarrage d'une instance arrêtée alors qu'elle était primaire, l'agent +positionnera son master score à `1` si aucun autre master score n'est connu au +sein du cluster. Les master scores n'étant jamais supprimés par le cluster, +cette mécanique est principalement utile lors du tout premier démarrage. + +Une fois la promotion effectuée, le score positionné par l'agent pour assurer +son statu d'instance primaire est de `1001`. + +Le score des instances secondaires est mis à jour lors de l'opération `monitor` +sur le primaire. Il peut donc être nécessaire d'attendre un cycle de cette +opération avant que les scores ne soient mis à jour, par exemple, suite à une +bascule. Voici les scores attribués: + +* positif: le statut de réplication de l'instance est `stream` +* `-1`: statut de réplication est `startup` ou `backup` +* `-1000`: l'instance n'est pas connectée au primaire +* négatif: l'instance a un lag supérieur au paramètre `max_lag` positionné +sur la ressource `pgsqlms` + +Les scores positifs distribués aux secondaires en réplication sont dégressifs +par pas de `10` à partir de `1000`. L'ordre dépend de deux critères: le lag +avec le primaire et le nom de l'instance tel que positionné dans +`application_name`. + +Suite au précédent TP, vous devriez observer les scores suivants: + +~~~console +# crm_simulate -sL|grep promotion +pgsqld:0 promotion score on hanode1: 1003 +pgsqld:1 promotion score on hanode2: 1000 +pgsqld:2 promotion score on hanode3: 990 +~~~ + +Tout d'abord, nous observons que le cluster a choisi de démarrer trois clones +en respect de la valeur par défaut du paramètre `clone-max`, positionnée au +nombre de nœuds existants. Ces ressources sont suffixé d'un identifiant: +`pgsqld:0`, `pgsqld:1` et `pgsqld:2`. + +Concernant le placement des clones, le cluster actuellement configuré doit +présenter des scores similaires à ceux-ci: + +~~~console +# crm_simulate -sL|grep 'native_color: pgsqld' +native_color: pgsqld:0 allocation score on hanode1: 1002 +native_color: pgsqld:0 allocation score on hanode2: 0 +native_color: pgsqld:0 allocation score on hanode3: 0 +native_color: pgsqld:1 allocation score on hanode1: -INFINITY +native_color: pgsqld:1 allocation score on hanode2: 1001 +native_color: pgsqld:1 allocation score on hanode3: 0 +native_color: pgsqld:2 allocation score on hanode1: -INFINITY +native_color: pgsqld:2 allocation score on hanode2: -INFINITY +native_color: pgsqld:2 allocation score on hanode3: 991 +~~~ + +Les scores `1002`, `1001` et `991` correspondent à la somme des _master scores_ +avec le _stickiness_ de `1` associé à la ressource. + +Voici pourquoi et comment sont distribués les scores `-INFINITY`: + +1. le premier clone `pgsqld:0` pouvait démarrer n'importe où. +2. une fois `pgsqld:0` démarré sur `hanode1`, les clones ne pouvant coexister sur + le même nœud (`clone-node-max=1`), `pgsqld:1` a un score `-INFINITY` sur + `hanode1`, mais peu démarrer sur n'importe lequel des deux autres nœuds +3. `pgsqld:2` a un score de `-INFINITY` sur `hanode1` et `hanode2` à cause de la + présence des deux autres clones. Il ne peut démarrer que sur `hanode3`. + +NB: il se peut que vos clones soient répartis différemment. + +::: + +----- + +### TP: étude du premier démarrage + +::: notes + +Le log de `LRMd` étant configuré en mode debug, les messages de debug de PAF +son visibles dans les log. + +1. identifier l'opération `start` dans les log de Pacemaker __sur le primaire__ +2. identifier les messages de `pgsqlms` concernant son statut avant et après démarrage +3. identifier la décision de l'agent de positionner son master score +4. identifier sur le DC la décision de créer une nouvelle transition pour + promouvoir l'instance primaire +5. identifier l'opération de promotion sur le primaire +6. identifier sur le primaire la distributions des scores + +::: + +----- + +### Correction: Étude du premier démarrage + +::: notes + +Le log de `LRMd` étant configuré en mode debug, les messages de debug de PAF +son visibles dans les log. + +1. identifier l'opération `start` dans les log de Pacemaker __sur le primaire__ + +~~~ +lrmd: info: executing - rsc:pgsqld action:start call_id:27 +~~~ + +2. identifier les messages de `pgsqlms` concernant son statut avant et après démarrage + +~~~ +pgsqlms(pgsqld) DEBUG: _controldata: instance "pgsqld" state is "shut down" +~~~ + +Au début de l'opération `start`, `pgsqlms` vérifie toujours le statut de +l'instance en effectuant les mêmes contrôles que l'opération `monitor`. Il +détecte bien ici que l'instance est arrêtée en tant que primaire. + +Pour comparaison, une instance secondaire est signalée avec le message suivant: + +~~~ +pgsqlms(pgsqld) DEBUG: instance "pgsqld" state is "shut down in recovery" +~~~ + +Une fois l'opération confirmée, nous constatons bien que le l'instance est +démarrée en tant que standby. + +~~~ +pgsqlms(pgsqld) DEBUG: _confirm_role: instance pgsqld is a secondary +pgsqlms(pgsqld) INFO: Instance "pgsqld" started +~~~ + + +3. identifier la décision de l'agent de positionner son master score + +~~~ +pgsqlms(pgsqld) INFO: No master score around. Set mine to 1 +~~~ + +Vous remarquerez que ce message n'apparaît sur les autres instances.' + +4. identifier sur le DC la décision de créer une nouvelle transition pour + promouvoir l'instance primaire + +~~~ +pengine: debug: pgsqld:1 master score: 1 +pengine: info: Promoting pgsqld:1 (Slave hanode1) +pengine: debug: pgsqld:0 master score: -1 +pengine: debug: pgsqld:2 master score: -1 +pengine: info: pgsqld-clone: Promoted 1 instances of a possible 1 to master +pengine: debug: Assigning hanode1 to pgsql-master-ip +[...] +pengine: info: Leave pgsqld:0 (Slave hanode2 ) +pengine: notice: * Promote pgsqld:1 (Slave -> Master hanode1) +pengine: info: Leave pgsqld:2 (Slave hanode3 ) +pengine: notice: * Start pgsql-master-ip (hanode1 ) +~~~ + +Cette transition décide de promouvoir l'instance sur `hanode1` et d'y +démarrer l'adresse IP associée grâce à la colocation créée. + +5. identifier l'opération de promotion sur le primaire + +~~~ +crmd: info: Performing op=pgsqld_promote_0 +lrmd: info: executing - rsc:pgsqld action:promote +[...] +pgsqlms(pgsqld)[29050]: Mar 20 21:52:40 INFO: Promote complete +lrmd: info: finished - rsc:pgsqld action:promote exit-code:0 +crmd: notice: Result of promote operation for pgsqld on hanode1: 0 (ok) +~~~ + +6. identifier sur le primaire la distributions des scores + +Une fois la promotion réalisée et avant de la confirmer au cluster, l'agent +vérifie le statut de l'instance de la même manière que l'opération `monitor`. +L'adresse IP n'étant pas encore associée à ce moment là, aucun secondaire n'est +alors connecté. Vous devriez donc observer les messages suivants: + +~~~ +pgsqlms(pgsqld) WARNING: No secondary connected to the master +pgsqlms(pgsqld) WARNING: "hanode3" is not connected to the primary +pgsqlms(pgsqld) WARNING: "hanode2" is not connected to the primary +~~~ + +Au prochain appel à l'opération `monitor`, vous devriez ensuite observer: + +~~~ +pgsqlms(pgsqld) INFO: Update score of "hanode2" from -1000 to 1000 because of a change in the replication lag (0). +pgsqlms(pgsqld) INFO: Update score of "hanode3" from -1000 to 990 because of a change in the replication lag (0). +~~~ + +::: + +----- + +# Administration du cluster + +----- + +## Démarrer/arrêter le cluster + +* pas de mécanique d'arrêt contrôlé et simultané de tous les nœuds +* désactiver les ressources avant d'éteindre le cluster +* au cas par cas ou avec l'option `stop-all-resources` +* utiliser l'attribut de nœuds `standby` pour un nœud isolé + +::: notes + +Pacemaker n'a pas de mécanique prévue pour interrompre tous les nœuds du +cluster de façon contrôlée. Ainsi, si les nœuds sont éteints les uns après +les autres, quele qu'en soit la raison, le cluster peut avoir le temps de +réagir et planifier des opérations qui pourront être exécutées ou non. + +Même avec un outil comme `pcs` qui exécute les commandes d'arrêts sur tous +les nœuds en même temps, il y a toujours un risque de race condition. + +À ce propos, voir ce mail et la discussion autour: + + + +Il existe deux solutions pour éteindre le cluster, arrêter les ressources ou +positionner le paramètre de cluster `stop-all-resources` à `true`. + +Si l'arrêt ne concerne qu'un seul serveur (eg. mise à jour du noyau, +évolution matériel, ...), il est possible de le positionner en +« veille » grâce à l'attribut de nœud `standby`. Lorsque cet attribut est +activé sur un nœud, Pacemaker bascule toutes les ressources qu'il héberge +ailleurs dans le cluster et n'en démarrera plus dessus. + +::: + +----- + +### TP: arrêt du cluster + +::: notes + +1. placer `hanode3` en mode standby +2. observer les contraintes pour `pgsqld-clone` +3. retirer le mode standby de `hanode3` +4. désactiver toutes les ressources +5. éteindre le cluster +6. démarrer le cluster +7. réactiver les ressources. + +::: + +----- + +### Correction: arrêt du cluster + +::: notes + +1. placer `hanode3` en mode standby + +~~~console +# pcs node standby hanode3 --wait +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 ] + Stopped: [ hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +Toutes les ressources de `hanode3` ont bien été interrompues. + +NOTE: `pcs node standby ` à remplacé `pcs cluster standby` dans la +version 0.10.1 de pcs. + + +2. observer les contraintes pour `pgsqld-clone` + +~~~console +# pcs constraint location show resource pgsqld-clone +Location Constraints: +~~~ + +Il n'y a aucune contrainte, le cluster refuse simplement de démarrer une +ressource sur `hanode3`. + +3. retirer le mode standby de `hanode3` + +~~~console +# pcs node unstandby hanode3 --wait +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +4. désactiver toutes les ressources + +Deux solutions. La première consiste à positionner `stop-all-resources=true`: + +~~~console +# pcs property set stop-all-resources=true + +# [...] après quelques secondes + +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + Stopped: [ hanode1 hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Stopped +~~~ + +L'intérêt de se paramètre est que le cluster va interrompre toutes les +ressources en une seule transition: + +~~~ +pengine: debug: unpack_config: Stop all active resources: true +pengine: debug: native_color: Forcing fence_vm_hanode1 to stop +pengine: debug: native_color: Forcing fence_vm_hanode2 to stop +pengine: debug: native_color: Forcing fence_vm_hanode3 to stop +pengine: debug: native_color: Forcing pgsqld:1 to stop +pengine: debug: native_color: Forcing pgsqld:0 to stop +pengine: debug: native_color: Forcing pgsqld:2 to stop +pengine: notice: * Stop fence_vm_hanode1 ( hanode2 ) +pengine: notice: * Stop fence_vm_hanode2 ( hanode1 ) +pengine: notice: * Stop fence_vm_hanode3 ( hanode1 ) +pengine: notice: * Stop pgsqld:0 ( Slave hanode2 ) +pengine: notice: * Stop pgsqld:1 ( Master hanode1 ) +pengine: notice: * Stop pgsqld:2 ( Slave hanode3 ) +pengine: notice: * Stop pgsql-master-ip ( hanode1 ) +~~~ + +Son désavantage est que le cluster réagit après que le paramètre ait été +positionné. L'outil `pcs` ne peut donc pas attendre la fin de la transition +pour rendre la main, ce qui est gênant dans le cadre d'un script par exemple. + +La seconde solution consiste à arrêter chacune des ressources, une à une. +Dans ce cas, nous pouvons demander à `pcs` d'attendre la fin de l'opération, +mais il faut potentiellement exécuter plusieurs commandes donc. + +~~~console +# pcs resource disable pgsqld-clone --wait +~~~ + +5. éteindre le cluster + +~~~console +# pcs cluster stop --all +~~~ + +6. démarrer le cluster + +~~~console +# pcs cluster start --all +~~~ + +7. réactiver les ressources. + +Attendre que le cluster soit formé et qu'un DC soit élu. + +~~~console +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + Stopped: [ hanode1 hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Stopped +# pcs property set stop-all-resources=false + +[...] après quelques secondes + +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +::: + +----- + +## Maintenances du cluster + +* `maintenance-mode` + * concerne toutes les ressources + * désactive toutes les opérations + * arrête les opérations `monitor` +* `is-managed` + * ressource par ressource + * ne désactive pas les opérations `monitor` + * ne réagit plus aux changements de statut +* commandes `cleanup` ou `refresh` pour rafraîchir une ressource + +::: notes + +L'attribut de ressource `is-managed` permet de désactiver les réactions du +cluster pour la ressource concernée. Une fois cet attribut positionné à +`false`, le cluster n'exécute plus aucune nouvelle action de sa propre +initiative. Cependant, les opérations récurrentes de `monitor` sont maintenues. +Un statut différent de celui attendu n'est simplement pas considéré comme une +erreur. + +Le paramètre `maintenance-mode` quand à lui permet de placer l'ensemble du +cluster en mode maintenance lorsqu'il est positionné à `true`. Ce paramètre +de cluster concerne __toutes__ les ressources. + +Une fois le mode maintenance activé, comme avec l'attribut `is-managed`, +Pacemaker n'exécute plus aucune opération de sa propre initiative, mais il +désactive __aussi__ toutes les opérations récurrentes de `monitor`. + +Quelque soit la méthode utilisée pour désactiver temporairement les réactions +du cluster, une fois que ce dernier reprend le contrôle, il compare le statut +des ressources avec celui qu'elles avaient auparavant. Ainsi, si une ressource +a été arrêtée ou déplacée entre temps, il peut déclencher des actions +correctives ! Avant de quitter l'un ou l'autre des modes, veillez à simuler la +réaction du cluster à l'aide de `crm_simulare`. + +Lorsque `maintenance-mode` est activé, il peut être utile de demander au +cluster de rafraîchir le statut des ressources. Deux commandes existent: +`crm_ressource --cleanup` ou `crm_ressource --refresh` (et leurs équivalents +avec `pcs`). + +La première ne travaille que sur les ressources ayant eu une erreur. Elle +nettoie l'historique des erreurs, les `failcount`, puis exécute une +seule opération `monitor` pour recalculer le statut de la ressource. Elle n'a +aucun effet sur les ressources n'ayant aucune erreur. + +La seconde commande effectue les mêmes opérations, travaille aussi sur les +ressources saines et nettoie tout l'historique en plus des erreurs. + +::: + +----- + +### TP: maintenance + +::: notes + +1. désactiver `is-managed` pour la ressource `pgsqld-clone` +2. arrêter manuellement PostgreSQL sur `hanode2` +3. observer la réaction du cluster +4. exporter la CIB courante dans le fichier `is-managed.xml` et y activer le + paramètre `is-managed` pour la ressource `pgsqld-clone` +5. simuler la réaction du cluster en utilisant la CIB `is-managed.xml` en entrée +6. appliquer la modification de `is-managed.xml` et observer la réaction du + cluster +7. activer le mode maintenance sur l'ensemble du cluster +8. arrêter manuellement PostgreSQL sur `hanode3` +9. exécuter une commande `cleanup` pour `pgsqld` sur le seul nœud `hanode2` +10. exécuter une commande `cleanup` pour `pgsqld` sur le seul nœud `hanode3` +11. exécuter une commande `refresh` pour `pgsqld` sur le seul nœud `hanode3` +12. simuler la sortie du mode maintenance puis appliquer la modification au + cluster + +::: + +----- + +### Correction: maintenance + +::: notes + +1. désactiver `is-managed` pour la ressource `pgsqld-clone` + +~~~console +# pcs resource unmanage pgsqld-clone +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + pgsqld (ocf::heartbeat:pgsqlms): Master hanode1 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode2 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode3 (unmanaged) + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +2. arrêter manuellement PostgreSQL sur `hanode2` + +Notez que nous ne pouvons pas utiliser `systemctl`. Le service est +désactivé et arrêté aux yeux de systemd. + +~~~console +# sudo -iu postgres /usr/pgsql-12/bin/pg_ctl -D /var/lib/pgsql/12/data/ -m fast stop +~~~ + +3. observer la réaction du cluster + +Après quelques secondes, le cluster constate que `pgsqld` est arrêté sur +`hanode2`, mais il ne réagit pas. + +~~~console +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + pgsqld (ocf::heartbeat:pgsqlms): Master hanode1 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode3 (unmanaged) + Stopped: [ hanode2 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +Les log sur le DC présentent bien la non réaction du `pengine`: + +~~~ +pengine: debug: pgsqld_monitor_16000 on hanode2 returned 'not running' (7) instead of the expected value: 'ok' (0) +pengine: info: resource pgsqld:1 isn't managed +[...] +pengine: debug: custom_action: Action pgsqld:0_start_0 (unmanaged) +pengine: debug: custom_action: Action pgsqld:0_demote_0 (unmanaged) +pengine: debug: custom_action: Action pgsqld:0_stop_0 (unmanaged) +pengine: debug: custom_action: Action pgsqld:0_promote_0 (unmanaged) +pengine: debug: custom_action: Action pgsqld:1_start_0 (unmanaged) +pengine: debug: custom_action: Action pgsqld:1_stop_0 (unmanaged) +pengine: debug: custom_action: Action pgsqld:1_start_0 (unmanaged) +pengine: info: LogActions: Leave fence_vm_hanode1 (Started hanode2) +pengine: info: LogActions: Leave fence_vm_hanode2 (Started hanode1) +pengine: info: LogActions: Leave fence_vm_hanode3 (Started hanode1) +pengine: info: LogActions: Leave pgsqld:0 (Master unmanaged) +pengine: info: LogActions: Leave pgsqld:1 (Slave unmanaged) +pengine: info: LogActions: Leave pgsqld:2 (Stopped unmanaged) +pengine: info: LogActions: Leave pgsql-master-ip (Started hanode1) +~~~ + +4. exporter la CIB courante dans le fichier `is-managed.xml` et y activer le +paramètre `is-managed` pour la ressource `pgsqld-clone` + +~~~console +# pcs cluster cib is-managed.xml +# pcs -f is-managed.xml resource manage pgsqld-clone +~~~ + +5. simuler la réaction du cluster en utilisant la CIB `is-managed.xml` en entrée + +Le cluster décide de redémarrer l'instance sur `hanode2`. + +~~~console +# crm_simulate -Sx is-managed.xml +[...] +Transition Summary: + * Recover pgsqld:2 ( Slave hanode2 ) + +Executing cluster transition: + * Pseudo action: pgsqld-clone_pre_notify_stop_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_stop_0 + * Pseudo action: pgsqld-clone_stop_0 + * Resource action: pgsqld stop on hanode2 + * Pseudo action: pgsqld-clone_stopped_0 + * Pseudo action: pgsqld-clone_post_notify_stopped_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-post_notify_stopped_0 + * Pseudo action: pgsqld-clone_pre_notify_start_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_start_0 + * Pseudo action: pgsqld-clone_start_0 + * Resource action: pgsqld start on hanode2 + * Pseudo action: pgsqld-clone_running_0 + * Pseudo action: pgsqld-clone_post_notify_running_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-post_notify_running_0 + * Resource action: pgsqld monitor=16000 on hanode2 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +6. appliquer la modification de `is-managed.xml` et observer la réaction du cluster + +~~~console +# pcs cluster cib-push is-managed.xml +~~~ + +Le cluster détecte __immédiatement__ un statut différent de celui attendu et +lève une erreur: + +~~~console +# pcs resource failcount show pgsqld +Failcounts for resource 'pgsqld' + hanode2: 1 +~~~ + +Dans les log du DC: + +~~~ +pengine: debug: pgsqld_monitor_16000 on hanode2 returned 'not running' (7) instead of the expected value: 'ok' (0) +pengine: warning: Processing failed monitor of pgsqld:1 on hanode2: not running | rc=7 +pengine: info: Start recurring monitor (16s) for pgsqld:1 on hanode2 +pengine: info: Start recurring monitor (16s) for pgsqld:1 on hanode2 +pengine: info: Leave fence_vm_hanode1 (Started hanode2) +pengine: info: Leave fence_vm_hanode2 (Started hanode1) +pengine: info: Leave fence_vm_hanode3 (Started hanode1) +pengine: info: Leave pgsqld:0 (Master hanode1 ) +pengine: notice: * Recover pgsqld:1 (Slave hanode2 ) +pengine: info: Leave pgsqld:2 (Slave hanode3 ) +pengine: info: Leave pgsql-master-ip (Started hanode1) +~~~ + +7. activer le mode maintenance sur l'ensemble du cluster + +Le cluster ne gère plus aucune les ressource. + +~~~console +# pcs property set maintenance-mode=true +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode3 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Master hanode1 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode2 (unmanaged) + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 (unmanaged) +~~~ + +8. arrêter manuellement PostgreSQL sur `hanode3` + +~~~console +# sudo -iu postgres /usr/pgsql-12/bin/pg_ctl -D /var/lib/pgsql/12/data/ -m fast stop +~~~ + +Le cluster ne détecte pas le changement de statut de la ressource. + +9. exécuter une commande `cleanup` pour `pgsqld` sur le seul nœud `hanode2` + +~~~console +# pcs resource cleanup pgsqld --node=hanode2 +Cleaned up pgsqld:0 on hanode2 +Cleaned up pgsqld:1 on hanode2 +Cleaned up pgsqld:2 on hanode2 + +# pcs resource failcount show pgsqld +No failcounts for resource 'pgsqld' + +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode3 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Master hanode1 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode2 (unmanaged) + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 (unmanaged) +~~~ + +Nous observons que l'historique des incidents de `pgsqld` sur `hanode2` a disparu. + +Le clone `pgsqld` est cependant toujours vu comme démarré sur `hanode3`. + +10. exécuter une commande `cleanup` pour `pgsqld` sur le seul nœud `hanode3` + +Rien ne change. La commande n'a pas d'effet sur les ressources n'ayant pas eu +d'incident. + +~~~console +# pcs resource cleanup pgsqld --node=hanode3 +Cleaned up pgsqld:0 on hanode3 +Cleaned up pgsqld:1 on hanode3 +Cleaned up pgsqld:2 on hanode3 + +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode3 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Master hanode1 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode2 (unmanaged) + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 (unmanaged) +~~~ + +11. exécuter une commande `refresh` pour `pgsqld` sur le seul nœud `hanode3` + +Le cluster a détecté que la ressource était arrêtée et le consigne dans la +CIB. + +~~~console +# pcs resource refresh pgsqld --node=hanode3 +Cleaned up pgsqld:0 on hanode3 +Cleaned up pgsqld:1 on hanode3 +Cleaned up pgsqld:2 on hanode3 +Waiting for 3 replies from the CRMd... OK + +# pcs resource failcount show pgsqld +No failcounts for resource 'pgsqld' + +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Master hanode1 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode2 (unmanaged) + Stopped: [ hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 (unmanaged) +~~~ + +12. simuler la sortie du mode maintenance puis appliquer la modification au +cluster + +Le cluster prévoie de démarrer l'instance sur `hanode3` + +~~~console +# pcs cluster cib maintenance-mode.xml +# pcs -f maintenance-mode.xml property set maintenance-mode=false +# crm_simulate -Sx maintenance-mode.xml +[...] +Transition Summary: + * Start pgsqld:2 ( hanode3 ) + +Executing cluster transition: + * Resource action: fence_vm_hanode1 monitor=60000 on hanode2 + * Resource action: fence_vm_hanode2 monitor=60000 on hanode1 + * Resource action: fence_vm_hanode3 monitor=60000 on hanode1 + * Pseudo action: pgsqld-clone_pre_notify_start_0 + * Resource action: pgsql-master-ip monitor=10000 on hanode1 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_start_0 + * Pseudo action: pgsqld-clone_start_0 + * Resource action: pgsqld start on hanode3 + * Pseudo action: pgsqld-clone_running_0 + * Pseudo action: pgsqld-clone_post_notify_running_0 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Pseudo action: pgsqld-clone_confirmed-post_notify_running_0 + * Resource action: pgsqld monitor=15000 on hanode1 + * Resource action: pgsqld monitor=16000 on hanode2 + * Resource action: pgsqld monitor=16000 on hanode3 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +Après avoir appliqué la modification sur le cluster, ce dernier démarre +effectivement la ressource, mais aucune erreur n'est levée. Le cluster +s'aperçoit simplement qu'il peut déployer une instance de plus. + +~~~console +# pcs cluster cib-push maintenance-mode.xml +# pcs resource failcount show pgsqld +No failcounts for resource 'pgsqld' +~~~ + +::: + +----- + +## Simuler des événements + +* la commande `crm_simulate` permet de simuler les réactions du cluster +* elle peut aussi injecter des événements, eg.: + * crash d'un nœud + * injecter une opération et son code retour, avant transition + * décider du code retour d'une opération pour la prochaine transition +* chaque appel exécute une seule transition +* possibilité de chaîner les simulations en reprenant le résultat de la précédente +* utile pour analyser les transitions passées + +::: notes + +Jusqu'à présent l'outil `crm_simulate` a été utilisé pour simuler les +réactions du cluster en fonction d'une situation stable: une CIB de travail +dans un fichier XML que nous manipulons (`crm_simulate -S -x FICHIER`) ou la +CIB en cours d'utilisation par le cluster (`crm_simulate -S -L`). + +Il est aussi possible d'utiliser cet outil pour injecter des opérations et +leur code retour grâce à l'argument `--op-inject` ou `-i`. Le format de +l'argument est alors le suivant: +`${resource}_${task}_${interval}@${node}=${rc}`, avec: + +* `${resource}`: le nom de la ressource +* `${task}`: l'opération' +* `${interval}`: l'intervalle de récurrence de la commande, en millisecondes +* `${node}`: le nœud sur lequel l'opération est simulée +* `${rc}`: le code retour. + +Le code retour doit être précisé de façon numérique. La liste des codes +retours est disponible dans le chapitre [_Ressource Agent_ (_RA_)]. + +Par exemple, la commande suivante injecte une opération `monitor` indiquant que +la ressource `pgsqld` est arrêtée sur `hanode2`: + +~~~ +--op-inject=pgsqld_monitor_15000@hanode2=7 +~~~ + +L'argument `--op-fail` ou `-F` permet de prédire le code retour d'une opération +si elle est planifiée durant la simulation. Le format est identique à celui de +`--op-inject`. Il est donc possible d'injecter une opération en entrée de la +simulation avec `--op-inject` et de prédire le code retour d'une ou plusieurs +des opérations planifiées par le cluster en réponse. + +D'autres événements sont supportés, tel que l'arrêt d'un nœud ou sa +défaillance (respectivement `--node-down` et `--node-fail`), le changement de +quorum (`--quorum`) ou le retour d'un nœud (`--node-up`). + +Quelque soit la simulation effectué, il est utile d'en sauvegarder l'état de +sortie grâce à l'argument `--save-output=FICHIER`. Chaque simulation ne crée +qu'une seule transition. Le fichier obtenu peut donc être réutilisé +directement en entrée d'une autre simulation afin d'étudier les réactions du +cluster suite à la défaillance d'une première transition par exemple. + +Ces actions restent cependant de simples simulation, à aucun moment l'agent +n'est exécuté. Ainsi, les éventuels paramètres positionnés par ce dernier +au cours des opérations ne seront pas positionnés. Vous pouvez néanmoins les +positionner vous même dans les fichiers XML de simulation à l'aide des outils +`pcs`, `crm_attribute`, `crm_master`, ... + +Enfin, Chaque transition calculée et appliquée en production par le cluster +est enregistrée localement par le `pengine`. Par exemple, dans les log: + +~~~ +pengine: notice: Calculated transition 71, saving inputs in /var/lib/pacemaker/pengine/pe-input-135.bz2 +~~~ + +Il est possible d'observer le contenu de cette transition très simplement +grâce à `crm_simulate`, ce qui est utile dans l'analyse d'un événement passé: + +~~~console +# crm_simulate --simulate --xml-file /var/lib/pacemaker/pengine/pe-input-135.bz2 +Using the original execution date of: 2020-03-26 17:30:27Z + +Current cluster status: +[...] +~~~ + +::: + +----- + +## Détection de panne + +* perte d'un nœud + * détectée par Corosync + * immédiatement communiqué à Pacemaker + * bascules rapides +* le temps de détection d'une panne sur la ressource dépend du `monitor interval` +* la transition calculée dépendent du type et du rôle de la ressource +* le cluster essaie de redémarrer sur le même nœud si possible +* pas de failback automatique + +::: notes + +En cas de panne, la ressource est arrêtée ou déplacée vers un autre nœud +dans les cas suivants: + +* perte totale du nœud où résidait la ressource +* `failcount` de la ressource supérieur ou égal au `migration-threshold` +* erreur retournée par l'opération `monitor` de type `hard` + (voir [_Ressource Agent_ (_RA_)]) +* perte du quorum pour la partition locale + +Dans le cas de la perte du nœud, Corosync détecte très rapidement qu'un membre +a quitté le groupe brusquement. Il indique immédiatement à Pacemaker que le +nombre de membre du cluster a changé. La première action de Pacemaker est +habituellement de déclencher un _fencing_ du nœud disparu, au cas où ce dernier +ne soit pas réellement éteint ou qu'il puisse revenir inopinément et rendre le +cluster instable. Les ressources hébergées sur le nœud disparu sont déplacées +une fois le _fencing_ confirmé. + +Dans le cas d'une ressource est défaillante, si l'erreur retournée par +l'opération a un niveau de criticité `hard` (voir [_Ressource Agent_ (_RA_)]), +la ressource est démarrée sur un autre nœud. + +Dans les autres cas, tant que le `failcount` ne dépasse pas le +`migration-threshold` de la ressource, le cluster tente de redémarrer cette +dernière sur le même nœud (`recovery`). + +Que la ressource soit redémarrée sur le même nœud ou déplacée ailleurs, +Pacemaker tente toujours un arrêt (opération `stop`) de celle-ci. Or, si +l'opération `stop` échoue, elle est "promue" en fencing lors de la transition +suivante. Ce comportement est dicté par la propriété `on-fail=fence` de +l'action `stop` (valeur par défaut). Il est __fortement__ déconseillé de +modifier ce comportement. + +Les chapitres suivants présentent les réactions du cluster en fonction du +rôle de l'instance: secondaire ou primaire. + +De plus, Pacemaker n'a pas d'opération de `failback`. Du reste, ce type +d'opération se prête mal à l'automatisation dans le cadre d'un SGBD. Concernant +PostgreSQL, la procédure de failback est aussi différente en fonction du +rôle de l'instance au moment de la défaillance. + +::: + +----- + +## Défaillance d'un secondaire + +* transition: `stop` -> `start` +* cas détecté par l'agent + * `notify` pré-stop: phase de recovery de PostgreSQL + +::: notes + +Un incident sur un standby est traité par le cluster par une action `recovery` +qui consiste à enchaîner les deux opérations `stop` et `start` ainsi que les +différentes actions `notify` pré et post opération. + +L'agent PAF détecte ces transitions de `recovery` du cluster sur le même nœud. +Il tente alors de corriger le crash de l'instance locale en la démarrant afin +que celle-ci puisse effectuer sa phase de _recovery_ usuelle. Cette opération +est réalisée en tout début de transition durant l'action `notify` pré-stop. + +![Primary recovery](medias/paf-standby-recover.png) + +::: + +----- + +### TP: Failover d'un secondaire + +::: notes + +Supprimer toutes éventuelles contraintes temporaires liées aux TP précédents. + +Ce TP simule d'abord un incident sur un secondaire, puis compare la simulation +avec la réalité. + +1. positionner le paramètre `migration-threshold` de pgsqld à `2` +2. créer un fichier de simulation `fail-secondary-0.xml` pour travailler dessus +3. injecter une erreur `soft` lors du monitor sur la ressource `pgsqld` de + `hanode3`. Enregistrer le résultat dans `fail-secondary-1.xml` +4. envoyer un signal SIGKILL aux processus `postgres` sur `hanode3` et vérifier + le comportement simulé +5. injecter la même erreur en utilisant comme situation de départ + `fail-secondary-1.xml` +6. Tuer une seconde fois les processus `postgres` sur `hanode3` +7. reproduire en simulation le comportement observé. Enregistrez les + résultats dans `fail-secondary-2.xml` puis `fail-secondary-3.xml` + +::: + +----- + +### Correction: Failover d'un secondaire + +::: notes + +Ce TP simule d'abord un incident sur un secondaire, puis compare la simulation +avec la réalité. + + +1. positionner le paramètre `migration-threshold` de pgsqld à `2` + +~~~console +# pcs resource update pgsqld meta migration-threshold=2 +~~~ + +2. créer un fichier de simulation `fail-secondary-0.xml` pour travailler dessus + +~~~console +# pcs cluster cib fail-secondary-0.xml +~~~ + +3. injecter une erreur `soft` lors du monitor sur la ressource `pgsqld` de + `hanode3`. Enregistrer le résultat dans `fail-secondary-1.xml` + +~~~console +# crm_simulate --simulate \ + --xml-file=fail-secondary-0.xml \ + --save-output=fail-secondary-1.xml \ + --op-inject=pgsqld_monitor_16000@hanode3=1 + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 + +Performing requested modifications + + Injecting pgsqld_monitor_15000@hanode3=1 into the configuration + + Injecting attribute fail-count-pgsqld#monitor_15000=value++ into /node_state '3' + + Injecting attribute last-failure-pgsqld#monitor_15000=1585235516 into /node_state '3' + +Transition Summary: + * Recover pgsqld:0 ( Slave hanode3 ) + +Executing cluster transition: + * Cluster action: clear_failcount for pgsqld on hanode3 + * Pseudo action: pgsqld-clone_pre_notify_stop_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_stop_0 + * Pseudo action: pgsqld-clone_stop_0 + * Resource action: pgsqld stop on hanode3 + * Pseudo action: pgsqld-clone_stopped_0 + * Pseudo action: pgsqld-clone_post_notify_stopped_0 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-post_notify_stopped_0 + * Pseudo action: pgsqld-clone_pre_notify_start_0 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_start_0 + * Pseudo action: pgsqld-clone_start_0 + * Resource action: pgsqld start on hanode3 + * Pseudo action: pgsqld-clone_running_0 + * Pseudo action: pgsqld-clone_post_notify_running_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-post_notify_running_0 + * Resource action: pgsqld monitor=16000 on hanode3 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +Le cluster redémarre l'instance sur le même nœud. Son `failcount` est +incrémenté de `1`. + +La transition effectue bien une action `stop` suivie d'une action `start`. + +~~~console +# pcs -f fail-secondary-1.xml resource failcount show pgsqld +Failcounts for resource 'pgsqld' + hanode3: 1 +~~~ + +4. envoyer un signal `SIGKILL` aux processus `postgres` sur `hanode3` et vérifier + le comportement simulé + +~~~console +# pkill -SIGKILL postgres +~~~ + +Le comportement simulé est bien le même que celui observé. + +~~~console +# pcs resource failcount show pgsqld +Failcounts for resource 'pgsqld' + hanode3: 1 + +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +5. injecter la même erreur en utilisant comme situation de départ + `fail-secondary-1.xml` + +~~~console +# crm_simulate --simulate \ + --xml-file=fail-secondary-1.xml \ + --save-output=fail-secondary-2.xml \ + --op-inject=pgsqld_monitor_16000@hanode3=1 + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 + +Performing requested modifications + + Injecting pgsqld_monitor_16000@hanode3=1 into the configuration + + Injecting attribute fail-count-pgsqld#monitor_16000=value++ into /node_state '3' + + Injecting attribute last-failure-pgsqld#monitor_16000=1585243357 into /node_state '3' + +Transition Summary: + * Stop pgsqld:0 ( Slave hanode3 ) due to node availability + +Executing cluster transition: + * Cluster action: clear_failcount for pgsqld on hanode3 + * Pseudo action: pgsqld-clone_pre_notify_stop_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_stop_0 + * Pseudo action: pgsqld-clone_stop_0 + * Resource action: pgsqld stop on hanode3 + * Pseudo action: pgsqld-clone_stopped_0 + * Pseudo action: pgsqld-clone_post_notify_stopped_0 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-post_notify_stopped_0 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 ] + Stopped: [ hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +Le `failcount` ayant atteint la valeur de `migration-threshold`, la ressource +doit quitter le nœud. Néanmoins, tous les autres nœuds possédant déjà un +clone et le paramètre `clone-node-max` étant à `1`, ce troisème clone ne peut +démarrer nulle part. + +~~~console +# pcs -f fail-secondary-2.xml resource failcount show pgsqld +Failcounts for resource 'pgsqld' + hanode3: 2 +~~~ + +6. Tuer une seconde fois les processus `postgres` sur `hanode3` + +~~~console +# pkill -SIGKILL postgres +~~~ + +Cette fois-ci, le comportement est différent. La ressource n'est pas +simplement isolée, c'est tout le nœud `hanode3` est isolé. + +~~~console +# pcs status nodes +Pacemaker Nodes: + Online: hanode1 hanode2 + Standby: + Maintenance: + Offline: hanode3 +[...] +~~~ + +Les log de `hanode3` montrent les erreurs suivantes: + +~~~ +lrmd[3248]: info: executing - rsc:pgsqld action:stop call_id:85 +pgsqlms(pgsqld): ERROR: Instance "pgsqld" controldata indicates a running secondary instance, the instance has probably crashed +pgsqlms(pgsqld): ERROR: Unexpected state for instance "pgsqld" (returned 1) +lrmd[3248]: info: finished - rsc:pgsqld action:stop call_id:85 pid:9962 exit-code:1 exec-time:161ms queue-time:0ms +~~~ + +L'agent PAF est très stricte et contrôle l'état de l'instance avant chaque +opération. Lors de l'opération stop, il détecte que l'instance se trouve +dans un état incohérent et lève alors une erreur. + +À partir de cette erreur, les log du DC présentent les messages suivants: + +~~~ +crmd: warning: status_from_rc: Action 2 (pgsqld_stop_0) on hanode3 failed (target: 0 vs. rc: 1): Error + +pengine: warning: Processing failed stop of pgsqld:0 on hanode3: unknown error | rc=1 +pengine: warning: Cluster node hanode3 will be fenced: pgsqld:0 failed there +pengine: warning: Scheduling Node hanode3 for STONITH +pengine: notice: Stop of failed resource pgsqld:0 is implicit after hanode3 is fenced +pengine: notice: * Fence (reboot) hanode3 'pgsqld:0 failed there' +pengine: info: Leave fence_vm_hanode1 (Started hanode2) +pengine: info: Leave fence_vm_hanode2 (Started hanode1) +pengine: info: Leave fence_vm_hanode3 (Started hanode1) +pengine: notice: * Stop pgsqld:0 (Slave hanode3 ) +pengine: info: Leave pgsqld:1 (Master hanode1) +pengine: info: Leave pgsqld:2 (Slave hanode2) +pengine: info: Leave pgsql-master-ip (Started hanode1) +pengine: warning: Calculated transition 75 (with warnings), saving inputs in /var/lib/pacemaker/pengine/pe-warn-0.bz2 + +crmd: notice: te_fence_node: Requesting fencing (reboot) of node hanode3 +stonith-ng: notice: initiate_remote_stonith_op: Requesting peer fencing (reboot) of hanode3 +stonith-ng: notice: crm_update_peer_state_iter: Node hanode3 state is now lost | nodeid=3 previous=member source=crm_update_peer_proc +crmd: notice: crm_update_peer_state_iter: Node hanode3 state is now lost +~~~ + +Une nouvelle transition est calculée et l'opération `stop` est "promue" en +fencing. + +7. reproduire en simulation le comportement observé. Enregistrez les + résultats dans `fail-secondary-2.xml` puis `fail-secondary-3.xml` + +~~~console +# crm_simulate --simulate \ + --xml-file=fail-secondary-1.xml \ + --save-output=fail-secondary-2.xml \ + --op-inject=pgsqld_monitor_16000@hanode3=1 \ + --op-fail=pgsqld_stop_0@hanode3=1 +[...] +Performing requested modifications + + Injecting pgsqld_monitor_16000@hanode3=1 into the configuration + + Injecting attribute fail-count-pgsqld#monitor_16000=value++ into /node_state '3' + + Injecting attribute last-failure-pgsqld#monitor_16000=1585245905 into /node_state '3' + +Transition Summary: + * Stop pgsqld:0 ( Slave hanode3 ) due to node availability + +Executing cluster transition: + * Cluster action: clear_failcount for pgsqld on hanode3 + * Pseudo action: pgsqld-clone_pre_notify_stop_0 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_stop_0 + * Pseudo action: pgsqld-clone_stop_0 + * Resource action: pgsqld stop on hanode3 + Pretending action 2 failed with rc=1 + + Injecting attribute fail-count-pgsqld#stop_0=value++ into /node_state '3' + + Injecting attribute last-failure-pgsqld#stop_0=1585245905 into /node_state '3' + * Pseudo action: pgsqld-clone_stopped_0 + * Pseudo action: pgsqld-clone_post_notify_stopped_0 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-post_notify_stopped_0 + +Revised cluster status: +Node hanode3 (3): UNCLEAN (online) +Online: [ hanode1 hanode2 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + pgsqld (ocf::heartbeat:pgsqlms): FAILED hanode3 + Masters: [ hanode1 ] + Slaves: [ hanode2 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 + +# crm_simulate --simulate \ + --xml-file=fail-secondary-2.xml \ + --save-output=fail-secondary-3.xml + +Current cluster status: +Node hanode3 (3): UNCLEAN (online) +Online: [ hanode1 hanode2 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + pgsqld (ocf::heartbeat:pgsqlms): FAILED hanode3 + Masters: [ hanode1 ] + Slaves: [ hanode2 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 + +Transition Summary: + * Fence (reboot) hanode3 'pgsqld:0 failed there' + * Stop pgsqld:0 ( Slave hanode3 ) due to node availability + +Executing cluster transition: + * Pseudo action: pgsqld-clone_pre_notify_stop_0 + * Fencing hanode3 (reboot) + * Pseudo action: pgsqld_post_notify_stop_0 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_stop_0 + * Pseudo action: pgsqld-clone_stop_0 + * Pseudo action: pgsqld_stop_0 + * Pseudo action: pgsqld-clone_stopped_0 + * Pseudo action: pgsqld-clone_post_notify_stopped_0 + * Resource action: pgsqld notify on hanode1 + * Resource action: pgsqld notify on hanode2 + * Pseudo action: pgsqld-clone_confirmed-post_notify_stopped_0 + * Pseudo action: pgsqld_notified_0 + +Revised cluster status: +Online: [ hanode1 hanode2 ] +OFFLINE: [ hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 ] + Stopped: [ hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +::: + +----- + +## Failback d'un secondaire + +* suite à un incident sur la ressource ou la perte de son nœud +* état incohérent de l'instance: statut différent du `pg_control` +* PAF lève une erreur systématiquement pour toutes les opérations +* une erreur sur l'action `stop` conduit à un fencing +* conclusion: placer l'instance dans un état stable +1. positionner la ressource en `is-managed=false` +2. ré-intégrer le nœud dans le cluster +3. démarrer la ressource manuellement, puis l'arrêter (état stable) +4. effectuer un `refresh` de la ressource +5. positionner `is-managed=true` pour la ressource + +::: notes + +Suite au crash d'une instance secondaire, si le cluster n'a pas réussi à +l'arrêter localement, le serveur entier a dû être isolé (cf TP +[Correction: Défaillance d'un secondaire]). L'instance est alors dans un état +instable: son fichier interne `pg_control` indique un statut `in archive +recovery` alors que cette dernière n'est pas démarrée et n'accepte aucune +connexion. + +Dans cette situation, l'agent retourne une erreur pour toutes les opérations. +Au démarrage du cluster sur le nœud concerné, ce dernier va vouloir +contrôler l'état des ressources sur ce nœud et l'opération de `probe` +(l'opération `monitor` non récurrente) va retourner une erreur. + +Il est même possible que le cluster tente d'effectuer un `recovery` de la +ressource en effectuant les opérations `stop` puis `start`. Dans ce cas là, +le nœud se fait une nouvelle fois isoler. + +Pour ré-intégrer le nœud et la ressource, l'idéal est de suivre la +procédure suivante: + +1. positionner `is-managed=false` pour la ressource +2. démarrer le cluster sur le nœud à ré-intégrer +3. démarrer manuellement l'instance sur le nœud +4. valider que cette dernière réplique correctement +5. arrêter l'instance +6. effectuer une commande `refresh` de la ressource +7. supprimer `is-managed=false` pour la ressource + +Pour plus de facilité, il est possible d'utiliser ici `systemctl` pour +démarrer et arrêter la ressource. L'important est qu'en fin de procédure, +`systemd` ne voit pas l'instance comme étant démarrée de son point vue, +cette dernière étant gérée non pas par lui mais par Pacemaker. + +::: + +----- + +### TP: Failback d'un secondaire + +::: notes + +1. désactiver la gestion du cluster de `pgsqld-clone` +2. démarrer le cluster sur `hanode3` +3. démarrer manuellement l'instance PostgreSQL sur `hanode3` +4. valider que cette dernière réplique correctement +5. arrêter l'instance +6. effectuer une commande `refresh` de `pgsqld` +7. supprimer `is-managed=false` pour la ressource + +::: + +----- + +### Correction: Failback d'un secondaire + +::: notes + +1. désactiver la gestion du cluster de `pgsqld-clone` + +~~~console +# pcs resource unmanage pgsqld-clone +~~~ + +2. démarrer le cluster sur `hanode3` + +~~~console +# pcs cluster start +~~~ + +Attendre que le nœud soit bien ré-intégré dans le cluster. + +3. démarrer manuellement l'instance PostgreSQL sur `hanode3` + +~~~console +# systemctl start postgresql-12 +~~~ + +4. valider que cette dernière réplique correctement + +Depuis l'instance primaire, la ressource est détectée comme démarrée et +PostgreSQL nous indique qu'elle réplique correctement: + +~~~console +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode2 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode3 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Master hanode1 (unmanaged) + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 + +# sudo -iu postgres psql +postgres=# select state, application_name + from pg_stat_replication + where application_name = 'hanode3'; + state | application_name +-----------+------------------ + streaming | hanode3 +(1 row) +~~~ + +5. arrêter l'instance + +~~~console +# systemctl stop postgresql-12 +# systemctl show -p ActiveState postgresql-12 +ActiveState=inactive +~~~ + +Après vérification, plus aucun processus `postgres` n'est démarré. Son +statut est cohérent: + +~~~console +# /usr/pgsql-12/bin/pg_controldata /var/lib/pgsql/12/data/|grep state +Database cluster state: shut down in recovery +~~~ + +6. effectuer une commande `refresh` de `pgsqld` + +~~~console +# pcs resource failcount show pgsqld hanode3 +Failcounts for resource 'pgsqld' on node 'hanode3' + hanode3: 3 + +# pcs resource refresh pgsqld --node=hanode3 +Cleaned up pgsqld:0 on hanode3 +Cleaned up pgsqld:1 on hanode3 +Cleaned up pgsqld:2 on hanode3 + + * The configuration prevents the cluster from stopping or starting 'pgsqld-clone' (unmanaged) +Waiting for 3 replies from the CRMd... OK + +# pcs resource failcount show pgsqld hanode3 +No failcounts for resource 'pgsqld' on node 'hanode3' +~~~ + +Toutes les erreurs sont supprimées et le failcount est remis à 0. + +7. supprimer `is-managed=false` pour la ressource + +~~~console +# pcs resource manage pgsqld-clone +~~~ + +La ressource est démarrée sur `hanode3`. + +::: + +----- + +## Défaillance du primaire + +1. transaction calculée + * `demote` -> `stop` -> `start` -> `promote` +2. fencing du nœud hébergeant l'instance primaire en échec si nécessaire +3. si migration, promotion du secondaire avec le meilleur master score + 1. le secondaire désigné compare les `LSN` des secondaires + 2. poursuite de la promotion s'il est toujours le plus avancé + 3. sinon, annulation de la promotion et nouvelle transition + +::: notes + +En cas d'incident concernant l'instance primaire, la transition calculée +effectue les quatre opérations suivantes dans cet ordre: `demote`, `stop`, +`start` et `promote`. Ici aussi, les différentes actions `notify` pré et post +opération sont bien entendu exécutées. + +Comme pour un secondaire, l'agent PAF détecte une transition effectuant ces +opérations sur l'instance primaire sur un même nœud. Dans ce cas là, l'agent +tente alors de corriger le crash de l'instance locale en la démarrant afin que +celle-ci puisse effectuer sa phase de _recovery_ usuelle. Cette opération est +réalisée en tout début de transition durant l'action `notify` pré-demote. + +![Primary recovery](medias/paf-primary-recover.png) + +Le choix de l'instance à promouvoir se fait en fonction des derniers master +scores connus. Afin de s'assurer que le secondaire désigné est bien toujours le +plus avancé dans la réplication, une élection est cependant déclenchée. En +voici les étapes: + +1. opération `notify` pré-promote: chaque secondaire positionne son `LSN` + courant dans un attribut de nœud +2. opération `promote`: l'instance désignée pour la promotion vérifie qu'il a + bien le LSN le plus avancé +3. si un LSN plus avancé est trouvé: + * il positionne son master score à `1` + * il positionne le master score du secondaire plus avancé à `1000` + * il lève une erreur + * la transition est annulée et une nouvelle est calculée + * retour à l'étape 1. + +![Primary recovery](medias/paf-election.png) + +::: + +----- + +### TP: Failover du primaire + +::: notes + +1. simuler une erreur `soft` pour `pgsqld-clone` sur `hanode1` +2. tuer tous les processus PostgreSQL avec un signal `KILL` +3. étudier la réaction du cluster +4. nettoyer les `failcount` de `pgsqld-clone` +5. simuler une erreur `OCF_ERR_ARGS` sur `pgsqld-clone` +6. supprimer le fichier `/var/lib/pgsql/12/data/global/pg_control` sur `hanode1` +7. étudier la réaction du cluster + +::: + +----- + +### Correction: Failover du primaire + +::: notes + +1. simuler une erreur `soft` pour `pgsqld-clone` sur `hanode1` + +~~~console +# crm_simulate --simulate --live --op-inject=pgsqld_monitor_15000@hanode1=1 + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 + +Performing requested modifications + + Injecting pgsqld_monitor_15000@hanode1=1 into the configuration + + Injecting attribute fail-count-pgsqld#monitor_15000=value++ into /node_state '1' + + Injecting attribute last-failure-pgsqld#monitor_15000=1585328861 into /node_state '1' + +Transition Summary: + * Recover pgsqld:2 ( Master hanode1 ) + +Executing cluster transition: + * Cluster action: clear_failcount for pgsqld on hanode1 + * Pseudo action: pgsqld-clone_pre_notify_demote_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_demote_0 + * Pseudo action: pgsqld-clone_demote_0 + * Resource action: pgsqld demote on hanode1 + * Pseudo action: pgsqld-clone_demoted_0 + * Pseudo action: pgsqld-clone_post_notify_demoted_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-post_notify_demoted_0 + * Pseudo action: pgsqld-clone_pre_notify_stop_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_stop_0 + * Pseudo action: pgsqld-clone_stop_0 + * Resource action: pgsqld stop on hanode1 + * Pseudo action: pgsqld-clone_stopped_0 + * Pseudo action: pgsqld-clone_post_notify_stopped_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Pseudo action: pgsqld-clone_confirmed-post_notify_stopped_0 + * Pseudo action: pgsqld-clone_pre_notify_start_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_start_0 + * Pseudo action: pgsqld-clone_start_0 + * Resource action: pgsqld start on hanode1 + * Pseudo action: pgsqld-clone_running_0 + * Pseudo action: pgsqld-clone_post_notify_running_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-post_notify_running_0 + * Pseudo action: pgsqld-clone_pre_notify_promote_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_promote_0 + * Pseudo action: pgsqld-clone_promote_0 + * Resource action: pgsqld promote on hanode1 + * Pseudo action: pgsqld-clone_promoted_0 + * Pseudo action: pgsqld-clone_post_notify_promoted_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-post_notify_promoted_0 + * Resource action: pgsqld monitor=15000 on hanode1 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 +~~~ + +Un `recover` est planifié pour `pgsqld` sur `hanode1`. Ce dernier correspond +aux opérations suivantes dans cet ordre: + +Action Sub-action Nœud(s) +---------- ------------ --------------------------------- + `notify` pre-demote `hanode1`, `hanode2`, `hanode3` + `demote` N/A `hanode1` + `notify` post-demote `hanode1`, `hanode2`, `hanode3` + `notify` pre-stop `hanode1`, `hanode2`, `hanode3` + `stop` N/A `hanode1` + `notify` post-stop `hanode2`, `hanode3` + `notify` pre-start `hanode2`, `hanode3` + `start` N/A `hanode1` + `notify` post-start `hanode1`, `hanode2`, `hanode3` + `notify` pre-promote `hanode1`, `hanode2`, `hanode3` + `promote` N/A `hanode1` + `notify` post-promote `hanode1`, `hanode2`, `hanode3` + +2. tuer tous les processus PostgreSQL avec un signal `KILL` + +~~~console +# pkill -SIGKILL postgres +~~~ + +3. étudier la réaction du cluster + +L'agent `pgsqlms` détecte que l'instance a a été interrompue brusquement: + +~~~ +pgsqlms(pgsqld): DEBUG: _confirm_stopped: no postmaster process found for instance "pgsqld" +pgsqlms(pgsqld): DEBUG: _controldata: instance "pgsqld" state is "in production" +pgsqlms(pgsqld): ERROR: Instance "pgsqld" controldata indicates a running primary instance, the instance has probably crashed +~~~ + +En réaction, `pengine` décide de redémarrer l'instance sur le même nœud +(sur le DC): + +~~~ +pengine: info: Start recurring monitor (15s) for pgsqld:1 on hanode1 +pengine: info: Leave fence_vm_hanode1 (Started hanode2) +pengine: info: Leave fence_vm_hanode2 (Started hanode1) +pengine: info: Leave fence_vm_hanode3 (Started hanode1) +pengine: info: Leave pgsqld:0 (Slave hanode2 ) +pengine: notice: * Recover pgsqld:1 (Master hanode1 ) +pengine: info: Leave pgsqld:2 (Slave hanode3 ) +pengine: info: Leave pgsql-master-ip (Started hanode1) +~~~ + +Durant l'opération `notify` pré-demote, l'agent tente un recovery de +l'instance afin de la remettre en ordre de marche: + +~~~ +pgsqlms(pgsqld): INFO: Trying to start failing master "pgsqld"... +[...] +pgsqlms(pgsqld): INFO: State is "in production" after recovery attempt +~~~ + +Le reste de la transition se déroule comme prévu et l'instance revient bien +en production. Le comportement est bien le même que celui simulé. Voici les +actions déclenchées par le DC (log remis en forme): + +~~~ +# grep -E 'crmd:.*Initiating' /var/log/cluster/corosync.log +[...] +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode1 +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode2 +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode3 + +crmd: notice: Initiating demote pgsqld_demote_0 locally on hanode1 + +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode1 +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode2 +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode3 + +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode1 +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode2 +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode3 + +crmd: notice: Initiating stop pgsqld_stop_0 locally on hanode1 + +crmd: notice: Initiating notify pgsqld_post_notify_stop_0 on hanode2 +crmd: notice: Initiating notify pgsqld_post_notify_stop_0 on hanode3 + +crmd: notice: Initiating notify pgsqld_pre_notify_start_0 on hanode2 +crmd: notice: Initiating notify pgsqld_pre_notify_start_0 on hanode3 + +crmd: notice: Initiating start pgsqld_start_0 locally on hanode1 + +crmd: notice: Initiating notify pgsqld_post_notify_start_0 on hanode1 +crmd: notice: Initiating notify pgsqld_post_notify_start_0 on hanode2 +crmd: notice: Initiating notify pgsqld_post_notify_start_0 on hanode3 + +crmd: notice: Initiating notify pgsqld_pre_notify_promote_0 on hanode1 +crmd: notice: Initiating notify pgsqld_pre_notify_promote_0 on hanode2 +crmd: notice: Initiating notify pgsqld_pre_notify_promote_0 on hanode3 + +crmd: notice: Initiating promote pgsqld_promote_0 locally on hanode1 + +crmd: notice: Initiating notify pgsqld_post_notify_promote_0 on hanode1 +crmd: notice: Initiating notify pgsqld_post_notify_promote_0 on hanode2 +crmd: notice: Initiating notify pgsqld_post_notify_promote_0 on hanode3 +~~~ + +4. nettoyer les `failcount` de `pgsqld-clone` + +~~~console +# pcs resource failcount reset pgsqld +~~~ + +5. simuler une erreur `OCF_ERR_ARGS` sur `pgsqld-clone` + +Le code retour `OCF_ERR_ARGS` correspond à une erreur de niveau `hard`. Ainsi, +bien que le `migration-threshold` ne soit pas atteint, le cluster doit basculer +l'instance ailleurs. + +~~~console +# crm_simulate --simulate --live --op-inject=pgsqld_monitor_15000@hanode1=2 + +Current cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode1 ] + Slaves: [ hanode2 hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode1 + +Performing requested modifications + + Injecting pgsqld_monitor_15000@hanode1=2 into the configuration + + Injecting attribute fail-count-pgsqld#monitor_15000=value++ into /node_state '1' + + Injecting attribute last-failure-pgsqld#monitor_15000=1585330828 into /node_state '1' + +Transition Summary: + * Promote pgsqld:0 ( Slave -> Master hanode2 ) + * Stop pgsqld:2 ( Master hanode1 ) due to node availability + * Move pgsql-master-ip ( hanode1 -> hanode2 ) + +Executing cluster transition: + * Resource action: pgsqld cancel=16000 on hanode2 + * Cluster action: clear_failcount for pgsqld on hanode1 + * Pseudo action: pgsqld-clone_pre_notify_demote_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_demote_0 + * Pseudo action: pgsqld-clone_demote_0 + * Resource action: pgsqld demote on hanode1 + * Pseudo action: pgsqld-clone_demoted_0 + * Pseudo action: pgsqld-clone_post_notify_demoted_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-post_notify_demoted_0 + * Pseudo action: pgsqld-clone_pre_notify_stop_0 + * Resource action: pgsql-master-ip stop on hanode1 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Resource action: pgsqld notify on hanode1 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_stop_0 + * Pseudo action: pgsqld-clone_stop_0 + * Resource action: pgsqld stop on hanode1 + * Pseudo action: pgsqld-clone_stopped_0 + * Pseudo action: pgsqld-clone_post_notify_stopped_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Pseudo action: pgsqld-clone_confirmed-post_notify_stopped_0 + * Pseudo action: pgsqld-clone_pre_notify_promote_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Pseudo action: pgsqld-clone_confirmed-pre_notify_promote_0 + * Pseudo action: pgsqld-clone_promote_0 + * Resource action: pgsqld promote on hanode2 + * Pseudo action: pgsqld-clone_promoted_0 + * Pseudo action: pgsqld-clone_post_notify_promoted_0 + * Resource action: pgsqld notify on hanode2 + * Resource action: pgsqld notify on hanode3 + * Pseudo action: pgsqld-clone_confirmed-post_notify_promoted_0 + * Resource action: pgsql-master-ip start on hanode2 + * Resource action: pgsqld monitor=15000 on hanode2 + * Resource action: pgsql-master-ip monitor=10000 on hanode2 + +Revised cluster status: +Online: [ hanode1 hanode2 hanode3 ] + + fence_vm_hanode1 (stonith:fence_virsh): Started hanode2 + fence_vm_hanode2 (stonith:fence_virsh): Started hanode1 + fence_vm_hanode3 (stonith:fence_virsh): Started hanode1 + Master/Slave Set: pgsqld-clone [pgsqld] + Masters: [ hanode2 ] + Slaves: [ hanode3 ] + Stopped: [ hanode1 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode2 +~~~ + +6. supprimer le fichier `/var/lib/pgsql/12/data/global/pg_control` sur `hanode1` + +~~~console +# rm -f /var/lib/pgsql/12/data/global/pg_control +~~~ + +7. étudier la réaction du cluster + +Le cluster prévoie la même transition que celle simulée. Cependant, à cause +de l'état incohérent de l'instance, les opération `demote` et `stop` +interrompent deux transitions et la dernière erreur provoque l'isolation de +`hanode1`. + +Première transition, correspondant à ce qui avait été simulé: + +~~~ +pengine: notice: * Stop pgsqld:0 ( Master hanode1 ) +pengine: info: Leave pgsqld:1 ( Slave hanode3 ) +pengine: notice: * Promote pgsqld:2 ( Slave -> Master hanode2 ) +pengine: notice: * Move pgsql-master-ip ( hanode1 -> hanode2 ) + +crmd: debug: Unpacked transition 136: 41 actions in 41 synapses + +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode1 +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode2 +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode3 + +crmd: notice: Initiating demote pgsqld_demote_0 on hanode1 +crmd: warning: Action 15 (pgsqld_demote_0) on hanode2 failed + +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode1 +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode2 +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode3 +~~~ + +La seconde transition prévoit de terminer l'arrêt de l'instance sur `hanode1` +puis d'effectuer la promotion sur `hanode2`. Elle termine en erreur sur +l'opération `stop`: + +~~~ +pengine: notice: * Stop pgsqld:0 ( Slave hanode1 ) +pengine: info: Leave pgsqld:1 ( Slave hanode3 ) +pengine: notice: * Promote pgsqld:2 ( Slave -> Master hanode2 ) +pengine: notice: * Stop pgsql-master-ip ( hanode1 ) + +crmd: debug: Unpacked transition 137: 24 actions in 24 synapses + +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode1 +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode2 +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode3 + +crmd: notice: Initiating stop pgsqld_stop_0 on hanode1 +crmd: warning: Action 3 (pgsqld_stop_0) on hanode1 failed + +crmd: notice: Initiating notify pgsqld_post_notify_stop_0 on hanode3 +crmd: notice: Initiating notify pgsqld_post_notify_stop_0 on hanode2 +~~~ + +La troisième transition prévoie d'isoler `hanode1` afin de s'assurer que +l'instance est bien arrêtée, puis de promouvoir l'instance sur `hanode2` et y +déplacer l'adresse IP virtuelle. Cette dernière arrive au bout: + +~~~ +pengine: notice: * Fence (reboot) hanode2 'pgsqld:0 failed there' +pengine: notice: * Stop pgsqld:0 ( Master hanode1 ) +pengine: info: Leave pgsqld:1 ( Slave hanode3 ) +pengine: notice: * Promote pgsqld:2 ( Slave -> Master hanode2 ) +pengine: notice: * Move pgsql-master-ip ( hanode2 -> hanode2 ) + +crmd: debug: Unpacked transition 138: 43 actions in 43 synapses + +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode3 +crmd: notice: Initiating notify pgsqld_pre_notify_demote_0 on hanode2 + +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode3 +crmd: notice: Initiating notify pgsqld_post_notify_demote_0 on hanode2 + +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode3 +crmd: notice: Initiating notify pgsqld_pre_notify_stop_0 on hanode2 + +crmd: notice: Initiating notify pgsqld_post_notify_stop_0 on hanode3 +crmd: notice: Initiating notify pgsqld_post_notify_stop_0 on hanode2 + +crmd: notice: Initiating notify pgsqld_pre_notify_promote_0 on hanode3 +crmd: notice: Initiating notify pgsqld_pre_notify_promote_0 on hanode2 + +crmd: notice: Initiating promote pgsqld_promote_0 on hanode2 + +crmd: notice: Initiating notify pgsqld_post_notify_promote_0 on hanode3 +crmd: notice: Initiating notify pgsqld_post_notify_promote_0 on hanode2 +~~~ + +Dans les log, nous trouvons aussi les traces de l'élection qui a lieu entre +`hanode2` et `hanode3`: + +~~~ +attrd: info:Setting lsn_location-pgsqld[hanode2]: (null) -> 21#100672008 +attrd: info:Setting lsn_location-pgsqld[hanode3]: (null) -> 21#100672008 +[...] +pgsqlms(pgsqld): DEBUG: checking if current node is the best candidate for promotion +pgsqlms(pgsqld): DEBUG: comparing with "hanode3": TL#LSN is 21#100672008 +pgsqlms(pgsqld): INFO: Promote complete +~~~ + +::: + + +----- + +## Failback du primaire + +* suite à un incident sur la ressource ou la perte de son nœud +* même problématique que pour un secondaire +* l'instance doit en plus être reconstruite en secondaire +* le reste de la procédure est similaire au failback d'un secondaire + +::: notes + +Suite à la perte brutale d'une instance primaire, le cluster bascule le rôle +`Master` sur le meilleur secondaire disponible. Néanmoins, il est possible que +l'ancien primaire possède toujours des données qui n'avaient pas été +répliquées. Dans ces circonstances, il n'est pas recommandé de rattacher +directement l'ancien primaire au nouveau. Il est nécessaire de le +"resynchroniser". + +Différentes méthodes sont disponibles mais ne sont pas abordées dans ce +document. Par exemple: `pg_rewind`, restauration _PITR_ ou `pg_basebackup`. + +Une fois l'instance resynchronisée, le reste de la procédure est identique à +celle détaillée dans le chapitre [Failback d'un secondaire]: + +1. re-synchroniser l'instance sur le nœud +2. positionner `is-managed=false` pour la ressource +3. démarrer le cluster sur le nœud à ré-intégrer +4. démarrer manuellement l'instance sur le nœud +5. valider que cette dernière réplique correctement +6. arrêter l'instance +7. effectuer une commande `refresh` de la ressource +8. supprimer `is-managed=false` pour la ressource + +Pour plus de facilité, il est possible d'utiliser ici `systemctl` pour +démarrer et arrêter la ressource. L'important est qu'en fin de procédure, +`systemd` ne voit pas l'instance comme étant démarrée de son point vue, +cette dernière étant gérée non pas par lui mais par Pacemaker. + +::: + +----- + +### TP: Failback du primaire + +::: notes + +1. re-synchroniser l'instance `hanode1` +2. désactiver la gestion du cluster de `pgsqld-clone` +3. démarrer le cluster sur `hanode1` +4. démarrer manuellement l’instance PostgreSQL sur `hanode1` +5. valider que cette dernière réplique correctement +6. arrêter l’instance sur `hanode1` +7. effectuer une commande `refresh` de `pgsqld` +8. supprimer `is-managed=false` pour la ressource + +::: + +----- + +### Correction: Failback du primaire + +::: notes + +1. re-synchroniser l'instance `hanode1` + +~~~console +# su - postgres +$ rm -r ~postgres/12/data/* +$ /usr/pgsql-12/bin/pg_basebackup -h 10.20.30.5 -D ~postgres/12/data/ -P +$ touch ~postgres/12/data/standby.signal +~~~ + +NB: le paramètre `primary_conninfo` ou le fichier `pg_hba.conf` n'ont pas à +être corrigés, ces derniers étant positionnés en dehors du `PGDATA`. + +2. désactiver la gestion du cluster de `pgsqld-clone` + +~~~console +# pcs resource unmanage pgsqld-clone +~~~ + +3. démarrer le cluster sur `hanode1` + +~~~console +# pcs cluster start +~~~ + +4. démarrer manuellement l’instance PostgreSQL sur `hanode1` + +~~~console +# systemctl start postgresql-12 +~~~ + +5. valider que cette dernière réplique correctement + +Depuis `hanode2`, la ressource n'est détectée comme démarrée, cette +dernière étant arrêté lors du démarrage du cluster sur `hanode1`. Le nœud +ayant été redémarré, il n'y a pas non plus d'opération `monitor` +récurrente pour `pgsqld` sur `hanode1`. + +~~~console +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + pgsqld (ocf::heartbeat:pgsqlms): Master hanode2 (unmanaged) + pgsqld (ocf::heartbeat:pgsqlms): Slave hanode3 (unmanaged) + Stopped: [ hanode1 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode2 + +# sudo -iu postgres psql +postgres=# select state, application_name + from pg_stat_replication + where application_name = 'hanode1'; + state | application_name +-----------+------------------ + streaming | hanode1 + +(1 row) +~~~ + +6. arrêter l’instance sur `hanode1` + +~~~console +# systemctl stop postgresql-12 +~~~ + +Attendre que Pacemaker détecte l'arrêt de l'instance. + +7. effectuer une commande `refresh` de `pgsqld` + +~~~console +# pcs resource failcount show pgsqld hanode1 +Failcounts for resource 'pgsqld' on node 'hanode1' + hanode1: 2 + +# pcs resource refresh pgsqld --node=hanode1 +Cleaned up pgsqld:0 on hanode1 +Cleaned up pgsqld:1 on hanode1 +Cleaned up pgsqld:2 on hanode1 + + * The configuration prevents the cluster from stopping or starting 'pgsqld-clone' (unmanaged) +Waiting for 3 replies from the CRMd... OK + +# pcs resource failcount show pgsqld hanode1 +No failcounts for resource 'pgsqld' on node 'hanode1' +~~~ + +8. supprimer `is-managed=false` pour la ressource + +~~~console +# pcs resource manage pgsqld-clone +~~~ + +::: + +----- + +## Détails d'un switchover + +* opération planifiée +* macro-procédure: + 1. arrêt propre de l'instance primaire + 2. redémarrage de l'instance primaire en secondaire + 3. vérification du secondaire désigné + 4. élection et promotion du secondaire + +::: notes + +Dans le cadre de cette formation, un _switchover_ désigne la promotion +contrôlée d'une instance secondaire et le raccrochage de l'ancien primaire en +tant que secondaire, sans reconstruction. + +Le switchover s'appuie sur la procédure standard de PostgreSQL pour effectuer +la bascule.: + +* __Rétrograder le primaire__ + + Cette étape consiste à éteindre l'instance primaire et la redémarrer en tant + que secondaire. Avant qu'elle ne s'arrête, l'instance primaire envoie tous + les journaux de transactions nécessaires aux secondaires **connectées**. + + Cette étape est effectuée durant l'opération `demote`. +* __Contrôle du secondaire__ + + Cette étape consiste à vérifier sur le secondaire que tous les journaux de + transaction de l'ancien primaire ont bien été reçu, jusqu'au `shutdown + checkpoint`. + + L'agent interrompt la transition en cas d'échec de ces contrôle. Le cluster + décide alors que faire en fonction des contraintes en place. + + Cette étape est réalisée lors de l'opération `notify` exécutée juste + avant la promotion. +* __Promotion du secondaire__ + + Exécution de `pg_ctl promote` sur l'instance secondaire. Cette étape est + réalisée par l'opération `promote`. + +Le choix du secondaire à promouvoir dépend de la procédure choisie pour +déplacer le rôle. Il existe deux méthodes pour demander au cluster de +déplacer le rôle `Master` vers un autre nœud. + +La première consiste à bannir le rôle `Master` de son emplacement actuel. +Cela implique de positionner une contrainte location `-INFINITY` pour le +rôle `Master` sur son nœud courant. Attention, la contrainte concerne bien +le rôle et non la ressource ! Dans cette situation, le cluster choisi et +promeut alors le clone avec le master score le plus élevé. Cette procédure +se traduit avec les commandes `pcs` suivantes: + +~~~ +pcs resource ban --master +# ou +pcs resource move --master +~~~ + +La seconde méthode consiste à imposer l'emplacement du rôle `Master` avec +une contrainte de location `INFINITY` sur un nœud. Cette procédure +se traduit avec la commande `pcs` suivante: + +~~~ +pcs resource move --master +~~~ + +Dans ces commandes, `` désigne la ressource multi-state et non +le nom des clones. + +Dans les deux cas, il faut penser à supprimer ces contraintes après le +switchover avec la commande `pcs resource clear `. +L'utilisation de l'option `resource-stickiness` au niveau du cluster ou des +ressources permet à la ressource de rester sur son nouveau nœud après la +suppression de la contrainte de localisation. + +::: + +----- + +### TP: Switchover + +::: notes + +1. provoquer une bascule vers le nœud `hanode2` +2. afficher les contraintes pour la ressource `pgsqld-clone` +3. observer les scores au sein du cluster +4. retirer la contrainte positionnée par la bascule +5. observer la transition proposée dans les log du DC +6. répéter les même opérations en effectuant la bascule avec chacune des + commandes suivantes : + +~~~ +pcs resource move pgsqld-clone --master +pcs resource ban pgsqld-clone --master +~~~ + +Pour chacune, observer : + +* les contraintes posées par `pcs` +* le statut de la ressource sur le nœud où la contrainte est posée + +7. retirer les contraintes des commandes précédentes sur la ressource + +::: + +----- + +### Correction: Switchover + +::: notes + + +1. provoquer une bascule vers le nœud `hanode3` + +~~~console +# pcs resource move --master --wait pgsqld-clone hanode3 +Resource 'pgsqld-clone' is master on node hanode3; slave on nodes hanode1, hanode2. +~~~ + +2. afficher les contraintes pour la ressource `pgsqld-clone` + +~~~console +# pcs constraint location show resource pgsqld-clone +Location Constraints: + Resource: pgsqld-clone + Enabled on: hanode3 (score:INFINITY) (role: Master) +~~~ + +Une constrainte de localisation avec un poid `INFINITY` a été créée pour le +rôle `Master` de `pgsqld-clone` sur `hanode2`. + +3. observer les scores au sein du cluster + +~~~console +# crm_simulate -sL|grep 'promotion score' +pgsqld:0 promotion score on hanode3: INFINITY +pgsqld:2 promotion score on hanode1: 1000 +pgsqld:1 promotion score on hanode2: 990 + +~~~ + +Cette contrainte de localisation influence directement le score de promotion +calculé. + +4. retirer la contrainte positionnée par la bascule + +~~~console +# pcs resource clear pgsqld-clone + +# crm_simulate -sL|grep "promotion score" +pgsqld:0 promotion score on hanode3: 1003 +pgsqld:2 promotion score on hanode1: 1000 +pgsqld:1 promotion score on hanode2: 990 + +# pcs constraint location show resource pgsqld-clone +Location Constraints: +~~~ + +La situation revient à la normale et l'instance principale reste à son +nouvel emplacement. + +5. observer la transition proposée dans les log du DC + +~~~ +pengine: debug: Allocating up to 3 pgsqld-clone instances to a possible 3 nodes (at most 1 per host, 1 optimal) +pengine: debug: Assigning hanode1 to pgsqld:1 +pengine: debug: Assigning hanode2 to pgsqld:2 +pengine: debug: Assigning hanode3 to pgsqld:0 +pengine: debug: Allocated 3 pgsqld-clone instances of a possible 3 +pengine: debug: pgsqld:0 master score: 1000000 +pengine: info: Promoting pgsqld:0 (Slave hanode3) +pengine: debug: pgsqld:1 master score: 1001 +pengine: debug: pgsqld:2 master score: 990 +pengine: info: pgsqld-clone: Promoted 1 instances of a possible 1 to master +pengine: debug: Assigning hanode3 to pgsql-master-ip +pengine: info: Start recurring monitor (15s) for pgsqld:0 on hanode3 +pengine: info: Cancelling action pgsqld:0_monitor_16000 (Slave vs. Master) +pengine: info: Cancelling action pgsqld:1_monitor_15000 (Master vs. Slave) +pengine: info: Start recurring monitor (16s) for pgsqld:1 on hanode1 +pengine: info: Start recurring monitor (15s) for pgsqld:0 on hanode3 +pengine: info: Start recurring monitor (16s) for pgsqld:1 on hanode2 +pengine: info: Start recurring monitor (10s) for pgsql-master-ip on hanode3 +pengine: info: Leave fence_vm_hanode1 (Started hanode2) +pengine: info: Leave fence_vm_hanode2 (Started hanode1) +pengine: info: Leave fence_vm_hanode3 (Started hanode1) +pengine: notice: * Promote pgsqld:0 (Slave -> Master hanode3) +pengine: notice: * Demote pgsqld:1 (Master -> Slave hanode2) +pengine: info: Leave pgsqld:2 (Slave hanode1 ) +pengine: notice: * Move pgsql-master-ip (hanode2 -> hanode3 ) +~~~ + +6. répéter les même opérations en effectuant la bascule avec chacune des + commandes suivantes : + +~~~ +pcs resource move pgsqld-clone --master +pcs resource ban pgsqld-clone --master +~~~ + +Ces deux commandes sont similaires. Dans les deux cas, une contrainte de +localisation avec un score `-INFINITY` est positionnée pour le rôle `Master` +sur le nœud l'hébergeant. + +~~~console +# pcs resource ban --master --wait pgsqld-clone +Warning: Creating location constraint cli-ban-pgsqld-clone-on-hanode1 with a score of -INFINITY for resource pgsqld-clone on node hanode1. +This will prevent pgsqld-clone from being promoted on hanode1 until the constraint is removed. This will be the case even if hanode1 is the last node in the cluster. +Resource 'pgsqld-clone' is master on node hanode2; slave on nodes hanode1, hanode3. + +# pcs constraint location show resource pgsqld-clone +Location Constraints: + Resource: pgsqld-clone + Disabled on: hanode1 (score:-INFINITY) (role: Master) + + +# crm_simulate -sL|grep "promotion score" +pgsqld:1 promotion score on hanode1: 1001 +pgsqld:2 promotion score on hanode3: 990 +pgsqld:0 promotion score on hanode2: -INFINITY +~~~ + +7. retirer les contraintes des commandes précédentes sur la ressource + +~~~console +# pcs resource clear pgsqld-clone +# crm_simulate -sL|grep "promotion score" +pgsqld:2 promotion score on hanode1: 1001 +pgsqld:1 promotion score on hanode2: 1000 +pgsqld:0 promotion score on hanode3: 990 +~~~ + +::: + +----- + +# Supervision + +Ce chapitre aborde les différents axes de supervision d'un cluster Pacemaker. + +----- + +## Sondes + +* supervision basique avec `crm_mon` +* état du cluster avec `check_crm` (on pourrait ne pas remarquer les bascules!) + * [check_crm](https://exchange.nagios.org/directory/Plugins/Clustering-and-High-2DAvailability/Check-CRM/details) +* état des __rings__ corosync avec `check_corosync_rings` + * [check_corosync_rings](https://exchange.nagios.org/directory/Plugins/Clustering-and-High-2DAvailability/Check-Corosync-Rings/details) + +::: notes + +Il existe peu de projet permettant d'intégrer la supervision d'un cluster +Pacemaker au sein d'un système centralisé, eg. Nagios ou dérivés. Nous pouvons +citer `crm_mon`, `check_crm` ou `check_corosync_rings`. + +**crm\_mon** + +L'outil `crm_mon` est capable de produire une sortie adaptée à Nagios grâce +à l'argument `--simple-status`. Néanmoins, la remontée d'erreur est limitée +à la seule disponibilité des nœuds, mais pas des ressources. + +Voici un exemple avec le cluster dans son état normal: + +~~~console +# crm_mon --simple-status +CLUSTER OK: 3 nodes online, 7 resources configured +~~~ + +L'outil ne rapporte pas d'erreur en cas d'incident sur une ressource: + +~~~console +# killall postgres + +# pcs resource show + Master/Slave Set: pgsqld-clone [pgsqld] + pgsqld (ocf::heartbeat:pgsqlms): FAILED hanode1 + Masters: [ hanode2 ] + Slaves: [ hanode3 ] + pgsql-master-ip (ocf::heartbeat:IPaddr2): Started hanode2 + +# crm_mon --simple-status +CLUSTER OK: 3 nodes online, 7 resources configured +~~~ + +Mais remonte une erreur en cas de perte d'un nœud: + +~~~console +# pcs stonith fence hanode3 +Node: hanode3 fenced + +# crm_mon --simple-status +CLUSTER WARN: offline node: hanode3 +~~~ + +Cette sonde est donc peu utile, car souvent en doublon avec une sonde +pré-existante confirmant que le serveur est bien démarré. Elle peut +éventuellement servir à confirmer que les services Pacemaker/Corosync sont +bien démarrés sur chaque nœud du cluster. + + +**check\_crm** + +Malheureusement, l'outil n'a pas été mis à jour depuis 2013. Il dépend du +paquet `libmonitoring-plugin-perl` sous Debian et dérivés et de `epel-release` et +`perl-Monitoring-Plugin.noarch` sous les RedHat et dérivés. + +Le module perl ayant changé de nom depuis, il est nécessaire de modifier deux +lignes dans le code source: + +~~~console +sed -i 's/Nagios::Plugin/Monitoring::Plugin/' check_crm.pl +~~~ + +Ci-dessous, le cas d'une ressource ayant subit au moins une erreur. L'option -f +permet d'indiquer le nombre minimal d'erreur avant que la sonde ne lève une +alerte: + +~~~console +# ./check_crm.pl +check_crm WARNING - : pgsqld failure detected, fail-count=1 + +# ./check_crm.pl -f 3 +check_crm OK - Cluster OK + +# pcs resource failcount reset pgsqld +[...] + +# ./check_crm.pl +check_crm OK - Cluster OK +~~~ + +L'argument `-c` de la sonde permet de lever une alerte si une +contrainte existe sur une ressource suite à un déplacement forcé +(eg. `crm_resource --ban`). Malheureusement, cette commande dépend de `crmsh` +et ne fonctionne donc pas avec `pcs`. + + +**check\_corosync\_rings** + +L'outil **check\_corosync\_rings** permet de détecter les incidents réseau +au niveau Corosync. Par exemple, voici le cas d'un anneau défaillant : + +~~~console +# ifdown eth1 +Device 'eth1' successfully disconnected. + +# ./check_corosync_ring.pl +check_cororings CRITICAL - Running corosync-cfgtool failed + +# corosync-cfgtool -s +Printing ring status. +Local node ID 1 +RING ID 0 + id = 192.168.122.2 + status = ring 0 active with no faults +RING ID 1 + id = 192.168.100.2 + status = Marking ringid 1 interface 192.168.100.2 FAULTY* + +# ifup eth1 +Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3) + +# corosync-cfgtool -s +Printing ring status. +Local node ID 1 +RING ID 0 + id = 192.168.122.2 + status = ring 0 active with no faults +RING ID 1 + id = 192.168.100.2 + status = ring 1 active with no faults + +# ./check_corosync_ring.pl +check_cororings OK - ring 0 OK ring 1 OK +~~~ + +::: + +----- + +## Alertes Pacemaker + +* Déclenche une action en cas d'évènement +* Possibilité d'exécuter un script +* Exemples fournis : écriture dans un fichier de log, envoi de mail, envoi trap SNMP +* Disponible depuis Pacemaker 1.1.15 + +::: notes + +Depuis la version 1.1.15, Pacemaker offre la possibilité de lancer des +[alertes](https://clusterlabs.org/pacemaker/doc/en-US/Pacemaker/1.1/html/Pacemaker_Explained/ch07.html) +en fonction de certains évènements: nœud défaillant, ressource qui démarre +ou s'arrête, etc. + +Le principe est assez simple, Pacemaker lance un script et lui transmet des +variables d'environnement, un _timestamp_ et des destinataires (`recipient`). +Cela laisse une grande liberté dans l'écriture de script. + +Pacemaker propose plusieurs scripts en exemple stockés dans +`/usr/share/pacemaker/alerts` : + + * `alert_file.sh.sample` : écriture de l'évènement dans un fichier texte + * `alert_smtp.sh.sample` : envoi d'un mail + * `alert_snmp.sh.sample` : envoi d'une "trap" snmp + +Voici un exemple de configuration avec `alert_file.sh.sample` : + +~~~xml + + + + + + + + + + +~~~ + +Dans cet exemple, Pacemaker exécutera le script +`/usr/share/pacemaker/alerts/alert_file.sh` et lui transmet : + + * `timestamp-format` : format du timestamp + * `logfile_destination` : défini comme un `recipient`, emplacement du fichier de destination + +Le script est appelé autant de fois que de `recipient` définis. + +Ci-après comment une telle alerte peut être déployée en utilisant les outils +classiques. Bien entendu, une méthode plus intégrée et simple est proposée +par l'outil `pcs`. + +~~~ +cp /usr/share/pacemaker/alerts/alert_file.sh.sample /usr/share/pacemaker/alerts/alert_file.sh +chmod +x /usr/share/pacemaker/alerts/alert_file.sh +touch /var/log/cluster/alerts.log +chown hacluster:haclient /var/log/cluster/alerts.log +crm_shadow --create alert +cat < alert.xml + + + + + + + + + + +EOF +cibadmin --modify --xml-file alert.xml +crm_shadow -d +crm_shadow -f --commit alert +~~~ + +Dans les logs : + +~~~ +info: parse_notifications: We have an alerts section in the cib +Found alert: id=alert_sample, path=[...]/alert_file.sh, timeout=30000, tstamp_format=%H:%M:%S.%06N +Alert has recipient: id=logfile_destination, value=/var/log/cluster/alerts.log +~~~ + +Suite à un changement dans le cluster, nous observons dans le fichier +`alerts.log` par exemple: + +~~~ +11:47:24.397811: Resource operation 'notify' for 'pgsqld' on 'hanode2': ok +11:47:25.408174: Resource operation 'demote' for 'pgsqld' on 'hanode2': ok +11:47:26.032790: Resource operation 'notify' for 'pgsqld' on 'hanode2': ok +11:47:26.549325: Resource operation 'stop' for 'pgsql-master-ip' on 'hanode2': ok +11:47:26.789720: Resource operation 'notify' for 'pgsqld' on 'hanode2': ok +11:47:27.341088: Resource operation 'stop' for 'pgsqld' on 'hanode2': ok +~~~ + +Il pourrait être intéressant d'adapter ce script pour utiliser l'outil +`logger` au lieu d'écrire directement dans un fichier. Ces modifications sont +laissés à l'exercice du lecteur. + +::: + +----- + +### TP: Alertes Pacemaker + +::: notes + +1. installer `alert_file.sh.sample` dans `/var/lib/pacemaker/alert_file.sh` et + positionner son propriétaire et le droit d'exécution dessus. +2. créer le fichier de log `/var/log/cluster/pcmk_alert.log` +3. attribuer à ce fichier les mêmes droits et propriétaire que + `/var/log/cluster/corosync.log` +4. créer une configuration `logrotate` pour ce fichier de log +5. ajouter une alerte utilisant `alert_file.sh` avec `pcs`. + préciser le format de la date. +6. ajouter `/var/log/cluster/pcmk_alert.log` comme destinataire de l'alerte +7. vérifier avec `pcs` l'existence de votre alerte +8. provoquer une bascule de `pgsqld-clone` +9. comparer les log sur les trois nœuds + +::: + +----- + +### Correction: Alertes Pacemaker + +::: notes + +1. installer `alert_file.sh.sample` dans `/var/lib/pacemaker/alert_file.sh` et + positionner son propriétaire et le droit d'exécution dessus. + +Sur les trois nœuds du cluster: + +~~~console +# install --owner=hacluster --group=haclient --mode=0755 \ + /usr/share/pacemaker/alerts/alert_file.sh.sample \ + /var/lib/pacemaker/alert_file.sh +~~~ + +2. créer le fichier de log `/var/log/cluster/pcmk_alert.log` + +Sur les trois nœuds du cluster: + +~~~console +# touch /var/log/cluster/pcmk_alert.log +~~~ + +3. attribuer à ce fichier les mêmes droits et propriétaire que + `/var/log/cluster/corosync.log` + +Sur les trois nœuds du cluster: + +~~~console +# chown hacluster:haclient /var/log/cluster/pcmk_alert.log +# chmod 0660 /var/log/cluster/pcmk_alert.log +~~~ + +4. créer une configuration `logrotate` pour ce fichier de log + +Sur les trois nœuds du cluster: + +~~~console +# cat <<'EOF' > /etc/logrotate.d/pcmk_alert +/var/log/cluster/pcmk_alert.log { + missingok + compress + copytruncate + daily + rotate 31 + minsize 2048 + notifempty +} +EOF +~~~ + +5. ajouter une alerte utilisant `alert_file.sh` avec `pcs` + +~~~console +# pcs alert create id=alert_file \ + description="Log events to a file." \ + path=/var/lib/pacemaker/alert_file.sh \ + meta timestamp-format="%Y-%m-%d %H:%M:%S.%03N" +~~~ + +6. ajouter `/var/log/cluster/pcmk_alert.log` comme destinataire de l'alerte + +~~~console +# pcs alert recipient add alert_file id=my-alert_logfile \ + value=/var/log/cluster/pcmk_alert.log +~~~ + +7. vérifier avec `pcs` l'existence de votre alerte + +~~~console +# pcs alert show +Alerts: + Alert: alert_file (path=/var/lib/pacemaker/alert_file.sh) + Description: Log events to a file. + Recipients: + Recipient: my-alert_logfile (value=/var/log/cluster/pcmk_alert.log) +~~~ + +8. provoquer une bascule de `pgsqld-clone` + +~~~console +# pcs resource move --master --wait pgsqld-clone hanode2 +# pcs resource clear pgsqld-clone +~~~ + +9. comparer les log sur les trois nœuds + +L'instance primary était sur `hanode1`. Nous trouvons dans ses log les +opérations nécessaires pour déplacer le rôle `Master` ailleurs: + +~~~ +# cat /var/log/cluster/pcmk_alert.log +16:09:40.796250: Resource operation 'notify' for 'pgsqld' on 'hanode1': ok +16:09:41.437972: Resource operation 'demote' for 'pgsqld' on 'hanode1': ok +16:09:41.666059: Resource operation 'notify' for 'pgsqld' on 'hanode1': ok +16:09:42.159610: Resource operation 'stop' for 'pgsql-master-ip' on 'hanode1': ok +16:09:42.415470: Resource operation 'notify' for 'pgsqld' on 'hanode1': ok +16:09:43.396618: Resource operation 'notify' for 'pgsqld' on 'hanode1': ok +16:09:43.611377: Resource operation 'monitor (16000)' for 'pgsqld' on 'hanode1': ok +~~~ + +L'instance cible était sur `hanode2`, nous trouvons dans ses log les +opérations nécessaires à sa promotion: + +~~~ +# cat /var/log/cluster/pcmk_alert.log +16:09:40.781285: Resource operation 'notify' for 'pgsqld' on 'hanode2': ok +16:09:41.583250: Resource operation 'notify' for 'pgsqld' on 'hanode2': ok +16:09:42.364046: Resource operation 'notify' for 'pgsqld' on 'hanode2': ok +16:09:42.909637: Resource operation 'promote' for 'pgsqld' on 'hanode2': ok +16:09:43.286059: Resource operation 'notify' for 'pgsqld' on 'hanode2': ok +16:09:43.753243: Resource operation 'start' for 'pgsql-master-ip' on 'hanode2': ok +16:09:44.013828: Resource operation 'monitor (10000)' for 'pgsql-master-ip' on 'hanode2': ok +16:09:44.135493: Resource operation 'monitor (15000)' for 'pgsqld' on 'hanode2': master (target: 8) +~~~ + +Enfin, nous ne trouvons sur `hanode3` que les opérations de notification: + +~~~ +# cat /var/log/cluster/pcmk_alert.log +16:09:40.824536: Resource operation 'notify' for 'pgsqld' on 'hanode3': ok +16:09:41.654399: Resource operation 'notify' for 'pgsqld' on 'hanode3': ok +16:09:42.201205: Resource operation 'notify' for 'pgsqld' on 'hanode3': ok +16:09:43.413522: Resource operation 'notify' for 'pgsqld' on 'hanode3': ok +~~~ + +::: + diff --git a/docs/workshop/fr/workshop-PAF.md b/docs/workshop/fr/workshop-PAF.md index 3d2e6ad..4882dc1 100644 --- a/docs/workshop/fr/workshop-PAF.md +++ b/docs/workshop/fr/workshop-PAF.md @@ -355,24 +355,19 @@ L'installation recommandée (et supportée) suivant les distributions de RHEL et |:---------:|:--------:|:---------:|------------------------------| | EL 7 | 2.x | 1.1.x | pcsd 0.9 | | EL 8 | 3.x | 2.0.x | pcsd 0.10 | -| Debian 8 | 1.4 | 1.1.x | crmsh | -| Debian 9 | 2.4 | 1.1.x | pcs 0.9 ou crmsh 2.3 | -| Debian 10 | 3.0 | 2.0.x | pcs 0.10 ou crmsh 4.0 | - -L'équipe de maintenance des paquets Pacemaker n'a pu intégrer les dernières -versions des composants à temps pour la version 8 de Debian. Il a été décidé -d'utiliser officiellement le dépôt backport de Debian pour distribuer ces -paquets dans Debian 8. Les versions 8 et 9 de Debian partagent donc les mêmes -versions des paquets concernant Pacemaker. - -L'initialisation du cluster avec `crmsh` 2.x n'est toujours pas fonctionnelle -et ne devrait pas être corrigée, la branche 3.x étant désormais la branche -principale du projet. La version 3.0 de `crmsh` supporte l'initialisation d'un +| Debian 9 | 2.4 | 1.1.x | pcs 0.9 or crmsh 2.3 | +| Debian 10 | 3.0 | 2.0.x | pcs 0.10 or crmsh 4.0 | +| Debian 11 | 3.1 | 2.0.x | pcs 0.10 or crmsh 4.2 | + +Sous Debian 9, l'initialisation du cluster avec `crmsh` 2.x n'était toujours pas +fonctionnelle. La version 3.0 de `crmsh` supportait l'initialisation d'un cluster sous Debian mais avec un peu d'aide manuelle et quelques erreurs -d'intégration. +d'intégration. La branche principale du projet est désormais la 4.x, mais +les auteurs de ce tutoriel ne l'ont pas encore testée. -L'utilisation de `pcsd` et `pcs` est désormais pleinement fonctionne sous -Debian. Voir à ce propos: +Bien que `crmsh` soit l'outil d'administration historique sous les OS Debian et +dérivés, l'utilisation de `pcsd` et `pcs` y est pleinement fonctionnel depuis +la version 9 de Debian. Voir à ce propos: ::: @@ -443,10 +438,10 @@ ces outils, ils sont très pratiques au quotidien et facilitent grandement la gestion du cluster. De plus, ils intègrent toutes les bonnes pratiques relatives aux commandes supportées. -Tout au long de cette formation, nous utilisons le couple `pcs` afin de -simplifier le déploiement et l'administration du cluster Pacemaker. Il est -disponible sur la plupart des distributions Linux et se comportent de la même -façon, notamment sur Debian et EL et leurs dérivés. +Tout au long de cette formation, nous utilisons `pcs` afin de simplifier le +déploiement et l'administration du cluster Pacemaker. Il est disponible sur la +plupart des distributions Linux et se comportent de la même façon, notamment +sur Debian et EL et leurs dérivés. Ce paquet installe le CLI `pcs` et le daemon `pcsd`. Ce dernier s'occupe seulement de propager les configurations et commandes sur tous les nœuds. @@ -517,7 +512,7 @@ Pacemaker sont présents. Notamment: ::: notes 1. installer le paquet `pcs` -2. activer le daemon `pcsd` au démarrage de l'instance et le démarrer +2. activer le daemon `pcsd` au démarrage du serveur et le démarrer ::: @@ -555,12 +550,12 @@ ou * authentification des daemons `pcsd` entre eux * création du cluster à l'aide de `pcs` - crée la configuration corosync sur tous les serveurs -* configuration de Pacemaker des _processus_ de Pacemaker +* configuration des _processus_ de Pacemaker ::: notes -La création du cluster se résume à créer le fichier de configuration de -Corosync, puis à démarrer de Pacemaker. +La création du cluster se résume à créer le même fichier de configuration de +Corosync sur tous les nœuds, puis démarrer Pacemaker dessus. L'utilisation de `pcs` nous permet de ne pas avoir à éditer la configuration de Corosync manuellement. Néanmoins, un pré-requis à l'utilisation de `pcs` est @@ -576,8 +571,9 @@ processus, pas la gestion du cluster. Notamment, où sont les journaux applicatifs et leur contenu. Pour la famille des distributions EL, son emplacement est `/etc/sysconfig/pacemaker`. Pour la famille des distributions Debian, il sont emplacement est `/etc/default/pacemaker`. Ce fichier en -concerne QUE l'instance locale de Pacemaker. Chaque instance peut avoir un -paramétrage différent, mais cela est bien entendu déconseillé. +concerne QUE l'instance locale de Pacemaker. Contrairement à Corosync, chaque +instance Pacemaker peut avoir un paramétrage différent, mais cela est bien +entendu déconseillé. :::