Blog de BearstechBlog actualité bearstech : technologiehttps://bearstech.com/societe/blog/https://bearstech.com/static/img/logo.svg2024-01-19T14:44:54ZL'équipe Bearstechcontact@bearstech.comSécuriser et optimiser le build des images Docker pour vos applications.
False
urn:uuid:ddd76f04-d4d7-533b-ad2e-a0fdb92bee1b2024-01-11T16:58:32Z2024-01-19T14:44:54ZBearstechcontact@bearstech.com
Explorez des méthodes éprouvées pour sécuriser et optimiser le build de vos images Docker. Maîtrisez les bonnes pratiques pour builder des applications Docker sûres.
Docker se distingue par sa flexibilité et ses possibilités de personnalisation. Cette liberté, si elle n'est pas gérée avec prudence, peut mener à des pratiques suboptimales, compromettant la performance et la sécurité de vos systèmes. Dans cet article, nous vous présentons notre méthodologie, rigoureuse, pour minimiser ces risques, assurer la maintenabilité et optimiser vos applications sur nos infrastructures Docker.
Dans un article précédent, on vous avait parlé des bonnes pratiques de Bearstech pour la gestion et la mise à jour sécurisée des images Docker.
Les images Docker qui sont maintenues par Bearstech bénéficient de la même rigueur que nous apportons au reste de notre infrastructure, en particulier du point de vue de la sécurité, le tout en proposant à nos clients un moyen de s'assurer que les images qu'ils utilisent sont bien à jour.
Ces images dérivent toutes de notre image de base bearstech/debian et grâce au système de "layers" de Docker, l'image de base Debian est partagée par toutes les images de notre arborescence : au final le coût de stockage des images sur les serveurs reste très modeste et n'est PAS proportionnel au nombre d'images.
A partir de nos images de base, vous pouvez builder facilement votre image pour vos applications : Nodejs, Php, Python, Ruby ...
Principe d'unicité de Docker
Afin de respecter le principe d'unicité de Docker : 1 conteneur = 1 service (voir la documentation de Docker ou cette conversation), nos images sont généralistes, elles ne contiennent que les librairies nécessaires à l'exécution des tâches dédiées à l'instance applicative et à son lien avec les autres services dont elle aura besoin pour fonctionner (serveur web, bdd, cache ...).
Exemple de build d'une application utilisant l'image PHP de Bearstech
Par exemple, dans le cas de l'image Docker PHP maintenue par Bearstech, le build de l'image d'une application PHP va hériter de 3 images:
Debian
php-cli : intègre les éléments de base de php (php-cli, mysql, gd ...)
php : intègre les éléments pour un runtime web (fpm, cache, redis, xdebug ...)
Comme Bearstech assure le suivi en permanence des mises à jour de sécurité Debian sur toutes les images que nous maintenons, ceci inclut PHP.
Les versions de PHP maintenues dépendent donc de la version de Debian afin que les images contiennent bien tous les patch de sécurité à jour.
A l'heure actuelle, les versions suivantes sont maintenues sous Docker:
Debian 10 (buster) -> php-cli:7.3 -> php:7.3
Debian 11 (bullseye) -> php-cli:7.4 -> php:7.4
Debian 12 (bookworm) -> php-cli:8.2 -> php:8.2
Nous maintenons également des versions intermédiaires de PHP selon le principe du "Rolling Release": la versions déployée suit les mises à jour mineures PHP au fil de l'eau, mais quand le projet PHP les abandonne, elles ne reçoivent plus de patches de sécurité :
Debian 11 (bullseye) -> php-cli:8.1-rr -> php:8.1-rr
Pour les applications qui ont besoin d'ajouter des librairies ou un framework (Symfony, Laravel ...) via Composer, vous avez la possibilité d'utiliser notre image php-composer qui est maintenue selon la même logique :
Debian 10 (buster) -> php-cli:7.3 -> php-composer:7.3
Debian 11 (bullseye) -> php-cli:7.4 -> php-composer:7.4
Debian 11 (bullseye) -> php-cli:8.1-rr -> php-composer:8.1-rr
Debian 12 (bookworm) -> php-cli:8.2 -> php-composer:8.2
Optimiser le build sur une CI avec Gitlab
Comme chacune des images importe les couches des images précédentes, la mise en cache au niveau du serveur d'intégration continue (CI) est efficiente, et tout ce qu'aura à faire le build de votre image sera d'ajouter l'opération qui consiste à copier le code de votre application.
Un simple Dockerfile comme suit devrait suffire:
FROM bearstech/php:8.2
ARG UID=1001
RUN useradd app --uid $UID --shell /bin/bash
COPY . /var/www/app
USER app
CMD ["/usr/sbin/php-fpm"]
De cette manière, depuis l'image de base Debian à celle de votre application, en passant par l'image de l'environnement d'application, chaque image bénéficie des mises à jour de sécurité héritées de la version parente.
A noter également, pour les applications qui ont besoin d'installer des librairies via Composer, l'utilisation de l'image bearstech/php-composer permet de traiter cette étape en amont du build de votre application dans la CI Gitlab, via une commande du type:
docker run --rm -u `id -u` -v `pwd`:/var/www/app -w /var/www/app bearstech/php-composer:8.2 bash -c "composer install"
Layer caching
Vous pouvez aussi optimiser le temps de build de l'image de votre application en suivant les principes du "Layer Caching"
Dans la CI, vous allez récupérer la dernière version de votre image via un docker pull qui sera utilisée comme cache pour builder la nouvelle version de votre image grâce à l'argument --cache-from donné à la commande docker build:
docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest .
Il est donc important de labelliser correctement vos images afin de savoir quelle version a été versionnée en dernier ("latest") et de l'inclure dans un flux d'imbrication des couches ("layer"), au fur et à mesure des montées en version de votre application.
Toutes ces étapes sont reproductibles et automatisables grâce à notre workflow devops. Celui-ci permet d'organiser de manière efficace le travail des développeurs en plaçant en continu notre travail d'infogérance (OPS) dans les procédés d'intégration et de déploiement de vos applications. Vous pouvez lire aussi à ce sujet nos articles qui expliquent en quoi notre workflow vous permet d'améliorer la fiabilité de vos applications, et vous assure des déploiements cohérents et reproductibles.
Débugger vos requêtes HTTP en une ligne plutôt que mille
False
urn:uuid:c3a196a2-3ee5-5c1a-9b1d-5fcc9045ce552023-11-22T22:26:44Z2023-11-23T15:51:31ZBearstechcontact@bearstech.com
Nous vous proposons une approche minimaliste permettant de debugger simplement non pas une réponse HTTP mais la requête elle-même.
Nous gérons pour nos clients des centaines de plateformes, il nous arrive donc souvent de devoir assister au débogage ce qui peut impliquer de valider si les réponses d'un site/API sont bien cohérentes avec les requêtes qu'il reçoit.
Si le gros du travail de débogage se fait du côté de la réponse, il est parfois utile de vérifier en premier lieu que la requête est correctement formée.
Dans notre cas on cherchait à débugger une réponse passant par une série de proxies (Apache et Nginx), et on voulait vérifier que différents éléments étaient bien transmis de proxy en proxy (headers d'authentification, URI, paramètres, etc.) dont certains ne se retrouvent pas dans les logs du serveur HTTP.
Tout ce travail de débogage peut aussi être utile au développeur qui travaille sur son API (pour les mêmes raisons que nous) ou avec une API tiers pour vérifier que les appels partants de son code sont bien formés selon les spécifications de cette API.
Voyons ensemble comment debugger nos appels via un serveur qui répondra à chaque requête son contenu (on l'appellera "echo").
TL;DR
L'idée de départ de ce post est de simplifier cet outil qui s'est trouvé très utile lors d'une séance de debug: https://code.mendhak.com/docker-http-https-echo/.
En une ligne plutôt que mille :
print_r($_SERVER);
Le kit de débogage
Pour une mise en place rapide de ce kit de débogage, partons de nos images docker. Voici l'arborescence nécessaire :
|____docker-compose.yml
|____echo
| |____Dockerfile
| |____echo.php
|____nginx-echo.conf
On y trouve le 'docker-compose.yml' contenant simplement un conteneur nginx (qui servira sur 'localhost:8000') et un conteneur PHP :
services:
nginx:
image: bearstech/nginx
container_name: echo-nginx
restart: unless-stopped
volumes:
- ./nginx-echo.conf:/etc/nginx/conf.d/default.conf
ports:
- 127.0.0.1:8000:80
php:
build: ./echo
container_name: echo-php
restart: unless-stopped
La configuration nginx utilisée est minimale et fait simplement appel au conteneur PHP en utilisant toujours le même script :
server {
listen 80;
root /var/www/default/;
location / {
include fastcgi_params;
fastcgi_pass echo-php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/default/echo.php;
}
}
L'image PHP est buildée depuis le dossier 'echo' qui contient le Dockerfile nécessaire :
FROM bearstech/php:8.2
ARG uid=1001
RUN useradd echo --uid $uid --shell /bin/bash --home /var/www
COPY echo.php /var/www/default/echo.php
WORKDIR /var/www
RUN chown -R $uid.$uid /var/www
USER echo
ainsi que le fichier echo.php :
<?php
print_r($_SERVER);
?>
Avec cela en place, on lance simplement :
$ docker-compose up --build
Nous avons un serveur d'echo qui affiche tous les headers (HTTP_*), le site requêté (HTTP_HOST), l'URI (REQUEST_URI) et ses paramètres (QUERY_STRING), etc. :
$ curl -H 'My-Super-Header: my-header-value' "127.0.0.1:8000/my-uri?my-param=my-param-value"
Array
(
[HOSTNAME] => e2880d12e72e
[PHP_VERSION] => 8.2
[PWD] => /var/www
[HOME] => /var/www
[LANG] => en_US.UTF-8
[SHLVL] => 0
[PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[DEBIAN_FRONTEND] => noninteractive
[USER] => echo
[HTTP_MY_SUPER_HEADER] => my-header-value
[HTTP_ACCEPT] => */*
[HTTP_USER_AGENT] => curl/8.4.0
[HTTP_HOST] => 127.0.0.1:8000
[SCRIPT_FILENAME] => /var/www/default/echo.php
[REDIRECT_STATUS] => 200
[SERVER_NAME] =>
[SERVER_PORT] => 80
[SERVER_ADDR] => 172.21.0.3
[REMOTE_USER] =>
[REMOTE_PORT] => 39722
[REMOTE_ADDR] => 172.21.0.1
[SERVER_SOFTWARE] => nginx/1.18.0
[GATEWAY_INTERFACE] => CGI/1.1
[REQUEST_SCHEME] => http
[SERVER_PROTOCOL] => HTTP/1.1
[DOCUMENT_ROOT] => /var/www/default
[DOCUMENT_URI] => /my-uri
[REQUEST_URI] => /my-uri?my-param=my-param-value
[SCRIPT_NAME] => /my-uri
[CONTENT_LENGTH] =>
[CONTENT_TYPE] =>
[REQUEST_METHOD] => GET
[QUERY_STRING] => my-param=my-param-value
[FCGI_ROLE] => RESPONDER
[PHP_SELF] => /my-uri
[REQUEST_TIME_FLOAT] => 1700665959.4737
[REQUEST_TIME] => 1700665959
)
Voilà, vous avez désormais un serveur répondant sur 'localhost:8000' et qui répète toutes les requêtes entrantes sur votre serveur.
Happy debug!
Pourquoi Bearstech recommande d’autres solutions que Kubernetes ?
False
urn:uuid:6bb3e83c-1d2c-5d82-97c9-4449d156da712023-09-07T21:57:00Z2023-09-14T18:09:38ZBearstechcontact@bearstech.com
Nous avons fréquemment des demandes de support sur la partie conteneurs avec Kubernetes, il nous semble important de clarifier notre approche sur ce type de produit.
L’objectif de cet article n’est pas de critiquer la technologie Kubernetes en elle-même, mais plutôt d’évaluer son usage et sa pertinence en fonction des besoins spécifiques de nos clients. Dans cet article, nous nous concentrerons principalement sur les enjeux liés à l’autoscaler; les autres fonctionnalités de Kubernetes n’étant pas critiques pour nos clients et ne sont pas compatibles avec notre méthodologie, laquelle repose sur 19 ans d’expertise et de travail en commun.
Notre position n’est pas dogmatique, lorsque les besoins de nos clients le justifient nous savons adapter la complexité de nos réponses à leurs exigences. Nous proposons notre propre méthode d’ajustement automatisé des ressources. Il nous arrive même d’utiliser l’autoscaler d’AWS … Il convient toutefois de noter que la grande majorité de nos clients ont un trafic relativement prévisible.
Pour les projets sur lesquels nous avons travaillés, K8S ne constitue pas une solution qui pouvait apporter un gain significatif sur le rapport scalabilité / rentabilité.
Même si l'élasticité du système K8S permet d'aborder directement les problématiques de montée en charge en allouant des ressources dynamiquement, nous recommandons de garder le contrôle sur la prévisibilité et l'optimisation des coûts en optant pour des règles d'infogérance maîtrisées de bout en bout.
K8s ne rend pas automatiquement les applications élastiques / scalables, l'essentiel du travail demeurant applicatif
En effet, sur la partie horizontale, un autoscaler ne gère que l'ajout de CPU/RAM, ce qui revient à une scalabilité horizontale, mais ce n'est qu'un problème que les applications peuvent rencontrer parmi d'autres (contention des IO, surcharges SQL, API tierces, etc ...)
Le redimensionnement des ressources CPU/RAM est le problème le plus trivial sur lequel nous pouvons agir, en changeant les specs d'une VM suite à une alerte : cela ne prend que quelques minutes chez Bearstech.
L'autoscaler ne réagit qu'avec un temps de retard sur une situation déjà dégradée (en général au moins 5 minutes), et sans contrôle, l'autoscaler peut faire les montagnes russes aussi longtemps qu'il le souhaite... Il ne règle donc pas le problème de la continuité de service et de la tenue en charge 24/7 de l'application.
Ce dernier point nécessite une réflexion en amont et une expertise en architecture et performance des infrastructures d'hébergement.
Nous proposons une scalabilité basée sur des métriques, un monitoring spécifique adapté aux applicatifs que nous infogérons
Le monitoring est le coeur de notre métier, chez Bearstech, chaque ressource ajoutée dans l'infra doit être entièrement provisionnée (OS, services, code applicatif, données) et intégrée (monitorée, connectées aux services tiers).
Si l'environnement d'exploitation a besoin de plus de ressources, il faut prévoir également un déploiement d’application automatique en préalable (mais non suffisant), et il faut une intégration intime avec la partie système.
Si un automate est plus rapide qu’un opérateur pour réagir à une surcharge, il n’est par contre pas instantané (un délai de 5min est typique) ni forcément mieux informé qu’un opérateur (il peut y avoir des sur-déclenchements).
Un point important à prendre en compte: si l’application n’est pas limitée par la ressource gérée par l’automate, il ne pourra pas apporter de solution utile. En effet, des seuils sont à définir afin de ne pas risquer des effets d'emballement à cause de modules de développement qui n'ont pas été désactivés, ou d'un système de cache non prévu pour le multi-serveur ...
Mais aussi, toutes les ressources ne sont pas scalables horizontalement (SQL l’est par exemple très difficilement) ;
Malgré ses envies de scalabilité infinie, l'automate doit être paramétré pour avoir un niveau de contrôle sur la consommation des ressources.
Chez Bearstech, ce contrôle a lieu au niveau du service de monitoring qui dépend de notre système de supervision.
Chez K8S, ce contrôle se fait via un paramétrage de variables définissant le niveau de QoS (quotas, limits et requests ...). Il nous a donc semblé contre-productif d'empiler plusieurs systèmes de contrôles, voire de les mettre en concurrence.
Notre expertise de l'infogérance de systèmes d'informations nous permet donc de concevoir des architectures qui garantissent l'optimisation constante de la consommation énergétique des infrastructures que nous maintenons en exploitation. Nous considérons qu'il en va de notre responsabilité d'opérateur dans un secteur où l'empreinte carbone doit être aussi limitée que possible.
Nos solutions d'élasticité sont plus transparentes, prévisibles et responsables
Nous avons mis au point des procédures pour industrialiser les méthodes de virtualisation afin de dimensionner des machines qui correspondent pour le mieux aux besoins en ressources des applications qui nous sont confiées.
Ces procédures sont consolidées et déployables en quelques minutes. Elles peuvent ainsi faire l'objet de procédures automatisables, dans la condition que les applications puissent bénéficier d'une architecture adaptée.
1. Déploiement applicatif
Lorsqu’un autoscale décide de rajouter par exemple une VM, c’est lui qui va devoir installer l’application et la connecter aux services dont elle a besoin (SQL, NFS, etc). Il doit donc savoir à chaque instant quelle est la version de l’application en production, et comment la déployer. Bearstech va vous conseiller et vous accompagner pour spécifier les modalités de livraison de l’application en production. Notre workflow devops est particulièrement adapté pour ce type de besoin.
2. Ressources partagées
Nous effectuons un travail d'identification des données que les processus exécutant l’application devront partager à chaque instant, car celles-ci seront gérées par une infrastructure tierce. On y trouve en général :
les fichiers manipulés par l’application via le filesystem de l’OS
les fichiers manipulés par l’application via un protocole objet
une base de données : cluster SQL
une base de données NoSQL
des sessions : cluster Redis …
Chacun de ces services peut être déployé et infogéré par Bearstech, et devra lui-même être dimensionné en fonction des dimensions minimales et surtout maximales de l’autoscaler.
Il est important de réaliser que chacune de ces ressources partagées peut être un goulet d’étranglement de l’application et nécessite donc une attention particulière. Le seul fait d’avoir déployé un autoscaler est loin de garantir un succès en production lors du prochain pic de charge sans avoir mis en oeuvre avec nous, les analyses requises.
3. Configuration, test et exploitation
Une application est plus qu’une somme de services reliés entre eux, les interactions peuvent être rapidement complexes.
Notre expérience nous permet de choisir des architectures et dimensions cohérentes et fonctionnelles sans connaître l’application a priori, mais il demeure indispensable d’effectuer un test de charge sur une infrastructure:
le test permet de configurer l’autoscaler en fonction des performances attendues de l’application
le test permet d’anticiper comment réagit l’autoscaler et avoir un modèle de référence
le test permet de vérifier où se trouve le goulet d’étranglement à chaque palier de charge
En exploitation, il est important d’effectuer une analyse régulière du comportement de l'autoscaler, à la fois d’un point de vue fonctionnel (absorbe les pics de charge) et financier (ne se déclenche pas à l’excès).
La surveillance de l’autoscaler est donc intimement liée au suivi des performances de l’application au cours de ses évolutions, et nous pouvons vous fournir l'outillage pour surveiller la qualité de votre code. Là aussi notre workflow devops est doté d'outils qui répondent à ce type de besoin.
Edit :
Correction de l'affirmation "En effet, un autoscaler ne gère que l'ajout de CPU/RAM" par "En effet, sur la partie horizontale, un autoscaler ne gère que l'ajout de CPU/RAM"
Correction introduction
Mettre à jour les images Docker : la méthode de Bearstech
False
urn:uuid:56decb2a-7f41-5408-866d-1eb7960e26d22023-07-07T11:53:19Z2023-07-10T09:06:22ZBearstechcontact@bearstech.com
Découvrez les bonnes pratiques de Bearstech pour la gestion et la mise à jour sécurisées des images Docker.
Bearstech propose une série d'images Docker pour des clients les utilisant, en lien étroit avec notre métier d'hébergeur (Nginx, PHP, Nodejs, ...) : https://hub.docker.com/u/bearstech.
Ces images sont maintenues avec la même rigueur que nous apportons au reste de notre infrastructure, en particulier du point de vue de la sécurité, le tout en proposant à nos client un moyen de s'assurer que les images qu'ils utilisent sont bien à jour. Voyons quelles sont les bonnes pratiques que nous avons mis en place à ce sujet.
L'arborescence de nos images Docker
On peut définir une arborescence de ces images Docker à partir du champ "FROM" défini au début de chaque Dockerfile.
Toutes nos images dérivent donc de notre image de base (bearstech/debian), qui est disponible avec les tags de chaque version Debian encore maintenue (Buster, Bullseye et Bookworm au moment de la rédaction de cet article). Cette image n'est pas créée à partir d'un Dockerfile mais "from scratch" grace à l'outil mmdebstrap.
Afin de maintenir ses images Docker, il est important de connaître cette arborescence :
La nécessité de reconstruire une image à n'importe quel niveau implique la nécessité de reconstruire toutes les images qui en dérivent (si image1 est rebuildée, alors image1.1, image1.2, image1.2.1 et image1.3 doivent être reconstruites). De même il n'est pas utile de vérifier la nécessité de reconstruire une image si son image "mère" le nécessite.
Cette arborescence peut être formalisée dans un fichier plat, par exemple en YAML, même si ce n'est pas la solution que nous avons retenue :
image1:
image1.1:
image1.2:
image1.2.1:
image1.3:
image2:
image2.1:
[...]
Suivi des mises à jour des images Docker
Afin de suivre en interne les mises à jour de nos images, nous utilisons le système de labels des images Docker, soit dans un Dockerfile:
LABEL votre.label=valeur-du-label
On peut alors obtenir les informations d'une image via :
$ docker inspect --format='{{json .Config.Labels}}' bearstech/debian:buster | jq
{
"org.opencontainers.image.authors": "Bearstech",
"org.opencontainers.image.revision": "2244cebd8a4a2226cfa409ed8d2d0adf722f9e48",
"org.opencontainers.image.url": "https://hub.docker.com/r/bearstech/debian",
"org.opencontainers.image.version": "bearstech/debian:buster-2023-07-01"
}
Les deux labels utiles pour nous étant:
org.opencontainers.image.revision contient un hash de commit et nous permet donc de savoir l'état du dépôt au moment du build,
org.opencontainers.image.version que nous avons formalisé en bearstech/IMAGE:TAG-DATE (ici bearstech/debian:buster-2023-07-01), ce tag n'étant pas déployé sur le hub Docker mais a son existence propre en interne.
Ce deuxième tag permet d'avoir immédiatement une information pratique sur la nature et version de l'image, alors que la plupart des images se contentent du hash qui laisse en général assez perplexe (par ex: où consulter une table de correspondance hash -> date ?).
Pourquoi Debian
Vous aurez remarqué que nous n'avons pas choisi une distribution "légère spéciale conteneur" telle que la fameuse Alpine. Il y a plusieurs raisons à ceci :
la principale est que notre modèle de maintenance est basée sur le principe Debian des branches stables + patches de sécurité. Le comfort pour les développeurs (environnement stable pendant 2 ans) et pour l'infogéreur (garantie de pouvoir déployer des patches de sécurité sans incidents et sans demander la permission aux développeurs) est incomparable
nous avons par ailleurs plus de 20 ans d'expérience, de recettes et d'outils sur les systèmes Debian, il aurait été dommage de ne pas en profiter...
et enfin il n'y a pas de contre-indication, car grâce au système de "layers" de Docker, l'image de base Debian est partagée par toutes nos images de notre arborescence : au final le coût de stockage des images sur les serveurs reste très modeste et n'est PAS proportionnel au nombre d'images
Quand mettre à jour les images Docker
Pour la plupart de nos images, nous appliquons la même règle de sécurité que nos serveurs en suivant les mises à jour de sécurité Debian de la pile logicielle que nous maintenons. Nous avons donc opté pour un système nous notifiant quotidiennement des mises à jour de sécurité sur les différentes images. Voici par exemple le mail reçu ayant déclenché la mise à jour de l'image bearstech/debian:buster du 7 juillet:
error: security upgrades on debian:buster:
debian-archive-keyring 2019.1+deb10u1 -> 2019.1+deb10u2 (Debian-Security:10/oldoldstable)
Les images dérivant de bearstech/debian:buster nécessitent également d'être reconstruites au moins à cause de ces mises à jour de sécurité et ne sont donc ni testées (pour un gain de temps substentiel), ni mentionnées car leur reconstruction est automatique dans le processus de reconstruction de l'image bearstech/debian:buster.
Certaines images nécessitent des tests supplémentaires :
images utilisant des logiciels en "rolling release" (PHP dans une version non packagée par Debian, Node.js, etc.) via des dépôts APT hors Debian (nous appliquons alors toute mise à jour de paquet dès qu'elles sont mises à disposition)
logiciels spécifiques hors dépôt apt (Ruby, Gitlab, ...) pour lesquels il faut écrire des scripts "maison" pour vérifier l'existence de nouvelles mises à jour
KISS and generic
Comme souvent, le meilleur moyen garantir un niveau de maintenance satisfaisant est de garder le fonctionnement et le processus de mise à jour aussi simples que possible, et de rendre générique tout ce qui peut l'être.
Le processus de publication d'une image est chez nous toujours le même:
build de la nouvelle image
tests effectuées sur l'image
archivage interne et publication sur le hub Docker
mêmes étapes pour les images dérivant de cette image
Voici donc le résultat pour la publication de l'image bearstech/debian:buster:
$ docker-bearstech-full-build debian:buster
info: building image debian:buster
info: testing image debian:buster
info: pushing image debian:buster
info: image debian:buster published
info: rebuilding debian:buster dependencies: php-cli:7.3
info: building image php-cli:7.3
info: testing image php-cli:7.3
info: pushing image php-cli:7.3
info: image php-cli:7.3 published
info: rebuilding php-cli:7.3 dependencies: php-composer:7.3 php:7.3
info: building image php-composer:7.3
info: testing image php-composer:7.3
info: pushing image php-composer:7.3
info: image php-composer:7.3 published
info: building image php:7.3
info: testing image php:7.3
info: pushing image php:7.3
info: image php:7.3 published
Chaque étape est bloquante (pas de publication sur le hub Docker si les tests ne passent pas) et peut être rejouée indépendemment :
$ docker-bearstech-test debian:buster
[...]
# Résultats de tests laissés à notre discrétion
[...]
info: image bearstech/debian:buster-2023-07-01 tested successfully
Enfin, si certaines étapes du build peuvent être rendues génériques, cela allègera les Dockerfiles et vous y gagnerez en homogénéité. Voici par exemple un Dockerfile utilisé à la fin de chaque build d'image pour y ajouter nos labels :
$ cat labels/Dockerfile
ARG IMAGE
ARG TAG
ARG BUILD_DATE
FROM bearstech/$\{'IMAGE'}:$\{TAG}-$\{BUILD_DATE}
ARG IMAGE
ARG TAG
ARG GIT_REVISION
ARG BUILD_DATE
LABEL org.opencontainers.image.authors=Bearstech
LABEL org.opencontainers.image.revision=$\{GIT_REVISION}
LABEL org.opencontainers.image.version=bearstech/$\{IMAGE}:$\{TAG}-$\{BUILD_DATE}
LABEL org.opencontainers.image.url=https://hub.docker.com/r/bearstech/$\{IMAGE}
Sur l'image sans labels bearstech/debian:buster-2023-07-01 qui vient d'être buildée, il nous suffit de lancer cette commande (intégrée au processus de construction) pour y ajouter nos labels :
$ docker build --build-arg IMAGE=debian --build-arg TAG=buster --build-arg BUILD_DATE=$(date +%Y-%m-%d) --build-arg GIT_REVISION=$(git rev-parse HEAD) labels/
Avertir de la mise à jour d'une image
Il est de notre responsabilité de mettre à jour les images que nous proposons mais il revient à nos clients de mettre à jour leurs propres images qui en dérivent. Pour cela, nous avons intégré à notre dashboard multicloud un module affichant les mises à jour d'images Docker disponibles.
Si de plus vous avez souscrit à notre système de workflow, il ne vous reste plus qu'un clic pour redéployer vos applications et profiter de ces mises à jour sans effort et en toute sérénité.
Conclusion
Dans un article précédent nous avions détaillé la position de bearstech vis-à-vis de Docker, en particulier son utilisation en production.
Cet article vient préciser comment nous gérons dans les faits les images dont nous avons la résponsabilité.
Comme toujours, notre approche vise plusieurs objectifs : mettre en œuvre les images les plus simples et sécurisées possible, tout en facilitant autant que faire se peut le quotidien de nos clients dans le cadre de nos prestations d'infogérance.
La maintenance et la mise jour des images Docker est une tâche complexe qui requièrent une grande rigueur et organisation.
Notre approche méthodique nous permet de relever ces défis efficacement !
Fonctionnement du workflow DevOps idéal (2ème partie)
False
urn:uuid:7e53aade-fabd-5965-994b-42258aa749df2023-06-15T12:09:01Z2023-06-15T12:47:16ZBearstechcontact@bearstech.com
Dans cet article nous vous présentons le fonctionnement d'un workflow DevOps idéal avec quelques cas pratiques
Dans l'article précédent, nous avons vu les principes sur lesquels le workflow devops de Bearstech repose (opensource, transparence, mesure de la fiabilité des applications). Dans cet article, nous allons vous présenter son fonctionnement et quelques cas pratiques qui peuvent s'appliquer aux différentes étapes du cycle de vie des projets informatiques.
Notre workflow
Notre but étant de viser la fiabilité des applications, nous avons conçu un environnement de travail sécurisé et transparent qui peut s'adapter à tous types de projets. Il respecte les bonnes pratiques d'un développement qui prend au sérieux les questions de sécurité et de performance applicatives.
Bearstech propose un workflow modulaire, qui n’impose que peu de règles prédéfinies, qui se paramètrent dans des fichiers, de manière transparente. Il effectue pour le développeur les opérations de préparation de l'environnement d'exploitation:
provisionner un serveur
paramétrer des services web
générer des certificats pour authentifier l’application
provisionner un service de BDD
définir un système de cache ...
De plus, il apporte un environnement de travail complet, maintenu par Bearstech :
pour versionner le code, créer des branches et des merge requests
pour automatiser des tâches sur la CI selon les étapes de livraison du code : intégration, tests, recette, staging, production
échanger avec mon équipe, suivre les sorties de tests, des déploiements, analyser la productivité ...
Les développeurs disposent ainsi d'une plateforme qui regroupe un ensemble d'outils qui leur permettent d'assembler les couches logicielles plus simplement, de valider l'intégration de leurs applications dans un contexte d'exploitation stable, tout en gardant le contrôle sur propres leurs environnements de travail.
Instancier l'application sur la CI
Le workflow devops de Bearstech est modulaire, il peut donc couvrir pas mal de cas d'usages pour les applications courantes. Les services à invoquer se paramètrent dans le fichier .gitlab-ci.yml des projets.
Dans le cas d'un scénario de workflow qui souhaite valider le bon fonctionnement d'une application par des tests d'intégration et des tests fonctionnels, il faudra spécifier à la CI les règles nécessaires pour instancier l'application de manière temporaire avant son déploiement vers les environnements de staging ou de production.
Fichiers requis
Dans ce cas, il sera souhaitable d'utiliser d'embarquer l'application dans des conteneurs. Le workflow aura besoin au moins de 3 fichiers pour fonctionner:
.gitlab-ci.yml pour lister les actions à exécuter sur la CI. Dans le cas de notre scénario, il faudra au moins 2 étapes: le build de l'image Docker, et le déploiement.
Dockerfile pour l'image de l'application et ses dépendances à embarquer.
docker-compose.yml pour lister les services utilisés par l'application.
Reverse proxy
Notre workflow met à disposition un reverse-proxy qui permet d'exposer publiquement et de manière sécurisée les conteneurs. Nous utilisons Traefik car il permet de gérer dynamiquement les configurations. Dans le workflow c'est lui qui dispatche les requêtes aux conteneurs.
Le workflow inclut les directives Docker pour lier Traefik à votre application. Traefik va écouter la socket Docker (docker.sock) pour ouvrir les connexions sur le réseau privé créé par Docker, et permet ensuite de s'y connecter en http pour intéragir avec le ou les conteneurs.
En production, Traefik ne tourne pas dans un conteneur, mais il écoute la socket docker.sock, il intercepte les événements de création de conteneurs, il les inspecte, récupère l'ip du réseau et expose l'application proprement: le workflow interdit d'exposer publiquement les ports des applications qui tournent sous Docker, seul le port du reverse-proxy Traefik est public (80 et 443).
Réaliser les tests dans la CI
Tests unitaires
Grâce à la CI et à Docker, il est désormais possible d'automatiser les tests unitaires qui doivent être réalisés avant le build de l'image de l'application. Dans la documentation du workflow, nous avons décrit une procédure pour réaliser des tests unitaires sur une application écrite en Python en utilisant l'utilitaire pytest.
Tests fonctionnels
Une fois l'application et le reverse-proxy instanciés sur la CI, il est ensuite possible de lancer des tests directement sur l'infrastructure temporaire qui, dans notre workflow, tourne dans un conteneur LXC afin de bien sécuriser l'environnement.
Nous avons écrit pas mal d'article sur le sujet des tests fonctionnels qui permettent de valider la pile logicielle d'une applicaton (Tests fonctionnels avec browserless et Cas d'usage pour des tests fonctionnels avancés), aussi nous n'allons pas nous étendre à nouveau sur les outils qui permettent d'émuler un navigateur headless afin d'obtenir dans la CI une sortie propre pour le résultat des tests.
Un déploiement flexible
Les contraintes ne sont pas les mêmes en production et en staging, c'est pourquoi notre workflow s'adapte aux besoins de flexibilité pour les environnements de recette et aux besoins de stabilité et de performance pour les environnements de production.
Par son aspect modulaire, notre système de déploiement prend en compte les besoins de flexibilité pour les phases de développement et de recette, pour ensuite couvrir les besoins de stabilité en préprod et en production.
Pour plus de détails sur ces deux aspects du déploiement, nous vous invitons à consulter la documentation de notre workflow pour les principes de déploiement d'application hébergées en natif avec son quick-start, et ceux pour les applications conteneurisées avec son quick-start.
Ce déploiement modulaire permet de couvir les besoins d'organisation des projets informatiques actuels. Voici quelques exemples pratiques de déploiement qui démontrent la souplesse du workflow:
L'agilité
L'app-review
Cette méthode de déploiement permet de comparer plusieurs versions de l'application simultanément. Cette méthode est particulièrement utile en développement pour valider telle ou telle fonctionnalité. Couplée à Docker, notre workflow permet de déployer des conteneurs en fonction des branches de votre projet, et configure automatiquement un point d'accès HTTP qui reprend le nom de la branche dans l'url.
Cela permet de publier l’application sur une url temporaire, à côté des url “officielles” déployées sur les environnements (staging et production). Le workflow devops de Bearstech implémente cette technique au moyen du reverse-proxy en déployant les conteneurs dans un environnement spécifique à la branche de commit (voir notre documentation technique à ce sujet).
Le Déploiement "Blue/green"
Cette méthode de publication permet à un nombre limité d'utilisateurs d'accéder à certaines fonctionnalités, avant de les diffuser à tous les autres.
Notre workflow permet lier la branche du dépôt qui déclenche le déploiement et la machine cible (target). Ainsi, les fonctionnalités qui sont destinées à être validées dans un environnement spécifique peuvent être livrées au moment voulu.
Attention, ce mode de déploiement doit être adjoint à un loadbalancer qui s'occupe de répartir le trafic entre les différents environnements. Le paramétrage du loadbalancer est une opération distincte du workflow (voir exemple un exemple de paramétrage chez OVH pour une répartition du trafic en fonction des ports).
Le rollback
En cas de dysfonctionnement de l'application en production qui n'a pas pu être détecté en amont (typiquement lors la mise à jour de modules tiers), pouvoir revenir à une version précédente de l'application est une opération que le système de déploiement permet de simplifier considérablement.
En effet, que ce soit dans le cadre d'un déploiement natif ou avec des conteneurs, chaque déploiement a lieu en identifiant l'ID d'un commit:
le déploiement natif effectue un git pull sur l'id de commit qui a déclenché la pipeline, et cela permet de rejouer en cas de besoin une pipeline qui utilisera une version précédente du code de l'application.
le déploiement de conteneurs utilisera un principe similaire, en permettant de rejouer le build d'une image Docker qui utilise une version précédente du code de l'application.
A noter qu'en ce qui concerne les données stockées en BDD ou leurs structures, il faudra utiliser une procédure de restauration qui s'appuiera sur un backup (dump) auquel on pourra adjoindre une reconstruction de sa structure, si ces modifications sont également versionnées dans le code du projet.
Infogérance
Une fois la gestion des dépendances fiabilisée grâce à la CI et aux bonnes pratiques du workflow, la continuité passe par l'infogérance des services en exploitation. L'infogérance des dépendances système et applicative consiste à automatiser leurs mises à jour de sécurité, et à disposer d'un monitoring pour déclencher des alertes.
Notre workflow intègre la mise à disposition des sondes de surveillance nécessaires à la mise en oeuvre d'un monitoring efficace pour les services exploités par l'application.
Nous mettons à la disposition de nos clients une interface web dédiée qui leur permet d'accéder à une synthèse de leurs environnements.
L'infogérance s'organise différemment selon le mode de déploiement utilisé:
Infogérance pour les services natifs
L'infogérance se fait de manière classique: les paquets bénéficient des mises à jour de sécurité selon la version stable de la distribution exploitée en production. Les métriques sont récoltées en provenance des ressources du système (CPU, RAM, Réseau, Disque ...) et des services instanciés (serveurs web, SGBD, systèmes de cache ...)
Les mises à jour de sécurité et la surveillance des métriques se fait au niveau système. C'est à dire que l'automatisation des procédures de mise à jour et de récolte des mesures intervient dans le cadre des procédures de maintenance définies par la version de Debian utilisée. Vous n'avez donc rien à faire pour garantir que votre application bénéficie d'un environnement système stable et sécurisé. Si vos applications ont besoin de librairies spécifiques (Imagick, ClamAV, Memcached, Composer ...) nous pouvons les installer à la demande.
Synthèse visible dans l'interface web de l'infogérance Bearstech pour les dépendances applicatives d'une application Wordpress exploitée nativement: la version du wordpress core et des modules qui l’accompagnent est analysée afin d’indiquer si une version supérieure est disponible (dans ce cas le badge de version s’affiche en rouge).
Infogérance des services conteneurisés
Les applications conteneurisées ont une pile système indépendante du système hôte. Bearstech ne peut donc pas intervenir directement sur cette partie, car le choix du système sur lequel repose l'application devient la responsabilité des développeurs.
L'infogérance s'applique donc à 2 niveaux : sur l'environnement d'exploitation (maintenance de l'OS de la machine hôte), et sur l'image Docker de base qui sert à builder l'application. Bearstech maintient à jour les images pour les distributions Debian Buster et Bullseye, et selon l'applicatif. A l'heure actuelle, nous maintenons les images Docker pour PHP (de la version 7.0 à 8.2), NodeJS (versions 16, 18 et 20), Ruby (version 3), et Nginx (latest). En production, les métriques de chaque conteneur sont récoltées au niveau de leur consommation CPU, RAM, Réseau et Disque.
Afin de garantir une sécurité optimale pour les images Docker, nous maintenons des images applicatives pour les projets courants. Ces images reposent sur les procédures de mises à jour de sécurité des releases Debian. Nous encourageons donc fortement les développeurs à utiliser nos images afin de builder leurs applications.
Synthèse visible dans l'interface web de l'infogérance Bearstech pour les conteneurs instanciés sur un serveur, avec l'état de mise à jour de l'image de base: La colonne “FROM” à droite indique le statut de l’image Docker de base (le “from” du Dockerfile) à partir de laquelle l’image de l’application est construite:
vert: l’image de base est à jour,
rouge: l’image de base est plus récente que celle utilisée par l’application. L’image de l’application doit être rebuildée et redéployée pour bénéficier des dernières mises à jour de sécurité
jaune: le statut de l’image de base est inconnu.
Conclusion
Le workflow devops que propose Bearstech n'est pas seulement un ensemble d'outils qui permettent de mettre en oeuvre les bonnes pratiques (sécuriser, tester, améliorer ...) pour intégrer et déployer les applications. C'est aussi un cadre logiciel générique qui repose sur des services opensource qui ont fait leur preuve (Gitlab, Grafana, Telegraf, Ansible ...) et que Bearstech maintient pour vous afin de vous garantir la transparence des processus, et la robustesse d'une plateforme qui vous accompagnera tout au long du cycle de vie de vos applications, et vous fera gagner en rentabilité sur vos projets.
Plus qu'un service, c'est l'expérience de 18 ans d'expertises dans l'infogérance des applications sur le web qui vous sont transmises avec ce workflow.
Vous souhaitez en savoir plus ?
Découvrez notre workflow DevOps et échangeons sur vos enjeux technologiques.
Demander une présentation
Pourquoi notre workflow Devops est le plus efficace et rentable que vous puissiez trouver aujourd'hui (1ère partie)
False
urn:uuid:c7437c3d-a4bf-5a67-98ae-6d74e4a3c7ff2023-06-06T10:47:49Z2023-06-08T10:01:03ZBearstechcontact@bearstech.com
Améliorez la fiabilité de vos applications avec un workflow DevOps complet et transparent. Gérez les dépendances et assurez des déploiements cohérents et reproductibles.
Chez Bearstech, nous utilisons des procédés "devops" depuis toujours, déjà motivés par une approche éco-responsable pour l'optimisation des ressources allouées sur de nombreuses infrastructures cloud dont nous assurons l'infogérance, nous avons opté pour la technologie Xen dès 2007 afin de créer des machines virtuelles qui fonctionnent au plus près des besoins des applications.
Petit à petit notre démarche a évolué pour stocker les rôles d'installation et la définition de notre infrastructure sur des dépôts de version tels que SVN puis Git dans une approche "GitOps" qui nous a permis de consolider l'automatisation du déploiement d'une partie de notre infrastructure, en respectant les principes qui ont été décrits par RedHat:
Un workflow standard pour le développement d'applications
Une sécurité renforcée avec la définition des besoins de l'application dès le départ
Une meilleure fiabilité grâce à la visibilité et au contrôle de versions via Git
La cohérence entre tous les clusters, clouds et environnements sur site
Bearstech est donc une société qui a su industrialiser son infrastructure afin de concevoir, sécuriser, déployer, et maintinir des systèmes informatiques fiables.
Mais alors pourquoi proposer un workflow devops pour le déploiement d’applications ?
Le devops c'est quoi ?
D’un point de vue business, la mouvance "devops" est un moyen de rentabiliser les projets informatiques en intégrant la qualité dans le processus de développement.
C'est un mouvement qui vise à optimiser les indicateurs clés de l’avancement des projets informatiques:
“lead time” : vise à réduire le délai de mise en œuvre
“process time” : vise améliorer le temps de traitement des demandes
“percent complete and accurate” : vise à augmenter le taux des fonctionnalités finalisées dans un cycle de développement.
Pour tenir ces objectifs, il faut réduire la fragilité des applications.
La dette technique
La fragilité des applications, c’est ce qu’on appelle la "dette technique". Elle peut être causée par l'accumulation de code dupliqué qui multiplie les risques de bugs, ou par des régressions : le code de librairies / modules / dépendances qui n'est pas à jour ou qui est obsolète. Pour ça, il "suffit" faire face au problème en factorisant le code et en augmentant la couverture de code par les tests.
Ensuite il y a aussi le fait que l'environnement de développement est difficilement reproductible pour le rendre compatible avec ce qui sera utilisé en production, surtout quand on travaille à plusieurs: mon environnement est-il bien à jour ? mes dépendances sont-elles bien toutes installées ? bénéficient-elles de la bonne version ? et mes collègues aussi ? etc...
Tester dans un environnement reproductible, et qui soit commun à tout le monde, et à chaque étape du développement, n'est pas aussi simple que cela peut paraître, et c'est là que Bearstech intervient afin de mettre à disposition son expertise pour déterminer un cadre méthodologique (avec ses outils) qui permet d'apporter des preuves de la fiabilité d'une application dans ses différents environnements d'exploitation.
Limites de la conteneurisation
Docker a l'avantage de définir un langage commun entre les devs et les admins pour régler la question des dépendances logicielles pour une application donnée, et assurer un environnement prévisible et reproductible sur toute la chaîne d'intégration de l'application, jusqu'à son déploiement en production.
Toutefois, la reproductibilité a ses limites et on n'est jamais à l'abri d'une différence de version mineure entre 2 images Docker et cela peut entraîner quelques effets de bords. C'est pourquoi l'utilisation d'un serveur de CI qui va builder l'image contenant l'application afin d'y effectuer des tests d'intégration peut être particulièrement utile:
gain de temps puisque cette tâche est automatisée
historique des tests consultable pour tous les membres du projet
systématisation des tests d'intégration
En conteneurisant une application on peut facilement définir un environnement stable, et même de manière temporaire pour valider la fiabilité de l’application en faisant jouer des tests unitaires ou des tests fonctionnels, avant la publication en production.
Mais tous les projets n’ont pas vocation à être conteneurisés en production, notamment les projets qui n’évoluent pas souvent, pourtant ce travail d’empaquetage des dépendances a un intérêt: les devs et les admins se mettent d'accord sur les dépendances, leurs versions, et le tout est décrit dans des fichiers. C'est une sorte de contrat.
Infrastructure As Code
Les technologies utilisées par le workflow devops de Bearstech sont toutes open-source et exploitent ce qu’on appelle l’Infrastructure As Code.
Bearstech utilise ces outils depuis de nombreuses années, dès lors que nous nous sommes mis à écrire des rôles Xen pour provisionner des machines virtuelles.
Notre workflow devops est centré sur un Gitlab, avec sa facilité pour versionner le code, créer des demandes, valider des merge-request, jouer avec les branches …
Et avec son serveur de CI, nous définissons des runners pour les projets qui lancent des traitements automatiques sur le code des applications dans un environnement shell ou docker.
A chaque étape du workflow, nous utilisons des procédés spécifiques d'IaC.
Développer:
Pour le développement, il est probable que les développeurs préféreront travailler dans un environnement Docker. Les dépendances logicielles peuvent ainsi être gravées (dans le silicium) de fichiers (Dockerfile et docker-compose) afin de permettre à la CI de reproduire l'environnement applicatif utilisé par les développeurs.
Intégrer:
Afin de valider l'intégration de l'application dans un environnement système, la CI va reproduire les étapes d'installation des composants, et lancer les services de l'application directement sur la CI. C'est le rôle du fichier .gitlab-ci d'enchaîner ces différentes étapes, puis d'ajouter les tests puis le déploiement.
Le workflow se sert de la registry Gitlab qui permet de stocker les éléments construits dans la CI. Chacun des éléments est lié au job d'une pipeline dont il est originaire. On peut y stocker:
des images Docker
des artefacts
des assets packagés
Tester:
Une fois l'application intégrée et instanciée sur la CI, il est possible de définir des tests fonctionnels sur l'application qui seront joués grâce à des images Docker qui embarquent des navigateurs headless (voir notre article sur les tests fonctionnels avancés)
Déployer:
Le déploiement suit la phase des tests. Il va s'appuyer sur les variables (d'environnement et personnalisées) transmises par Gitlab, et exécuter les phases d'installation des éléments construits durant l'intégration (images Docker, assets, artefacts ...) à partir du code contenu dans le projet Gitlab. Notre workflow prévoit plusieurs modes de déploiements selon les besoins des projets:
applications exploitées nativement:
sites statiques (Jamstack ...)
sites LAMP (Wordpress ...)
applications conteneurisées
Le système de déploiement prévu par notre workflow peut s'adapter aux besoins les plus fréquents des applications web. Il s'appuie sur des procédés écrits en shell ou sur des recettes Ansible.
Newsletter
Inscrivez-vous à notre newsletter pour être tenu informé de notre actualité, de nos prochains webinars et articles.
Abonnez-vous à notre newsletter
Profiter des bonnes pratiques
Échouer tôt
Échouer tôt pour réduire le temps et les coûts de réparation : il est moins coûteux de corriger un défaut au fur et à mesure qu'il est détecté tôt dans le cycle.
Dans notre workflow, le procédé du "Shift Left" s'appuie sur l'utilisation des pipelines de Gitlab et le retour d'information qu'elles apportent lors du build de l'application, ou lors des tests, ou lors de la phase de déploiement facilitent la vie du développeur. Il peut ainsi déterminer les points bloquants à mettre en place lors des tests d'intégration ou des tests fonctionnels pour valider ou non le déploiement de l'application.
Un scénario d'intégration et de déploiement simple
Le test d'intégration dans la CI permet de valider le bon fonctionnement des dépendances logicielles. Si le test ne passe pas, le push de l'image Docker et le déploiement ne se lancent pas:
Déployer sereinement
Déploiement de conteneurs
Le workflow de Bearstech permet de lever une bonne partie de la fragilité des conteneurs en exploitation :
Dans le workflow, les conteneurs ne bénéficient jamais de super-privilèges: il est obligatoire de spécifier un utilisateur non root dans les images de vos applications
il est interdit de définir des volumes dans les images, ils sont créés au déploiement par le workflow, et correctement partagés sur la machine hôte
les services publiés dans les conteneurs ne sont jamais exposés publiquement, ils sont derrière un reverse-proxy (Traefik) qui s'occupe de la couche TLS
les services sensibles comme les BDD sont déployés de manière native, elles ne tournent pas dans des conteneurs
les logs de vos applications sont centralisés et accessibles directement depuis le conteneur en cours d'exploitation
Déploiement d'applications natives
Tous les projets n’ont pas vocation à être conteneurisés, c’est pourquoi notre workflow n’impose aucune règle prédéfinie, et s’adapte aussi aux modes de déploiement natifs, sans avoir besoin de builder des images Docker (mais on peut aussi mixer les 2 modèles).
le projet sera déployé et instancié vers une machine cible de manière native, en utilisant les ressources d'une VM derrière un serveur web.
La CI s’occupe de compiler les assets, si besoin, et de les mettre à disposition dans les packages de Gitlab.
Ensuite, le workflow s'occupe de récupérer le code et les packages, puis de les déployer en configurant convenablement l'environnement d’exploitation. Il s’occupe aussi des certificats via LetsEncrypt.
Un workflow qui couvre toutes les étapes du cycle de développement
Du développement à la mise en production, le workflow enchaîne les tâches nécessaires à la validation des applications avant leur livraison, et permet ensuite de les déployer selon les besoins :
en staging, il peut être utile d'utiliser les conteneurs pour réaliser des déploiements différentiables selon les branches, pour faire de l'app-review.
en production, on pourra opter pour un déploiement de l'application en natif pour bénéficier d'une infogérance qui privilégie la stabilité et la sécurité du système.
Dans cet exemple de pipeline qui contient 2 points bloquants, une application est intégrée, testée, puis déployée en staging puis en production, depuis un serveur de CI infogéré, en utilisant les services de déploiement fournis par Bearstech.
A noter que le serveur de CI infogéré par Bearstech bénéficie également d'une infogérance. C'est un serveur qui doit être sécurisé car il peut être soumi à des opérations sensibles notamment si il utilise des conteneurs peu respectueux des règles de sécurité. C'est pourquoi nos serveurs de CI intègrent la technologie LXC (Linux Conteneurs) afin d'isoler les environnements d'exécution du reste de l'infrastructure du workflow.
Services infogérés en production
La stabilité de l'environnement d'exploitation est une condition nécessaire pour améliorer la fiabilité des applications.
Il est pratique de développer (et de tester) avec des services directement fournis par les images Docker. Mais pour la production, les contraintes sont différentes: il est vivement conseillé de profiter de réglages fins du service, du backup, d’une potentielle réplication, mais surtout de métrologie et d’une astreinte.
Les services pris en charge par Bearstech bénéficient d'infogérance et d'hébergement (mise à jour, maintenance, astreinte). En choisissant cette option avec le workflow, pour un ou plusieurs services, il est alors possible d'ordonner à l’infrastructure et à nos outils de créer les ressources nécessaires pour permettre aux applications de consommer le service infogéré (routage, authentification ...).
La supervision et le monitoring sont fournis par les outils de Bearstech.
Analyser pour s'améliorer
Le workflow devops de Bearstech est trans-disciplinaire, il apporte des outils d'analyse aux développeurs front et back pour améliorer leur code, aux administrateurs pour obtenir des mesures et tracer les logs, aux devops pour ajouter librement des étapes dans les procédures d'intégration, et aux chefs de projets pour pouvoir déployer plus fréquemment et sereinement.
Voici quelques exemples de services qui peuvent être ajoutés au workflow et qui peuvent aider à l'amélioration des applications.
Pa11y
Pa11y est un service d’analyse d’accéssibilité de votre site web. Il génère un rapport en se basant sur le respect des directives fournies par le Web Content Accessibility Guidelines (WCAG).
Bearstech peut intégrer dans le workflow un accès à Pa11y afin de générer un rapport d'accessibilité afin de vous aider à valider la compatiblité du code produit avec ses directives.
Sitespeed
Bearstech peut mettre à dispostion un accès au service Sitespeed qui analyse la performance de votre site web côté client.
La génération du rapport Sitespeed peut être intégré à la CI du projet en invoquant un script qui sera joué à chaque déploiement, et vous donner ensuite à la performance de chargement des pages web, et un indice de bilan carbone calculé par rapport à une évaluation de la consommation énergétique de l’application.
Les métriques récoltées par Sitespeed peuvent aussi être reportées dans notre outil de supervision sous Grafana.
Sonarqube
Sonarqube est un service d’analyse de qualité de code. L’outil analyse et fournit des indices sur la détection de bugs, de vulnérabilités, le taux de couverture des tests, le taux de duplication de code.
Beartech peut mettre à dispostion un service Sonarqube pour lancer une analyse du code de l'application par l'intermédiaire de la CI. Par exemple après la validation de la recette, au moment de passer sur un serveur d'homologation, il peut être judicieux de finaliser les développements en s'aidant du rapport de vulnérabilités produit par Sonarqube.
Conclusion
Les principes du workflow reposent donc sur la reproductibilité des applications dans des environnements conformes à ce qui sera déployé en production afin de pouvoir mesurer leur fiabilité par des tests. La conformité des environnements doit valider la compatiblité des dépendances système et logicielles entre elles par une procédure de conteneurisation de l'application ou la mise à disposition d'un environnement de recette. Notre workflow permet de déployer les applications de manière native ou sous la forme de conteneurs. Les environnements d'exploitation bénéficient tous de l'infogérance de Bearstech, et en y adjoignant des services d'analyse de performance, notre workflow vous permet le suivi en continu de la qualité de service de vos applications.
Vous souhaitez en savoir plus ?
Découvrez notre workflow DevOps et échangeons sur vos enjeux technologiques.
Demandez une démonstration
Comment choisir votre prestataire d’infogérance ?
False
urn:uuid:b68b4906-7c00-5fec-b98e-787427f1c8122023-03-31T12:12:30Z2023-03-31T13:08:40ZBearstechcontact@bearstech.com
Choisir un prestataire d'infogérance peut être complexe et stressant. Nous vous proposons quelques conseils pratiques pour faciliter cette décision et sélectionner le partenaire idéal pour votre entreprise.
Faire appel à une prestation d’infogérance est une tâche délicate : la complexité des enjeux techniques et la perte de contrôle qu’elle implique rendent la sélection d’un prestataire complexe et parfois anxiogène. Toutefois, externaliser la gestion de son système d’information (SI) peut s’avérer pertinent, voire largement préférable dans certains cas. En effet, internaliser systématiquement la gestion des infrastructures peut être une distraction ou une source de tension au sein de vos équipes.
Dans cet article, nous vous proposons une liste partielle et partiale des facteurs clés pour séléctionner votre futur prestataire d’infogérance.
Afin de clarifier au mieux les ambitions et limites de cet article, nous précisons que notre perspective est façonnée par notre métier : l’hébergement et l’infogérance Cloud. Bien sûr, l’infogérance regroupe un gradient de missions pouvant inclure : téléphonie, support poste de travail ou encore la TMA de mainframe … Mais nous pensons que les conseils que nous vous apportons ici peuvent s'appliquer à l'essentiel des prestations d'infogérance.
L’infogérance présente plusieurs avantages, tels que la réduction des coûts, l’accès à des compétences spécialisées et la possibilité de se concentrer sur son cœur de métier. Dans cet article, nous vous guiderons à travers les étapes clés pour choisir le bon prestataire d’infogérance qui répondra à vos besoins et vous accompagnera dans la réussite de vos projets.
Bearstech propose ses missions d’infogérance depuis 2004. Fort de notre expérience diversifiée dans de nombreux contextes techniques et opérationnels, notre équipe accompagne un grand nombre de clients de tout type (taille, métier, exigence technique). C’est en nous appuyant sur cet historique que nous vous proposons de passer en revue les critères essentiels à prendre en compte pour choisir un prestataire d’infogérance, afin d’assurer une collaboration fructueuse et durable, car dans de nombreux cas, le prestataire d’infogérance sera au cœur de vos enjeux métiers.
Dans cette page, nous passerons en revue les éléments clés pour bien choisir votre prestataire d’infogérance et ainsi établir une relation satisfaisante et durable.
Évaluer précisément vos besoins
Avant tout, il est essentiel de bien comprendre vos besoins en matière d’infogérance. Notons, qu’une évaluation approfondie va au-delà d’une simple liste de technologies et de ressources matérielles. Il est également important de prendre en compte les méthodes de travail de vos équipes. Comment fonctionnent-elles au quotidien ? Quelles sont les pratiques et les processus mis en œuvre pour répondre à vos besoins métier ?
Cette compréhension approfondie est cruciale, car l’un des principaux défis lorsque l’on collabore avec un expert en charge de la gestion de votre système d’information (et des responsabilités associées) est d’aligner les visions et les pratiques de travail. En ce qui concerne les pratiques, il s’agit généralement de l’aspect le plus simple à résoudre : il suffit de trouver un terrain d’entente et d’adopter des solutions alternatives. Toutefois, harmoniser les visions peut s’avérer plus complexe.
Il est bien sûr important de bien présenter les enjeux techniques pour que votre prestataire valide la faisabilité et le coût de la prestation. Mais d’experience, lorsque le positionnement du prestataire est clair, les points de frictions les plus complexes à résoudre sont ceux qui relève des méthodes et de la vision.
Préciser le niveau d’exigence en terme de sécurité et de disponibilité
N’oubliez pas de préciser le niveau d’exigence et vos attentes en termes de sécurité et de disponibilité, ces informations essentielles doivent être incluses dans la présentation de votre projet. Une communication claire sur ces aspects permettra à votre prestataire d’infogérance potentiel de comprendre vos besoins spécifiques et d’adapter son offre en conséquence.
Exemple : Une infrastructure Haute disponibilité avec deux serveurs tournant en permance pour prendre le relais est effectivement le meilleur moyen pour limiter les indisponibilités liées aux pannes matérielles mais : La plupart du temps les indisponibilités sont dues à la performance des applications, aux pics de fréquentations non prévus ou à des problèmes de configuration et autres erreurs humaines. Dans ce contexte, les surcoûts (budgétaires et écologiques) lié au déploiement de deux serveurs pour répondre aux enjeux de disponibilité ne se justifie pas nécessairement.
Nota : Pour savoir si la haute-disponibilité se justifie, il convient d’évaluer le coût d’une indisponibilité jusqu'à le redéployement du serveur. Si ce coût multiplié par la probabilité de perdre le dit serveur est supérieur aux coûts de location du matériel supplémentaire et sa gestion opérationnelle sur le long terme, la haute disponibilité se justifie.
Intéressé par un webinar sur le sujet ?
Souhaitez-vous assister à un webinar traitant ce sujet ?
Avez-vous une autre idée de conférence ? Faites-le nous savoir
Fournissez les informations techniques nécessaires
Il est également indispensable de décrire avec précision les éléments techniques concernés par la prestation, tels que les besoins en ressources matérielles, les versions logicielles concernées, les configurations spécifiques, etc. En fournissant ces informations détaillées, vous permettrez à votre prestataire d’infogérance d’évaluer la faisabilité et le coût de la prestation, tout en évitant les mauvaises surprises ou les malentendus ultérieurs. Une bonne communication des informations techniques facilitera la mise en place d’une collaboration fructueuse avec votre prestataire d’infogérance.
Assurez-vous donc de bien définir vos attentes et de communiquer clairement vos besoins et vos objectifs à votre prestataire d’infogérance potentiel. Cela facilitera la collaboration et permettra d’établir une relation solide et durable, basée sur une compréhension mutuelle des enjeux et des responsabilités.
Demandez des références
Bien que les références client ne soient pas le critère de sélection le plus important, elles peuvent néanmoins fournir un aperçu de l’expérience et de la qualité du prestataire. Souvent, les prestataires sont fiers de partager leurs réussites en mentionnant des clients prestigieux.
Il est important de ne pas se contenter d’une simple liste de noms. Essayez, autant que possible, de demander des exemples concrets de projets et de prestations qui couvrent les points clés que vous avez identifiés.
Les références sont utiles, mais assurez-vous qu’elles correspondent vraiment à la mission pour laquelle vous sollicitez le prestataire.
Exemple: si vous recherchez un prestataire pour une mission récurrente sur le long terme, demandez des références qui correspondent à ce type de mission. Les prestations de conseil ponctuelles auront moins de poids dans votre évaluation.
Vérifiez également que le prestataire a travaillé avec des clients similaires à votre entreprise. Même si vous n’appréciez pas d’entendre le nom de vos concurrents, leur présence dans une liste de références peut en réalité être un atout, car cela indique que le prestataire a de l’expérience dans votre secteur d’activité.
Demandez une description synthétique de l’offre
Les contrats d’infogérance peuvent être complexes et difficiles à comprendre, surtout si vous êtes en quête d’un prestataire pour la première fois. C’est pourquoi il est essentiel de disposer d’une synthèse décisionnelle claire et concise, contenant uniquement les informations les plus importantes pour faciliter votre prise de décision.
Cette synthèse doit mettre en avant les critères essentiels pour votre projet et refléter ce que votre interlocuteur considère comme prioritaire. Elle permettra également de mieux comprendre les offres et d’identifier rapidement les points forts et les faiblesses de chaque proposition.
Lorsque vous consultez plusieurs prestataires, disposer d’un document synthétisant les éléments clés de chaque offre vous aidera à comparer plus efficacement les différentes propositions. Cela facilitera également la création de tableaux comparatifs et vous permettra d’analyser les avantages et les inconvénients de chaque option de manière rationnelle.
Si vous constatez qu’une information essentielle est manquante dans la synthèse fournie par un prestataire, n’hésitez pas à demander des précisions. Cela garantira une comparaison équilibrée et éclairée entre les différentes offres, vous permettant de choisir le prestataire d’infogérance le plus adapté à vos besoins et à vos attentes.
Comprendre les SLA
Il est essentiel de bien comprendre et comparer les niveaux de service proposés. Comparer des pommes et des poires est un risque de tous les instants lorsque l’on cherche un prestataire d’infogérance.
Pour éviter de comparer des éléments incomparables, assurez-vous de bien comprendre les notions clés telles que le GTI (Garantie de Temps d’Intervention) et le GTR (Garantie de Temps de Rétablissement). Il est également important de connaître les modalités d’astreinte et les conditions de leur sollicitation.
Les aspects liés à la surveillance des systèmes et aux méthodes de stockage des données doivent également être pris en compte. Interrogez-vous sur les éléments suivants : Qu’est-ce qui est surveillé et comment ? Où sont stockées les données et comment sont-elles sauvegardées (localisation et fréquence) ?
Exemple : Vous pensez que vous pouvez demandez une intervention d’astreinte directement via ticket, alors que seule les sondes peuvent activer l’astreinte.
Toutes ces informations sont cruciales, car elles constituent souvent l’essentiel d’une prestation d’infogérance. En les prenant en considération, vous serez en mesure de comparer efficacement les offres des différents prestataires et de choisir celui qui répond le mieux à vos besoins et exigences.
Choisissez un partenaire qui vous ressemble
Comme mentionné précédemment, il est crucial de s’assurer que vous et votre prestataire partagez une vision commune de la prestation d’infogérance. Dans le cadre des services, un piège courant est de penser acheter un type de service, alors que le prestataire en propose un autre. Pour éviter ce problème, il est important d’aller au-delà des aspects pratiques de la prestation et d’évaluer votre proximité en termes de vision.
Pour ce faire, échangez avec le prestataire sur vos objectifs à long terme, vos attentes en matière d’évolution et d’adaptation aux changements technologiques, ainsi que sur les valeurs qui guident vos décisions. Cela permettra d’identifier si le prestataire est en phase avec votre approche et s’il est capable de vous accompagner efficacement dans la réalisation de vos objectifs.
Il est également judicieux de discuter de la manière dont le prestataire envisage la collaboration et la communication avec votre équipe. Un partenariat réussi repose sur une communication fluide, des échanges réguliers et une compréhension mutuelle des besoins et des attentes. Vérifiez que le prestataire est prêt à s’adapter à vos méthodes de travail et à s’engager dans une relation de confiance et de transparence.
Exemple : Chez Bearstech nous n’intervenons que sur ticket, refusant les e-mails et les appels téléphoniques. Il est tout à fait possible d'organiser des réunions pour traiter des problématiques techniques complexes ou pour faciliter la prise de décision. Toutefois, ces réunions sont exceptionnelles et elles doivent être planifiées à l'avance. C’est une façon de procéder qui a des impacts pratiques et qui illustre très bien notre vision du métier : les demandes doivent passer par un outil sécurisé et doivent alimenter l'historique de la relation client et de la prestation. C’est un choix qui illustre selon nous les valeurs cardinales dans notre méthodologie : rigueur, transparance et collaboration. Tous nos collaborateurs et les équipes de nos clients, doivent avoir accès au contexte de la mission, correctement notée dans un outil centralisé.
En mesurant votre proximité en termes de vision, vous pourrez établir une relation solide et durable avec un prestataire d’infogérance qui vous ressemble et qui est en mesure de répondre à vos besoins spécifiques.
Dans le doute choississez Bearstech pour vos missions d’infogérance Cloud
Nous avions averti en début d'article que cet article serait partial …
Choisir un prestataire d’infogérance est un moment sensible, un prestataire d’infogérance se doit d’agir comme un partenaire de long terme et pour cause il contrôle souvent des aspects critiques de vos processus métier. Nous espérons que cet article vous aidera à aborder le sujet mieux outillé et à choisir votre futur prestataire idéal !
Docker en production : le cas d'usage de Bearstech
False
urn:uuid:e2ce4d08-e05d-5124-a03c-4ba2b7a90c762023-02-23T18:46:02Z2023-09-07T21:57:00ZBearstechcontact@bearstech.com
Nous vous exposons dans cet article les principales raisons pour lesquelles nous ne faisons pas le choix de Docker pour les environnements de production.
Docker s'est imposé au fil des ans comme une solution universelle pour gérer les environnements de développement. Il faut dire que la conteneurisation, popularisée par Docker, présente un avantage substantiel lorsqu'il est question d'installer des environnements et travailler localement.
Docker est reproductible ;
Docker offre des silos isolant l'environnement de travail ;
Docker permet de gérer le système comme une stack de développement.
Mais le passage en production est souvent un exercice complexe : le réseau, les volumes et autres briques viennent complexifier les opérations sur les machines de production.
Avant d'entrer dans le cœur du sujet, nous devons préciser que Docker est une solution tout à fait satisfaisante pour un grand nombre d'entreprises qui souhaitent le déployer et ont les compétences techniques, et les ressources humaines adéquates.
Chez Bearstech nous déployons très régulièrement des conteneurs Docker notamment dans le cadre de notre workflow DevOps. Mais lorsque qu'un projet est prêt pour la production, nous faisons souvent le choix de la VM sans conteneur.
Cet article vise à expliciter cette démarche et communiquer sur notre conception de l'administration système.
Nous avons organisé une série de webinars sur les limites de Docker : Le côté obscur de Docker où nous parlons d'exemples concrets où Docker se comporte d'une drôle de façon.
Les avantages de Docker en production
Docker en production présente des avantages notables que nous reprenons ici pour contextualiser notre perspective, c'est en pleine connaissance de cause que nous faisons le choix de ne pas déployer Docker systématiquement en production et nous devrons donc répondre à ces enjeux lorsque nous présentons notre approche.
D'abord, il peut permettre dans certaines conditions de densifier l'infrastructure en exploitant un maximum des ressources de la machine hôte.
Les applications sont isolées dans des containers ce qui offre en principe des niveaux de sécurité supplémentaires.
Le développement, la pré-production et la production sont identiques et facilement reproductibles.
L'ensemble des éléments nécessaires pour le fonctionnement des apps peuvent être gérés directement par les développeurs en éditant les Dockerfile et Docker Compose.
Pourquoi nous ne déployons pas Docker en production
Les inconvénients de Docker en production
Abordons d'abord les contraintes de Docker en général, puis nous explorerons ensemble les enjeux de Docker dans notre cas particulier.
Passé un certain nombre de conteneurs déployés, un orchestrateur devient incontournable, ajoutant une couche de complexité supplémentaire.
La gestion du réseau et la communication entre les conteneurs est elle aussi complexe et nécessite l'usage de reverse proxy comme træfik.
L'immense latitude qu'offre Docker présente des risques de sécurité : quand on peut tout faire… on peut aussi faire n'importe quoi. D'autant, qu'il peut devenir très délicat de vérifier et auditer les images Docker. Ceci est d'autant plus délicat que l'on demande à des développeurs de prendre la responsabilité (et donc le savoir-faire) des administrateurs systèmes (par ex. penser à mettre à jour le paquet système SSL en plus de ses propres dépendances applicatives, etc.)
Pour finir, Docker ajoute un grand nombre de couches logicielles supplémentaires qui coûtent en ressources. Par exemple un conteneur Nginx par projet, alors qu'il peut être mutualisé et fournir ainsi une scalabilité bien supérieure (colle : comment "tuner" 100 NGinxes de façon coopérative sur une même VM ?). Pour nombre de projets, Docker coûte plus qu'il apporte.
Docker dans le cadre de nos prestations d'infogérance
Bearstech gère des infrastructures informatiques depuis 2004 et nous travaillons au quotidien pour améliorer la performance, la sécurité et la disponibilité des services de nos clients.
Pour répondre à ces objectifs, nous avons déployé une large expertise de la gestion des VMs. Cela constitue évidemment un biais, mais nous savons bien sûr dépasser nos a priori et proposer les solutions les mieux adaptées à nos clients.
Nous travaillons depuis 2014 avec Docker, notamment dans le cadre de notre Workflow DevOps. Le conteneur n'était alors pas une nouveauté pour nous, puisque nous exploitions LXC depuis 2009 pour des projets spécifiques à haute densité.
Mais pour assurer nos missions dans les meilleurs conditions et à un coût raisonnable, nous faisons le choix de l'homogénéité sur l'ensemble de notre infrastructure, ne dérogeant à cette approche que lorsque le besoin client ne peut pas être satisfait par cette règle générale. Il faut noter, qu'il s'agit de la même raison pour laquelle nous ne déployons pas de bare metal pour nos clients.
Par ailleurs, Docker n'offre pas les garanties satisfaisantes lorsqu'il est question de bases de données :
En premier lieu, sur les gros volumes de données Docker perd en performance et en maintenabilité. Or, chez Bearstech, nous pensons que la base de données est le componsant le plus sensible des systèmes que nous infogérons.
Ensuite, les possibilités offertes par Docker permettent de contourner les bonnes pratiques de sécurité auxquelles nous nous astreignons, particulièrement dans un contexte de données sensibles.
Mais quid de la reproductibilité ? Certainement Docker nous permettrait d'accélérer la portabilité des environnements ? Oui, c'est indiscutable, Docker est un avantage sur ce point. C'est d'ailleurs son principal argument. Mais notons que nous avons chez Bearstech une démarche infrastructure as code qui nous offre la flexibilité et l'efficacité nécessaire pour répondre aux attentes spécifiques de chaque client.
De notre point de vue, les apports de Docker en la matière nous imposent des contreparties parfois bien trop coûteuses, pour un objectif déjà rempli par nos solutions de virtualisation (et conteneurisation).
Un autre avantage qui s'accompagne de compromis trop coûteux : la question de l'exploitation optimale des ressources. Nous avons souligné que Docker est très souvent un facteur favorable pour la densification de l'infrastructure.
L'exploitation maximale des ressources déployées est nécessaire aussi bien sur le plan budgétaire, qu'écologique. Mais au final, le choix entre virtualisation et conteneurisation dépend de stratégies plus ou moins établies.
Docker peut ironiquement mener souvent à des infrastructures moins denses : il nous est souvent demandé de déployer des clusters entiers de VMs avec des conteneurs pour une poignée d'applications en production - ce qui se justifie techniquement quand on doit garantir des performances prévisibles -, alors qu'une infrastructure nettement plus simple sans conteneur fournirait un service équivalent avec moins de ressources matérielles.
Chez Bearstech nous avons atteint un niveau de densification de notre infrastructure satisfaisant sans avoir à complexifier nos systèmes et nos procédures en ajoutant une technologie comme Docker, aussi puissante soit-elle. La conteneurisation est redondante avec notre approche de la virtualisation et les contraintes de Docker dépassent largement d'hypothétiques gains.
Docker présente un autre problème majeur dans le cadre de nos prestations : nous l'avons dit, il permet aux développeurs de gérer le système comme du code. Cet avantage, lors de la phase de prototypage devient un écueil pour l'exploitation des services en production.
Nos garanties en tant que prestataire (l'exploitation irréprochable des services, leur sécurité, les temps de réponse de notre d'astreinte) n'est pas compatible avec la possibilité donnée par Docker aux développeurs de gérer ses environnements via les Dockerfiles et Docker Compose.
Nous pourrions mettre en place des protocoles restreignant cette liberté, en imposant des Dockerfiles et des fichiers docker-compose.yml made in Bearstech mais dans cas, les contraintes apportées par cette approche rendent le choix de Docker beaucoup moins pertinent.
Notre rôle en tant qu'infogérant, que ce soit sur notre infrastructure, sur les services d'OVHCloud, de Google ou AWS est d'apporter des garanties quant à la sécurité, la disponibilité et la performance des applications.
Nous pouvons répondre à toutes les attentes de nos clients sans surcouche Docker et en tant qu'acteurs rationnels, nous préférons généralement la simplicité, sauf si la complexité est justifiée par des avantages clairs et mesurables.
Cas d'usage pour des tests fonctionnels avancés
False
urn:uuid:f5a06098-7fe3-59cc-97b2-087bcc0973102022-12-08T18:18:02Z2022-12-12T11:05:36ZBearstechcontact@bearstech.com
Les tests fonctionnels avancés font partie des bonnes pratiques de développement : nous vous proposons un cas d'usage étudié sous l'angle des outils Puppeteer et Playwright, dans le cadre d'un workflow d'intégration et déploiement continus.
Quel développeur ou administrateur système n'a pas connu un moment où un client appelle et explique que son application en ligne ne fonctionne pas correctement, alors que quand vous vous y rendez, tout fonctionne bien ? Vous constatez que les pages répondent correctement, dans un délai acceptable, que le serveur n'est pas surchargé, mais vous remarquez dans l'historique que le code a été changé récemment.
Vous vous rendez sur la page qui charge la fonctionnalité qui, au dire du client, ne fonctionne pas correctement: il s'agit d'un formulaire d'authentification (mais pourtant vous avez essayé, et vous avez réussi à vous authentifier). Vous savez qu'un essai n'est pas un test, qu'un test effectue des mesures qu'avec votre essai vous ne pouvez pas réaliser, autrement qu'avec vos yeux et le débogueur du navigateur.
Dans le cas de notre application, il faut savoir qu'elle tournait en production dans un environnement "haute disponibilité", c’est-à-dire que le serveur en front est redondé sur une autre machine, et qu'un équilibreur de charge s'occupe de la répartition du trafic. Nous avions remarqué qu'une portion de code avait été modifiée, et en y regardant de plus près, ce code contenait un bug qui n'était présent que sur l'un des frontaux. Ainsi, parfois l'erreur se produisait, et parfois non.
Les tests de bout en bout (E2E tests) seraient parvenus à déceler l'erreur: dans le cas d'une architecture haute dispo, les 2 frontaux doivent être testés indépendamment l'un de l'autre. Les tests ne doivent pas passer par le loadbalancer, mais par les urls des frontaux directement. Pour un humain, c'est une tâche rébarbative que de jouer un document de recette sur chacun des frontaux, mais pas pour un script.
Et c'est encore mieux si ce script est lancé automatiquement, idéalement après chaque commit qui a un impact sur le fonctionnement de l'application.
Les tests fonctionnels permettent de tester toute la pile système, et il vaut donc mieux les lancer dans un environnement qui reproduit la production (le staging) mais aussi en production (utile dans le cas évoqué dans cet artice).
Il existe de nombreux outils bien connus tels que Selenium pour automatiser des tests (lire notre article sur les tests avec browserless), mais pour cet exemple, nous allons prendre 2 autres librairies Puppeteer et Playwright (qui a le vent en poupe et semble prendre la suite de Puppeteer).
Ces frameworks de tests fonctionnels permettent de tester le rendu d'une page web dans des conditions réelles, proches de celles d'un utlisateur. Ceci permet de contrôler que des éléments sont correctement affichés, de cliquer sur un lien ou un bouton, voir même dans une zone de l'écran ou sur un pixel précis. Cela permet égualement de remplir un formulaire, le poster ou encore de remplir le panier d'un site ecommerce. Ces outils permettent d'analyser le rendu de la page web tant coté backend (serveur) que frontend (navigateur). Il est ainsi tout a fait possible de tester aussi bien des applications PHP/Python/Ruby/Node que des applications Javascript utilisant des frameworks tels que React et VueJs, pour ne citer qu'eux.
Pour notre cas d'usage, les tests doivent s'exécuter dans le cadre d'une chaîne d'intégration continue (CI), mise en place sur runner Gitlab qui instancie un shell. Nous aurons besoin de Docker afin de construire l'image de l'instance NodeJS qui va éxecuter Puppeteer ou Playwright.
Dans les 2 cas, notre CI va jouer un scénario écrit en Javascript, orchestré par la librairie Jest vers un environnement de staging. Les tests fonctionnels doivent être bloquants afin que la CI s'arrête en cas d'erreur, avant de déployer l'application en production.
Puppeteer:
L'écriture du test avec Puppeteer prévoit l'utilisation d'un navigateur headless: nous allons utiliser l'image officielle Docker de Browserless.
Le scénario est simple, nous allons créer le fichier browser.test.js et écrire le test qui vérifie que dans la page du site https://bearstech.com, on trouve bien le mot "Bearstech":
describe("TESTING", () => {
beforeAll(async () => {
if (!process.env.URL) {
throw "ENV key URL is missing";
}
const url = process.env.URL.startsWith("https://")
? process.env.URL
: `https://${process.env.URL}`;
await page.goto(url);
});
it('should display "Bearstech" text on page', async () => {
await expect(page).toMatch("Bearstech");
});
});
Ensuite, pour créer l'image qui va instancier Puppeteer, nous aurons besoin de l'installer (avec Jest) à partir du package.json:
{
"name": "functionnal-tests",
"version": "1.0.0",
"license": "MIT",
"scripts": {
"test": "jest"
},
"devDependencies": {
"jest": "^27.5.1",
"jest-html-reporter": "^3.4.2",
"jest-puppeteer": "^6.1.0",
"puppeteer": "^13.5.1"
}
}
Au même endroit, il nous faudra aussi:
le fichier jest-puppeteer.config.js qui sert à définir les paramètres de connexion au navigateur headless de Browserless
le fichier jest.config.js
Vous mettez ces 4 fichiers dans un répertoire "tests". Ensuite, il vous reste à écrire le Dockerfile qui doit charger une image NodeJS et copier notre dossier "tests" dans l'image. La commande à ajouter dans le Dockerfile est celle qui sera lancée par le conteneur pour exécuter le scénario: CMD ["yarn", "test"]
Pour plus de détail sur la réalisation de ce test, rendez-vous sur la documentation de notre Workflow DevOps
Playwright
C'est un nouveau framework dédié aux tests fonctionnels, maintenu par Microsoft, et qui prend en charge par défaut 3 navigateurs headless: Chromium, Firefox, et WebKit ainsi que plusieurs langages pour écrire les tests: python, node, java et .NET. Playwright propose ses propre images Docker officielles, mais comme chez Bearstech on aime bien comprendre ce que l'on fait, il nous semble plus efficace d'en créer une qui installe juste ce qu'il nous faut.
Jest a sorti un package encore en développement pour piloter playwright. Bien qu'il soit recommandé d'utiliser le "Playwright test-runner" depuis la page github du projet, on prend le risque d'utiliser Jest. Mais pas moyen d'utiliser un autre navigateur headless que ceux qui sont embarqués dans le framework. Les navigateurs sont patchés pour, d'après Playwright, mieux les piloter (ah Microsoft qui adore enfermer ses utilisateurs ...)
Notre scénario sera similaire au précédent, en ajoutant un test sur le click d'un bouton (il vaut mieux préciser ici un timeout à Jest):
[x] example.test.js
// Needs to be higher than the default Playwright timeout
jest.setTimeout(40 * 1000)
describe("Bearstech.com", () => {
it("should have the text like 'Infogérance' in the h1", async () => {
const url = process.env.URL;
await page.goto(url);
await expect(page).toHaveText("h1", "Infogérance")
})
it("should navigate to contact once you click on 'lancer votre projet'", async () => {
const elements = await page.$$('a.button');
await elements[0].click();
expect(page.url()).toMatch(/contact/)
})
})
Les fichiers de configurations sont les suivants:
[x] jest-playwright.config.jsmodule.exports = {
browsers: ["chromium"],
exitOnPageError: false, // GitHub currently throws errors
launchOptions: {
headless: true
}
}
[x] jest.config.js
module.exports = {
verbose: true,
preset: 'jest-playwright-preset'
}
[x] package.json
{
"name": "jest-playwright-example",
"version": "1.0.0",
"license": "MIT",
"scripts": {
"test": "jest"
},
"devDependencies": {
"jest": "^27.5.1",
"jest-circus": "^27.0.0",
"jest-environment-node": "^27.0.0",
"jest-runner": "^27.0.0",
"jest-playwright-preset": "^1.7.2",
"playwright": "^1.22.2"
},
"dependencies": {}
}
Ces 4 fichiers doivent être placés dans un répertoire "tests".
Reste ensuite à écrire notre Dockerfile NodeJS, qui doit procéder à l'installation de Playwright et de Jest, puis indiquer au conteneur quelle commande exécuter à son instanciation:
FROM bearstech/node-dev:16
RUN mkdir /tests
COPY tests/ /tests/
WORKDIR /tests
RUN npm install jest jest-playwright-preset playwright-chromium
RUN npx playwright install
RUN npx playwright install-deps
CMD ["npm", "run", "test"]
Attention, le build est assez long (l'image a une taille de 2Go au final) à cause du navigateur headless.
Au final, il ne reste plus qu'à builder puis à lancer le conteneur:
docker run --rm -it -e URL="https://bearstech.com" --workdir /tests testplaywright:latest
Conclusion
Les tests fonctionnels peuvent vous sauver la mise et vous faire gagner du temps en prouvant la stabilité et en assurant la non régression d'une application. Pour les projets en cours de développement ou les projets matures, les tests font partie du cycle d'exploitation d'une application. Il faut pouvoir se doter d'outils qui permettent de prouver et tracer l'état dans lequel elle se trouve à chaque instant.
Chez Bearstech, nous administrons des applications depuis 15 ans, et nous avons mis au point un workflow qui vous permettra d'intégrer vos tests facilement, et accompagnés d'experts qui vous guideront dans la mise en place de ces outils. N'hésitez pas à revenir vers nous pour obtenir un avis d'expert sur la performance de vos applications, l'infogérance de vos serveurs, ou juste pour de l'aide pour la réalisation de ce guide :smile:
Le changement de mot passe, c'est maintenant avec Vaultwarden
False
urn:uuid:d4c475d8-6e4c-531f-ad94-1378d8b150da2022-10-24T16:25:50Z2022-10-24T16:25:50ZBearstechcontact@bearstech.com
Nos pérégrinations dans l'univers des gestionnaires de mots de passe a trouvé un épilogue avec Vaultwarden, qui coche selon nous toutes les cases de ce que l'on attend de ce type d'outil.
Un peu de suivi sur la question de la gestion des mots de passe au quotidien. Il y a deux ans, nous vous présentions dans cet article les pré-requis et les choix technologiques (Seafile + KeePass) que nous avions retenu. Cette solution est restée fonctionnelle et satisfaisante, mais quelques (presque) nouveautés nous ont convaincu.
Nous vous avions parlé de syspass en mentionnant discrètement un "élégant clone de Bitwarden". Après 6 mois d'utilisation personnelle, il fut proposé au reste de l'équipe. Et après 6 mois d'utilisation collective, on vous en parle.
Il va être compliqué de parler de Vaultwarden sans parler de sa version open source certes, mais surtout commerciale, Bitwarden. Pour faire court et laisser à sa réimplémentation en Rust les lauriers de ses fonctionnalités, reconnaissons principalement l'efficacité de ses clients, qui fonctionnent parfaitement avec Vaultwarden. Que vous soyez sous Firefox, Chromium/Chrome, Android, iOS, vous retrouverez le même client, avec la même interface, sans grand reproche à lui faire (et nous n'avons pas testé les clients desktop, mais vu l'uniformité sur le reste des plateformes, on vous les conseille sans trop prendre de risque).
Passons maintenant à Vaultwarden!
Des fonctionnalités en pagaille
Un point essentiel dans l'acceptation de l'outil, on trouve rapidement dans l'interface l'outil pour importer vos anciens mot de passe avec plus de 50 formats supportés. Outre l'import de notre vieux fichier au format KeePass2, nous avons validé pour vous les imports : Chrome, Password Safe et Passbolt
Comparé à notre précédent système (un unique fichier chiffré avec une passphrase connue de l'ensemble de l'équipe), on a gagné quelques fonctionnalités. Tout d'abord, Vaultwarden nous permet maintenant une gestion des comptes utilisateurs et de groupes ("Organizations"). La gestion de compte permet facilement l'arrivée ou le départ d'utilisateurs, chacun possédant d'ailleurs son "Vault" privé dans lequel il peut stocker ses mots de passe. La gestion de groupes nous a permis d'étendre grandement le partage des mots de passe (pour atteindre le même niveau de satisfaction, on aurait dû faire plusieurs fichiers KeePass avec chacun leur passphrases, une lourdeur qui nous avait jusqu'alors bloqué dans un entre-deux où seulement la part minimum de nos mots de passe se retrouvaient partagés). On retrouve évidemment ce que l'on attend, les différents types d'utilisateurs ("User", "Manager", "Admin", "Owner"), la limitation d'accès à un groupe, voir même uniquement à un ou des dossiers d'un groupe. On notera en particulier la possibilité très appréciable de donner un accès en "Hide Passwords" (l'extension de l'explorateur sera capable de remplir le mot de passe mais l'utilisateur ne le verra pas !), parfait pour un intervenant externe, un stagiaire, ...
Vaultwarden fournit aussi un ensemble de rapports sur vos mots de passe. Vos mots de passe ont-ils (encore) été exposés dans des leaks récentes ou anciennes ? Utilisez-vous (encore) le même mot de passe pour différents comptes ? Avez-vous (encore) des mots de passe que l'on peut considérer comme faibles ? Est-ce que vous n'utilisez (encore) pas de 2FA alors que le site le propose ? Toute une série de questions auxquelles il est difficile de répondre manuellement vu le nombre de mots de passe utilisés. Vaultwarden vous offre ça en deux clics.
On trouve aussi un bon générateur de mot de passe et de passphrase configurable à souhait et appelable directement sur une page de création de compte avec un clic droit.
Et last but not least, l'intégration 2FA. Elle existe théoriquement sous KeePassXC, mais suivant les plateformes elle était accessible... ou non. Ici on la trouve directement dans chaque fiche de mot de passe et on peut même scanner directement via les applications sur téléphone pour renseigner le champ "automagiquement". On pourrait reprocher aux extensions de ne pas détecter le champ TOTP et le remplir automatiquement, mais il semblerait que ces champs soient moins bien uniformisés que ceux des identifiants/mots de passe. Au moment de la rédaction de ce paragraphe, j'ai tout de même découvert que l'extension de mon explorateur mettait dans le presse-papier le TOTP après avoir automatiquement rempli les identifiants, un simple "ctrl-v" à la page suivante suffi donc à remplir le code TOTP!
Enfin un petit bonus (pour utilisateurs paranoïaques) ou malus (pour celui qui oubliera sa passphrase), il n'y a pas de fonction de récupération de compte. D'un côté vous serez responsable de la perte de vos mots de passe, mais de l'autre vous n'avez pas à vous poser la question de la bienveillance ou non de votre admin préféré. Sans votre passphrase, ni récupération ni intrusion possible.
Installation et build de Vaultwarden
Utilisé dans un premier temps avec l'image Docker fournie, l'usage a été pérénisé en automatisant les deux builds bien documentées nécessaires au fonctionnement de Vaultwarden (Vaultwarden, le coeur en Rust, et web-vault, l'interface web). Vous pouvez aussi bien utiliser les releases de l'un comme de l'autre. La configuration Apache et le service Systemd sont triviaux.
Un peu de sucre d'admin parano
Le premier point qui nous a gêné était la perte d'historique par rapport à notre Seafile et donc la possibilité de corriger une erreur humaine. On s'est accordé que le problème n'était pas tant d'identifier le coupable que la possibilité de revenir en arrière. Nous avons donc décidé de rester sur une base de données sqlite3 (avec une petite quinzaine d'utilisateurs pour plus de 1 500 mots de passe stockés, on est à 6M) en se gardant un backup local de la base toutes les 5 minutes sur 24h (on pousse à un peu plus de 600M de backups, bien penser à utiliser la command backup de sqlite). Couplé avec notre système de backup glissant (8 derniers jours, 4 dernières semaines et 12 derniers mois), on s'est donné un niveau de stress minimal sur le risque de perdre des données.
Le deuxième point de tension était sur l'exposition au monde de l'interface de Vaultwarden. Bien que l'équipe de dev de Vaultwarden ait l'air très sérieuse, il nous a semblé difficile de l'être, nous, en utilisant Vaultwarden ouvertement via une URL publique (pour l'interface utilisateur, Vaultwarden propose une interface admin, celle là reste cachée, point). La solution la plus appropriée est bien évidemment le VPN de l'entreprise, ce qui a été mis en place. Mais ce faisant, on perdait son usage sur nos téléphones (et qui veut connecter son iDevice à un réseau sérieux ?). Ce n'était pas vraiment acceptable ni professionnellement, ni dans l'objectif de fournir aux employés ce gestionnaire de mots de passe y compris à usage personnel.
Un compromis a été trouvé en bloquant l'accès public à l'URL publique de notre Vaultwarden aux IP fixes des ours qui en ont (le très simple "Require ip" d'Apache fait le job) et en laissant aux autres l'accès via le VPN.
Pour ceux avec IP fixe, on peut synchroniser ordinateur et téléphone de chez soi, et utiliser le cache lors de déplacement.
Pour ceux sans IP fixe, on peut assez facilement faire un reverse proxy sur un ordinateur ayant accès au VPN pour donner à son téléphone l'accès sur son réseau local, et retomber donc sur le cas précédent (avec un petit jeu pour que votre CA et celui de l'entreprise soit reconnu).
server {
listen 443 ssl http2;
server_name vaultwarden.yourlocalnetwork.lan;
ssl_certificate /path/to/certificate.pem;
ssl_certificate_key /path/to/certificate.key;
location / {
proxy_pass https://vaultwarden.yourenterprisenetwork.lan;
}
}
Bilan
Après 6 mois d'utilisation chez Bearstech et un peu plus d'un an pour ma part, Vaultwarden s'impose comme une solution fiable pour la gestion de vos mots de passe et bénéficie du sérieux commercial de Bitwarden pour ses clients (extensions, apps, ...). L'essayer c'est l'adopter ! Et pour la suite on a promis de tester Cozy Pass, à dans 2 ans.