Florent Peterschmitt

Vieux Centreon et réplica MySQL/MariaDB : objectif MAJ

Il sera question ici de la migration d’un vieux Centreon tout moisi, fonctionnant avec du Nagios et NDOUtils, vers un Centreon 2.7.6, un peu mieux, avec du Centreon Engine et Centreon Broker.

Cette migration a été faite chez un client et s’est passée les doigts dans le pif, et sans trop de coupures.

Je ne vais pas détailler le processus de MAJ de Centreon, ni son installation, la documentation de Centreon se suffit à elle-même, et je vais aussi partir du principe que vous connaissez les fichiers de configuration de Centreon, ainsi que les merdouilles liées au processus d’upgrade (modifier les fichiers de migration SQL à la main, tout ça…).

Ici on va parler réplication MySQL / MariaDB et reprise de service en douceur.

Note : j’ai écris de billet après la prestation, et de mémoire, en relisant la doc faite chez le client et les morceaux de tâches Ansible qui m’ont aidé pour le setup des pollers. S’il y a des erreurs, un petit mail et je corrige.

État des lieux

  • CentOS 6.x x86_64
  • Base de données MySQL 5.1
  • Centreon 2.3.3 installé avec les sources
  • Nagios 3.x + NDOUtils compatible avec Centreon
  • 5 pollers dont un local (sur la machine BDD + Web)

Objectif et étapes

L’objectif est de migrer la totalité des composants vers des outils 100% made in Centreon, et avec le moins de temps de coupure possible, et le must, sans faire de trous dans les graphes \o/

  • CentOS 6.x x86_64
  • Base de donnée MariaDB 5.5 packagée par CES (Centreon)
  • Centreon 2.7.6 installé par les paquets
  • Centreon Broker Daemon, ou cbd, remplace ndo2db
  • Centreon Engine + Centreon Broker Module, remplace Nagios et ndomod
  • Réinstallation de l’instance BDD + Web sur une autre machine, ainsi que son poller local
  • Installation de Centreon Engine en parallèlle des Nagios.

La ré-installation de la BDD + Web sur une autre machine est en fait facultative, ici c’était parce que le client avec des thunes à mettre dans une grosse machines avec des gros SSD dégoulinants d’amour tout plein.

Aussi, pour passer facilement de Nagios à Centreon Engine, on va devoir utiliser temporairement la version 2.6.6 de Centreon, qui est la dernière version à prendre en charge Nagios et NDO. Au delà, le support est largué au profit de Centreon* uniquement.

Réplication de la BDD

La première étape, c’est de répliquer tranquillement les données en base. Centreon fonctionne quasi exclusivement avec sa BDD MySQL. On s’assure ainsi un dump complet de la base, et une récupération de l’état courant sans jamais oublier personne en chemin.

Note : même si on peut voir des modules InfluxDB apparaître pour Centreon-Broker, je ne l’ai pas testé (et Centreon n’étant pas une techno qui m’intéresse particulièrement, j’ai pas trop envie de m’y coller) et de toute façon le client n’aurait pas forcément souhaité installer grafana en plus.

Configuration

Déjà, il vous faut, de préférence, une base MySQL identique à la première : même configuration et même version.

Ensuite, on va configurer comme suit notre MySQL “master”, qui est la base qui contient présentement les données :

[mysqld]
net_write_timeout = 3600
max_allowed_packet = 1G
log-bin=mysqld-log-bin
server_id=1
open-files-limit = 32000
binlog_format=MIXED

Et sur notre MySQL “slave”, qui ne contient rien du tout pour le moment :

[mysqld]
relay-log=mysqld-log-relay
net_write_timeout = 3600
max_allowed_packet = 1G
server_id=2
read-only
open-files-limit = 32000
slave-skip-errors = 1062

Pour la réplication, un utilisateur dédié est nécessaire. Le/les slave(s) vont se connecter au master via cet utilisateur.

Création sur le master :

create user 'replication_user'@'%' identified by 'the_super_password';
grant replication slave on *.* to replication_user;
flush privileges;

Enfin il ne coûte rien de vérifier que nos MySQL vont pouvoir causer entre eux :

$ mysql
MariaDB [(none)]> show variables like 'skip_networking';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| skip_networking | OFF   |
+-----------------+-------+
1 row in set (0.00 sec)


$ netstat -laputen|grep 3306
tcp        0      0 0.0.0.0:3306                0.0.0.0:\*                   LISTEN

Et là on peut redémarrer nos deux MySQL pour prendre en compte la configuration.

service mysqld restart

Initialisation

Cette étape consiste à charger un gros dump en live dans notre slave, pour ensuite lui dire de rejouer les binlog à partir d’un certain point.

Attention : il vous faut impérativement vérifier l’espace disque disponible sur vos machines, et estimer le temps que ce dump va mettre. Sinon vous risquez de ne plus avoir de place pour les binlog, et je ne vous fait pas un dessin : ça va tout planter !

Bon, déjà, je n’ai pas vraiment trouvé de bonne méthode pour faire ça très proprement, vous allez voir.

Sur le master, on va exécuter ça :

mysqldump -uroot -ppassword --all-databases --skip-lock-tables --single-transaction --flush-logs --master-data=1 --quick | head -n 30|grep '^CHANGE MASTER TO'

On va se prendre un Got errno 32 on write, ce qui est normal vu qu’avec head on a fermé stdin alors que mysqldump contiuait à écrire. C’est la même erreur qu’on se prendrait en cas de fulldisk si je ne m’abuse.

Retenez cette valeur : MASTER_LOG_POS=XXX

Exemple de retour : CHANGE MASTER TO MASTER_LOG_FILE=’mariadb-log-bin.000018’, MASTER_LOG_POS=106;

Dans l’exemple, la valeur à retenir est 106. On va s’en servir pour faire démarrer notre slave à la bonne position de départ dans le prochain log-bin qui va être créé quand on démarrera le dump.

Pour les options utilisées dans la commande mysqldump, je vous laisse man mysqldump, c’est très bien expliqué.

Bien, maintenant on va réellement lancer le dump. Préparez deux shell : un dans un screen ou tmux, et l’autre sur la console MySQL de votre master.

Dans le premier, faites feu :

mysqldump -uroot -ppassword --all-databases --skip-lock-tables --single-transaction --flush-logs --master-data=1 --quick | gzip | ssh root@host_slave "zcat | mysql -uroot"

Sans attendre, dans le second :

mysql> SHOW MASTER STATUS\G
... bla bla bla ...
Master_Log_File: mysqld-log-bin.XXXXXX
... bla bla bla ...

Ça les amis, c’est le fichier à partir duquel notre slave va devoir rejouer les instructions, pour commencer la récupération.

Donc on se retrouve au final avec ces deux infos :

MASTER_LOG_POS=106
MASTER_LOG_FILE=mysqld-log-bin.XXXXXX

Ah ouais, heu, XXXXXX, ça va être des chiffres. Mettons, pour la suite, que ce nombre est 000002.

Mise en marche du slave

Déjà, attendez que votre mysqldump ai terminé et sans erreur. À la moindre coupure, vous pouvez tout recommencer.

Si ça arrive, sachez que vous pouvez supprimer les binlog du master qui ne sont plus en activité : ils ne servent plus à rien.

Par contre, si tout va bien, ne supprimez rien du tout, car naturellement, on va en avoir besoin.

Ouvrez une console MySQL sur le slave, on va changer sa configuration et lancer le processus de réplication.

Exécutez cette commande, en adaptant avec vos valeur pour MASTER_LOG_POS et MASTER_LOG_FILE :

CHANGE MASTER TO
  MASTER_HOST='host_master',
  MASTER_USER='replication_user',
  MASTER_PASSWORD='the_super_password',
  MASTER_PORT=3306,
  MASTER_CONNECT_RETRY=10,
  MASTER_LOG_FILE='mysqld-log-bin.000002',
  MASTER_LOG_POS=106;

Vous pouvez vérifier que les infos ont bien été prises en compte avec la commande SHOW SLAVE STATUS\G.

Quand tout va bien, exécutez SLAVE START;.

Tout au long de la récupération du slave sur le master, on devra avoir quelque chose comme ça :

show slave status \G;
# On ne doit pas trouver d’erreur :
    Last_IO_Errno: 0
    Last_IO_Error: 
    Last_SQL_Errno: 0
    Last_SQL_Error:
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes

# Le compteur de retard ne doit pas sans cesse s’incrémenter :
    Seconds_Behind_Master: XXXXX

Le compteur Seconds_Behind_Master va devoir tendre vers 0 avec le temps. Il pourra momentanément augmenter, mais s’il ne fait que d’augmenter, alors vous avez un problème : votre slave n’est pas capable d’absorber la charge ou votre master ne répond pas assez vite, ou les deux.

Vous vous souvenez de l’option slave-skip-errors = 1062 dans la configuration ? Visitez directement ce lien : http://www.ducea.com/2008/02/13/mysql-skip-duplicate-replication-errors/

Ça va vous arriver, en tout cas avec Centreon. Je n’ai pas eu le temps d’investiguer sur le pourquoi du comment, en revanche je sais qu’il n’y a pas réellement de problème et qu’il n’y aura pas de corruption. Ce genre d’erreur est à confronter avec votre environnement et la/les application(s) qui utilisent vos bases.

En tout cas, il est nécessaire de zapper cette erreur, sinon vous vous retrouverez à devoir manuellement, ou scriptemochement, sauter les erreurs. MySQL a déjà une option pour ça, utilisons la.

Quand le compteur Seconds_Behind_Master tombe à zéro, on pourra poursuivre la migration.

Transfert du master vers le slave (arrêt du master)

On va maintenant reconfigurer notre slave pour être utilisé en temps que master, et abandonner le master actuel.

Connectez-vous sur votre Centreon et modifiez la conf des ndomod (ou faites le à la main, je m’en fiche du moment que c’est fait) pour qu’ils aient un fichier de rétention en cas d’injoignabilité de ndo2db.

Modifiez aussi la configuration ndo2db pour pointer sur la BDD slave. Ne relancez surtout pas ndo2db pour le moment.

Appliquez cette conf, et faites un petit test pour vous assurer que le fichier est bien créé consommé lorsqu’une règle iptables empêche notre Nagios de causer avec ndo2db, puis consommé quand on la retire.

Arrêtez tous les services Centreon (centcore et centstorage).

Quand c’est fait, coupez vos instances de ndo2db. Et là encore, attention à l’espace disque sur les pollers : il ne s’agirait pas de faire un full parce que /var est taillé à la serpe.

Avant toute chose, vérifiez que votre slave a bien fini de se synchroniser avec le master.

Arrêtez l’instance de MySQL sur le master.

Ensuite, avec MySQL 5.1, on va devoir redémarrer le slave une fois pour repasser en mode “normal”.

  1. Supprimez la configuration qui a été ajoutée pour le slave
  2. Exécutez sur le slave slave stop; reset slave;
  3. Redémarrez mysqld du slave
  4. Vérifiez avec show slave status\G que vous n’obtenez plus rien. Si ce n’est pas le cas, je me suis vautré dans les commandes précédentes \^_\^

Eh bah là on est bon les enfants. On va pouvoir redémarrer ndo2db, qui, avec sa nouvelle conf, va venir peupler notre nouvelle base, et modifier les fichiers de configuration Centreon pour que centcore et centstorage viennent taper sur notre nouvelle base.

Les fichiers de conf sont normalement dans /etc/centreon, mais si c’est une installation par les sources, vous les avez peut-être dans /usr/local/centreon/etc/. Adaptez la conf des bases.

Reprise de service

Redémarrez donc ndo2db, centcore et centstorage. Constatez la bonne reprise du service.

Pour l’instant, seule la base SQL a été migrée. On va pouvoir passer aux choses sérieuses avec la MAJ.

MAJ

Coupez encore une fois ndo2db, centcore et centstorage.

Débrouillez-vous pour passer en version 2.6.6. Avec yum-plugin-versionlock, voici le versionlock.list approprié :

centreon-2.6.6-5.el6.noarch
centreon-base-2.6.6-5.el6.noarch
centreon-base-config-nagios-2.6.6-5.el6.noarch
centreon-common-2.6.6-5.el6.noarch
centreon-installed-2.6.6-5.el6.noarch
centreon-perl-libs-2.6.6-5.el6.noarch
centreon-web-2.6.6-5.el6.noarch
centreon-plugins-2.6.6-5.el6.noarch
centreon-plugin-meta-2.6.6-5.el6.noarch
centreon-trap-2.6.6-5.el6.noarch
ndoutils-1.4b9-6.el6.x86_64
centreon-broker-2.10.5-2.el6.x86_64
centreon-broker-cbmod-2.10.5-2.el6.x86_64
centreon-broker-core-2.10.5-2.el6.x86_64
centreon-broker-cbd-2.10.5-2.el6.x86_64
centreon-broker-storage-2.10.5-2.el6.x86_64
ndoutils-1.4b9-6.el6.x86_64

Installez Centreon en utilisant centreon et centreon-base-config-nagios, copiez les fichiers de conf Centreon, puis passez le processus de MAJ de Centreon.

Vous pouvez maintenant redémarrer vos ndo2db, centcore et centstorage, et vérifier que ça marche.

Passage en Centreon-Engine + Centreon Broker

  1. Installer centreon-engine et centreon-broker-cbmod sur les pollers
  2. Installer centreon-broker-daemon sur votre Central
  3. Configurez chaque future instance de centreon-engine, ainsi que centreon-broker-module et centreon-broker-daemon
  4. Copiez le ~/.ssh de l’utilisateur centreon sur votre nouvelle machine, c’est nécessaire pour joindre les pollers

Pour cela, la documentation de centreon devrait suffire, sinon il y a d’autres tutos qui expliquent comment configurer tout ce beau monde.

Une fois que vous avez tout configuré, poussez vous conf mais ne démarrez rien.

  1. Démarrez cbd sur le central, vérifiez qu’il tourne bien et accepte les connexions
  2. Arrêtez ndo2db, votre supervision continueras de tourner et en cas de pépin, la reprise de service avec NDO est faisable simplement en relançant le service
  3. Configurez Centreon pour utiliser Centreon Broker. Ça se trouve dans les paramètres d’administration
  4. De là vous ne devriez plus avoir de status, car cbd écrit dans centreon_storage, alors que NDO écrit dans centreon_status. Le fait d’avoir configuré Centreon en mode Centreon Broker fait qu’il regarde dans centreon_storage.
  5. Lancer vos Centreon Engine. Les status devraient montés quasi immédiatement. Si ça n’est pas le cas (du style le compte d’hôte qui passe de 0 à 100, puis re à 0, puis à 200, puis à 0 etc… vous vous êtes viandé dans la conf des instances de pollers)

À partir de là, si tout fonctionne, arrêtez vos Nagios

MAJ version Centreon 2.7.x

Ben là ya pas plus simple : on arrête les services Centreon du central, on retire le versionlock.list, on upgrade tout le monde (pollers compris, centreno-engine et cbmod), et on relance.

Vous devrez aussi lancer une reconstruction des graphes à partir des données en base. Les migrations des RRD n’ont jamais bien fonctionné, même avec les rrddump et rrdrestore.

Aussi faites gaffe, vous aurez peut-être besoin de faire du nettoyage pour certaines métriques inexistantes :

use centreon_storage; # adapter...
delete from metrics where (select count(*) from data_bin as db where db.id_metric=metric_id) = 0;

Comments