Introduction
To be effective, a software system must be deployable. The higher the cost of deployements, the less useful the system is. A goal of a software architecture, then, should be to make a system that can be easily deployed with a single action. Unfortunately, deployment strategy is seldom considered during initial development. This leads to architectures that may be make the system easy to develop, but leave it very difficult to deploy.
— Robert C. Martin, Clean Architecture
Il y a une raison très simple à aborder le déploiement dès maintenant : à trop attendre et à peaufiner son développement pour soi-même, on en oublie que sa finalité sera de se retrouver exposé et accessible depuis un serveur. Il est probable d’oublier une partie des désidérata, de zapper une fonctionnalité essentielle ou simplement de passer énormément de temps à adapter les sources pour qu’elles puissent être mises à disposition sur un environnement en particulier, une fois que leur développement aura été finalisé, testé et validé.
Simplicité
Because value is created only when our services are running into production, we must ensure that we are not only delivering fast flow, but that our deployments can also be performed without causing chaos and disruptions such as service outages, service impairments, or security or compliance failures.
— DevOps Handbook Introduction
Un bon déploiement ne doit pas dépendre de dizaines de petits scripts éparpillés sur le disque : l’objectif est que celui-ci soit rapide et fiable. Cet objectif peut être atteint au travers d’un partitionnement correct, incluant le fait que le composant principal s’assure que chaque sous-composant est correctement démarré intégré et supervisé.
Aborder le déploiement dès le début du développement permet également de rédiger les procédures d’installation, de mises à jour et de sauvegardes adaptées. A la fin de chaque intervalle de développement, les fonctionnalités auront dû avoir été intégrées, testées, fonctionnelles et un code propre, démontrable dans un environnement similaire à un environnement de production, et créées à partir d’un tronc commun au développement.
Déploier une nouvelle version doit être le plus simple possible, et doit se résumer, dans le pire des cas, à quelques lignes d’un script Bash.
Développement vs production
Le serveur que Django met à notre disposition via la commande runserver
est extrêmement pratique, mais il est uniquement prévu pour la phase développement.
Lorsque l’application tourne en production,
- Il est inutile de passer par du code Python pour charger des fichiers statiques (feuilles de style, fichiers JavaScript, images, … De même, Django propose par défaut une base de données SQLite, qui fonctionne parfaitement dès lors que l’on connait ses limites et que l’on se limite à un utilisateur à la fois.
- Il est légitime que la base de donnée soit capable de supporter plusieurs utilisateurs et connexions simultanés. En restant avec les paramètres par défaut, il est plus que probable que vous rencontriez rapidement des erreurs de verrou parce qu’un autre processus a déjà pris la main pour écrire ses données. En bref, vous avez quelque chose qui fonctionne, qui répond à un besoin, mais qui va attirer la grogne de ses utilisateurs pour des problèmes de latences, pour des erreurs de verrou ou simplement parce que le serveur répondra trop lentement.
L’objectif de cette partie est de parcourir les différentes possibilités qui s’offrent à nous en termes de déploiement, tout en faisant en sorte que le code soit le moins couplé possible à sa destination de production. L’objectif est donc de faire en sorte qu’une même application puisse être hébergées par plusieurs hôtes sans avoir à subir de modifications. Nous vous renvoyons vers les 12-facteurs dont nous avons déjà parlé et qui vous énormément nous aider, puisque ce sont des variables d’environnement qui vont réellement piloter le câblage entre l’application, ses composants et son hébergement.
Types d’infrastructures
RedHat proposait récemment un article intitulé What Is IaaS, qui présentait les principales différences entre types d’hébergement et les responsabilités qui en découlent :
On-site | IaaS | PaaS | SaaS | |
---|---|---|---|---|
Applications | ✅ | ✅ | ✅ | ❌ |
Données | ✅ | ✅ | ✅ | ❌ |
Exécution | ✅ | ✅ | ❌ | ❌ |
Middleware | ✅ | ✅ | ❌ | ❌ |
Système d’exploitation | ✅ | ✅ | ❌ | ❌ |
Virtualisation | ✅ | ❌ | ❌ | ❌ |
Serveurs | ✅ | ❌ | ❌ | ❌ |
Stockage | ✅ | ❌ | ❌ | ❌ |
Réseau | ✅ | ❌ | ❌ | ❌ |
Ainsi, on trouve :
- Le déploiment on-premises (on-site), qui exigent de gérer l’ensemble de l’infrastructure, du réseau à la maintenance de l’application.
- Les Infrastructures as a Service (IaaS), qui s’occupent des couches jusqu’à la virtualisation (vous disposez ainsi d’un accès complet au système d’exploitation, et devez vous débrouiller pour installer le reste).
- Les Platforms as a Service (PaaS), où vous devez “juste” déployer votre application, en respectant certains standards.
- Les Softwares as a service (SaaS), où vous n’avez plus d’autre à faire que d’utiliser ce qui a été développé et mis à disposition pour vous.
Méthodes de déploiement
Dans cette partie, nous aborderons les points suivants :
- Définir l’infrastructure et les composants nécessaires à notre application,
- Configurer l’hôte qui hébergera l’application et y déployer notre application: dans une machine physique, virtuelle ou dans un container. Nous aborderons aussi les déploiements via Ansible et Salt. A ce stade, nous aurons déjà une application disponible.
- Configurer les outils nécessaires à la bonne exécution de ce code et de ses fonctionnalités: les différentes méthodes de supervision de l’application, comment analyser les fichiers de logs, comment intercepter correctement une erreur si elle se présente et comment remonter correctement l’information.
Nous allons détailler ci-dessous trois méthodes de déploiement :
- Sur une machine hôte, en embarquant tous les composants sur un même serveur. Ce ne sera pas idéal, puisqu’il ne sera pas possible de configurer un load balancer, de routeur plusieurs basées de données, mais ce sera le premier cas de figure.
- Dans des containers, avec Docker-Compose (et à nouveau sur un seul serveur),
- Sur une Plateforme en tant que Service, pour faire abstraction de toute la couche de configuration du serveur.