diff --git a/illustrations/1_tester/README.md b/illustrations/1_tester/README.md new file mode 100644 index 0000000..94faafe --- /dev/null +++ b/illustrations/1_tester/README.md @@ -0,0 +1,7 @@ +(1) Installer `direnv` +(2) Configurer direnv avec votre shell +(3) Relancer le shell et se mettre dans le dossier 1_tester +(4) `direnv allow` +(5) Assurez vous que ça déclenche une "installation" de dépendances +(6) Assurez vous que vous avez `pytest` disponible (e.g. `which pytest`) + diff --git a/illustrations/3_docker/fabriquer-un-docker.nix b/illustrations/3_docker/fabriquer-un-docker.nix new file mode 100644 index 0000000..342b4a1 --- /dev/null +++ b/illustrations/3_docker/fabriquer-un-docker.nix @@ -0,0 +1,10 @@ +let pkgs = import {}; +in + { + nixDocker = pkgs.dockerTools.pullImage { + imageName = "lnl7/nix"; + finalImageTag = "2.0"; + imageDigest = "sha256:632268d5fd9ca87169c65353db99be8b4e2eb41833b626e09688f484222e860f"; + sha256 = "1x00ks05cz89k3wc460i03iyyjr7wlr28krk7znavfy2qx5a0hfd"; +}; +} diff --git a/illustrations/3_docker/redis.nix b/illustrations/3_docker/redis.nix new file mode 100644 index 0000000..a9969f4 --- /dev/null +++ b/illustrations/3_docker/redis.nix @@ -0,0 +1,40 @@ +{ pkgs ? import {} }: + +with pkgs; +let + entrypoint = writeScript "entrypoint.sh" '' + #!${stdenv.shell} + set -e + # allow the container to be started with `--user` + if [ "$1" = "redis-server" -a "$(${coreutils}/bin/id -u)" = "0" ]; then + chown -R redis . + exec ${gosu.bin}/bin/gosu redis "$BASH_SOURCE" "$@" + fi + exec "$@" + ''; +in +dockerTools.buildImage { + name = "redis"; + runAsRoot = '' + #!${stdenv.shell} + ${dockerTools.shadowSetup} + groupadd -r redis + useradd -r -g redis -d /data -M redis + mkdir /data + chown redis:redis /data + ''; + + contents = [ redis ]; + + config = { + Cmd = [ "redis-server" ]; + Entrypoint = [ entrypoint ]; + ExposedPorts = { + "6379/tcp" = {}; + }; + WorkingDir = "/data"; + Volumes = { + "/data" = {}; + }; + }; +} diff --git a/illustrations/3_docker/test-docker-nixos.nix b/illustrations/3_docker/test-docker-nixos.nix new file mode 100644 index 0000000..817d8e1 --- /dev/null +++ b/illustrations/3_docker/test-docker-nixos.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: +{ + # On active Docker. + virtualisation.docker.enable = true; + + docker-containers.database = { + image = "postgres:11-alpine"; + volumes = [ "postgres-data-example:/var/lib/postgresql/data" ]; + environment = { + POSTGRES_PASSWORD = "secret"; + POSTGRES_USER = "test"; + POSTGRES_DATABASE = "esgi"; + }; + }; +} diff --git a/illustrations/4_jenkins/jenkins.nix b/illustrations/4_jenkins/jenkins.nix new file mode 100644 index 0000000..e6cf75c --- /dev/null +++ b/illustrations/4_jenkins/jenkins.nix @@ -0,0 +1,6 @@ +{ pkgs, ... }: +{ + services.jenkins = { + enable = true; + }; +} diff --git a/slides/4_docker.md b/slides/4_docker.md index e69de29..86d8bf5 100644 --- a/slides/4_docker.md +++ b/slides/4_docker.md @@ -0,0 +1,230 @@ +--- +title: Reproducibilité des environnements +author: \textsc{Ryan Lahfa} +theme: metropolis +date: \today{} +lang: fr +--- + +# Docker, la reproducibilité, pourquoi et pourquoi pas ? + +## La reproducibilité + +La reproducibilité c'est un concept clef en tant que DevOps, car elle vous assure de vous tirer du: + +(a) Dependency hell des projets (NPM/Yarn, PyPI/Poetry/Pipfile, Maven, Go, Cargo, la liste ne s'arrête jamais.) +(b) La documentation imprécise, car la documentation devient le "code" +(c) Le code qui pourrit, vous revenez six mois plus tard et une mise à jour casse tout votre code +(d) Les barrières d'adoptions ou de réutilisation: personne ne veut contribuer à un projet compliqué à installer chez soi + +## Reproducibilité forte + +Est ce que votre distribution Linux est reproducible ? Cherchez ! + +> - C'est le cas de Debian (pas intégralement): +> - C'est le cas d'Arch Linux (non plus): +> - C'est le cas de NixOS (à 96,53 % sur l'image minimale à ce jour!): +> - Et sûrement d'autres. + +## Qu'appelle-t-on reproducibilité forte ? + +Est-ce que si vous changez le système de fichier, vos paquets produisent les mêmes octets? Est-ce que si vous changez les ordres des résultats de commandes comme `ls`, cela reste vrai ? Pour mieux comprendre, + +. . . + +Cette reproducibilité est assurée que lorsque vous mettez les moyens, des cgroups^[Mécanisme derrière Docker pour enfermer les processus dans un contexte différent.], occulter des chemins d'accès classiques, s'assurer qu'après non-déterministe, les paquets restent eux les mêmes. + +## Reproducibilité faible + +La reproducibilité faible c'est plutôt celle qui, à OS fixé, à système de fichier fixé, à "configuration" fixé, produit le même paquet sur votre machine. Elle ne transfère pas de machine à machine car elle dépend de paramètres comme la date, l'heure, le réseau ou des choses qui sont éphèmères mais pas méchant. + +. . . + +Docker est faiblement reproducible puisqu'il enferme une forme d'image qui contient des mappings UIDs "hardcodés", mais voyons encore plus d'exemples. + + +## Dockerfile + +``` +# DO NOT USE THIS DOCKERFILE AS AN EXAMPLE, IT IS BROKEN +FROM python:3 + +COPY yourscript.py / + +RUN pip install flask + +CMD [ "python", "./yourscript.py" ] +``` + +Ce n'est pas reproducible, puisque la version de Python varie. Celle de Flask aussi. + +## Mieux + +``` +FROM python:3.7.3-stretch +COPY requirements.txt /tmp/ +RUN pip install -r /tmp/requirements.txt +RUN useradd --create-home appuser +WORKDIR /home/appuser +USER appuser +COPY yourscript.py . +CMD [ "python", "./yourscript.py" ] +``` + +C'est mieux, mais l'utilisateur est crée avec quelle UID ? Quizz surprise. + +## Docker + +La liste est longue. + +> - +> - +> - + +Et on peut en rajouter, encore des couches et des couches. Entre les problèmes de noyau, les problèmes de système hôte, le cross-platform, les conteneurs de piètre qualité, le multi-processus dans un conteneur. + +. . . + +Question (réflexion) pour vous: pourquoi utiliser Docker plutôt qu'un gros binaire statiquement lié et une technologie de sandbox comme firejails, alors que c'est plus simple? + +## Pourquoi Docker c'est si intéressant ? + +On dit souvent que Docker est simple. C'est faux. + +> - Qui sait comment marche Docker ? +> - Qui sait quel système de fichier est utilisé et comment celui ci se comporte sur votre machine ? +> - Qui sait quelle surface d'attaque vous exposez avec Docker ? +> - Qui sait écrire des Dockerfile simples, performants, dans l'esprit de Docker qui ne prennent pas 50GB de votre espace disque ? + +## Pourquoi Docker c'est pas si intéressant ? + +Docker est avant tout une pièce du puzzle dans le travail d'un DevOps, c'est souvent la pièce, mettre son code dans un truc et le donner à une équipe ou l'envoyer sur un cluster. + +Mais vous déplacez le problème en faisant cela, au lieu de maintenir des scripts Bash ou des playbooks de déploiement, vous maintenez un déploiement de cluster Docker et des Dockerfile et des ACL et des, et des, et des. + +## Coût au niveau de l'organisation de Docker ? + +Docker a un coût organisationnel. + +. . . + +Vous sacrifiez une vague simplicité apparente **au départ** (i.e. utile pour des startups, qui ont besoin de faire face très vite à du traffic) pour des coûts de gestion (e.g. utiliser EKS, des clusters déjà préfaits des clouds). + +. . . + +En faisant cela, la question est: pour quel travail concret vous êtes payés ? Pour expliquer à l'entreprise qu'il faut payer EKS et vous payer pour écrire des Dockerfile difficilement maintenable et créer de la complexité apparente ? + +## Bienvenue aux OS magiques: CoreOS, RancherOS + +OK, y a des OS qui résolvent tout, c'est vrai. CoreOS, RancherOS, et plein d'autres entreprises se sont lancés dans la RedHat-ification de Docker pour le rendre plus business-friendly. + +Tout est inclus dedans et ça marche du tonnerre. + +## Adieu aux OS magiques + +Or, RancherOS est mort: + +. . . + +Or, CoreOS est mort (février 2020): (premier commentaire, lisez le.) + +. . . + +Or, rkt est mort aussi, je ne mets pas de lien, vous trouverez facilement. + +. . . + +Quelle solutions réalistes nous reste-t-il ? Peu. + +## Bonjour à Kubernetes + +Bienvenue à Kubernetes, le monde de Google. Une solution d'orchestration avec 100 000 pièces mouvantes, des versions qui cassent des anciennes fonctionnalités, des problèmes de sécurité, des bugs, des difficultés. + +. . . + +Mais, c'est magique ! Vous envoyez des conteneurs, ça scale tout seul, ça utilise le DNS tout seul, c'est vraiment une expérience très agréable. + +## Après… + +> - Qui sait déployer Ceph ? Même le CERN a des gens spécialisés pour le faire. +> - Qui sait lire les logs dans un Kubernetes ? Ah oui, mettre en place un mécanisme de collection de logs… +> - Qui sait débugger et attacher un bon vieux gdb sur Kubernetes ? +> - C'est quoi votre plan si tout votre cluster Kubernetes crash ? Vous faites quoi ? +> - Les backups ? + +Tout le monde expliquera que Kubernetes est difficile, et n'est pas nécessairement fait pour tout le monde, pourtant tout le monde en veut et tout le monde en a, le problème c'est le coût. À qui profite une telle complexité ? Bien évidemment, les clouds publiques, les ISP, les (re)vendeurs et même moi qui fait ce cours… + +## Bonjour mini-Kubernetes + +OK, il y a des Kubernetes tout petit avec l'agilité de Kube sans la souffrance de Kube, découvrez: + +. . . + +Intéressant, mais, à nouveau, c'est spécifique et de niche. Cependant, c'est bon pour démarrer et se déplacer vers une nouvelle chose après. + +## Coucou Dokku + +Mieux, dans 99 % des cas, une boîte veut se déplacer vite avec une équipe jeune en DevOps, alors dans ce cas là, on peut faire du bien avec Docker en utilisant + +. . . + +Essayez le, c'est simple, et c'est comme Heroku à la maison ! + +## Enfin, où va-t-on ? + +Pourquoi je critique autant Docker ? + +> - +> - +> - +> - +> - +> - +> - + +## Conclusion temporaire + +Bref, la liste est sans fin. Mais Docker n'est pas que le mal, c'est un outil intéressant, qui a sa place, mais qu'il faut utiliser avec parcimonie à nouveau. Ne succombez pas à la hype sinon vous serez à la fin de la Gartner hype, avec une compétence ultra niche qui sera inutilisable pour votre prochain poste. Et ça, c'est pas drôle, et c'est l'histoire qui le raconte. + +## Nix et Docker + +En attendant, vous pouvez tout à fait fabriquer des conteneurs Docker depuis Nix, dans le TP que nous allons faire avec `3_docker`. + +. . . + +> - Un exemple bidon +> - Un exemple de Redis +> - Comparez avec l'image du Docker Hub :) (pas de triche, pas d'Alpine sinon vous devez m'expliquer comment une build Alpine marche et quelles sont les risques des Docker alpine et pourquoi il ne faut pas les utiliser :D) + +## Nix et Docker + +``` +> du -hs /nix/store/sd21my0zyaz74f9f8mnf4cj8n7bs9xga-docker-image-redis.tar.gz +17M /nix/store/sd21my0zyaz74f9f8mnf4cj8n7bs9xga-docker-image-redis.tar.gz +``` + +Bon, clairement, y a pas photo, j'ai désinstallé aucun paquet, vous remarquerez, Nix **calcule** exactement ce qu'il faut. + +On peut aller plus loin: et optimiser les caches de Docker avec Nix "intelligemment" (avec de la théorie des graphes très élémentaire). + +. . . + +Quizz surprise: combien de layers maximum Docker peut avoir ? Et à votre avis, Nix ? + +## NixOS et Docker + +En attendant, comment utilise-t-on NixOS et Docker de façon intéressante ? + +. . . + +Vous pouvez gérer vos Docker depuis NixOS aussi, en important `3_docker/nixos-exemple.nix` dans votre `configuration.nix`. + +**Exercice** : Mettre BBB dans un fichier NixOS pour Docker: + +## Enfin, Docker vraiment ? + +À Google, on s'amuse à allier le meilleur des deux mondes: + +. . . + +Plus sérieusement, ne faites pas confiance aveuglément à Docker, ça reste un outil, qui a sa place et son mérite dans des situations précises, ne foncez pas sur un Docker, ne cédez pas à la hype. N'importe qui peut écrire un Dockerfile et faire du Docker, tout le monde ne prend pas nécessairement le temps de réfléchir à la surface, au coût, et à l'intérêt ou non de s'engager sur une stack dockerisée, ne faites pas cette erreur. diff --git a/slides/4_docker.md.handout.pdf b/slides/4_docker.md.handout.pdf new file mode 100644 index 0000000..fb6966d Binary files /dev/null and b/slides/4_docker.md.handout.pdf differ diff --git a/slides/4_docker.md.slides.pdf b/slides/4_docker.md.slides.pdf new file mode 100644 index 0000000..95d8b53 Binary files /dev/null and b/slides/4_docker.md.slides.pdf differ diff --git a/slides/5_ci.md b/slides/5_ci.md new file mode 100644 index 0000000..db0016a --- /dev/null +++ b/slides/5_ci.md @@ -0,0 +1,50 @@ +--- +title: Intégration continue et Nix +author: \textsc{Ryan Lahfa} +theme: metropolis +date: \today{} +lang: fr +--- + +# L'intégration continue + +## Jenkins + +Jenkins est le poids lourd des serveurs d'intégration continue, très utilisé en entreprise, particulièrement dans les contextes où on voit des fonctionnalités spéciales (Docker, KVM, etc.) + +. . . + +En revanche, déployer proprement un Jenkins n'est pas chose aisée, en TP d'application de NixOS, vous trouverez dans `5_jenkins`, un fichier à améliorer pour déployer Jenkins en quelques lignes, pour le reste: + +## Hydra + +Hydra est l'équivalent "NixOS" de Jenkins, plus fonctionnel et actuellement gère l'ensemble des paquets de NixOS, vous pouvez voir sur toutes les constructions en cours, reproducible à travers `curl` et `nix`, avec des mécanismes de sandboxing intéressant. + +. . . + +Par ailleurs, notez que l'écosystème Nix possède nixpkgs, l'un des plus grands référentiels de paquet, en effet: 44 019 paquets, c'est le premier sur deux classements au moins, d'après avec l'AUR et les Gentoo Ports qui suivent à côté. Clairement, Docker n'en a pas autant. Et pourtant, c'est autant d'images Docker de combinaisons de paquets, c'est $2^{44019}$ au moins d'images Docker réalisables, hein. Je vous laisse regarder le nombre. + +## TP: GitHub Actions + +L'objectif c'est de reprendre: pour lui rajouter un GitHub Actions. + +(a) Forker Mangaki Zero +(b) Supprimer le .github/workflow/main.yml et le publish aussi. +(c) Vous pouvez conserver les fichiers Nix. + +Maintenant, il faut écrire le GitHub Action et à la fin, on va rajouter un test si on y arrive, vous n'avez pas à rajouter du caching, c'est bonus, ne faites pas une build matricielle, juste le minimum. + +## Cachix + +À présent, qu'est ce qu'est Cachix ? + +Classiquement, un CI va mettre en cache les artéfacts de construction, mais bien souvent, en raison du fractionnement des gestionnaire de paquets, en raison des piètres systèmes de cache (hein, le système de layer de Docker?), il est très difficile d'avoir un cache intelligent. + +Avec , vous pouvez (si vous êtes open source) gratuitement bénéficier d'un cache magique en quelques secondes, en plus de cela, vous pouvez lui faire confiance (système de clef publique/privée qui signe un cache binaire, protège contre les supply attacks). + +Vous remarquerez que Mangaki Zero utilise Cachix pour stocker les artéfacts de construction, et produit donc des temps de tests complètement incomparable avec des technologies Docker de GitLab CI (trop lente). + +. . . + +Si vous n'êtes toujours pas convaincu, lisez . + diff --git a/slides/5_hautedisponibilite.md b/slides/6_hautedisponibilite.md similarity index 100% rename from slides/5_hautedisponibilite.md rename to slides/6_hautedisponibilite.md diff --git a/slides/6_hautedisponibilite.md.handout.pdf b/slides/6_hautedisponibilite.md.handout.pdf new file mode 100644 index 0000000..9a4a6ae Binary files /dev/null and b/slides/6_hautedisponibilite.md.handout.pdf differ diff --git a/slides/6_hautedisponibilite.md.slides.pdf b/slides/6_hautedisponibilite.md.slides.pdf new file mode 100644 index 0000000..44a81a2 Binary files /dev/null and b/slides/6_hautedisponibilite.md.slides.pdf differ