Optimisation des temps de build
Les temps de build (compilation) sont du temps perdu surtout si on est dans des phases de développement où on relance souvent les mêmes commandes d’installation. Je vais prendre comme exemple le temps de déploiement d’Ansible dans les différents outils que j’utilise dans mon Home Lab Devops.
Ansible est écrit en python qui est soit livré en
package, soit via le repository pypi. Mais voilà pour les packages, ils
sont souvent très en retard sur les versions et pour le repository pypi
seules les codes sources en tar.gz
sont mis à disposition. Il en est de
même pour les dépendances dont openssl
, cffi
et cryptography
.
Temps de build d’une image ansible-lint sans optimisation
Je vais commencer par prendre un temps de build de l’image de container ansible-lint qui intègre Ansible dans ses dépendances à partir d’une image alpine.
Son code source :
Allez on build en prenant soin de purger le cache de docker :
Le build a pris 3 min. Si on prends le temps de regarder les traces on voit
bien que le temps est pris pour compiler des librairies avec gcc
et rust
.
Pourquoi pas précompiler ces packages python au format wheel (stockage des
binaires) et les stocker dans un repository Pypi dans Nexus?
Création des Repository Pypi dans Nexus.
Connectez-vous à Nexus avec le compte admin. Allez dans le menu repository, cliquez sur [create repository].
Choisissez pypi (hosted) donnez un nom et autorisez le redeploy.
Pour éviter de toujours télécharger sur internet tous les packages python,
nous allons aussi déclarer un repo de type (proxy). Donnez-lui un nom et
saisissez l’url https://pypi.org
Pour ne déclarer qu’un seul repo dans la configuration de pip nous allons regrouper les deux repos précédents dans un repository pypi de type (group). Donnez-lui un nom et sélectionnez les deux repo créez précédemment.
Pour séparer les droits admin et en lecture, Nous allons Créer deux
rôles nx-python-admin et nx-python-read avec respectivement
les droits nx-repository-view-pypi-*-*
et nx-repository-view-pypi-*-read
.
Maintenant nous allons créer deux users : un python-admin et un
python-read avec leur rôle respectif. Allez dans le menu security/users
et
cliquez sur [Create Local User].
Compilation et stockage des packages au format Wheel
Je vais utiliser docker pour compiler et stocker les packages whl
et les
envoyer dans Nexus :
Par la suite on pourra ajouter dans le fichier requirements.txt
tous les
packages python que nous utilisons dans tous nos projets.
On peut allez voir le résultat dans Nexus. Browse > mypackages
Modification de l’image ansible-lint pour utiliser Nexus comme cache
Commençons par écrire la configuration pip
que nous allons injecter dans
l’image.
On modifie le Dockerfile pour l’utiliser :
On clean le cache de docker et on relance :
On divise le temps par 6 le temps de build. Cool non ?
Ecriture du projet de construction des packages wheel
Voici donc le projet qui va se charger de remplir le cache Nexus. Je vais
utiliser la parallélisation des jobs dans le CI Gitlab avec matrix
. Je l’ai
documenté dans ce billet
Je vais utiliser deux variables qui vont construire le nom de l’image :
- VERSION : pour la version de python
- DISTRIBUTION : pour mixer les distributions.
Pourquoi plusieurs distributions ? Parce que pour chacun le nom des packages wheel propres à chacune.
J’injecte ma configuration pip.conf
pour charger les packages depuis Nexus.
Donc si les packages wheel sont déjà compilés, ils ne le seront pas à
nouveaux.
Pour installer les packages j’utilise un script qui en fonction de la distribution utilise les bonnes commandes :
Plus loin
On voit que désormais on va passer moins de temps à attendre la compilation des packages python, si on prend soin de stocker les binaires dans Nexus. Il ne faudra pas oublier de déclarer partout l’utilisation de ce repository pypi, par exemple dans le déploiement de rundeck.
On peut reprendre ce principe pour les autres langages et aussi pour stocker des packages apt, yum, …