• At chevron_right

      Let's Encrypt sur HAProxy (Partie 1)

      raspbeguy · pubsub.gugod.fr / atomtest · Sunday, 5 November, 2017 - 23:00 · 6 minutes

    Vous vous en souvenez peut-être, nous avions effectué un tutoriel Let's Encrypt quelques jours après sa mise en bêta publique. D'ailleurs, il mériterait un petit relooking, vu que quelques détails ont un peu changé, et que d'autres clients ACME ont vu le jour. Par exemple on a honteusement passé sou...

    Vous vous en souvenez peut-être, nous avions effectué un tutoriel Let's Encrypt quelques jours après sa mise en bêta publique. D'ailleurs, il mériterait un petit relooking, vu que quelques détails ont un peu changé, et que d'autres clients ACME ont vu le jour. Par exemple on a honteusement passé sous silence l'excellent acme.sh qui a le mérite de ne pas demander une ribambelle de dépendance en temps que simple script Bash. De plus, le client principal (dont le nom est désormais Certbot) a désormais implémenté des extensions Apache et Nginx qui fonctionnent (presque) comme on le souhaite, à savoir modifier tout seul les configurations des sites pour fonctionner avec Let's Encrypt. Cependant je reste plus enclin à utiliser la méthode manuelle.

    À l'époque, je vous parlais d'une infrastructure simple, à savoir un unique serveur frontal : c'est lui qui interceptait les requêtes et qui les traitait, point barre. L'infra d'un site avec une audience restreinte, car tout doit être traité par une unique machine. Bonjour l'indispo surprise.

    Parlons à présent d'une architecture un peu plus ambitieuse, le genre de topologie qu'on peut trouver en production pour des sociétés importantes (et les technophiles enthousiastes). Cette première partie sera dédiée à l'explication de cette mystérieuse architecture et à la présentation d'une manière de la mettre en œuvre. Dans une seconde partie, on apprendra à y déployer ses certificats Let's Encrypt.

    Souvent donc, on ne se contente pas d'un unique frontal, mais de plusieurs frontaux, sous la coupe d'un répartiteur de charge, (load-balancer en anglais) qui se chargera de réceptionner les requêtes des utilisateurs et de les distribuer aux frontaux, selon une stratégie définie. Cette architecture a quatre avantages :

    • On gagne en charge maximale supportée, donc en nombre de visiteurs.
    • Multiplier les frontaux amoindrit fortement les risques de crash du site, car en cas de panne d'un frontal, les autres frontaux se partagent le trafic.
    • La mise en production d'une nouvelle version d'un site web peut se faire sans aucune interruption de service : il suffit de déployer sur un frontal à la fois.
    • Les frontaux sont sur un réseau privés et non directement accessible sur le réseau global, donc la sécurité du site est renforcée.

    load-balancer

    On constate que le répartiteur de charge est un potentiel goulot d'étranglement et il nous faut donc un programme optimisé pour la haute disponibilité afin que le flux des requêtes ne soit pas le facteur limitant.

    Disons maintenant que l'on souhaite apposer un certificat sur cette architecture. Question à dix sesterces : qui parmi ces serveurs doit porter ce certificat ?

    Si on choisit de faire porter le certificat par les frontaux, cela signifie qu'il faut que tous les frontaux doivent le porter, et qu'il faudra déployer le certificat sur toutes ces machine à chaque renouvellement. Mais surtout, cela signifie que, le trafic étant chiffré jusqu'aux frontaux, le répartiteur de charge ne pourra pas prendre en compte le contenu de la requête dans sa stratégie de répartition, ce qui est fort pénalisant. En effet, il est coutume de configurer le répartiteur de charge pour distribuer certaines URL sur un pool de frontaux différent du pool normal, par exemple le back-office (la page d'administration et de saisie de contenu du site). Enfin dernier point, si vous vous souvenez du fonctionnement du protocole ACME comme décrit dans notre tutoriel, vous saurez que le certificat doit être généré sur la machine qui en fait la demande et qui répondra au challenge ACME. Ceci implique qu'un des frontaux doit être désigné pour la génération des certificat, et donc que le répartiteur de charge doit rediriger toutes les requêtes de type ACME vers ce frontal, ce qui est à la fois moche et justement impossible car notre répartiteur de charge ne peut pas comprendre ce qu'il redirige à cause du chiffrement.

    La solution la plus sensée, qui maintient également le plus l'isométrie des frontaux, est de faire porter le certificat par le répartiteur de charge.

    Zoomons alors sur cette fameuse machine, le répartiteur de charge. On va partir d'un socle OpenBSD. Pourquoi pas un Linux ? Parce qu'on utilise souvent la même machine pour la répartition de charge et pour le pare-feu, et qu'OpenBSD est le système de prédilection pour faire un routeur libre. Et en plus j'aime bien cet OS, ça change un peu les idées.

    Sur ce socle, on va utiliser le répartiteur de charge HAProxy. Les seules tâches de HAProxy sont de porter le certificat du ou des sites (on parle de SSL-offloading) et d'aiguiller le trafic web sur les frontaux. Il ne peut pas générer de flux web par lui-même, il peut seulement relayer une requête à un autre service. Et d'ailleurs il est très bon pour ça.

    HAProxy est organisé en frontends et en backends : un frontend est la façade présentée au monde extérieur qui va recevoir les requêtes des internautes. Un backend est un pool de serveurs frontaux qui va traiter la requête. HAProxy doit donc choisir sur quel backend envoyer une requête, mais il doit également gérer le pool de frontaux que représente ce backend.

    Prenons un exemple de configuration simple. On passera les directives globales HAProxy qui ne sont pas intéressantes et présentent peu de valeur ajoutée. Et bien entendu, on part du principe que vos frontaux sont configurés, écoutent sur des adresses locales et tout le toutim.

    frontend mon_super_site
        bind *:80
        mode http
    
        acl url-back-office path_dir /admin
    
        use_backend back-office if url-back-office
        default_backend mes-frontaux
    
    backend back-office
        server backoffice 192.168.0.14:80
    
    backend mes-frontaux
        balance roundrobin
        server backoffice 192.168.0.11:80
        server backoffice 192.168.0.12:80
        server backoffice 192.168.0.13:80

    Dans cette configuration, le frontend écoute sur toutes les adresses IP attribuées au serveur, sur le port 80 (donc pour le moment, uniquement du trafic en clair). Le mode HTTP signifie qu'on utilise ce frontend pour répartir du flux web, et non pas comme le mode TCP ou l'on redirige un flux TCP intouché.

    On a écrit une ACL, autrement dit une condition. Retenez cette notion car les ACL sont au cœur du principe de HAProxy. Ici notre ACL est vraie si le chemin de l'URL commence par /admin et fausse sinon. On utilisera donc le backendback-office si l'ACL est vraie et sinon, on utilisera le backend par défaut mes-frontaux.

    Le backendback-office est très simple car il ne comporte qu'un serveur. Le backendmes-frontaux comporte trois serveurs répartis en round-robin.

    Et voilà, vous avez un répartiteur de charge. Si vous avez un certificat SSL, vous pouvez ajouter une ligne au frontend :

    bind *:443 ssl cert /chemin/vers/mon/certificat.pem

    Sauf que ça ne marchera pas. En tout cas pas tant que vous aurez mis votre certificat sous la forme attendue par HAProxy, à savoir la clef privée et le certificat dans le même fichier. Nous verrons cela dans la seconde partie, qui vous expliquera également (et finalement) comment diable utiliser Let's Encrypt avec ce bidule. En tout cas, si vous êtes perspicace, vous vous doutez que ça tournera en partie autour des ACL, car il y a bien une raison pour laquelle c'est le seul élément en gras de l'article.

    (Source de l'image d'en-tête : Great A'tuin par Schiraki)

    • At chevron_right

      Une Flask de Django

      motius · pubsub.gugod.fr / atomtest · Sunday, 24 September, 2017 - 22:00 · 17 minutes

    Bonjour à tous ! Pour ceux qui ont déjà fait du développement web avec Django le titre est évident, pour les autres, bienvenue sur mon introduction à Django ! Django est un excellent framework Python qui permet de développer rapidement des applications web, et qui est très complet. Il est plus long ...

    Bonjour à tous !

    Pour ceux qui ont déjà fait du développement web avec Django le titre est évident, pour les autres, bienvenue sur mon introduction à Django !

    Django est un excellent framework Python qui permet de développer rapidement des applications web, et qui est très complet. Il est plus long à prendre en main que Flask, un autre microframework Python que je vais utiliser comme exemple afin d'introduire quelques concepts de Django, et de montrer que ces idées bizarres ne sortent pas de nulle part.

    Parés ? C'est parti !

    Prérequis

    Ce tutoriel va référencer des tags du dépôt git à cette adresse. Je vous conseille aussi cet excellent tutoriel qui pourra compléter ce que j'écris ci-dessous. Enfin, la documentation de Django est complète et facile à utiliser.

    Je vous conseille donc de cloner le dépôt ci-dessus :

    git clone https://git.hashtagueule.fr/motius/django-tutorial.git

    et de suivre les tags que j'ai indiqués au fur et à mesure de l'avancement du tutoriel grâce à la commande :

    git checkout <tagname>

    Je préfixe les noms de tous les tags git de ce tutoriel par un "_", afin que ceux-ci ne polluent pas le projet si vous en réutilisez le dépôt git par la suite (git tag admet l'option -d pour ceux qui veulent vraiment se débarasser de mes tags).

    La quasi-totalité de ce tutoriel n'impose pas d'accès root sur le système de développement, je suppose tout de même que vous avez python3 et pip3 d'installés, un accès au réseau pour les packages Python supplémentaires, ainsi que le gestionnaire de versions de code git.

    J'utilise une debian GNU/Linux 9.1 Stretch pour le développement, mais ce tutoriel doit facilement être adaptable à d'autres distributions.

    Commençons en douceur avec Flask.

    Flask, en deux mots

    Je vais me faire battre, je vais parler de Flask alors que je l'ai utilisé en tout et pour tout 7 minutes 24 secondes dans ma courte vie.

    Installation

    Prenons l'exemple le plus basique avec Flask. La documentation du projet se trouve ici.

    Elle indique qu'il suffit de taper la commande suivante pour installer Flask :

    pip3 install --user Flask

    Le projet fil d'ariane

    Si vous avez suivi l'étape précédente, vous savez qu'il faut revenir à la version du tag "_v0_flask" comme ceci :

    git checkout _v0_flask

    pour cette partie du tutoriel. Vous pouvez alors faire tourner le serveur de test à l'aide de la commande :

    make

    Je vais faire une utilisation intensive des Makefiles, que j'affectionne, mais je vous encourage à les parcourir pour voir ce qu'ils exécutent.

    Ici, la commande est simplement :

    python3 ma_flasque.py

    Vous pouvez alors vous rendre à l'url suivante : http://localhost:5000 dans mon cas.

    Le pourquoi du comment

    La partie intéressante que je voulais mettre en avant avec cet exemple concerne la structure du code Flask : j'ai divisé le source en trois parties, les imports, les routes Flask, et le code pour faire tourner l'application. La deuxième partie concernant les routes et le code métier est celle qui nous intéresse.

    Les routes sont indiquées par un :

    @app.route('/', methods=["GET"])

    tandis que le code à exécuter dans le cas où l'utilisateur demande ('GET') la page par défaut de l'application ('/') se situe dans le code de la fonction Python index, qui dans notre cas retourne la chaîne de caractères "Hello World!" (tradition oblige) :

    def index():
        return "Hello World!"

    Ainsi, Flask pose les bases de la programmation avec le motif MVC, que Django utilise : on décrit de manière séparée le code de routage des URL et le code permettant d'obtenir le résultat demandé.

    Django utilisera des fichiers séparés pour le routage (Vues) et pour les fonctions Python du Contrôleur, mais le principe est le même.

    Il va falloir un peu de travail pour arriver au même résultat avec Django, mais n'aillez pas peur, on y arrivera. L'essentiel est de garder les yeux sur l'objectif : avoir une séparation entre le code de routage et le code métier.

    Django va un peu plus loin car il permet de s'interfacer très facilement avec une base de données et en propose une abstraction très propre, il possède un moteur de template pour prémâcher du HTML, permet d'installer des modules, mais tout ça viendra plus tard, je vous mets l'eau à la bouche...

    gâteau au chocolat

    Un gâteau au chocolat pour vous mettre l'eau à la bouche si ma description des fonctionnalités de Django n'a pas suffi.

    Même résultat avec Django

    Installation

    La page de téléchargement de Django indique, à l'heure actuelle, qu'il suffit de taper la commande suivante pour installer la dernière version de Django :

    pip3 install Django==1.11.5

    Si vous utilisez Django de manière professionnelle ou amateure, il faut consulter la page de téléchargement pour mettre à jour la version de Django utilisée.

    Vous pouvez aussi installer la version de votre distribution, par exemple à l'aide de

    su -c 'apt-get install python3-django'

    si vous utilisez une debian ou dérivée (Ubuntu, Mint...)

    On utilisera Django dans un virtualenv Python pour ce projet.

    Virtualenv

    Python est un langage de programmation modulaire dont le cœur des fonctionnalités est assez réduit, mais qui reste très puissant grâce au grand écosystème disponible de bibliothèques logicielles, officielles ou tierces.

    Celles-ci peuvent être importées dans un script par une primitive import du type :

    import os, sys
    import re
    import numpy as np
    from django.http import HttpResponse

    etc.

    Les virtualenv Python servent à gérer pour chaque projet ses dépendances exactes, à l'inclusion des numéros de version des bibliothèques utilisées, et ce sans interférer avec d'autres projets.

    On utilisera donc les virtualenv pour des questions de facilité, et parce qu'ils permettent de s'assurer de la pérennité d'un développement.

    Vous pouvez installer virtualenv à l'aide de la commande :

    sudo apt-get install python3-virtualenv

    ou en tapant :

    pip3 install --user virtualenv

    Premier projet Django dans un Virtualenv

    La version "_v1_django" permet d'installer Django dans un virtualenv Python. Si vous avez installé Django et Virtualenv comme indiqué précédemment, l'installation devrait se faire sans retélécharger des bibliothèques Python depuis internet.

    Elle suppose que vous installez toutes les bibliothèques avec pip, si ce n'était pas le cas, il faut éventuellement changer la variable VENV du Makefile, ou installer une version avec pip3.

    Pour installer le virtualenv, Django, créer un projet et une application, tapez simplement la commande :

    make

    Pour l'arrêter, tapez la combinaison de touches CTRL-C.

    Détaillons les étapes du Makefile :

    • création du répertoire d'installation de l'environnement de développement, représenté par la variable INSTALL_DIR dans le Makefile ;
    • création du virtualenv Python dans l'environnement de développement ;
    • mise à jour de pip3 dans l'environnement de développement ;
    • installation de Django ;
    • création du projet, dont le nom est représenté par la variable PROJECT_NAME ;
    • création de l'application APP_NAME.

    Vous remarquerez que chacune des étapes ne modifie que le répertoire d'installation situé à l'intérieur du répertoire git, jamais des bibliothèques système.

    Utilisation de Django

    Jusqu'ici, on n'a toujours pas écrit de code correspondant à notre application, seulement décrit une manière générale d'obtenir un projet Django d'équerre pour commencer. Il reste quelques étapes à connaître pour avancer dans le développement d'applications web avec Django sans que celui-ci se mette en travers de notre chemin.

    Migrations

    Lors de la création d'un projet Django, certaines applications sont installées pour nous, par exemple l'interface d'administration. Celle-ci n'est pas migrée, opération qu'il faut réaliser pour pouvoir l'utiliser.

    On a par ailleurs créé notre propre application, qui n'est pas non plus migrée.

    Il est nécessaire d'effectuer les migrations des applications, car celles-ci peuvent entraîner une modification du modèle en base de données.

    Obtenez le code de la version _v2_migration du projet git pour pouvoir migrer les applications du projet, et lancer le serveur Django de développement.

    La commande :

    make

    permet d'effectuer toutes les étapes décrites jusqu'ici :

    • installation de virtualenv, mise à jour de pip3, installation de django, etc. ;
    • création d'un projet django ;
    • création d'une application django ;
    • migrations du projet et de l'application ;
    • lancement du serveur de développement.

    Rendez-vous  à l'URL suivante pour la page par défaut de Django : http://localhost:8000

    Organisation du dépôt

    Le dépôt est organisé de la manière suivante :

    .
    +-- doc
    │   \-- README.md
    +-- exec\_django.sh
    +-- LICENSE
    +-- Makefile
    +-- mon\_django
    │   +-- Makefile
    │   +-- mon\_app
    │   \-- mon\_django
    +-- README.md
    \-- sandbox
        +-- bin
        +-- db.sqlite3
        +-- include
        +-- lib
        +-- Makefile -> ../mon\_django/Makefile
        +-- manage.py
        +-- mon\_app -> ../mon\_django/mon\_app
        +-- mon\_django -> ../mon\_django/mon\_django
        +-- pip-selfcheck.json
        +-- static
        \-- templates -> ../mon\_django/templates
    • les sources sont dans le répertoire mon_django (nom du projet) ;
    • la production est dans le répertoire sandbox ;
    • les sources ont des liens sympboliques vers la production ;
    • à la racine du projet se retrouvent éventuellement :
      • la documentation ;
      • la licence ;
      • les tests (unitaires, intégration).

    Cette organisation a pour but de simplifier le développement :

    • le Makefile (et les scripts qu'il appelle) permet de construire et reconstruire le projet à l'aide d'une seule commande ;
    • à chaque enregistrement d'une modification d'un fichier source sur disque, le serveur de développement Django redémarre avec la mise à jour, grâce aux liens symboliques vers les sources ;
    • la production est séparée des sources ;
    • le dépôt git peut être organisé en suivant les bonnes pratiques de développement Python :
      • disposition de la documentation ;
      • disposition des tests unitaires et intégration...

    Comparaison Django et Flask

    Ça y est, on a enfin tout un environnement prêt pour le développement. Vous allez me dire "était-ce bien la peine de faire tout ça pour en arriver au même point ?" Je crois que oui.

    Avantages de Django

    Pour plusieurs raisons :

    • le code de Django est plus organisé que celui de Flask, ce qui procure un avantage sur le long terme :
      • les vues et le contrôleur sont séparés ;
      • Django incite à faire du développement de petites applications réutilisables au sein de plusieurs projets
    • Django va permettre de s'interfacer facilement avec une base de données, ce qui fait qu'on a en fait de l'avance par rapport au cas où l'on serait restés avec Flask
    • j'ai mis en place un système de construction avec les Makefiles qui permet de tester son application à l'aide d'une seule commande, comme pour Flask.

    Je ne détaille pas les inconvénients de Django, il y en a un principal selon moi, la relative difficulté de le mettre en place, ce qui est fait par le système de construction logicielle avec Makefile.

    Comprendre le code de Django en comparaison avec celui de Flask

    Django fonctionne fondamentalement de la même manière que Flask pour le routage, mais il sépare les vues et le contrôleur :

    • on utilise généralement le fichier urls.py pour décrire la liste des urls proposées par une applications :
      • ces URL ne doivent pas se chevaucher, autrement une seule des URL serait prise en compte (la première rencontrée par Django) ;
      • la liste des URL de tous les fichiers urls.py de toutes les applications constitue l'API backend offerte par votre projet Django ;
    • on utilise le fichier views.py pour le code métier qui va recevoir les requêtes GET/POST HTTP ;
    • on peut éventuellement créer d'autres modules Python pour du code spécifique ;
    • on utilise le fichier models.py pour décrire les modèles des données de l'application, tels que ces données seront sauvegardées en base de données.

    Le développement avec Django

    Maintenant que vous avez vu l'installation de Django en virtualenv Python, ainsi que la théorie sur la manière dont il faut organiser le code Python, allons voir quelques exemples simples.

    Hello World!

    Obtenez la version _v3_application du dépôt. Elle contient un simple "Hello World!" si le client demande la page http://localhost:8000/, et une simple indication "Not found" pour toutes les autres pages. Comme pour chanque étape de ce tutoriel, la commande :

    make

    permet de faire le café (enfin presque). Par rapport à l'étape précédente, on dispose désormais d'une application Django dont le code Python est importé.

    café au lait

    Le café au lait que mon ordinateur ne sait toujours pas faire... Ça viendra.

    En lisant le code,on s'aperçoit que son organisation est similaire à celle de Flask : d'un côté on route les urls, on utilise un ou plusieurs fichiers urls.py pour ce faire, et dans les vues du fichier views.py de chaque application du projet, on peut écrire le code à exécuter pour chaque requête.

    urlpatterns = [
        url('^$', views.index),
        url(r'^admin/', admin.site.urls),
        url('^.*', appviews.p404),
    ]

    Le routage des URL du projet (et de chacune des applications) est défini à l'aide de regexPython. Je fait correspondre les URL suivantes :

    • http://localhost:8000/
    • http://localhost:8000

    au code ci-dessous :

    def index(request):
        return HttpResponse("Hello World!")

    à l'aide de la première règle de routage.

    La page suivante de la documentation permet une utilisation avancée des URL de routage de l'application. On peut par exemple utiliser un champ de l'URL comme paramètre.

    Je ne vous ai pas promis la lune mais presque, allons plus loin dans les fonctionnalités qui sont un des grands avantages de Django.

    Mon premier gabarit

    La version _v4_template permet d'utiliser les templates de Django. Je n'en fait qu'un usage très limité, je me limite à indiquer à Django où il doit aller chercher les fichiers de template correspondant au code HTML/CSS/JavaScript, servis par le serveur de développement, mais ce moteur de gabarits possède de nombreuses fonctionnalités, comme les variables, les tags, des boucles, des conditions...

    La page accessible à l'URL par défaut http://localhost:8000/ affiche le code du template index.html :

    def index(request):
        return render(request, "index.html", {})

    J'ai rajouté de manière explicite un paramètre optionnel : le dictionnaire vide {}. Il sert à préciser des variables Python à transmettre au moteur de gabarits.

    Toutes les autres requêtes redirigent vers la page 404.

    Un accès à la base de données

    Une grande quantité d'applications web nécessite une base de données. Django propose un moyen simple pour s'interfacer avec une base de données sans nécessairement en connaître les subtilités, fournit des garanties qui permettent éventuellement de changer de moteur de base de données, et permet au développeur de manipuler les objets en base facilement.

    La version _v5_bdd présente un exemple simple d'utilisation d'une base de données. Les URL suivantes sont valides :

    • http://localhost:8000/create/ : crée un objet en base de données ;
    • http://localhost:8000/delete/ : supprime tous les objets ;
    • http://localhost:8000/get_nb_objects/ : affiche le nombre d'objets en base de données.

    Attention, celles-ci ne le sont pas, il manque un / à la fin :

    • http://localhost:8000/create ;
    • http://localhost:8000/delete ;
    • http://localhost:8000/get_nb_objects.

    Si vous vous demandez pourquoi l'exemple marche bien que tous les objets aient le même nom et la même valeur de booléen, c'est parce qu'ils se voient attribuer un identifiant entier automatique croissant si on ne définit pas d'attribut ayant une clef primaire, cf. la documentation.

    Découpage en modules

    Vous remarquerez l'utilisation de la primitive Django include dans le code, par rapport à la version _v4_template, qui permet de découper le routage vers les URL d'une application.

    Utilisation d'un constructeur personnalisé

    Django utilise la fonction __init__ qui sert à construire des objets Python. La documentation explique comment attacher un constructeur aux objets sérialisés en base de données, plutôt que de recourir à une méthode build comme je m'y suis pris dans l'exemple _v5_bdd. L'exemple se trouve dans le code de la version  _v6_constructeur.

    Pour aller plus loin

    Je ferai peut-être une suite à ce tutoriel Django. Dans tous les cas, sachez que le point auquel nous sommes arrivés n'est pas suffisant ! En effet, on utilise toujours le serveur de développement de Django, qui n'est pas fait pour être utilisé en production, entre autres :

    "(notre métier est le développement d’environnements Web, pas de serveurs Web)."

    Mise en production

    D'autres éléments sont à considérer durant et après la phase de développement :

    • la mise en place d'un mécanisme de journalisation de l'application ;
    • la mise en place d'un chien de garde permettant de s'assurer que le serveur (nginx, apache, ou autre) sert toujours l'application que vous avez écrite ;
    • la mise en place d'une sauvegarde des données en base...

    Il s'agit d'un travail d'administration système indispensable. À ce travail s'ajoute éventuellement celui de développer une interface web ou autres, si besoin est.

    Modules

    Je n'ai pas parlé des modules de Django. Dans la version _v4_bdd, on utilise la fonction Django render, qui permet de retourner une chaîne de caractères en temps que réponse HTTP. Cela diffère de Flask, qui permet de simplement retourner une chaîne de caractères. L'explication tient au fait que Django utilise l'objet request pour le passer aux modules Django, dans la fonction render.

    Si vous êtes intéressés par le sujet, je vous conseille cette page, qui décrit les interactions possibles sur une requête, ainsi que la base de leur fonctionnement.

    Réutilisation

    Voilà un bon début de projet Django. Pour le réutiliser, n'oubliez pas :

    • de changer la clef API située dans le fichier mon_django/settings.py ;
    • de respecter la licence GPLv3.

    Vous pouvez également créer un répertoire git de zéro à partir d'un des tags du dépôt exemple. Pour cela, obtenez les sources du dépôt au tag que vous souhaitez :

    git checkout <tagname>

    Puis supprimez le dépôt git sans toucher au fichiers existant en enlevant l'arborescence sous le répertoire .git :

    rm -rf ./.git

    Enfin, créez un nouveau dépôt :

    git init

    Vous pouvez aussi garder le dépôt git en l'état, le script del_tags.sh permet de supprimer les tags commençant par "_".

    Conclusion

    Mon but ici n'est pas de prétendre que Django est meilleur que Flask, comme je l'ai indiqué au début de ce tutoriel, j'ai très peu touché à Flask. Flask est un prétexte pour moi pour montrer un des différents aspects de Django (le routage des requêtes). Par ailleurs, en lisant un peu sur le sujet, on s'aperçoit que beaucoup de modules peuvent être utilisés pour donner à Flask des capacités similaires à celles qui viennent avec Django, par exemple :

    • une interface d'administration ;
    • un module ORM pour s'interfacer avec une base de données...

    Il y a donc des arguments en faveur de Flask par rapport à Django, par exemple :

    • le code de Flask est composé de moins de lignes de code  ;
    • on peut choisir ce dont on a réellement besoin parmi des fonctionnalités offertes par la bibliothèque qu'on utilise...

    Django, a de son côté :

    • l'organisation générale d'un projet web :
      • Django encourage à structurer son code ;
      • Django suggère la division du code en applications ;
      • il permet aux développeurs de travailler sur des applications différentes, ce qui facilite la collaboration ;
    • il vient avec un moteur de templates ;
    • il vient avec un ORM...

    Cette comparaison n'est évidemment pas exhaustive, mais permet de se rendre compte des convergences et divergences de philosophie de ses deux projets.

    Vous voilà parés pour démarrer ! J'espère que ce tutoriel vous a été utile. Pour ma part, je trouve que Django est très sympathique à utiliser, sa documentation est facile à prendre en main pour un usage débutant, même si elle est touffue. Enfin sachez que raspbeguy et moi-même avons quelques projets web (parmi lesquels clickstart, et Hashtagueule Express) qui utiliseront peut-être cette technologie.

    Bonne journée et bon développement Python/Django !

    Motius

    PS : après avoir commencé cet article, je suis tombé sur celui-ci, en anglais. Je tiens à le mentionner car la majorité des articles Flask vs Django sont théoriques (souvent des descriptions fonctionnelles, assez intéressantes pour se familiariser rapidement avec les deux projets), mais je n'avais pas vu (ni vraiment cherché) d'article les comparant en mettant la main dans le code.

    • Ha chevron_right

      Une Flask de Django

      motius · pubsub.gugod.fr / hashtagueule · Sunday, 24 September, 2017 - 22:00 · 17 minutes

    Bonjour à tous ! Pour ceux qui ont déjà fait du développement web avec Django le titre est évident, pour les autres, bienvenue sur mon introduction à Django ! Django est un excellent framework Python qui permet de développer rapidement des applications web, et qui est très complet. Il est plus long ...

    Bonjour à tous !

    Pour ceux qui ont déjà fait du développement web avec Django le titre est évident, pour les autres, bienvenue sur mon introduction à Django !

    Django est un excellent framework Python qui permet de développer rapidement des applications web, et qui est très complet. Il est plus long à prendre en main que Flask, un autre microframework Python que je vais utiliser comme exemple afin d'introduire quelques concepts de Django, et de montrer que ces idées bizarres ne sortent pas de nulle part.

    Parés ? C'est parti !

    Prérequis

    Ce tutoriel va référencer des tags du dépôt git à cette adresse. Je vous conseille aussi cet excellent tutoriel qui pourra compléter ce que j'écris ci-dessous. Enfin, la documentation de Django est complète et facile à utiliser.

    Je vous conseille donc de cloner le dépôt ci-dessus :

    git clone https://git.hashtagueule.fr/motius/django-tutorial.git

    et de suivre les tags que j'ai indiqués au fur et à mesure de l'avancement du tutoriel grâce à la commande :

    git checkout <tagname>

    Je préfixe les noms de tous les tags git de ce tutoriel par un "_", afin que ceux-ci ne polluent pas le projet si vous en réutilisez le dépôt git par la suite (git tag admet l'option -d pour ceux qui veulent vraiment se débarasser de mes tags).

    La quasi-totalité de ce tutoriel n'impose pas d'accès root sur le système de développement, je suppose tout de même que vous avez python3 et pip3 d'installés, un accès au réseau pour les packages Python supplémentaires, ainsi que le gestionnaire de versions de code git.

    J'utilise une debian GNU/Linux 9.1 Stretch pour le développement, mais ce tutoriel doit facilement être adaptable à d'autres distributions.

    Commençons en douceur avec Flask.

    Flask, en deux mots

    Je vais me faire battre, je vais parler de Flask alors que je l'ai utilisé en tout et pour tout 7 minutes 24 secondes dans ma courte vie.

    Installation

    Prenons l'exemple le plus basique avec Flask. La documentation du projet se trouve ici.

    Elle indique qu'il suffit de taper la commande suivante pour installer Flask :

    pip3 install --user Flask

    Le projet fil d'ariane

    Si vous avez suivi l'étape précédente, vous savez qu'il faut revenir à la version du tag "_v0_flask" comme ceci :

    git checkout _v0_flask

    pour cette partie du tutoriel. Vous pouvez alors faire tourner le serveur de test à l'aide de la commande :

    make

    Je vais faire une utilisation intensive des Makefiles, que j'affectionne, mais je vous encourage à les parcourir pour voir ce qu'ils exécutent.

    Ici, la commande est simplement :

    python3 ma_flasque.py

    Vous pouvez alors vous rendre à l'url suivante : http://localhost:5000 dans mon cas.

    Le pourquoi du comment

    La partie intéressante que je voulais mettre en avant avec cet exemple concerne la structure du code Flask : j'ai divisé le source en trois parties, les imports, les routes Flask, et le code pour faire tourner l'application. La deuxième partie concernant les routes et le code métier est celle qui nous intéresse.

    Les routes sont indiquées par un :

    @app.route('/', methods=["GET"])

    tandis que le code à exécuter dans le cas où l'utilisateur demande ('GET') la page par défaut de l'application ('/') se situe dans le code de la fonction Python index, qui dans notre cas retourne la chaîne de caractères "Hello World!" (tradition oblige) :

    def index():
        return "Hello World!"

    Ainsi, Flask pose les bases de la programmation avec le motif MVC, que Django utilise : on décrit de manière séparée le code de routage des URL et le code permettant d'obtenir le résultat demandé.

    Django utilisera des fichiers séparés pour le routage (Vues) et pour les fonctions Python du Contrôleur, mais le principe est le même.

    Il va falloir un peu de travail pour arriver au même résultat avec Django, mais n'aillez pas peur, on y arrivera. L'essentiel est de garder les yeux sur l'objectif : avoir une séparation entre le code de routage et le code métier.

    Django va un peu plus loin car il permet de s'interfacer très facilement avec une base de données et en propose une abstraction très propre, il possède un moteur de template pour prémâcher du HTML, permet d'installer des modules, mais tout ça viendra plus tard, je vous mets l'eau à la bouche...

    gâteau au chocolat

    Un gâteau au chocolat pour vous mettre l'eau à la bouche si ma description des fonctionnalités de Django n'a pas suffi.

    Même résultat avec Django

    Installation

    La page de téléchargement de Django indique, à l'heure actuelle, qu'il suffit de taper la commande suivante pour installer la dernière version de Django :

    pip3 install Django==1.11.5

    Si vous utilisez Django de manière professionnelle ou amateure, il faut consulter la page de téléchargement pour mettre à jour la version de Django utilisée.

    Vous pouvez aussi installer la version de votre distribution, par exemple à l'aide de

    su -c 'apt-get install python3-django'

    si vous utilisez une debian ou dérivée (Ubuntu, Mint...)

    On utilisera Django dans un virtualenv Python pour ce projet.

    Virtualenv

    Python est un langage de programmation modulaire dont le cœur des fonctionnalités est assez réduit, mais qui reste très puissant grâce au grand écosystème disponible de bibliothèques logicielles, officielles ou tierces.

    Celles-ci peuvent être importées dans un script par une primitive import du type :

    import os, sys
    import re
    import numpy as np
    from django.http import HttpResponse

    etc.

    Les virtualenv Python servent à gérer pour chaque projet ses dépendances exactes, à l'inclusion des numéros de version des bibliothèques utilisées, et ce sans interférer avec d'autres projets.

    On utilisera donc les virtualenv pour des questions de facilité, et parce qu'ils permettent de s'assurer de la pérennité d'un développement.

    Vous pouvez installer virtualenv à l'aide de la commande :

    sudo apt-get install python3-virtualenv

    ou en tapant :

    pip3 install --user virtualenv

    Premier projet Django dans un Virtualenv

    La version "_v1_django" permet d'installer Django dans un virtualenv Python. Si vous avez installé Django et Virtualenv comme indiqué précédemment, l'installation devrait se faire sans retélécharger des bibliothèques Python depuis internet.

    Elle suppose que vous installez toutes les bibliothèques avec pip, si ce n'était pas le cas, il faut éventuellement changer la variable VENV du Makefile, ou installer une version avec pip3.

    Pour installer le virtualenv, Django, créer un projet et une application, tapez simplement la commande :

    make

    Pour l'arrêter, tapez la combinaison de touches CTRL-C.

    Détaillons les étapes du Makefile :

    • création du répertoire d'installation de l'environnement de développement, représenté par la variable INSTALL_DIR dans le Makefile ;
    • création du virtualenv Python dans l'environnement de développement ;
    • mise à jour de pip3 dans l'environnement de développement ;
    • installation de Django ;
    • création du projet, dont le nom est représenté par la variable PROJECT_NAME ;
    • création de l'application APP_NAME.

    Vous remarquerez que chacune des étapes ne modifie que le répertoire d'installation situé à l'intérieur du répertoire git, jamais des bibliothèques système.

    Utilisation de Django

    Jusqu'ici, on n'a toujours pas écrit de code correspondant à notre application, seulement décrit une manière générale d'obtenir un projet Django d'équerre pour commencer. Il reste quelques étapes à connaître pour avancer dans le développement d'applications web avec Django sans que celui-ci se mette en travers de notre chemin.

    Migrations

    Lors de la création d'un projet Django, certaines applications sont installées pour nous, par exemple l'interface d'administration. Celle-ci n'est pas migrée, opération qu'il faut réaliser pour pouvoir l'utiliser.

    On a par ailleurs créé notre propre application, qui n'est pas non plus migrée.

    Il est nécessaire d'effectuer les migrations des applications, car celles-ci peuvent entraîner une modification du modèle en base de données.

    Obtenez le code de la version _v2_migration du projet git pour pouvoir migrer les applications du projet, et lancer le serveur Django de développement.

    La commande :

    make

    permet d'effectuer toutes les étapes décrites jusqu'ici :

    • installation de virtualenv, mise à jour de pip3, installation de django, etc. ;
    • création d'un projet django ;
    • création d'une application django ;
    • migrations du projet et de l'application ;
    • lancement du serveur de développement.

    Rendez-vous  à l'URL suivante pour la page par défaut de Django : http://localhost:8000

    Organisation du dépôt

    Le dépôt est organisé de la manière suivante :

    .
    +-- doc
    │   \-- README.md
    +-- exec\_django.sh
    +-- LICENSE
    +-- Makefile
    +-- mon\_django
    │   +-- Makefile
    │   +-- mon\_app
    │   \-- mon\_django
    +-- README.md
    \-- sandbox
        +-- bin
        +-- db.sqlite3
        +-- include
        +-- lib
        +-- Makefile -> ../mon\_django/Makefile
        +-- manage.py
        +-- mon\_app -> ../mon\_django/mon\_app
        +-- mon\_django -> ../mon\_django/mon\_django
        +-- pip-selfcheck.json
        +-- static
        \-- templates -> ../mon\_django/templates
    • les sources sont dans le répertoire mon_django (nom du projet) ;
    • la production est dans le répertoire sandbox ;
    • les sources ont des liens sympboliques vers la production ;
    • à la racine du projet se retrouvent éventuellement :
      • la documentation ;
      • la licence ;
      • les tests (unitaires, intégration).

    Cette organisation a pour but de simplifier le développement :

    • le Makefile (et les scripts qu'il appelle) permet de construire et reconstruire le projet à l'aide d'une seule commande ;
    • à chaque enregistrement d'une modification d'un fichier source sur disque, le serveur de développement Django redémarre avec la mise à jour, grâce aux liens symboliques vers les sources ;
    • la production est séparée des sources ;
    • le dépôt git peut être organisé en suivant les bonnes pratiques de développement Python :
      • disposition de la documentation ;
      • disposition des tests unitaires et intégration...

    Comparaison Django et Flask

    Ça y est, on a enfin tout un environnement prêt pour le développement. Vous allez me dire "était-ce bien la peine de faire tout ça pour en arriver au même point ?" Je crois que oui.

    Avantages de Django

    Pour plusieurs raisons :

    • le code de Django est plus organisé que celui de Flask, ce qui procure un avantage sur le long terme :
      • les vues et le contrôleur sont séparés ;
      • Django incite à faire du développement de petites applications réutilisables au sein de plusieurs projets
    • Django va permettre de s'interfacer facilement avec une base de données, ce qui fait qu'on a en fait de l'avance par rapport au cas où l'on serait restés avec Flask
    • j'ai mis en place un système de construction avec les Makefiles qui permet de tester son application à l'aide d'une seule commande, comme pour Flask.

    Je ne détaille pas les inconvénients de Django, il y en a un principal selon moi, la relative difficulté de le mettre en place, ce qui est fait par le système de construction logicielle avec Makefile.

    Comprendre le code de Django en comparaison avec celui de Flask

    Django fonctionne fondamentalement de la même manière que Flask pour le routage, mais il sépare les vues et le contrôleur :

    • on utilise généralement le fichier urls.py pour décrire la liste des urls proposées par une applications :
      • ces URL ne doivent pas se chevaucher, autrement une seule des URL serait prise en compte (la première rencontrée par Django) ;
      • la liste des URL de tous les fichiers urls.py de toutes les applications constitue l'API backend offerte par votre projet Django ;
    • on utilise le fichier views.py pour le code métier qui va recevoir les requêtes GET/POST HTTP ;
    • on peut éventuellement créer d'autres modules Python pour du code spécifique ;
    • on utilise le fichier models.py pour décrire les modèles des données de l'application, tels que ces données seront sauvegardées en base de données.

    Le développement avec Django

    Maintenant que vous avez vu l'installation de Django en virtualenv Python, ainsi que la théorie sur la manière dont il faut organiser le code Python, allons voir quelques exemples simples.

    Hello World!

    Obtenez la version _v3_application du dépôt. Elle contient un simple "Hello World!" si le client demande la page http://localhost:8000/, et une simple indication "Not found" pour toutes les autres pages. Comme pour chanque étape de ce tutoriel, la commande :

    make

    permet de faire le café (enfin presque). Par rapport à l'étape précédente, on dispose désormais d'une application Django dont le code Python est importé.

    café au lait

    Le café au lait que mon ordinateur ne sait toujours pas faire... Ça viendra.

    En lisant le code,on s'aperçoit que son organisation est similaire à celle de Flask : d'un côté on route les urls, on utilise un ou plusieurs fichiers urls.py pour ce faire, et dans les vues du fichier views.py de chaque application du projet, on peut écrire le code à exécuter pour chaque requête.

    urlpatterns = [
        url('^$', views.index),
        url(r'^admin/', admin.site.urls),
        url('^.*', appviews.p404),
    ]

    Le routage des URL du projet (et de chacune des applications) est défini à l'aide de regexPython. Je fait correspondre les URL suivantes :

    • http://localhost:8000/
    • http://localhost:8000

    au code ci-dessous :

    def index(request):
        return HttpResponse("Hello World!")

    à l'aide de la première règle de routage.

    La page suivante de la documentation permet une utilisation avancée des URL de routage de l'application. On peut par exemple utiliser un champ de l'URL comme paramètre.

    Je ne vous ai pas promis la lune mais presque, allons plus loin dans les fonctionnalités qui sont un des grands avantages de Django.

    Mon premier gabarit

    La version _v4_template permet d'utiliser les templates de Django. Je n'en fait qu'un usage très limité, je me limite à indiquer à Django où il doit aller chercher les fichiers de template correspondant au code HTML/CSS/JavaScript, servis par le serveur de développement, mais ce moteur de gabarits possède de nombreuses fonctionnalités, comme les variables, les tags, des boucles, des conditions...

    La page accessible à l'URL par défaut http://localhost:8000/ affiche le code du template index.html :

    def index(request):
        return render(request, "index.html", {})

    J'ai rajouté de manière explicite un paramètre optionnel : le dictionnaire vide {}. Il sert à préciser des variables Python à transmettre au moteur de gabarits.

    Toutes les autres requêtes redirigent vers la page 404.

    Un accès à la base de données

    Une grande quantité d'applications web nécessite une base de données. Django propose un moyen simple pour s'interfacer avec une base de données sans nécessairement en connaître les subtilités, fournit des garanties qui permettent éventuellement de changer de moteur de base de données, et permet au développeur de manipuler les objets en base facilement.

    La version _v5_bdd présente un exemple simple d'utilisation d'une base de données. Les URL suivantes sont valides :

    • http://localhost:8000/create/ : crée un objet en base de données ;
    • http://localhost:8000/delete/ : supprime tous les objets ;
    • http://localhost:8000/get_nb_objects/ : affiche le nombre d'objets en base de données.

    Attention, celles-ci ne le sont pas, il manque un / à la fin :

    • http://localhost:8000/create ;
    • http://localhost:8000/delete ;
    • http://localhost:8000/get_nb_objects.

    Si vous vous demandez pourquoi l'exemple marche bien que tous les objets aient le même nom et la même valeur de booléen, c'est parce qu'ils se voient attribuer un identifiant entier automatique croissant si on ne définit pas d'attribut ayant une clef primaire, cf. la documentation.

    Découpage en modules

    Vous remarquerez l'utilisation de la primitive Django include dans le code, par rapport à la version _v4_template, qui permet de découper le routage vers les URL d'une application.

    Utilisation d'un constructeur personnalisé

    Django utilise la fonction __init__ qui sert à construire des objets Python. La documentation explique comment attacher un constructeur aux objets sérialisés en base de données, plutôt que de recourir à une méthode build comme je m'y suis pris dans l'exemple _v5_bdd. L'exemple se trouve dans le code de la version  _v6_constructeur.

    Pour aller plus loin

    Je ferai peut-être une suite à ce tutoriel Django. Dans tous les cas, sachez que le point auquel nous sommes arrivés n'est pas suffisant ! En effet, on utilise toujours le serveur de développement de Django, qui n'est pas fait pour être utilisé en production, entre autres :

    "(notre métier est le développement d’environnements Web, pas de serveurs Web)."

    Mise en production

    D'autres éléments sont à considérer durant et après la phase de développement :

    • la mise en place d'un mécanisme de journalisation de l'application ;
    • la mise en place d'un chien de garde permettant de s'assurer que le serveur (nginx, apache, ou autre) sert toujours l'application que vous avez écrite ;
    • la mise en place d'une sauvegarde des données en base...

    Il s'agit d'un travail d'administration système indispensable. À ce travail s'ajoute éventuellement celui de développer une interface web ou autres, si besoin est.

    Modules

    Je n'ai pas parlé des modules de Django. Dans la version _v4_bdd, on utilise la fonction Django render, qui permet de retourner une chaîne de caractères en temps que réponse HTTP. Cela diffère de Flask, qui permet de simplement retourner une chaîne de caractères. L'explication tient au fait que Django utilise l'objet request pour le passer aux modules Django, dans la fonction render.

    Si vous êtes intéressés par le sujet, je vous conseille cette page, qui décrit les interactions possibles sur une requête, ainsi que la base de leur fonctionnement.

    Réutilisation

    Voilà un bon début de projet Django. Pour le réutiliser, n'oubliez pas :

    • de changer la clef API située dans le fichier mon_django/settings.py ;
    • de respecter la licence GPLv3.

    Vous pouvez également créer un répertoire git de zéro à partir d'un des tags du dépôt exemple. Pour cela, obtenez les sources du dépôt au tag que vous souhaitez :

    git checkout <tagname>

    Puis supprimez le dépôt git sans toucher au fichiers existant en enlevant l'arborescence sous le répertoire .git :

    rm -rf ./.git

    Enfin, créez un nouveau dépôt :

    git init

    Vous pouvez aussi garder le dépôt git en l'état, le script del_tags.sh permet de supprimer les tags commençant par "_".

    Conclusion

    Mon but ici n'est pas de prétendre que Django est meilleur que Flask, comme je l'ai indiqué au début de ce tutoriel, j'ai très peu touché à Flask. Flask est un prétexte pour moi pour montrer un des différents aspects de Django (le routage des requêtes). Par ailleurs, en lisant un peu sur le sujet, on s'aperçoit que beaucoup de modules peuvent être utilisés pour donner à Flask des capacités similaires à celles qui viennent avec Django, par exemple :

    • une interface d'administration ;
    • un module ORM pour s'interfacer avec une base de données...

    Il y a donc des arguments en faveur de Flask par rapport à Django, par exemple :

    • le code de Flask est composé de moins de lignes de code  ;
    • on peut choisir ce dont on a réellement besoin parmi des fonctionnalités offertes par la bibliothèque qu'on utilise...

    Django, a de son côté :

    • l'organisation générale d'un projet web :
      • Django encourage à structurer son code ;
      • Django suggère la division du code en applications ;
      • il permet aux développeurs de travailler sur des applications différentes, ce qui facilite la collaboration ;
    • il vient avec un moteur de templates ;
    • il vient avec un ORM...

    Cette comparaison n'est évidemment pas exhaustive, mais permet de se rendre compte des convergences et divergences de philosophie de ses deux projets.

    Vous voilà parés pour démarrer ! J'espère que ce tutoriel vous a été utile. Pour ma part, je trouve que Django est très sympathique à utiliser, sa documentation est facile à prendre en main pour un usage débutant, même si elle est touffue. Enfin sachez que raspbeguy et moi-même avons quelques projets web (parmi lesquels clickstart, et Hashtagueule Express) qui utiliseront peut-être cette technologie.

    Bonne journée et bon développement Python/Django !

    Motius

    PS : après avoir commencé cet article, je suis tombé sur celui-ci, en anglais. Je tiens à le mentionner car la majorité des articles Flask vs Django sont théoriques (souvent des descriptions fonctionnelles, assez intéressantes pour se familiariser rapidement avec les deux projets), mais je n'avais pas vu (ni vraiment cherché) d'article les comparant en mettant la main dans le code.

    • At chevron_right

      Ça va devenir RAID dans votre serveur

      raspbeguy · pubsub.gugod.fr / atomtest · Sunday, 20 August, 2017 - 22:00 · 13 minutes

    Récemment j'ai du intervenir sur ma tour parce que j'avais plus tellement de place. J'ai du vite acheter un autre disque dur pour y remédier. Ce qui me donne l'occasion de parler de cette belle technologie sur laquelle je m'étais promis de faire un petit tuto un de ces jours. En théorie RAID est l'a...

    Récemment j'ai du intervenir sur ma tour parce que j'avais plus tellement de place. J'ai du vite acheter un autre disque dur pour y remédier. Ce qui me donne l'occasion de parler de cette belle technologie sur laquelle je m'étais promis de faire un petit tuto un de ces jours.

    En théorie

    RAID est l'acronyme de Redundant Array of Independent Disks (Alignement redondant de disques indépendants), et comme son nom l'indique, il va permettre de regrouper plusieurs disques durs et d'y instaurer une politique de stockage pour faire de la redondance, de l’agrégation de taille, enfin ça répond à plein de besoins différents. En fait on ne devrait pas vraiment parler d'un seul RAID, mais bel et bien de la famille des RAIDs, car en effet il y a autant de RAIDs que de besoins différent.

    On va présenter les assemblages RAID les plus utilisés. Pour plus de détails, je vous conseille la page Wikipédia qui est très claire et qui contient des schémas très explicites.

    Dans la suite, on va beaucoup parler de bandes de stockage : il s'agit d'une quantité de stockage de valeur prédéfinie, qui correspond à une "section" contiguë du disque qui la contient. Dans ce modèle, lors de l'écriture sur le volume, une bande est d’abord remplie avant d'en entamer une suivante. Il s'agit en fait d'abstraire le stockage et de pouvoir mieux comprendre la répartition des données sur les différents disques.

    RAID 0

    Les bandes sont tout bonnement distribuées sur les disques, toujours dans le même ordre. On remplit donc une bande par disque, puis une fois qu'on a touché à tous les disques, on repart du premier disque et on recommence une couche de bandes. Tous les disques contiennent des données différentes. Ainsi, si vous avez n disques durs de capacité exploitable x, la capacité totale du montage sera nx.

    • Avantages : Ce montage permet d'utiliser le plus grand espace possible de votre assemblage. De plus, en moyenne, les accès disques parallèles seront plus rapide, pour peu que ces accès disques se fassent dans des bandes différentes et sur des disques différents.
    • Inconvénients : Il suffit de perdre un seul disque pour corrompre l'intégralité des données. Or, statistiquement, plus on a de disques, plus on a de chances d'en perdre.

    RAID 1

    Les bandes sont écrites à l’identique sur tous les disques. Tous les disques contiennent exactement les même données. Ainsi, si vous avez n disques durs de capacité exploitable x, la capacité totale du montage sera x.

    • Avantages : C'est le montage qui permet la plus grande sécurité des données faces aux pannes : tant qu'il vous reste un disque fonctionnel, vos données sont intactes et complètes. Les accès disques sont aussi nettement améliorés, avec une vitesse théorique multipliée par le nombre de disques dans le montage.
    • Inconvénients : Il est frustrant d'avoir beaucoup de disques durs pour avoir au final l'espace d'un seul disque. Évidemment les données sont très sûres mais quand même, faut pas pousser...

    RAID 5

    Les bandes sont réparties sur tous les disques sauf un, qui reçoit une bande de parité. La bande de parité est tout simplement une bande dont chaque bit est obtenu en appliquant le OU exclusif (XOR) à l'ensemble des bits correspondants dans les bandes alignées des autres disques. Cette bande de parité est attribuée à chaque disque alternativement au fil des couches de bandes remplies. Donc si un disque vient à tomber en panne, pour chaque couche de bande, si la bande du disque en panne est la bande de parité, alors les données de la couche sont intactes. Si la bande contient de la donnée, alors elle peut être recalculée à partir des autres couches de données et celle de parité. C'est du calcul logique, et c'est la force du XOR. Ainsi, si vous avez n disques durs de capacité exploitable x, la capacité totale du montage sera (n-1)x.

    • Avantages : Un bon compromis entre place exploitable et sécurité des données. On se donne le droit de perdre un disque dur dans la bataille. Pour retrouver l'usage des données, il suffit de remplacer le disque défaillant et les données sont reconstruites.
    • Inconvénients : Ça dépends des cas, mais un droit à un unique disque dur en panne, ça peu être peu. Pour certain ça peut être insuffisant.

    RAID 6

    Il s'agit d'une extension du RAID 5 dans laquelle on se permet de pouvoir perdre plus d'un disque. La solution étant d'attribuer plus de bandes de "parité" par couche, une par nombre de pannes maximum permises. Ici, j'utilise les guillemets car il ne s'agit plus vraiment de la parité simple de la logique de base, mais d'un truc chelou reposant sur un principe tout autre dont je ne pas trop vous parler parce que j'en ignore tout. Donc si vous avez n disques durs de capacité exploitable x, et si vous mettez en place k bandes de redondance par couche, la capacité totale du montage sera (n-k)x.

    • Avantages : On se sent un peu plus à l’abri des intempéries matérielles, au pris d'un peu de place de stockage.
    • Inconvénients : Le principe chelou dont je vous ai parlé, enfin dont je ne vous ai pas parlé pour être honnête, eh bien il est tellement chelou qu'il pète pas mal les performances. Et pour couronner le tout, la plupart des implémentations de ce type d'assemblage est bien moins stable que les autres.

    Il est également possible de combiner les RAIDs. Une combinaison fréquente est le RAID 10 (RAID 1 + RAID 0). Par exemple si on a 10 disques, on peu monter 2 RAID 1 de 5 disques chacun, puis assembler ces deux volumes en RAID 0. On a également aussi le RAID 50, combinaison dur RAID 5 et du RAID 0 selon le même principe.

    La gestion du RAID

    Je vous parlais de différentes implémentations du RAID. En fait, le RAID n'est pas un programme en tant que soi, juste un ensemble de spécifications. Du coup chacun y va de sa sauce : il existe des implémentations libres et propriétaires, logicielles et matérielles. Les solutions matérielles se basent sur du matériel dédié (un contrôleur RAID), le système d'exploitation n'a donc pas à s'occuper de ça et le plus souvent ces solutions marchent out of the box, sans avoir besoin de configurer quoi que ce soit. Mais elles ont l'immense inconvénient d'être propriétaire dans leur quasi-totalité, et pour le coup il n'existe aucun standard. Dans certains cas, si votre contrôleur RAID rend l'âme, il vous faudra acquérir exactement le même modèle de contrôleur, sinon, peu importe que vos disques soient tous intacts, plus rien ne pourra les lire, et vous serez alors en légitime position d'être fort contrarié. À mon humble avis, le principal argument des RAIDs matériel auparavant était les meilleures performances. Aujourd'hui cet avantage est de plus en plus obsolète, car désormais les machines sont bien plus puissantes qu'il y a 15 ans et les programmes de RAID ont été nettement optimisés et stabilisés. Cette différence de performance est aujourd'hui presque intangible.

    En pratique

    J'ai hérité par un ami d'une tour de bureau. Elle est bien cool car elle contient une grande baie de disques et pas mal de ports SATA (bien entendu, vous pouvez faire votre RAID avec des disques branchés en USB si vous le souhaitez). J'ai donc décidé d'en faire un NAS fait main.

    Choix des armes

    J'ai donc initialement acheté 3 disques de 3 To chacun (des Western Digital Red, gamme dédiée justement aux usage en RAID) et j'ai opté pour un RAID 5 logiciel. Et sur Linux, le programme de RAID par excellence est mdadm. J'ai décidé de garder branché le disque dur d'origine (500 Go) mais de ne pas l'intégrer au RAID, il sert uniquement de disque de démarrage. Notez que si j'avais voulu optimiser les performances, j'aurais pu troquer ce disque pour un petit SSD, mais bon, je suis déjà content comme ça.

    Par ailleurs, pour faire de la place dans la baie de disques, j'ai du déménager le disque de démarrage dans la baie frontale, celle destinée à accueillir les périphériques comme le lecteur optique.

    Le 4ème disque du RAID, on en parlera plus tard. Je l'ai acheté bien après.

    Pour ça j'ai utilisé un adaptateur 3,5 pouces vers 5,25 pouces bien pratique, qui m'a permis de fixer bien solidement le disque dur au lieu de le laisser se balader dans la tour.

    Partitionnement et formatage

    Du côté software, je me retrouve avec un disque sda de démarrage, et sdb, sdc et sdd des disques vierges prêts à être assemblés en RAID. Avant ça, j'ai besoin de les partitionner. J'utilise donc fdisk pour les trois disques à tour de rôle, je choisis une table de partitions GPT et j'y crée une unique partition de type "Linux RAID" (code 29 dans fdisk).

    Création de l'assemblage RAID

    C'est tout bête, ça tient en une seule ligne de commande :

    mdadm --create --verbose /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 /dev/sdd1

    Dans cette commande, j'indique que le nom du volume abstrait sera /dev/md0, que ce sera un RAID 5, qu'il comporte 3 disques et je lui précise les partitions que je veux utiliser.

    Pour suivre l'évolution de la création de l'assemblage, jetez un coup d'oeil au fichier /proc/mdstat. Ce fichier sera votre nouvel ami, c'est lui qu'il faudra consulter dès que vous ferez une opération qui touche au RAID.

    Puis j'ajoute l'assemblage à la configuration de mdadm pour que celui-ci me l'assemble au démarrage :

    mdadm --detail --scan >> /etc/mdadm.conf

    Puis il ne vous reste plus qu'à mettre votre système de fichier préféré sur le volume créé !

    mkfs.ext4 /dev/md0

    Pour que votre assemblage soit monté au démarrage, j'ajoute à mon /etc/fstab :

    /dev/md0 /mnt/data ext4 defaults 0 0

    Il ne faut pas confondre assemblage et montage, il s'agit de deux étapes lors de la connexion d'un RAID. On doit assembler un RAID afin qu'il soit reconnu comme un volume propre, puis on doit monter notre volume pour pouvoir lire et écrire dessus.

    Enfin on monte le volume :

    mkdir /mnt/data
    mount /mnt/data

    Ayé vous avez un RAID 5 qui fonctionne !

    Il est recommandé de procéder régulièrement à des reconstruction de RAID, opération qui va vérifier la cohérence de l'assemblage. Il s'agit d'une opération transparente mais qui dure plusieurs heures et qui va se traduire par une forte augmentation de l'activité des disques. Pour ça il vous faudra lancer un petit programme sans arguments, raid-check, à un intervalle raisonnable, disons, toutes les semaines. Choisissez un horaire de faible activité, comme la nuit du samedi au dimanche à 3h du matin. Pour ça, faites vous plaisir, entre la crontab et les timers de systemd, on manque pas de solutions.

    Ajout d'un nouveau disque à l'assemblage

    Mon RAID 5 était constitué de 3 disques de 3 To ce qui nous fait 6 To exploitables, si vous avez bien suivi. 6 To, c'est un grand espace, il m'a suffi pendant presque 2 ans... Puis j'ai eu besoin de plus de place. J'ai donc racheté un autre disque (même modèle, même taille) que j'ai fourré dans ma tour. Je vous avoue que sur le coup, j'étais encore puceau au niveau extension de RAID, j'ai donc flippé énormément et j'ai fait une sauvegarde de mes 6 To sur divers disques externes que j'ai pu trouver dans ma caverne. Je vous raconte pas comme c'était pénible...

    Petites observations à ce niveau :

    1. Remarquez que l'ordre des disques dans le nommage des périphériques physiques (sdX) et tout sauf fixe. En théorie, il faut être préparé à ce que vos disques changent de noms. Votre petit sdb chéri que vous avez bordé et vu s'endormir dans le creux douillet de son lit un soir peut très bien vous trahir et s'appeler sdc au petit matin dès le prochain redémarrage. Bon c'est un peu exagéré, mais une chose est sure, il ne faut jamais faire confiance au nommage des périphériques physiques (c'est pour ça entre autres qu'il faut privilégier la désignation par UUID dans la fstab).
    2. mdadm se fiche complètement du nommage de ses périphériques. Il utilise sa propre magie noire pour déterminer les membres d'un assemblages. En conclusion, ne vous tracassez pas pour retrouver le nom de vos disques de votre assemblage, mdadm, lui, s'y retrouvera toujours.

    Cependant, faites quand même gaffe lorsque vous allez ajoutez votre nouveau disque dur. Par exemple chez moi, le nouveau disque s'est vu nommé sdb, tandis que les autres s'étaient vu relégués en sdc, sdd et sde. Faut juste le savoir et traiter les disques pour ce qu'ils sont, et non pas des étiquettes à trois lettres.

    Tout ce que j'ai eu à faire, en définitive, a été de partitionner-formater mon nouveau disque ainsi que l'ont été ses aînés, puis j'ai lancé les deux commandes suivantes :

    mdadm --add /dev/md0 /dev/sdb1
    mdadm --grow --raid-devices=4 --backup-file=/root/grow\_md0.bak /dev/md0

    La première va juste indiquer à mdadm qu'on lui ajoute un disque, mais sans plus. C'est la deuxième commande qui va lancer l'opération de reconstruction (rééquilibrage de l'assemblage). Opération qui dure plusieurs heures, donc suivez son déroulement dans /proc/mdstat.

    Une fois que c'est terminé, il faut maintenant procéder à l'extension du système de fichier lui même. Et là vous priez pour avoir choisi un système de fichier pas trop stupide qui accepte ce genre d'opération. Rassurez-vous, ext4 le supporte très bien.

    Il le supporte même tellement bien que vous pouvez le faire directement à chaud, sans démonter votre volume. Pour ça, premièrement, si vous utilisez une connexion SSH, ouvrez une session tmux. Il serait bête qu'un incident réseau de rien du tout vienne corrombre tout votre système de fichire tout de même. Puis il vous faudra exécuter :

    resize2fs -p /dev/md0

    Il va vous mettre en garde et ronchonner un tantinet que votre disque est toujours monté, mais écoutez, il s'en remettra, dans la vie on fait pas toujours ce qu'on veut. Les minutes passent, vous vous rongez les ongles, vous prenez un café, vous videz un pot de glace, et normalement, si tout se passe bien, le système de fichier aura été étendu à tout l'espace disponible sur l'assemblage. Félicitations !

    Conclusion

    J'ai rencontré beaucoup de monde m'ayant dit qu'ils préféraient rester éloigner autant que possible de RAID parce que ça leur faisait peur. En réalité, il n'y a rien d'effrayant là dedans. mdadm est un outil ma foi fort bien codé et les années ont prouvé qu'il était fiable. Il ne faut pas avoir peur du RAID. Enfin un peu quand même, faut pas faire n'importe quoi.

    • Ha chevron_right

      Ça va devenir RAID dans votre serveur

      raspbeguy · pubsub.gugod.fr / hashtagueule · Sunday, 20 August, 2017 - 22:00 · 13 minutes

    Récemment j'ai du intervenir sur ma tour parce que j'avais plus tellement de place. J'ai du vite acheter un autre disque dur pour y remédier. Ce qui me donne l'occasion de parler de cette belle technologie sur laquelle je m'étais promis de faire un petit tuto un de ces jours. En théorie RAID est l'a...

    Récemment j'ai du intervenir sur ma tour parce que j'avais plus tellement de place. J'ai du vite acheter un autre disque dur pour y remédier. Ce qui me donne l'occasion de parler de cette belle technologie sur laquelle je m'étais promis de faire un petit tuto un de ces jours.

    En théorie

    RAID est l'acronyme de Redundant Array of Independent Disks (Alignement redondant de disques indépendants), et comme son nom l'indique, il va permettre de regrouper plusieurs disques durs et d'y instaurer une politique de stockage pour faire de la redondance, de l’agrégation de taille, enfin ça répond à plein de besoins différents. En fait on ne devrait pas vraiment parler d'un seul RAID, mais bel et bien de la famille des RAIDs, car en effet il y a autant de RAIDs que de besoins différent.

    On va présenter les assemblages RAID les plus utilisés. Pour plus de détails, je vous conseille la page Wikipédia qui est très claire et qui contient des schémas très explicites.

    Dans la suite, on va beaucoup parler de bandes de stockage : il s'agit d'une quantité de stockage de valeur prédéfinie, qui correspond à une "section" contiguë du disque qui la contient. Dans ce modèle, lors de l'écriture sur le volume, une bande est d’abord remplie avant d'en entamer une suivante. Il s'agit en fait d'abstraire le stockage et de pouvoir mieux comprendre la répartition des données sur les différents disques.

    RAID 0

    Les bandes sont tout bonnement distribuées sur les disques, toujours dans le même ordre. On remplit donc une bande par disque, puis une fois qu'on a touché à tous les disques, on repart du premier disque et on recommence une couche de bandes. Tous les disques contiennent des données différentes. Ainsi, si vous avez n disques durs de capacité exploitable x, la capacité totale du montage sera nx.

    • Avantages : Ce montage permet d'utiliser le plus grand espace possible de votre assemblage. De plus, en moyenne, les accès disques parallèles seront plus rapide, pour peu que ces accès disques se fassent dans des bandes différentes et sur des disques différents.
    • Inconvénients : Il suffit de perdre un seul disque pour corrompre l'intégralité des données. Or, statistiquement, plus on a de disques, plus on a de chances d'en perdre.

    RAID 1

    Les bandes sont écrites à l’identique sur tous les disques. Tous les disques contiennent exactement les même données. Ainsi, si vous avez n disques durs de capacité exploitable x, la capacité totale du montage sera x.

    • Avantages : C'est le montage qui permet la plus grande sécurité des données faces aux pannes : tant qu'il vous reste un disque fonctionnel, vos données sont intactes et complètes. Les accès disques sont aussi nettement améliorés, avec une vitesse théorique multipliée par le nombre de disques dans le montage.
    • Inconvénients : Il est frustrant d'avoir beaucoup de disques durs pour avoir au final l'espace d'un seul disque. Évidemment les données sont très sûres mais quand même, faut pas pousser...

    RAID 5

    Les bandes sont réparties sur tous les disques sauf un, qui reçoit une bande de parité. La bande de parité est tout simplement une bande dont chaque bit est obtenu en appliquant le OU exclusif (XOR) à l'ensemble des bits correspondants dans les bandes alignées des autres disques. Cette bande de parité est attribuée à chaque disque alternativement au fil des couches de bandes remplies. Donc si un disque vient à tomber en panne, pour chaque couche de bande, si la bande du disque en panne est la bande de parité, alors les données de la couche sont intactes. Si la bande contient de la donnée, alors elle peut être recalculée à partir des autres couches de données et celle de parité. C'est du calcul logique, et c'est la force du XOR. Ainsi, si vous avez n disques durs de capacité exploitable x, la capacité totale du montage sera (n-1)x.

    • Avantages : Un bon compromis entre place exploitable et sécurité des données. On se donne le droit de perdre un disque dur dans la bataille. Pour retrouver l'usage des données, il suffit de remplacer le disque défaillant et les données sont reconstruites.
    • Inconvénients : Ça dépends des cas, mais un droit à un unique disque dur en panne, ça peu être peu. Pour certain ça peut être insuffisant.

    RAID 6

    Il s'agit d'une extension du RAID 5 dans laquelle on se permet de pouvoir perdre plus d'un disque. La solution étant d'attribuer plus de bandes de "parité" par couche, une par nombre de pannes maximum permises. Ici, j'utilise les guillemets car il ne s'agit plus vraiment de la parité simple de la logique de base, mais d'un truc chelou reposant sur un principe tout autre dont je ne pas trop vous parler parce que j'en ignore tout. Donc si vous avez n disques durs de capacité exploitable x, et si vous mettez en place k bandes de redondance par couche, la capacité totale du montage sera (n-k)x.

    • Avantages : On se sent un peu plus à l’abri des intempéries matérielles, au pris d'un peu de place de stockage.
    • Inconvénients : Le principe chelou dont je vous ai parlé, enfin dont je ne vous ai pas parlé pour être honnête, eh bien il est tellement chelou qu'il pète pas mal les performances. Et pour couronner le tout, la plupart des implémentations de ce type d'assemblage est bien moins stable que les autres.

    Il est également possible de combiner les RAIDs. Une combinaison fréquente est le RAID 10 (RAID 1 + RAID 0). Par exemple si on a 10 disques, on peu monter 2 RAID 1 de 5 disques chacun, puis assembler ces deux volumes en RAID 0. On a également aussi le RAID 50, combinaison dur RAID 5 et du RAID 0 selon le même principe.

    La gestion du RAID

    Je vous parlais de différentes implémentations du RAID. En fait, le RAID n'est pas un programme en tant que soi, juste un ensemble de spécifications. Du coup chacun y va de sa sauce : il existe des implémentations libres et propriétaires, logicielles et matérielles. Les solutions matérielles se basent sur du matériel dédié (un contrôleur RAID), le système d'exploitation n'a donc pas à s'occuper de ça et le plus souvent ces solutions marchent out of the box, sans avoir besoin de configurer quoi que ce soit. Mais elles ont l'immense inconvénient d'être propriétaire dans leur quasi-totalité, et pour le coup il n'existe aucun standard. Dans certains cas, si votre contrôleur RAID rend l'âme, il vous faudra acquérir exactement le même modèle de contrôleur, sinon, peu importe que vos disques soient tous intacts, plus rien ne pourra les lire, et vous serez alors en légitime position d'être fort contrarié. À mon humble avis, le principal argument des RAIDs matériel auparavant était les meilleures performances. Aujourd'hui cet avantage est de plus en plus obsolète, car désormais les machines sont bien plus puissantes qu'il y a 15 ans et les programmes de RAID ont été nettement optimisés et stabilisés. Cette différence de performance est aujourd'hui presque intangible.

    En pratique

    J'ai hérité par un ami d'une tour de bureau. Elle est bien cool car elle contient une grande baie de disques et pas mal de ports SATA (bien entendu, vous pouvez faire votre RAID avec des disques branchés en USB si vous le souhaitez). J'ai donc décidé d'en faire un NAS fait main.

    Choix des armes

    J'ai donc initialement acheté 3 disques de 3 To chacun (des Western Digital Red, gamme dédiée justement aux usage en RAID) et j'ai opté pour un RAID 5 logiciel. Et sur Linux, le programme de RAID par excellence est mdadm. J'ai décidé de garder branché le disque dur d'origine (500 Go) mais de ne pas l'intégrer au RAID, il sert uniquement de disque de démarrage. Notez que si j'avais voulu optimiser les performances, j'aurais pu troquer ce disque pour un petit SSD, mais bon, je suis déjà content comme ça.

    Par ailleurs, pour faire de la place dans la baie de disques, j'ai du déménager le disque de démarrage dans la baie frontale, celle destinée à accueillir les périphériques comme le lecteur optique.

    Le 4ème disque du RAID, on en parlera plus tard. Je l'ai acheté bien après.

    Pour ça j'ai utilisé un adaptateur 3,5 pouces vers 5,25 pouces bien pratique, qui m'a permis de fixer bien solidement le disque dur au lieu de le laisser se balader dans la tour.

    Partitionnement et formatage

    Du côté software, je me retrouve avec un disque sda de démarrage, et sdb, sdc et sdd des disques vierges prêts à être assemblés en RAID. Avant ça, j'ai besoin de les partitionner. J'utilise donc fdisk pour les trois disques à tour de rôle, je choisis une table de partitions GPT et j'y crée une unique partition de type "Linux RAID" (code 29 dans fdisk).

    Création de l'assemblage RAID

    C'est tout bête, ça tient en une seule ligne de commande :

    mdadm --create --verbose /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 /dev/sdd1

    Dans cette commande, j'indique que le nom du volume abstrait sera /dev/md0, que ce sera un RAID 5, qu'il comporte 3 disques et je lui précise les partitions que je veux utiliser.

    Pour suivre l'évolution de la création de l'assemblage, jetez un coup d'oeil au fichier /proc/mdstat. Ce fichier sera votre nouvel ami, c'est lui qu'il faudra consulter dès que vous ferez une opération qui touche au RAID.

    Puis j'ajoute l'assemblage à la configuration de mdadm pour que celui-ci me l'assemble au démarrage :

    mdadm --detail --scan >> /etc/mdadm.conf

    Puis il ne vous reste plus qu'à mettre votre système de fichier préféré sur le volume créé !

    mkfs.ext4 /dev/md0

    Pour que votre assemblage soit monté au démarrage, j'ajoute à mon /etc/fstab :

    /dev/md0 /mnt/data ext4 defaults 0 0

    Il ne faut pas confondre assemblage et montage, il s'agit de deux étapes lors de la connexion d'un RAID. On doit assembler un RAID afin qu'il soit reconnu comme un volume propre, puis on doit monter notre volume pour pouvoir lire et écrire dessus.

    Enfin on monte le volume :

    mkdir /mnt/data
    mount /mnt/data

    Ayé vous avez un RAID 5 qui fonctionne !

    Il est recommandé de procéder régulièrement à des reconstruction de RAID, opération qui va vérifier la cohérence de l'assemblage. Il s'agit d'une opération transparente mais qui dure plusieurs heures et qui va se traduire par une forte augmentation de l'activité des disques. Pour ça il vous faudra lancer un petit programme sans arguments, raid-check, à un intervalle raisonnable, disons, toutes les semaines. Choisissez un horaire de faible activité, comme la nuit du samedi au dimanche à 3h du matin. Pour ça, faites vous plaisir, entre la crontab et les timers de systemd, on manque pas de solutions.

    Ajout d'un nouveau disque à l'assemblage

    Mon RAID 5 était constitué de 3 disques de 3 To ce qui nous fait 6 To exploitables, si vous avez bien suivi. 6 To, c'est un grand espace, il m'a suffi pendant presque 2 ans... Puis j'ai eu besoin de plus de place. J'ai donc racheté un autre disque (même modèle, même taille) que j'ai fourré dans ma tour. Je vous avoue que sur le coup, j'étais encore puceau au niveau extension de RAID, j'ai donc flippé énormément et j'ai fait une sauvegarde de mes 6 To sur divers disques externes que j'ai pu trouver dans ma caverne. Je vous raconte pas comme c'était pénible...

    Petites observations à ce niveau :

    1. Remarquez que l'ordre des disques dans le nommage des périphériques physiques (sdX) et tout sauf fixe. En théorie, il faut être préparé à ce que vos disques changent de noms. Votre petit sdb chéri que vous avez bordé et vu s'endormir dans le creux douillet de son lit un soir peut très bien vous trahir et s'appeler sdc au petit matin dès le prochain redémarrage. Bon c'est un peu exagéré, mais une chose est sure, il ne faut jamais faire confiance au nommage des périphériques physiques (c'est pour ça entre autres qu'il faut privilégier la désignation par UUID dans la fstab).
    2. mdadm se fiche complètement du nommage de ses périphériques. Il utilise sa propre magie noire pour déterminer les membres d'un assemblages. En conclusion, ne vous tracassez pas pour retrouver le nom de vos disques de votre assemblage, mdadm, lui, s'y retrouvera toujours.

    Cependant, faites quand même gaffe lorsque vous allez ajoutez votre nouveau disque dur. Par exemple chez moi, le nouveau disque s'est vu nommé sdb, tandis que les autres s'étaient vu relégués en sdc, sdd et sde. Faut juste le savoir et traiter les disques pour ce qu'ils sont, et non pas des étiquettes à trois lettres.

    Tout ce que j'ai eu à faire, en définitive, a été de partitionner-formater mon nouveau disque ainsi que l'ont été ses aînés, puis j'ai lancé les deux commandes suivantes :

    mdadm --add /dev/md0 /dev/sdb1
    mdadm --grow --raid-devices=4 --backup-file=/root/grow\_md0.bak /dev/md0

    La première va juste indiquer à mdadm qu'on lui ajoute un disque, mais sans plus. C'est la deuxième commande qui va lancer l'opération de reconstruction (rééquilibrage de l'assemblage). Opération qui dure plusieurs heures, donc suivez son déroulement dans /proc/mdstat.

    Une fois que c'est terminé, il faut maintenant procéder à l'extension du système de fichier lui même. Et là vous priez pour avoir choisi un système de fichier pas trop stupide qui accepte ce genre d'opération. Rassurez-vous, ext4 le supporte très bien.

    Il le supporte même tellement bien que vous pouvez le faire directement à chaud, sans démonter votre volume. Pour ça, premièrement, si vous utilisez une connexion SSH, ouvrez une session tmux. Il serait bête qu'un incident réseau de rien du tout vienne corrombre tout votre système de fichire tout de même. Puis il vous faudra exécuter :

    resize2fs -p /dev/md0

    Il va vous mettre en garde et ronchonner un tantinet que votre disque est toujours monté, mais écoutez, il s'en remettra, dans la vie on fait pas toujours ce qu'on veut. Les minutes passent, vous vous rongez les ongles, vous prenez un café, vous videz un pot de glace, et normalement, si tout se passe bien, le système de fichier aura été étendu à tout l'espace disponible sur l'assemblage. Félicitations !

    Conclusion

    J'ai rencontré beaucoup de monde m'ayant dit qu'ils préféraient rester éloigner autant que possible de RAID parce que ça leur faisait peur. En réalité, il n'y a rien d'effrayant là dedans. mdadm est un outil ma foi fort bien codé et les années ont prouvé qu'il était fiable. Il ne faut pas avoir peur du RAID. Enfin un peu quand même, faut pas faire n'importe quoi.

    • Ha chevron_right

      Empreintes de fichier

      motius · pubsub.gugod.fr / hashtagueule · Monday, 12 October, 2015 - 22:00 · 2 minutes

    Bonjour à tous ! Aujourd'hui, on va parler empreintes de fichiers. Petit tour du principe, des algorithmes, et des nouveautés... Les empreintes digitales permettent d'identifier de manière unique un individu, cependant l'information contenue dans une empreinte est très faible par rapport à toute l'i...

    Bonjour à tous !

    Aujourd'hui, on va parler empreintes de fichiers. Petit tour du principe, des algorithmes, et des nouveautés...

    Les empreintes digitales permettent d'identifier de manière unique un individu, cependant l'information contenue dans une empreinte est très faible par rapport à toute l'information que représente un individu.

    De même, il existe en informatique un challenge comparable, qui consiste à permettre d'identifier de manière unique des fichiers. On utilise donc un algorithme qui -- en théorie -- est très sensible à la variations de bits dans un fichier, de telle sorte qu'il soit impossible -- ou presque -- que deux fichiers distincts aient la même empreinte.

    Les cas d'utilisation d'empreintes sont nombreux :

    • vérification rapide qu'un téléchargement ne comporte pas d'erreur ;
    • identification d'un fichier dans un gestionnaire :
      • git pour des fichiers source ;
      • YouTube pour ses vidéos ;
      • etc.

    Beaucoup d'algorithmes ont été développés : MD4 (très vieux), MD5 (déprécié pour toutes les applications liées à la sécurité) SHA1 (pour Secure Hash Algorithm) SHA2, SHA3...

    Dans la mesure de l'efficacité d'un algorithme, on distingue :

    • la sureté, c'est-à-dire la capacité d'un algorithme de donner une empreinte différente pour deux fichiers différents ;
    • la sécurité liée à l'algorithme, qui garantit qu'une attaque contre l'algorithme (soit en essayant beaucoup de fichiers, soit en trouvant une "fonction inverse") est quasiment impossible.

    Ainsi, la sureté d'un algorithme correspond à la capacité de cet algorithme de détecter une modification du fichier. De MD5 à SHA-3, tous en sont relativement capable.

    La sécurité de ces algorithmes est essentielle. Prenons Bob, et un attaquant Jeb. Le but de Jeb est de pouvoir créer un fichier ayant la même empreinte que celui attendu par Bob, pour pouvoir le substituer à celui que Bob a demandé sur le réseau.

    Eh bien figurez-vous que la sécurité de SHA vient d'être une nouvelle fois remise en cause. Dès 2005, des chercheurs avaient réussi à trouver des collisions (ce qui se passe quand deux fichiers ont la même empreinte). Désormais, le site Ars nous parle d'attaques plus systématiques sur l'algorithme SHA-1.

    Tout ceci est bien dommage étant donné que les navigateurs web (Firefox, Iceweasel, Chromium, Opéra, Chrome, ...) ont abandonné MD5 il y a peu (il n'est plus supporté), et que la fin de support de SHA-1 est prévue pour fin 2017.

    En attendant, la relève est là (SHA-2, SHA-3) mais encore faut-il que les sites webs que vous visitez supportent SHA-2, ce qui n'est pas gagné. Seuls quelques rares utilisent les bons algorithmes au bon endroit (Wikipédia, Google, Twitter, ...)

    Tout ceci arrive au moment même ou la NSA (la partie sécurité intérieure) rend obsolète AES-128 (pour AES-256) et SHA-256 (une des quatres version de SHA2 pour les documents classés Secret Défense :

    • SHA-224
    • SHA256
    • SHA-384
    • SHA-512)

    pour SHA-384...

    Bonne journée !

    Motius

    • At chevron_right

      Empreintes de fichier

      motius · pubsub.gugod.fr / atomtest · Monday, 12 October, 2015 - 22:00 · 2 minutes

    Bonjour à tous ! Aujourd'hui, on va parler empreintes de fichiers. Petit tour du principe, des algorithmes, et des nouveautés... Les empreintes digitales permettent d'identifier de manière unique un individu, cependant l'information contenue dans une empreinte est très faible par rapport à toute l'i...

    Bonjour à tous !

    Aujourd'hui, on va parler empreintes de fichiers. Petit tour du principe, des algorithmes, et des nouveautés...

    Les empreintes digitales permettent d'identifier de manière unique un individu, cependant l'information contenue dans une empreinte est très faible par rapport à toute l'information que représente un individu.

    De même, il existe en informatique un challenge comparable, qui consiste à permettre d'identifier de manière unique des fichiers. On utilise donc un algorithme qui -- en théorie -- est très sensible à la variations de bits dans un fichier, de telle sorte qu'il soit impossible -- ou presque -- que deux fichiers distincts aient la même empreinte.

    Les cas d'utilisation d'empreintes sont nombreux :

    • vérification rapide qu'un téléchargement ne comporte pas d'erreur ;
    • identification d'un fichier dans un gestionnaire :
      • git pour des fichiers source ;
      • YouTube pour ses vidéos ;
      • etc.

    Beaucoup d'algorithmes ont été développés : MD4 (très vieux), MD5 (déprécié pour toutes les applications liées à la sécurité) SHA1 (pour Secure Hash Algorithm) SHA2, SHA3...

    Dans la mesure de l'efficacité d'un algorithme, on distingue :

    • la sureté, c'est-à-dire la capacité d'un algorithme de donner une empreinte différente pour deux fichiers différents ;
    • la sécurité liée à l'algorithme, qui garantit qu'une attaque contre l'algorithme (soit en essayant beaucoup de fichiers, soit en trouvant une "fonction inverse") est quasiment impossible.

    Ainsi, la sureté d'un algorithme correspond à la capacité de cet algorithme de détecter une modification du fichier. De MD5 à SHA-3, tous en sont relativement capable.

    La sécurité de ces algorithmes est essentielle. Prenons Bob, et un attaquant Jeb. Le but de Jeb est de pouvoir créer un fichier ayant la même empreinte que celui attendu par Bob, pour pouvoir le substituer à celui que Bob a demandé sur le réseau.

    Eh bien figurez-vous que la sécurité de SHA vient d'être une nouvelle fois remise en cause. Dès 2005, des chercheurs avaient réussi à trouver des collisions (ce qui se passe quand deux fichiers ont la même empreinte). Désormais, le site Ars nous parle d'attaques plus systématiques sur l'algorithme SHA-1.

    Tout ceci est bien dommage étant donné que les navigateurs web (Firefox, Iceweasel, Chromium, Opéra, Chrome, ...) ont abandonné MD5 il y a peu (il n'est plus supporté), et que la fin de support de SHA-1 est prévue pour fin 2017.

    En attendant, la relève est là (SHA-2, SHA-3) mais encore faut-il que les sites webs que vous visitez supportent SHA-2, ce qui n'est pas gagné. Seuls quelques rares utilisent les bons algorithmes au bon endroit (Wikipédia, Google, Twitter, ...)

    Tout ceci arrive au moment même ou la NSA (la partie sécurité intérieure) rend obsolète AES-128 (pour AES-256) et SHA-256 (une des quatres version de SHA2 pour les documents classés Secret Défense :

    • SHA-224
    • SHA256
    • SHA-384
    • SHA-512)

    pour SHA-384...

    Bonne journée !

    Motius

    • Ha chevron_right

      Le mot de passe...

      motius · pubsub.gugod.fr / hashtagueule · Wednesday, 9 September, 2015 - 22:00 · 3 minutes

    Bonjour à tous ! Ah la la, les mots de passe, une sacrée affaire ! On devrait d'ailleurs dire phrase de passe, pour éviter que les gens ne les choisissent dans le dictionnaire. Heureusement, hashtagueule est là pour faire un petit tour de la question. Comment choisir un mot de passe, à quoi est-ce q...

    Bonjour à tous !

    Ah la la, les mots de passe, une sacrée affaire ! On devrait d'ailleurs dire phrase de passe, pour éviter que les gens ne les choisissent dans le dictionnaire. Heureusement, hashtagueule est là pour faire un petit tour de la question.

    Comment choisir un mot de passe, à quoi est-ce que ça doit ressembler, doit-il vraiment comporter 18 caractères ?

    Un mot de passe, c'est tout d'abord personnel. Évitez le nom de votre animal de compagnie, c'est d'ailleurs une très mauvaise idée de la part de certains webmails de les utiliser. Jiminy ou Croquette ne sont pas des bons "mots de passe", barrez-les de la liste.

    Un mot de passe, ça contient :

    • majuscules ;
    • minuscules ;
    • caractères spéciaux ('"[|-]_=^+ç/!§.;?*÷׿¡%€) ;
    • chiffres ;
    • un assez grand nombre de caractères (10 au minimum, 8 pour des sites sans importance).

    De plus :

    • il n'y a pas de mot du dictionnaire. D'aucun dictionnaire, en fait, messieurs les latinistes, et hellènes, anglophiles...
    • Il n'y a pas de lieu géographique (lieu de naissance).
    • Il n'y as pas de date, ni de nom (toto42, gilles63, 1984).
    • et surtout, surtout, ce n'est jamais 1234, 0000.

    Alors comment s'y prendre ?

    Il existe trois méthodes qui résistent à une attaque de type "bruteforce" ou "par  dictionnaire" :

    1. prendre une phrase que l'on connaît, et la transformer ;
    2. utiliser un générateur de mots de passe ;
    3. choisir un grand nombre de mots au hasard dans un très grand dictionnaire.

    Détaillons la première méthode. Je prends cette phrase, trop peu connue :

    • Le Petit Prince : "On ne voit bien qu'avec le cœur. L'essentiel est invisible pour les yeux."

    et je la transforme ainsi (je ne garde que les premières lettres des mots) :

    • LPP:"Onvbq'ac.L'eeiply."
    • L2P:"0nvbq'4c.L'e2iply."

    La seconde méthode impose d'avoir confiance dans le logiciel qu'on utilise.

    On a le choix entre plusieurs solutions logicielles sous GNU/Linux :

    • apg ;
    • pwgen ;
    • un basique $ cat /dev/urandom ;-)

    Personnellement, j'apprécie le logiciel apg, dans les dépôts de Debian/Ubuntu :

    $ apg -a 1 -n 50 -m 40 -x 40 -M SNCL

    détaillons les options :

    • -a 1 pour forcer le comportement automatique (pas d'entrée utilisateur, plus rapide).
    • -n 50 : génère 50 mots de passe. Permet de laisser le choix.
    • - m 60 -x 60 : taille minimale et maximale des mots de passe générés de 60 caractères. La encore, permet de choisir un sous-ensemble de caractères.
    • -M : permet de spécifier le type de mot de passe. les options sont :
      • S : impose la présence d'un caractère spécial, s : permet la présence d'un caractère spécial.
      • N : impose la présence d'un chiffre, n : permet la présence d'un chiffre.
      • C : impose la présence d'une majuscule, c : permet la présence d'une majuscule.
      • L : impose la présence d'un minuscule, l : permet la présence d'une minuscule.

    La dernière méthode est récente et peut être plus facile à retenir : il s'agit de piocher au hasard des mots dans un grand dictionnaire. S'il y a suffisamment de mot, que le dictionnaire est suffisamment grand, et qu'on les a bien piochés au hasard (et pas au début ou à la fin), alors le temps nécessaire pour créer tous les couples sera trop long. Exemples :

    • Éléphant miel Barbiturique repolluaient plaquebière plaisantin hôpital
    • izolovat resouffrirons Réébarbées Espanbrun bootabilisa collimateront biliotin

    qui ont le double avantage d'être complexes, et de nous cultiver un peu ^^. Pour obtenir ces résultats, j'ai utiliser la fonction page aléatoire du Wiktionnaire. J'admets qu'utiliser des mots à consonance française (1er exemple) est plus facile.

    Enfin, si vous voulez tester un peu vos idées de mots de passe, ne les envoyez jamais sur un site web. Vous n'avez aucune garantie que celui-ci ne va pas les enregistrer. Utilisez des mots de passe à la construction identique. Il y en a deux sites permettant d'en tester la robustesse que je peux vous conseiller :

    À bientôt !

    Motius

    • At chevron_right

      Le mot de passe...

      motius · pubsub.gugod.fr / atomtest · Wednesday, 9 September, 2015 - 22:00 · 3 minutes

    Bonjour à tous ! Ah la la, les mots de passe, une sacrée affaire ! On devrait d'ailleurs dire phrase de passe, pour éviter que les gens ne les choisissent dans le dictionnaire. Heureusement, hashtagueule est là pour faire un petit tour de la question. Comment choisir un mot de passe, à quoi est-ce q...

    Bonjour à tous !

    Ah la la, les mots de passe, une sacrée affaire ! On devrait d'ailleurs dire phrase de passe, pour éviter que les gens ne les choisissent dans le dictionnaire. Heureusement, hashtagueule est là pour faire un petit tour de la question.

    Comment choisir un mot de passe, à quoi est-ce que ça doit ressembler, doit-il vraiment comporter 18 caractères ?

    Un mot de passe, c'est tout d'abord personnel. Évitez le nom de votre animal de compagnie, c'est d'ailleurs une très mauvaise idée de la part de certains webmails de les utiliser. Jiminy ou Croquette ne sont pas des bons "mots de passe", barrez-les de la liste.

    Un mot de passe, ça contient :

    • majuscules ;
    • minuscules ;
    • caractères spéciaux ('"[|-]_=^+ç/!§.;?*÷׿¡%€) ;
    • chiffres ;
    • un assez grand nombre de caractères (10 au minimum, 8 pour des sites sans importance).

    De plus :

    • il n'y a pas de mot du dictionnaire. D'aucun dictionnaire, en fait, messieurs les latinistes, et hellènes, anglophiles...
    • Il n'y a pas de lieu géographique (lieu de naissance).
    • Il n'y as pas de date, ni de nom (toto42, gilles63, 1984).
    • et surtout, surtout, ce n'est jamais 1234, 0000.

    Alors comment s'y prendre ?

    Il existe trois méthodes qui résistent à une attaque de type "bruteforce" ou "par  dictionnaire" :

    1. prendre une phrase que l'on connaît, et la transformer ;
    2. utiliser un générateur de mots de passe ;
    3. choisir un grand nombre de mots au hasard dans un très grand dictionnaire.

    Détaillons la première méthode. Je prends cette phrase, trop peu connue :

    • Le Petit Prince : "On ne voit bien qu'avec le cœur. L'essentiel est invisible pour les yeux."

    et je la transforme ainsi (je ne garde que les premières lettres des mots) :

    • LPP:"Onvbq'ac.L'eeiply."
    • L2P:"0nvbq'4c.L'e2iply."

    La seconde méthode impose d'avoir confiance dans le logiciel qu'on utilise.

    On a le choix entre plusieurs solutions logicielles sous GNU/Linux :

    • apg ;
    • pwgen ;
    • un basique $ cat /dev/urandom ;-)

    Personnellement, j'apprécie le logiciel apg, dans les dépôts de Debian/Ubuntu :

    $ apg -a 1 -n 50 -m 40 -x 40 -M SNCL

    détaillons les options :

    • -a 1 pour forcer le comportement automatique (pas d'entrée utilisateur, plus rapide).
    • -n 50 : génère 50 mots de passe. Permet de laisser le choix.
    • - m 60 -x 60 : taille minimale et maximale des mots de passe générés de 60 caractères. La encore, permet de choisir un sous-ensemble de caractères.
    • -M : permet de spécifier le type de mot de passe. les options sont :
      • S : impose la présence d'un caractère spécial, s : permet la présence d'un caractère spécial.
      • N : impose la présence d'un chiffre, n : permet la présence d'un chiffre.
      • C : impose la présence d'une majuscule, c : permet la présence d'une majuscule.
      • L : impose la présence d'un minuscule, l : permet la présence d'une minuscule.

    La dernière méthode est récente et peut être plus facile à retenir : il s'agit de piocher au hasard des mots dans un grand dictionnaire. S'il y a suffisamment de mot, que le dictionnaire est suffisamment grand, et qu'on les a bien piochés au hasard (et pas au début ou à la fin), alors le temps nécessaire pour créer tous les couples sera trop long. Exemples :

    • Éléphant miel Barbiturique repolluaient plaquebière plaisantin hôpital
    • izolovat resouffrirons Réébarbées Espanbrun bootabilisa collimateront biliotin

    qui ont le double avantage d'être complexes, et de nous cultiver un peu ^^. Pour obtenir ces résultats, j'ai utiliser la fonction page aléatoire du Wiktionnaire. J'admets qu'utiliser des mots à consonance française (1er exemple) est plus facile.

    Enfin, si vous voulez tester un peu vos idées de mots de passe, ne les envoyez jamais sur un site web. Vous n'avez aucune garantie que celui-ci ne va pas les enregistrer. Utilisez des mots de passe à la construction identique. Il y en a deux sites permettant d'en tester la robustesse que je peux vous conseiller :

    À bientôt !

    Motius