**Ceci est une ancienne révision du document !**
Mattermost : Procédure de mise à jour
Images Docker
Pour déployer Mattermost, Picasoft utilise 2 images Docker : une image pour l’application (que l’on appellera app
) et une image pour la base de données PostgreSQL (que l’on appellera db
).
Récupération du code mis à jour
Pour builder et pousser les images, on va récupérer le repository Git qui pointe sur l'upstream maintenue par Mattermost.
On clone le repository et on se place dans le dossier.
Il faut ensuite modifier fichier docker-compose.yml
du repository pour permettre de builder la version libre de Mattermost. Normalement, les lignes suivantes ne doivent pas être commentées :
[...] app: build: context: app # comment out 2 following lines for team edition args: - edition=team [...]
Pour finir, on vérifie que le repository va bien builder la version que l’on souhaite de Mattermost. On peux vérifier avec la commande suivante:
cat app/Dockerfile | grep "ENV MM_VERSION"
Si ce n’est pas la dernière version, alors il faut ouvrir une PR sur l’upstream pour demander la mise à jour.
Build et tag des images
Lorsque le dossier est prêt, on build très simplement les images à l’aide de docker-compose
:
docker-compose build
Le build peut durer un certain temps, une fois terminé on obtient trois images : mattermostapp
et ,
mattermostdbmattermostweb
. On peut les voir à l’aide de la commande
docker images :
<code bash>
kyane@laptop:~ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mattermostweb latest bd616f47c38b 3 seconds ago 109MB
mattermostapp latest e0bdbeb94060 3 seconds ago 303MB
mattermostdb latest 724ed4c6030a 3 seconds ago 451MB
</code>
On ignore l’image
pica01mattermostweb
.
On va maintenant ajouter des tags à nos images , nous ne l’utilisons pas pour Picasoft car nous avons notre propre reverse-proxy (Traefik). On peut la supprimer avec
docker rmi mattermostwebapp
et db
pour ensuite les pousser sur le registry Docker de Picasoft. On va utiliser, pour chaque image, les tags latest
et X.Y.Z
(correspondant au numéro de version de Mattermost). On renomme les images pour les pousser sur le registry de Picasoft, elles auront donc la forme registry.picasoft.net:5000/NOMIMAGE:TAG
. Par exemple, si nous venons de builder la version 4.3.0
de Mattermost, on va lancer les commandes suivantes :
<code bash>
# Tag de l’image app
docker tag mattermostapp registry.picasoft.net:5000/pica-mattermost:latest
docker tag mattermostapp registry.picasoft.net:5000/pica-mattermost:4.3.0
# Tag de l’image db
docker tag mattermostdb registry.picasoft.net:5000/pica-mattermost-db:latest
docker tag mattermost_db registry.picasoft.net:5000/pica-mattermost-db:4.3.0
# On pousse tout sur le registry
docker push registry.picasoft.net:5000/pica-mattermost:latest
docker push registry.picasoft.net:5000/pica-mattermost:4.3.0
docker push registry.picasoft.net:5000/pica-mattermost-db:latest
docker push registry.picasoft.net:5000/pica-mattermost-db:4.3.0
</code>
Nos images sont prêtes et à jour dans le registry. On termine par un petit ménage des images Docker en local, maintenant qu’elles sont poussées ce n’est plus utile de les conserver :
<code bash>
docker rmi mattermostapp
docker rmi mattermostdb
docker rmi registry.picasoft.net:5000/pica-mattermost:latest
docker rmi registry.picasoft.net:5000/pica-mattermost:4.3.0
docker rmi registry.picasoft.net:5000/pica-mattermost-db:latest
docker rmi registry.picasoft.net:5000/pica-mattermost-db:4.3.0
</code>
===== Déploiement =====
==== Préparation ====
Pour déployer notre nouvelle version, on se rend maintenant sur la machine de production qui fait tourner Mattermost (normalement, ). Bien entendu, on ne fait pas une mise à jour n’importe comment, il faut s’assurer :
* que l’on a une backup récente de la base de données. C’est normalement le cas puisqu’elles sont automatiques;
* que Mattermost n’est pas trop utilisé. On ne fais pas un déploiement à 19H, la coupure va déranger tout le monde;
* que les autres bénévoles sont au courant de la mise à jour. Même si la coupure de service est courte, un⋅e sysadmin qui voit que le service est tombé va s’affoler pour rien :)
Bref on ne se lance que lorsque l’on est prêt. Pour commencer il faut modifier les images Docker qui sont utilisées par les conteneurs de Mattermost et de sa base de données. Cela se passe dans le fichier
/DATA/docker/docker-compose.yml de la machine, dans les services
mattermost et
mattermost-db. Il suffit simplement de changer le numéro de version de l’image.
Attention !! On utilise uniquement les images ayant pour tag le numéro d’une version. On utilise JAMAIS
docker-composelatest
pour éviter de tout casser, et en plus c’est plus clair comme cela.
Lorsque c’est prêt, on pull les nouvelles images Docker sur la machine. On n’est pas obligé de le faire manuellement, se chargera de le faire au redémarrage des conteneurs. Cependant cela permet de réduire le downtime, puisque l’image sera déjà en local au moment du redémarrage (on économise le temps de pull).
<code bash>
docker pull registry.picasoft.net:5000/pica-mattermost:4.3.0
docker pull registry.picasoft.net:5000/pica-mattermost-db:4.3.0
</code>
==== Bascule en production ====
Lorsque tout est bien prêt et que l’on a prévu les collègues, on peut enfin opérer à la bascule sur la nouvelle version. En pratique, on va simplement couper les conteneurs de l’application Mattermost, puis de sa base de données. On relance ensuite directement les deux services (dans l’ordre inverse), qui vont donc démarrer sur les nouvelles images.
Pour être sûr que tout se passe vite, sans typo ou autre problème, on peut faire tout ceci en une seule commande :
<code bash>
cd /DATA/docker/ && docker stop mattermost-app && docker stop -t 60 mattermost-db \
&& docker rm mattermost-app && docker rm mattermost-db \
&& docker-compose up -d mattermost-db && sleep 5 && docker-compose up -d mattermost
</code>
Il est important de stopper les conteneurs avant de les effacer, pour éteindre correctement la base de données et minimiser le risque de corruption. L’option
-t 60 indique un timeout de 60 secondes (par défaut c’est 10 secondes).
Normalement tout s’enchaine bien et les services repartent sur les nouvelles images. On peut vérifier rapidement en se connectant sur le Mattermost de Picasoft, que ça tourne bien. Dans le menu, l’onglet “À Propos” permet de vérifier la version du serveur.
docker logs mattermost-app
Il est fortement recommandé de regarder les logs des conteneurs ( et
docker logs mattermost-db) pour regarder si il n’y a pas de grosse erreur pouvant indiquer un dysfonctionnement.
En cas de soucis, on remet les anciennes images dans le
docker-compose.yml puis on relance la commande ci-dessus pour revenir en arrière. Si cela crash toujours, on fait un rollback de la base de données.
pica01’’.
==== Réindexation de la base de donnée ====
Il est arrivé qu’après une procédure d’upgrade “violente”, la base de données Postgresql ne conserve plus ses propriétés intrinsèques. La base se retrouve corrompue et les contraintes d’intégrités ne sont plus respectées. Cela donne lieu à des problèmes de connexions au sein de Mattermost.
Pour corriger ce problème, une réindexation de la base de données est nécessaire.
Attention avant toute opération de ce genre, veuillez effectuer une sauvegarde de la base de données
<code bash>
root@pica01:~# docker exec -it mattermost-db bash
bash-4.3# psql -U postgres
psql (9.4.15)
Type “help” for help.
postgres=# \c mattermost
You are now connected to database “mattermost” as user “postgres”.
mattermost=# reindex DATABASE mattermost;
NOTICE: table “pgcatalog.pgclass” was reindexed
NOTICE: table “pgcatalog.pgstatistic” was reindexed
NOTICE: table “pgcatalog.pgtype” was reindexed
NOTICE: table “public.oauthaccessdata” was reindexed
NOTICE: table “pgcatalog.pgauthid” was reindexed
NOTICE: table “pgcatalog.pgattribute” was reindexed
NOTICE: table “pgcatalog.pgproc” was reindexed
NOTICE: table “public.audits” was reindexed
NOTICE: table “pgcatalog.pgusermapping” was reindexed
NOTICE: table “pgcatalog.pgattrdef” was reindexed
NOTICE: table “pgcatalog.pgconstraint” was reindexed
NOTICE: table “pgcatalog.pgindex” was reindexed
NOTICE: table “pgcatalog.pgoperator” was reindexed
NOTICE: table “pgcatalog.pgopfamily” was reindexed
NOTICE: table “pgcatalog.pgopclass” was reindexed
NOTICE: table “pgcatalog.pgam” was reindexed
NOTICE: table “pgcatalog.pgamop” was reindexed
NOTICE: table “pgcatalog.pgamproc” was reindexed
NOTICE: table “pgcatalog.pglanguage” was reindexed
NOTICE: table “pgcatalog.pgdatabase” was reindexed
NOTICE: table “pgcatalog.pgaggregate” was reindexed
NOTICE: table “pgcatalog.pgrewrite” was reindexed
NOTICE: table “pgcatalog.pgtrigger” was reindexed
NOTICE: table “pgcatalog.pgeventtrigger” was reindexed
NOTICE: table “pgcatalog.pgdescription” was reindexed
NOTICE: table “pgcatalog.pgcast” was reindexed
NOTICE: table “pgcatalog.pgenum” was reindexed
NOTICE: table “pgcatalog.pgnamespace” was reindexed
NOTICE: table “pgcatalog.pgconversion” was reindexed
NOTICE: table “pgcatalog.pgdepend” was reindexed
NOTICE: table “pgcatalog.pgdbrolesetting” was reindexed
NOTICE: table “pgcatalog.pgtablespace” was reindexed
NOTICE: table “pgcatalog.pgpltemplate” was reindexed
NOTICE: table “pgcatalog.pgauthmembers” was reindexed
NOTICE: table “pgcatalog.pgshdepend” was reindexed
NOTICE: table “pgcatalog.pgshdescription” was reindexed
NOTICE: table “pgcatalog.pgtsconfig” was reindexed
NOTICE: table “pgcatalog.pgtsconfigmap” was reindexed
NOTICE: table “pgcatalog.pgtsdict” was reindexed
NOTICE: table “pgcatalog.pgtsparser” was reindexed
NOTICE: table “pgcatalog.pgtstemplate” was reindexed
NOTICE: table “pgcatalog.pgextension” was reindexed
NOTICE: table “pgcatalog.pgforeigndatawrapper” was reindexed
NOTICE: table “pgcatalog.pgforeignserver” was reindexed
NOTICE: table “pgcatalog.pgforeigntable” was reindexed
NOTICE: table “pgcatalog.pgdefaultacl” was reindexed
NOTICE: table “pgcatalog.pgseclabel” was reindexed
NOTICE: table “pgcatalog.pgshseclabel” was reindexed
NOTICE: table “pgcatalog.pgcollation” was reindexed
NOTICE: table “pgcatalog.pgrange” was reindexed
NOTICE: table “pgcatalog.pglargeobject” was reindexed
NOTICE: table “public.channelmembers” was reindexed
NOTICE: table “informationschema.sqlimplementationinfo” was reindexed
NOTICE: table “informationschema.sqllanguages” was reindexed
NOTICE: table “informationschema.sqlpackages” was reindexed
NOTICE: table “informationschema.sqlsizing” was reindexed
NOTICE: table “informationschema.sqlsizingprofiles” was reindexed
NOTICE: table “public.channels” was reindexed
NOTICE: table “public.commands” was reindexed
NOTICE: table “public.compliances” was reindexed
NOTICE: table “public.emoji” was reindexed
NOTICE: table “pgcatalog.pglargeobjectmetadata” was reindexed
NOTICE: table “public.fileinfo” was reindexed
NOTICE: table “pgcatalog.pginherits” was reindexed
NOTICE: table “public.licenses” was reindexed
NOTICE: table “public.oauthapps” was reindexed
NOTICE: table “informationschema.sqlfeatures” was reindexed
NOTICE: table “informationschema.sqlparts” was reindexed
NOTICE: table “public.oauthauthdata” was reindexed
NOTICE: table “public.outgoingwebhooks” was reindexed
NOTICE: table “public.posts” was reindexed
NOTICE: table “public.preferences” was reindexed
NOTICE: table “public.reactions” was reindexed
NOTICE: table “public.sessions” was reindexed
NOTICE: table “public.status” was reindexed
NOTICE: table “public.systems” was reindexed
NOTICE: table “public.teammembers” was reindexed
NOTICE: table “public.teams” was reindexed
NOTICE: table “public.tokens” was reindexed
NOTICE: table “public.users” was reindexed
NOTICE: table “public.clusterdiscovery” was reindexed
NOTICE: table “public.jobs” was reindexed
NOTICE: table “public.commandwebhooks” was reindexed
NOTICE: table “public.useraccesstokens” was reindexed
NOTICE: table “public.channelmemberhistory” was reindexed
NOTICE: table “public.pluginkeyvaluestore” was reindexed
NOTICE: table “public.incomingwebhooks” was reindexed
REINDEX
mattermost=# <ctrl d>
exit
</code>
Si tout va bien, on fait un petit message sur le channel Général pour annoncer que la MAJ s’est bien passée, en ajoutant un petit lien vers le changelog de Mattermost. On pense aussi à nettoyer les anciennes images Docker de la machine