tuto 2022 5, 6

This commit is contained in:
nemunaire 2021-11-20 00:00:30 +01:00
parent 3d7c03fbbd
commit 2af52619c7
43 changed files with 1073 additions and 431 deletions

View file

@ -25,7 +25,7 @@ steps:
- make -C tutorial/4 - make -C tutorial/4
- mv tutorial/4/tutorial.pdf dist/tutorial-4.pdf - mv tutorial/4/tutorial.pdf dist/tutorial-4.pdf
- make -C tutorial/5 - make -C tutorial/5
- mv tutorial/5/tutorial.pdf dist/tutorial-5.pdf - mv tutorial/5/tutorial-5-srs.pdf tutorial/5/tutorial-5-gistre.pdf dist/
- make -C tutorial/k8s - make -C tutorial/k8s
- mv tutorial/k8s/tutorial.pdf dist/tutorial-6.pdf - mv tutorial/k8s/tutorial.pdf dist/tutorial-6.pdf
- make -C subject/1 - make -C subject/1

View file

@ -256,6 +256,7 @@ Et de ces quelques articles :
* [File-based capabilities](https://lwn.net/Articles/211883/) * [File-based capabilities](https://lwn.net/Articles/211883/)
* [A bid to resurrect Linux capabilities](https://lwn.net/Articles/199004/) * [A bid to resurrect Linux capabilities](https://lwn.net/Articles/199004/)
* [False Boundaries and Arbitrary Code Execution](https://forums.grsecurity.net/viewtopic.php?f=7&t=2522#p10271) * [False Boundaries and Arbitrary Code Execution](https://forums.grsecurity.net/viewtopic.php?f=7&t=2522#p10271)
* [Linux Capabilities on HackTricks](https://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-capabilities)
Pour revenir à Docker, un certain nombre de *capabilities* sont désactivées par Pour revenir à Docker, un certain nombre de *capabilities* sont désactivées par
défaut ; vous pouvez en ajouter et en retirer via les arguments `--cap-add` et défaut ; vous pouvez en ajouter et en retirer via les arguments `--cap-add` et

View file

@ -1,20 +1,47 @@
include ../pandoc-opts.mk include ../pandoc-opts.mk
SOURCES = tutorial.md \ SOURCES_SRS = tutorial-srs.md \
../devops/devops.md \ ../devops/devops.md \
../devops/what.md \ ../devops/what.md \
../devops/tools.md \ ../devops/tools.md \
../devops/tools-gitea.md \
../devops/tools-gitea-ansible.md \
../devops/tools-gitea-end.md \
../devops/tools-drone.md \
../devops/tools-drone-ansible.md \
../devops/tools-drone-oauth.md \
../devops/tools-drone-runner.md \
../devops/tools-drone-runner-ansible.md \
../devops/tools-end.md \
../devops/ci.md \ ../devops/ci.md \
../devops/publish-docker.md \ ../devops/publish-docker.md \
../docker-internals/oci.md \ rendu-srs.md
../docker-internals/registry.md \
rendu.md SOURCES_GISTRE = tutorial-gistre.md \
../devops/what-gistre.md \
../devops/what-gistre-see-srs.md \
../devops/tools.md \
../devops/tools-gitea.md \
../devops/tools-gitea-cmd.md \
../devops/tools-gitea-end.md \
../devops/tools-drone.md \
../devops/tools-drone-cmd.md \
../devops/tools-drone-oauth.md \
../devops/tools-drone-runner.md \
../devops/tools-drone-runner-cmd.md \
../devops/tools-end.md \
../devops/ci-gistre.md \
../devops/run-gistre.md \
rendu-gistre.md
all: tutorial.pdf all: tutorial-5-srs.pdf tutorial-5-gistre.pdf
tutorial.pdf: ${SOURCES} tutorial-5-srs.pdf: ${SOURCES_SRS}
pandoc ${PANDOCOPTS} -o $@ $+
tutorial-5-gistre.pdf: ${SOURCES_GISTRE}
pandoc ${PANDOCOPTS} -o $@ $+ pandoc ${PANDOCOPTS} -o $@ $+
clean:: clean::
rm tutorial.pdf rm tutorial-5-srs.pdf tutorial-5-gistre.pdf

View file

@ -10,11 +10,15 @@ abstract: |
\vspace{1em} \vspace{1em}
À la demande de Nabih, ce TP a été raccourci
\vspace{1em}
Tous les éléments de ce TP (exercices et projet) sont à rendre à Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le **mercredi 4 novembre 2020 à 12 h <virli@nemunai.re> au plus tard le **jeudi 18 novembre 2021 à 23 h
42**. Consultez la dernière section de chaque partie pour plus d'informations 42**. Consultez la dernière section de chaque partie pour plus d'informations
sur les éléments à rendre. Et n'oubliez pas de répondre aux [questions de sur les éléments à rendre. Et n'oubliez pas de répondre aux [questions de
cours](https://virli.nemunai.re/quiz/5). cours](https://virli.nemunai.re/quiz/13).
En tant que personnes sensibilisées à la sécurité des échanges électroniques, En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à

View file

@ -0,0 +1,121 @@
\newpage
## Intégration continue
::::: {.question}
La mise en place de l'environnement de CI/CD n'est pas le cœur de la version
GISTRE du TP (elle l'est pour les SRS). Aussi cette partie est aussi guidée que
possible et toutes les commandes vous sont données pour réduire les frictions
de mise en œuvre.
Mais comme indiqué dans l'introduction au DevOps, vous serez susceptibles
d'arriver dans une entreprise qui pratique correctement le DevOps. Dans cette
situation, l'ensemble des développeurs et des administrateurs système (les
*Ops*), doivent faire en sorte que leurs travaux soient intégrés dans les
outils d'intégration continue. Les *Ops* vont évidemment plutôt gérer la mise
en place des outils, proprement, c'est ce que demande de faire le TP SRS. Pour
vous il s'agit plus de savoir interagir avec, en sachant manipuler la
configuration des dépôts.
:::::
Une fois Gitea et Drone installés et configurés, nous allons pouvoir rentrer
dans le vif du sujet : faire de l'intégration continue sur notre premier projet !
### Créez un dépôt pour `linky2influx`
Après avoir créé (ou migré pour les plus malins !) le dépôt
[`linky2influx`](https://git.nemunai.re/nemunaire/linky2influx) dans Drone,
synchronisez les dépôts, puis activez la surveillance de `linky2influx`.
Nous allons devoir rédiger un fichier `.drone.yml`, que l'on placera à la racine
du dépôt. C'est ce fichier qui sera traité par DroneCI pour savoir comment
compiler et tester le projet.
::::: {.warning}
Un fichier `.drone.yml` existe déjà à la racine du dépôt. Celui-ci pourra vous
servir d'inspiration, mais il ne fonctionnera pas directement sur votre
installation.
**Vous rencontrerez des problèmes inattendus si vous utilisez le fichier
`.drone.yml` du dépôt.** Vous **DEVEZ** partir d'un fichier vide et suivre la
documentation pour obtenir un `.drone.yml` fonctionnel.
:::::
### Définir les étapes d'intégration
Toutes les informations nécessaires à l'écriture du fichier `.drone.yml` se
trouvent dans [l'excellente documentation du
projet](https://docs.drone.io/pipeline/docker/examples/languages/golang/).
Les étapes sont sensiblement les mêmes que dans le `Dockerfile` présent sur le
dépôt.
Committons puis poussons notre travail. Dès qu'il sera reçu par Gitea, nous
devrions voir l'interface de Drone lancer les étapes décrites dans le fichier.
::::: {.warning}
**IMPORTANT :** si vous avez l'impression que ça ne marche pas et que vous avez
réutilisé le fichier présent sur le dépôt au lieu de partir de l'exemple donné
dans la documentation, **commencez en partant de l'exemple de la
documentation** ! Le fichier présent sur le dépôt **ne fonctionnera pas** dans
votre situation !
:::::
![Drone en action](../devops/drone-run-linky.png){height=7.5cm}
Lorsqu'apparaît enfin la ligne `git.nemunai.re/linky2influx`, le projet est compilé !
### Publier le binaire correspondant aux tags/jalons
Nous savons maintenant que notre projet compile bien dans un environnement
différent de celui du développeur ! Néanmoins, le binaire produit est perdu dès
lors que la compilation est terminée, car nous n'en faisons rien.
Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire
au sein de la liste des fichiers téléchargeable aux côtés des tags.
Vous aurez sans doute besoin de :
- <https://docs.drone.io/pipeline/conditions/>
- <http://plugins.drone.io/drone-plugins/drone-gitea-release/>
Attention à ne pas stocker votre clef d'API dans le fichier YAML !
![Binaire publié automatiquement sur Gitea](../devops/tag-released.png){height=8cm}
::::: {.more}
Lorsque l'on est plusieurs à travailler sur le projet ou pour accroître la
sécurité, il convient de créer, un compte *bot* qui sera responsable de la
création des *releases*. Ce sera donc sa clef d'API que l'on indiquera dans
l'interface de Drone.
:::::
### Publier pour plusieurs architectures ?
Le compilateur Go est fourni avec l'ensemble des backends des différentes
architectures matérielles qu'il supporte, nous pouvons donc aisément faire de
la compilation croisée pour d'autres architectures.
Essayons maintenant de compiler `linky2influx` pour plusieurs architectures afin de
vérifier que cela fonctionne bien !
Un exemple est donné tout en haut de cette page :
<https://docs.drone.io/pipeline/environment/syntax/>.
En faisant varier `$GOARCH` en `mips`, `powerpc`, ... nous pouvons générer les
binaires correspondant à chaque architecture et système.
Ajoutez à votre fichier `.drone.yml` les deux architectures pour lesquelles les
Raspberry Pi d'Électropcool sont compatibles. Nommez les fichiers selon
l'architecture que pourrait renvoyer `uname -m`, cela pourrait nous simplifier la tâche ensuite...
\
Une fois taggé et poussé sur notre dépôt, nous aurons une version exécutable
utilisable à la fois sur notre machine de développement, mais aussi sur les
Raspberry Pi déjà déployées dans les bâtiments. Nous avons atteint l'un des
deux objectifs qui nous était demandé. Tâchons maintenant de trouver un

View file

@ -1,59 +1,66 @@
\newpage \newpage
Intégration continue ## Intégration continue
====================
Une fois Gitea et Drone installés et configurés, nous allons pouvoir rentré Une fois Gitea et Drone installés et configurés, nous allons pouvoir rentrer
dans le vif du sujet : faire de l'intégration continue sur notre premier projet ! dans le vif du sujet : faire de l'intégration continue sur notre premier projet !
## `youp0m`
### Créez un dépôt pour `youp0m` ### Créez un dépôt pour `youp0m`
Reprenez les travaux réalisés au TP précédent. Nous allons notamment avoir Reprenez les travaux réalisés au TP précédent. Nous allons notamment avoir
besoin du `Dockerfile` dans la section suivante. besoin du `Dockerfile` dans la section suivante.
Après avoir créé (ou migré pour les plus malins !) le dépôt Après avoir créé (ou migré pour les plus malins !) le dépôt
[`youp0m`](https://gitea.nemunai.re/nemunaire/youp0m), dans Drone, [`youp0m`](https://git.nemunai.re/nemunaire/youp0m) dans Drone,
synchronisez les dépôts, puis activez la surveillance de `youp0m`. synchronisez les dépôts, puis activez la surveillance de `youp0m`.
Vous allez devoir rédiger un fichier `.drone.yml`, que l'on placera à la Nous allons devoir rédiger un fichier `.drone.yml`, que l'on placera à la racine
racine du dépôt (celui qui existe déjà dans le dépôt pourra servir du dépôt. C'est ce fichier qui sera traité par DroneCI pour savoir comment
d'inspiration, mais il ne fonctionnera pas directement sur votre
installation). C'est ce fichier qui sera traité par DroneCI pour savoir comment
compiler et tester le projet. compiler et tester le projet.
::::: {.warning}
Un fichier `.drone.yml` existe déjà à la racine du dépôt. Celui-ci pourra vous
servir d'inspiration, mais il ne fonctionnera pas directement sur votre
installation.
**Vous rencontrerez des problèmes inattendus si vous utilisez le fichier
`.drone.yml` du dépôt.** Vous **DEVEZ** partir d'un fichier vide et suivre la
documentation pour obtenir un `.drone.yml` fonctionnel.
:::::
### Définir les étapes d'intégration ### Définir les étapes d'intégration
Toutes les informations nécessaire à l'écriture du fichier `.drone.yml` se Toutes les informations nécessaires à l'écriture du fichier `.drone.yml` se
trouvent dans [l'excellente documentation du trouvent dans [l'excellente documentation du
projet](https://docs.drone.io/pipeline/docker/examples/languages/golang/). projet](https://docs.drone.io/pipeline/docker/examples/languages/golang/).
Les étapes sont sensiblement les mêmes que dans le `Dockerfile` que vous avez Les étapes sont sensiblement les mêmes que dans le `Dockerfile` que nous avons
écrit lors du TP précédent. écrit lors du TP précédent.
Comittez puis pousser votre travail, dès qu'il sera reçu par Gitea, vous Committons puis poussons notre travail. Dès qu'il sera reçu par Gitea, nous
devriez voir l'interface de Drone lancer les étapes décrites dans le fichier. devrions voir l'interface de Drone lancer les étapes décrites dans le fichier.
![Drone en action](../devops/drone-run.png){height=6cm}
::::: {.warning}
**IMPORTANT :** si vous avez l'impression que ça ne marche pas et que vous avez **IMPORTANT :** si vous avez l'impression que ça ne marche pas et que vous avez
réutilisé le fichier présent sur le dépôt au lieu de partir de l'exemple donné réutilisé le fichier présent sur le dépôt au lieu de partir de l'exemple donné
dans la documentation, **commencez en partant de l'exemple de la dans la documentation, **commencez en partant de l'exemple de la
documentation** ! Le fichier présent sur le dépôt ne fonctionnera pas dans documentation** ! Le fichier présent sur le dépôt **ne fonctionnera pas** dans
votre situation ! votre situation !
:::::
![Drone en action](../devops/drone-run.png){height=8cm}
Lorsqu'apparaît enfin la ligne `git.nemunai.re/youp0m`, le projet est compilé ! Lorsqu'apparaît enfin la ligne `git.nemunai.re/youp0m`, le projet est compilé !
### Inspection qualité ### Inspection qualité
Nous n'avons pas encore de test à proprement parlé. Nous allons utiliser Nous n'avons pas encore de test à proprement parler. Nous allons utiliser
[Sonarqube](https://www.sonarqube.org/) pour faire une revue qualité du code ! [Sonarqube](https://www.sonarqube.org/) pour faire une revue qualité du code !
Tout d'abord, il faut lancer le conteneur Sonarqube (pensez à l'ajouter à votre Tout d'abord, il faut lancer le conteneur Sonarqube (SRS, pensez à l'ajouter à
playbook !) : votre playbook !) :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -83,7 +90,7 @@ différent de celui du développeur ! Néanmoins, le binaire produit est perdu d
lors que la compilation est terminée, car nous n'en faisons rien. lors que la compilation est terminée, car nous n'en faisons rien.
Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire Ajoutons donc une nouvelle règle à notre `.droneci.yml` pour placer le binaire
au sein de la liste des fichiers téléchargeable aux côtés des tags. au sein de la liste des fichiers téléchargeables aux côtés des tags.
Vous aurez sans doute besoin de : Vous aurez sans doute besoin de :
@ -94,25 +101,9 @@ Attention à ne pas stocker votre clef d'API dans le fichier YAML !
![Binaire publié automatiquement sur Gitea](../devops/tag-released.png){height=8cm} ![Binaire publié automatiquement sur Gitea](../devops/tag-released.png){height=8cm}
::::: {.more}
Lorsque l'on est plusieurs à travailler sur le projet ou pour accroître la Lorsque l'on est plusieurs à travailler sur le projet ou pour accroître la
sécurité, il convient de créer, un compte *bot* qui sera responsable de la sécurité, il convient de créer, un compte *bot* qui sera responsable de la
création des *releases*. Ce sera donc sa clef d'API que l'on indiquera dans création des *releases*. Ce sera donc sa clef d'API que l'on indiquera dans
l'interface de Drone. l'interface de Drone.
:::::
### Publier pour plusieurs architectures ?
Le compilateur Go est fourni avec l'ensemble des backends des différentes
architectures matérielles qu'il supporte, nous pouvons donc aisément faire de
la compilation croisée pour d'autres architectures.
Essayons maintenant de compiler `youp0m` pour plusieurs architecture afin de
vérifier que cela fonctionne bien !
Un exemple est donné tout en haut de cette page :
<https://docs.drone.io/pipeline/environment/syntax/>.
En faisant varier `$GOARCH` en `arm`, `arm64`, `mips`, ... nous pouvons générer
les binaires correspondant à chaque architecture et système.
Ajoutez au moins 2 autres architectures à votre fichier `.drone.yml`.

View file

@ -4,7 +4,7 @@ Le mouvement DevOps
=================== ===================
Jusqu'à récemment, et encore dans de nombreuses entreprises, les développeurs Jusqu'à récemment, et encore dans de nombreuses entreprises, les développeurs
et les administrateurs systèmes faisaient partis de deux équipes différentes : et les administrateurs système faisaient partie de deux équipes différentes :
les uns développant sur leurs machines avec les dernières bibliothèques, les uns développant sur leurs machines avec les dernières bibliothèques,
utilisant les derniers frameworks à la mode, sans se préoccuper de la sécurité utilisant les derniers frameworks à la mode, sans se préoccuper de la sécurité
(ils travaillent en `root` ou avec `sudo` ;)), tandis que les autres tentaient (ils travaillent en `root` ou avec `sudo` ;)), tandis que les autres tentaient
@ -17,17 +17,17 @@ utilisé sur un système à jour, et qu'il ne tourne pas en `root`), qu'à la
mémoire, il ne faut pas que les autres services présents sur la même machine en mémoire, il ne faut pas que les autres services présents sur la même machine en
pâtissent). pâtissent).
Une guerre faisait donc rage entre les développeurs qui ne comprennaient pas Une guerre faisait donc rage entre les développeurs qui ne comprenaient pas que
que les administrateurs système ne pouvaient pas maintenir autant de version les administrateurs système ne pouvaient pas maintenir autant de versions d'une
d'une bibliothèque qu'il y avait de service : par exemple dans le cas de bibliothèque qu'il y avait de services : par exemple dans le cas de plusieurs
plusieurs services en PHP, on pouvait leur demander de déployer des services en PHP, on pouvait leur demander de déployer des applications
applications utilisant la version 5.1, et la 5.2 pour d'autres, ... lorsqu'il y utilisant la version 5.6, et la 7.2 pour d'autres, ... lorsqu'il y avait des
avait des incompatibilités mineures et plus personne pour s'occuper de la incompatibilités mineures et plus personne pour s'occuper de la maintenance
maintenance d'un vieux service toujours utilisé. d'un vieux service toujours utilisé.
Le même principe est aussi valable pour Python, Ruby, ... : les développeurs Le même principe est aussi valable pour Python, Ruby, ... : les développeurs
ont toujours eu tendance à vouloir utiliser les dernières améliorations d'un ont toujours eu tendance à vouloir utiliser les dernières améliorations d'un
langage, mais les administrateurs systèmes n'ont alors pas de paquets stables langage, mais les administrateurs système n'ont alors pas de paquets stables
dans la distribution. En effet, les distributions stables telles que Debian, dans la distribution. En effet, les distributions stables telles que Debian,
RedHat ou CentOS ont des cycles de vie assez long et se concentrent plus sur la RedHat ou CentOS ont des cycles de vie assez long et se concentrent plus sur la
stabilité.\ stabilité.\
@ -58,10 +58,11 @@ sont chargées de développer la fiabilité des systèmes d'information de
production. Ce sont les équipes SRE, pour Site Reliability Engineering. On production. Ce sont les équipes SRE, pour Site Reliability Engineering. On
confie alors complètement la responsabilité de l'environnement de production confie alors complètement la responsabilité de l'environnement de production
aux développeurs qui sont chargés de l'automatiser. Au delà de l'automatisation aux développeurs qui sont chargés de l'automatiser. Au delà de l'automatisation
des déploiements des services, il s'agit ici de développer des mécanismes des déploiements de services, il s'agit ici de développer des mécanismes
permettant au système de réagir face aux situations telles que les montées en permettant au système de réagir face aux situations telles que les montées en
charges, les pannes, ... charges, les pannes, ...
::::: {.warning}
Attention par contre aux entreprises qui recrutent un profil DevOps, car cela a Attention par contre aux entreprises qui recrutent un profil DevOps, car cela a
autant de sens que recruter un développeur Scrum ou un développeur cycle en V : autant de sens que recruter un développeur Scrum ou un développeur cycle en V :
DevOps est une méthodologie. Les entreprises qui recrutent un DevOps DevOps est une méthodologie. Les entreprises qui recrutent un DevOps
@ -71,6 +72,7 @@ généralement assez difficile à vivre. Alors qu'au contraire, la mouvance DevO
doit être prise au sérieux par l'ensemble des développeurs. Lors d'un entretien doit être prise au sérieux par l'ensemble des développeurs. Lors d'un entretien
d'embauche pour ce genre de poste, assurez-vous bien de ne pas être le seul à d'embauche pour ce genre de poste, assurez-vous bien de ne pas être le seul à
faire du DevOps. faire du DevOps.
:::::
## Intégration continue ## Intégration continue
@ -92,7 +94,7 @@ vers un dossier accessible. Cela permet ainsi aux développeurs de voir les
problèmes et de pousser les analyses avec leurs propres outils. problèmes et de pousser les analyses avec leurs propres outils.
Sans déploiement continu (la section suivante), c'est également ces produits de Sans déploiement continu (la section suivante), c'est également ces produits de
compilation que les administrateurs systèmes vont déployer sans peine, lorsque compilation que les administrateurs système vont déployer sans peine, lorsque
les développeurs considéreront avoir atteint un jalon, une version stable. les développeurs considéreront avoir atteint un jalon, une version stable.
@ -100,7 +102,7 @@ les développeurs considéreront avoir atteint un jalon, une version stable.
Une fois tous les tests passés et les objets produits (on parle d'*artifact* ou Une fois tous les tests passés et les objets produits (on parle d'*artifact* ou
d'*assets*), il est possible de déclencher un déploiement : il s'agit de rendre d'*assets*), il est possible de déclencher un déploiement : il s'agit de rendre
accessible aux utilisateurs finaux le services ou les objets. accessible aux utilisateurs finaux le service ou les objets.
Dans le cas d'un programme à télécharger Dans le cas d'un programme à télécharger
([Python](https://buildbot.python.org/all/#/), VLC, ([Python](https://buildbot.python.org/all/#/), VLC,
@ -111,17 +113,19 @@ vers la dernière version (pour que les utilisateurs aient la notifications).
Ou bien dans le cas d'un service en ligne (GitHub, Netflix, GMail, ...), il Ou bien dans le cas d'un service en ligne (GitHub, Netflix, GMail, ...), il
s'agira de mettre à jour le service. s'agira de mettre à jour le service.
Parfois les deux seront à faire : à la fois publier un paquet ou un conteneur Parfois les deux seront à faire : à la fois publier un paquet ou un
et mettre à jour un service en ligne : [le serveur conteneur et mettre à jour un service en ligne : par exemple, [le
Synapse](https://buildkite.com/matrix-dot-org/synapse) du protocole de serveur Synapse](https://buildkite.com/matrix-dot-org/synapse) du
messagerie Matrix ou encore protocole de messagerie Matrix ou encore
[Gitlab](https://gitlab.com/gitlab-org/gitlab/-/pipelines).\ [Gitlab](https://gitlab.com/gitlab-org/gitlab/-/pipelines), tous deux
publient des paquets à destination de leurs communautés, et mettent à
jour leur service en ligne.\
Il existe pour cela de très nombreuses stratégies : lorsque l'on n'a pas Il existe pour cela de très nombreuses stratégies : lorsque l'on n'a pas
beaucoup de trafic ni beaucoup de machines, on peut simplement éteindre beaucoup de trafic ni beaucoup de machines, on peut simplement éteindre
l'ancien service et démarrer le nouveau, si ça prend quelques millisecondes en l'ancien service et démarrer le nouveau, si ça prend quelques millisecondes en
étant automatisé, cela peut être suffisant compte tenu du faible étant automatisé, cela peut être suffisant compte tenu du faible
traffic. trafic.
Lorsque l'on a un trafic élevé, de nombreux clients et donc que le service est Lorsque l'on a un trafic élevé, de nombreux clients et donc que le service est
réparti sur plusieurs machines, on ne peut pas se contenter de tout éteindre et réparti sur plusieurs machines, on ne peut pas se contenter de tout éteindre et
@ -143,8 +147,8 @@ surveiller afin d'être le plus proactif possible dans la résolution des
problèmes. La pire situation est celle dans laquelle c'est un utilisateur qui problèmes. La pire situation est celle dans laquelle c'est un utilisateur qui
nous informe d'un problème... (sur Twitter !?) nous informe d'un problème... (sur Twitter !?)
Nous avons réalisé durant le précédent TP, une partie collecte de métriques, Nous avons réalisé précédemment une partie collecte de métriques, avec nos
avec nos conteneurs TICK. Nous n'allons donc pas nous en occuper aujourd'hui. conteneurs TICK. Nous n'allons donc pas nous en occuper aujourd'hui.
\ \
Notez tout de même qu'il y a deux grandes catégories de logiciels de Notez tout de même qu'il y a deux grandes catégories de logiciels de
@ -167,8 +171,8 @@ Kapacitor, qui permet après avoir analysé les données, d'alerter en fonction
d'une évolution. d'une évolution.
L'instrumentation d'une application est une bonne manière de faire remonter des L'instrumentation d'une application est une bonne manière de faire remonter des
métrique (combien de clients actuellement connectés, combien de métriques (combien de clients actuellement connectés, combien de
messages/transactions traités, ...). Ce sont autant d'information que l'on peut messages/transactions traités, ...). Ce sont autant d'informations que l'on peut
faire remonter dans sa base de données de métriques. faire remonter dans sa base de données de métriques.
\ \
@ -185,12 +189,11 @@ un service distribuable, qui est proche de la surcharge, acheter de l'espace de
stockage supplémentaire auprès du fournisseur, ... stockage supplémentaire auprès du fournisseur, ...
\ \
Enfin, citons dans cette partie le [Chaos Enfin, citons le [Chaos Monkey](https://fr.wikipedia.org/wiki/Chaos_Monkey),
Monkey](https://fr.wikipedia.org/wiki/Chaos_Monkey), conçu par Netflix, qui est conçu par Netflix, qui est un programme qui va casser de manière aléatoire des
un programme qui va casser de manière aléatoire des éléments de l'environnement éléments de l'environnement de production. Le but est de provoquer sciemment
de production. Le but est de provoquer sciemment des pannes, des latences, des pannes, des latences, ... à n'importe quel niveau du produit, afin d'en
... à n'importe quel niveau du produit, afin d'en tester (brulatement certes) tester (brulatement certes) sa résilience. Cela oblige les développeurs, les
sa résilience. Cela oblige les développeurs, les opérationnels et les opérationnels et les architectes à concevoir des services hautement tolérant
architectes à concevoir des services hautement tolérant aux pannes, ce qui fait aux pannes, ce qui fait que le jour où une véritable panne survient, elle n'a
que le jour où une véritable panne survient, elle n'a aucun impact sur la aucun impact sur la production (enfin on espère !).
production (enfin on espère !).

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View file

@ -10,16 +10,18 @@ jour ensuite (par exemple, dans le cas de Firefox ou de LibreOffice, une fois
testés, les paquets sont envoyés sur le serveur d'où ils seront distribués ; il testés, les paquets sont envoyés sur le serveur d'où ils seront distribués ; il
n'y a pas de service/docker à relancer). n'y a pas de service/docker à relancer).
À l'inverse, `youp0m` est à la fois un programme que l'on peut télécharger et À l'inverse, `youp0m` ou `linky2influx` sont à la fois des programmes que l'on
un service un ligne qu'il faut déployer pour mettre à jour facilement. Pour peut télécharger et des services qu'il faut déployer pour les mettre à
simplifier le déploiement, nous utilisons des images Docker. Il faut cependant jour. Pour simplifier le déploiement, nous utilisons des images Docker. Il faut
les générer ... cependant les générer ...
## Mise en place du registre ## Mise en place du registre
*Si vous avez choisi Gitlab, vous pouvez utiliser directement le registre ::::: {.more}
Docker intégré. Si vous utilisez Gitea, continuez cette section.* Si vous avez choisi Gitlab, vous pouvez utiliser directement le registre
Docker intégré. Si vous utilisez Gitea, continuez cette section.
:::::
Afin de disposer de notre propre registre Docker sur lequel publier nos images, Afin de disposer de notre propre registre Docker sur lequel publier nos images,
nous allons utiliser l'image de registre fournie par Docker. Elle se lance nous allons utiliser l'image de registre fournie par Docker. Elle se lance
@ -31,10 +33,11 @@ docker run --rm -d --name registry --network droneci -p 5000:5000 registry:2
``` ```
</div> </div>
Vous trouverez davantage d'informations Vous trouverez davantage d'informations pour le déploiement
[ici](https://docs.docker.com/registry/deploying/). [ici](https://docs.docker.com/registry/deploying/).
Vous pouvez tester son bon fonctionnement avec la commande suivante : Nous pouvons tester le bon fonctionnement de notre registre avec la commande
suivante :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -67,12 +70,14 @@ docker run --rm -p 8080:8080 localhost:5000/youp0m
``` ```
</div> </div>
::::: {.more}
On notera que ceci est possible exclusivement parce que le registre On notera que ceci est possible exclusivement parce que le registre
`localhost:5000` est considéré non-sûr par défaut. C'est à dire qu'il n'a pas `localhost:5000` est considéré non-sûr par défaut. C'est à dire qu'il n'a pas
besoin de certificat TLS sur sa connexion HTTP pour être utilisé.\ besoin de certificat TLS sur sa connexion HTTP pour être utilisé.\
Si on avait dû utiliser un autre nom de domaine, il aurait fallu Si on avait dû utiliser un autre nom de domaine, il aurait fallu
[l'ajouter à la liste des [l'ajouter à la liste des
`insecure-registries`](https://docs.docker.com/registry/insecure/). `insecure-registries`](https://docs.docker.com/registry/insecure/).
:::::
## Suite du déploiement ## Suite du déploiement
@ -80,9 +85,9 @@ Si on avait dû utiliser un autre nom de domaine, il aurait fallu
Pour aujourd'hui, nous en resterons là pour le déploiement, car nous n'avons Pour aujourd'hui, nous en resterons là pour le déploiement, car nous n'avons
pas d'environnement de production sur lequel déployer notre service. pas d'environnement de production sur lequel déployer notre service.
Vous pouvez néamnoins tester les plugins Vous pouvez néanmoins tester les plugins
[`scp`](http://plugins.drone.io/appleboy/drone-scp/) ou [`scp`](http://plugins.drone.io/appleboy/drone-scp/) ou
[`ansible`](http://plugins.drone.io/drone-plugins/drone-ansible/), si vous avez [`ansible`](http://plugins.drone.io/drone-plugins/drone-ansible/) si vous avez
une machine virtuelle avec une connexion SSH. N'hésitez pas à l'ajouter à votre une machine virtuelle avec une connexion SSH. N'hésitez pas à l'ajouter à votre
`.droneci.yml`. `.droneci.yml`.

View file

@ -0,0 +1,194 @@
\newpage
## Lancement du module sur la machine cible
Mettons de côté le déploiement continu, pour nous concentrer sur la manière
dont nous allons pouvoir exécuter notre module de relevé de compteur Linky.
\
Le binaire de notre module se lance de la manière suivante :
<div lang="en-US">
```shell
42sh$ ./linky2influx --influx-host localhost --influx-username myuser \
--influx-password mypasswd /dev/ttyEnedis0
# or
42sh$ INFLUXDB_HOST=localhost INFLUXDB_USERNAME=myuser INFLUXDB_PASSWORD=mypasswd \
./linky2influx /dev/ttyEnedis0
```
</div>
`/dev/ttyEnedis0` est le périphérique correspondant à notre liaison série
vers le compteur. On considère qu'une règle `udev` a été écrite pour créer
l'entrée correspondante dans `/dev`.
\
L'objectif est d'établir la méthode qui sera la plus efficace pour
Électropcool, car elle devra sans doute demander à chacune des équipes de
réaliser le packaging des modules qu'elles maintiennent. Il faut pour cela en
tester plusieurs. Certaines peuvent sans doute déjà être éliminées car
inadaptés, c'est à vous de déterminer parmi les technologies d'empacketages
proposées, et celles que vous connaissez, lesquelles vous écartez d'emblée,
lesquelles vous souhaitez garder pour explorer davantage, et enfin laquelle
retient votre attention.
Vous êtes tenu de retenir au minimum 2 solutions distinctes (on considère que
les technologies listées sur la même lignes sont similaires).
La liste de technologies proposées est à la suivante :
- conteneur Docker ou podman,
- conteneur LXC (avec base alpine ou nu),
- conteneur OCI via runc,
- service systemd ou systemd-nspawn,
- packages `.ipk` via Yocto/Bitbake,
- package Nix,
- paquet Snap, FlatPack ou AppImage,
- [k3s](https://k3s.io/),
- ...
Les sections suivantes vous donneront une idée des éléments attendus pour chacun.
### Docker, podman, ...
Nous avons déjà un `Dockerfile` dans notre dépôt, vous avez juste à écrire un
script shell permettant de lancer le module, il doit bien évidemment avoir
accès au périphérique correspondant au compteur.
<div lang="en-US">
```
login_x-TP5/docker/run.sh
```
</div>
### Conteneur LXC
LXC peut s'utiliser de multiple manière différentes, y compris avec des images
OCI. Choisissez la méthode qui vous semble la plus appropriée, il est attendu
au moins un script pour lancer notre conteneur, s'il est différent d'un
<div lang="en-US">
```shell
42sh# lxc-create --template linky2influx --name l2i && lxc-start -n l2i`.
```
</div>
<div lang="en-US">
```
login_x-TP5/lxc/run.sh
```
</div>
En complément, vous pouvez inclure au dépôt de `linky2influx` le modèle
permettant de créer le conteneur LXC, ainsi qu'un exemple de configuration :
<div lang="en-US">
```
login_x-TP5/linky2influx/lxc-scripts/template.sh
login_x-TP5/linky2influx/lxc-scripts/sample.config
```
</div>
### Conteneur OCI via `runc`
`runc` a besoin d'un fichier `config.json` et éventuellement `runtime.json`. La
ligne de commande pour lancer `runc` n'est pas demandée, l'image OCI résultant
du `Dockerfile` sera utilisée et présente pour l'exécution.
### Service systemd ou systemd-nspawn
Le service `systemd` est redondant avec un système Yocto contenant `systemd`,
vous pourriez écrire le script `systemd` et profiter de l'utiliser dans votre
recette `bitbake`.
Un service basé sur `nspawn` peut par contre être potentiellement intéressant,
il pourra être intégré au dépôt :
<div lang="en-US">
```
login_x-TP5/linky2influx/systemd/linky2influx.nspawn
```
</div>
### Yocto
Vous pourriez vouloir écrire une recette Bitbake pour créer et déployer le
module via un paquet `.ipk` ou similaire en fonction de votre configuration.
Écrivez la recette au sein de `meta-electropcool` :
<div lang="en-US">
```
login_x-TP5/meta-electropcool/recipes-support/linky2influx/linky2influx_9999.bb
```
</div>
### Nix
L'expression Nix correspondant au paquet pourra être intégré au dépôt
<div lang="en-US">
```
login_x-TP5/linky2influx/linky2influx.nix
```
</div>
Précisez ensuite dans un `README-nix.md` à côté, la manière dont vous souhaitez
utiliser le package Nix ensuite.
### Snap, Flatpack, AppImage
Intégrez au dépôt le fichier de description, par exemple :
<div lang="en-US">
```
login_x-TP5/linky2influx/snapcraft.yaml
```
</div>
Il faudra également préciser avec un fichier `run.sh` la manière dont lancer
votre conteneur :
<div lang="en-US">
```
login_x-TP5/{snap,flatpack}/run.sh
```
</div>
### k3s
Nous en apprendrons davantage sur Kubernetes au prochain TP, mais si vous
connaissez déjà, vous pourriez vouloir écrire un *Chart* Helm :
<div lang="en-US">
```
login_x-TP5/k3s/linky2influx.yaml
```
</div>
Inutile de vous casser la tête avec ça si vous ne connaissez pas !
### Votre solution
N'hésitez pas à apporter une autre solution originale, que celles qui seraient
listées ici.
<div lang="en-US">
```
login_x-TP5/k3s/linky2influx.yaml
```
</div>
\
À vous de jouer !

View file

@ -0,0 +1,32 @@
Voici à quoi pourrait ressembler le playbook Ansible démarrant notre conteneur
Drone :
<div lang="en-US">
```yaml
- name: Launch drone container
docker_container:
name: droneci
image: drone/drone:1
volumes:
- /var/lib/drone:/data
state: started
restart_policy: unless-stopped
memory: 1G
memory_swap: 1G
networks:
- name: drone
- name: gitea
published_ports:
- "80:80"
env:
DRONE_GITEA_CLIENT_ID: "{{ client.id }}"
DRONE_GITEA_CLIENT_SECRET: "{{ client.secret }}"
DRONE_GITEA_SERVER: "http://gitea:3000"
DRONE_RPC_SECRET: "{{ shared_secret }}"
DRONE_SERVER_HOST: "droneci"
DRONE_SERVER_PROTO: "http"
```
</div>
C'est à vous de définir un `shared_secret`, c'est une chaîne aléatoire qui
permettra aux *Runner*s (section suivante) de s'authentifier.

View file

@ -0,0 +1,26 @@
Voici à quoi pourrait ressembler la ligne de commande démarrant notre conteneur
Drone :
<div lang="en-US">
```shell
export DRONE_GITEA_CLIENT_ID=#FIXME
export DRONE_GITEA_CLIENT_SECRET=#FIXME
export DRONE_RPC_SECRET=$(openssl rand -base64 30)
docker container run --name droneci -d \
-v /var/lib/drone:/data \
--network gitea -p 80:80 \
-e DRONE_GITEA_CLIENT_ID -e DRONE_GITEA_CLIENT_SECRET -e DRONE_GITEA_SERVER=http://gitea:3000 \
-e DRONE_RPC_SECRET -e DRONE_SERVER_HOST=droneci -e DRONE_SERVER_PROTO=http \
drone/drone:1
docker network connect drone droneci
```
</div>
La dernière commande permet à notre conteneur Drone d'être à la fois présent
dans le réseau `gitea` et `drone`, ce qui permet de garder les deux réseaux
distincts.
Gardez la variable d'environnement `DRONE_RPC_SECRET` dans un coin, nous en
aurons encore besoin juste après.

View file

@ -0,0 +1,15 @@
::::: {.question}
La version 2 de Drone, encore plus pratique et sympathique est disponible en
test. Vous pouvez tout à fait l'utiliser pour la suite du TP. Cela ne change
pas la version des *runners* à utiliser.
:::::
Une fois lancé, rendez-vous sur l'interface de DroneCI : <http://droneci/>
Vous serez automatiquement redirigé vers la page d'authentification de Gitea,
puis vers l'autorisation OAuth d'accès de Drone à Gitea. Il faut bien
évidemment valider cette demande, afin que Drone ait accès à nos dépôts.
![OAuth Drone](../devops/oauth-drone.png){width=9cm}

View file

@ -0,0 +1,25 @@
Voici à quoi pourrait ressembler le playbook Ansible démarrant notre agent Drone :
<div lang="en-US">
```yaml
- name: Launch drone runer
docker_container:
name: droneci-runner
image: "drone/drone-runner-docker:1"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
state: started
restart_policy: unless-stopped
memory: 2G
memory_swap: 2G
networks:
- name: drone
env:
DRONE_RPC_PROTO: "http"
DRONE_RPC_HOST: "droneci"
DRONE_RPC_SECRET: "{{ shared_secret }}"
DRONE_RUNNER_CAPACITY: "2"
DRONE_RUNNER_NAME: "my-runner"
DRONE_RUNNER_NETWORKS: "drone,gitea"
```
</div>

View file

@ -0,0 +1,11 @@
Voici à quoi pourrait ressembler la ligne de commande démarrant notre agent Drone :
<div lang="en-US">
```shell
docker container run --name droneci-runner -d \
-v /var/run/docker.sock:/var/run/docker.sock --network drone \
-e DRONE_RPC_PROTO=http -e DRONE_RPC_HOST=droneci -e DRONE_RPC_SECRET \
-e DRONE_RUNNER_CAPACITY=2 -e DRONE_RUNNER_NAME=my-runner -e DRONE_RUNNER_NETWORKS=drone,gitea \
drone/drone-runner-docker:1
```
</div>

View file

@ -0,0 +1,15 @@
### *Runner*
Notre conteneur `droneci` est uniquement une interface graphique qui va
centraliser d'un côté les nouveaux commits à traiter, et de l'autre les
résultats retournés par les agents chargés d'exécuter le code.
Il serait impensable d'exécuter arbitrairement du code en parallèle d'une
application privilégiée (ici, notre conteneur `droneci` a accès aux dépôts
potentiellement privés de Gitea). Les agents qui sont amenés à traiter du code
arbitraire s'exécutent à part et peuvent être de différents types. Dans le
vocabulaire de Drone, on les appelle des ~~blade~~*runners*.
Nous allons lancer un *runner* Docker : il s'agit d'un type d'agent qui va
exécuter nos étapes de compilation dans des conteneurs Docker (oui, quand on
disait que Drone était conçu autour de Docker, c'était pas pour rire !)

View file

@ -0,0 +1,24 @@
## Logiciel d'intégration continue
De nombreuses solutions sont disponibles sur Internet, la plupart du temps
gratuites pour les projets libres ([Travis CI](https://travis-ci.org/),
[CircleCI](https://circleci.com/), ...).
Mais nous allons déployer notre propre solution, en utilisant [Drone
CI](https://drone.io/). C'est une solution d'intégration continue libre et
moderne, conçue tout autour de Docker. Idéale pour nous !
### Interface de contrôle et de dispatch des tâches
La documentation du projet est extrêmement bien faite, suivons la marche à
suivre pour [relier Gitea à
Drone](https://docs.drone.io/server/provider/gitea/).
Drone va avoir besoin d'authentifier les utilisateurs afin d'accéder aux dépôts
privés (avec l'autorisation des utilisateurs). Pour cela, comme l'indique la
documentation de Drone, on va utiliser OAuth2 : dans Gitea, il va falloir créer
une *application OAuth2*. Le formulaire de création se trouve dans la
configuration du compte utilisateur, sous l'onglet *Applications*. Drone aura
également besoin d'une URL de redirection. Dans notre cas, ce sera :
`http://droneci/login`.

View file

@ -0,0 +1 @@
L'environnement étant prêt, il ne reste plus qu'à nous lancer dans nos projets !

View file

@ -0,0 +1,29 @@
Votre playbook ressemblera à quelque chose comme ça :
<div lang="en-US">
```yaml
- name: Launch gitea container
docker_container:
name: gitea
image: "gitea/gitea:{{ version }}"
volumes:
- /var/lib/gitea:/data
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
state: started
restart_policy: unless-stopped
memory: 1G
memory_swap: 1G
networks:
- name: gitea
published_ports:
- "2222:22"
- "3000:3000"
env:
RUN_MODE: "prod"
DOMAIN: "gitea"
SSH_DOMAIN: "gitea"
INSTALL_LOCK: "true"
SECRET_KEY: "{{ secret_key }}"
```
</div>

View file

@ -0,0 +1,13 @@
La ligne de commande pour lancer Gitea ressemblera à quelque chose comme ça :
<div lang="en-US">
```shell
export SECRET_KEY=$(openssl rand -base64 30)
docker container run --name gitea -d \
-v /var/lib/gitea:/data -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro \
--network gitea -p 2222:22 -p 3000:3000 \
-e RUN_MODE=prod -e DOMAIN=gitea -e SSH_DOMAIN=gitea -e INSTALL_LOCK=true -e SECRET_KEY \
gitea/gitea:1
```
</div>

View file

@ -0,0 +1,15 @@
Plus d'infos sur cette page : <https://docs.gitea.io/en-us/install-with-docker/>.
Une fois le conteneur lancé, vous pouvez accéder à l'interface de gitea sur le
port 3000 de votre machine (à moins que vous n'ayez opté pour un autre port).
Vous pouvez ajouter un nouvel administrateur avec la commande suivante :
<div lang="en-US">
```bash
docker exec gitea gitea admin user create --username "${USER}" --random-password \
--must-change-password=false --admin --email "${USER}@epita.fr"
```
</div>
Notez le mot de passe généré pour [vous y connecter](http://localhost:3000/user/login).

View file

@ -0,0 +1,43 @@
## Gestionnaire de versions
Avant de pouvoir commencer notre aventure, il est nécessaire d'avoir un
gestionnaire de versions. Nous allons ici utiliser Git.
### Problématique du stockage des produits de compilation
Outre les interfaces rudimentaires fournies au dessus de Git
([gitweb](https://git.wiki.kernel.org/index.php/Gitweb)), il y a de nombreux
projets qui offrent davantage que le simple hébergement de dépôts. Vous pouvez
voir sur GitHub notamment qu'il est possible d'attacher à un tag un [certain
nombre de fichiers](https://github.com/docker/compose/releases/latest).
On notera également que depuis le 1er septembre, GitHub propose un [registre
Docker](https://github.blog/2020-09-01-introducing-github-container-registry/)
que l'on peut lier avec ses dépôts. Une fonctionnalité que GitLab propose
[depuis
2016](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/).
En effet, la problématique du stockage des produits de compilation est
vaste. Si au début on peut se satisfaire d'un simple serveur web/FTP/SSH pour
les récupérer manuellement, on a vite envie de pouvoir utiliser les outils
standards directement : `docker pull ...`, `npm install ...`, ...
Des programmes et services se sont spécialisés là-dedans, citons notamment
[Artifactory](https://jfrog.com/artifactory/) ou [Nexus
Repository](https://www.sonatype.com/nexus/repository-oss) et bien d'autres.
Dans un premier temps, nous allons nous contenter de publier un binaire associé
à un tag de notre projet.
### Installation et configuration
Allez c'est parti ! première chose à faire : installer et configurer
[Gitea](https://gitea.io/) (ceux qui le souhaitent peuvent choisir
[gitlab](https://gitlab.org/) ou une autre plate-forme, mais la suite sera
moins guidée).
Nous allons utiliser l'image :
[`gitea/gitea`](https://hub.docker.com/r/gitea/gitea) (ou
[`gitlab/gitlab-ce`](https://hub.docker.com/r/gitlab/gitlab-ce)).

View file

@ -1,199 +1 @@
\newpage \newpage
Les bons outils
===============
## Gestionnaire de versions
Avant de pouvoir commencer notre aventure, il est nécessaire d'avoir un
gestionnaire de versions. Nous allons ici utiliser Git.
### Problématique du stockage des produits de compilation
Outre les interfaces rudimentaires fournies au dessus de Git
([gitweb](https://git.wiki.kernel.org/index.php/Gitweb)), il y a de nombreux
projets qui offrent davantage que le simple hébergement de dépôts. Vous pouvez
voir sur GitHub notamment qu'il est possible d'attacher à un tag un [certain
nombre de fichiers](https://github.com/docker/compose/releases/latest).
On notera également que depuis le 1er septembre, GitHub propose un [registre
Docker](https://github.blog/2020-09-01-introducing-github-container-registry/)
que l'on peut lier avec ses dépôts. Une fonctionnalité que GitLab propose
[depuis
2016](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/).
En effet, la problématique du stockage des produits de compilation est
vaste. Si au début on peut se satisfaire d'un simple serveur web/FTP/SSH pour
les récupérer manuellement, on a vite envie de pouvoir utiliser les outils
standards directement : `docker pull ...`, `npm install ...`, ...
Des programmes et services se sont spécialisés là dedans, citons notamment
[Artifactory](https://jfrog.com/artifactory/) ou [Nexus
Repository](https://www.sonatype.com/nexus/repository-oss) et bien d'autres.
Dans la première partie du TP, nous allons nous contenter de publier un binaire
associé à un tag de notre projet.
### Installation et configuration
Aller c'est parti ! première chose à faire : installer et configurer
[Gitea](https://gitea.io/) (ceux qui le souhaitent peuvent choisir
[gitlab](https://gitlab.org/) ou une autre plate-forme, mais la suite du TP
sera moins guidée pour eux).
Nous allons utiliser l'image :
[`gitea/gitea`](https://hub.docker.com/r/gitea/gitea) (ou
[`gitlab/gitlab-ce`](https://hub.docker.com/r/gitlab/gitlab-ce)).
Votre playbook resemblera à quelque chose comme ça :
<div lang="en-US">
```yaml
- name: Launch gitea container
docker_container:
name: gitea
image: "gitea/gitea:{{ version }}"
volumes:
- /var/lib/gitea:/data
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
state: started
restart_policy: unless-stopped
memory: 1G
memory_swap: 1G
networks:
- name: gitea
published_ports:
- "2222:22"
- "3000:3000"
env:
RUN_MODE: "prod"
DOMAIN: "gitea"
SSH_DOMAIN: "gitea"
INSTALL_LOCK: "true"
SECRET_KEY: "{{ secret_key }}"
```
</div>
Plus d'infos sur cette page : <https://docs.gitea.io/en-us/install-with-docker/>.
Une fois le conteneur lancé, vous pouvez accéder à l'interface de gitea sur le
port 3000 de votre machine (à moins que vous n'ayez opté pour un autre port).
Vous pouvez ajouter un nouvel administrateur avec la commande suivante :
<div lang="en-US">
```bash
docker exec gitea gitea admin user create --username "${USER}" --random-password \
--must-change-password=false --admin --email "${USER}@epita.fr"
```
</div>
Notez le mot de passe généré pour [vous y connecter](http://localhost:3000/user/login).
## Logiciel d'intégration continue
De nombreuses solutions sont disponibles sur Internet, la plupart du temps
gratuite pour les projets libres ([Travis CI](https://travis-ci.org/),
[CircleCI](https://circleci.com/), ...).
Mais nous allons déployer notre propre solution, en utilisant [Drone
CI](https://drone.io/). C'est une solution d'intégration continue libre et
moderne, conçue tout autour de Docker. Idéale pour nous !
### Interface de contrôle et de dispatch des tâches
La documentation du projet est extrêmement bien faite, suivons la marche à
suivre pour [relier Gitea à
Drone](https://docs.drone.io/server/provider/gitea/).
L'URL de redirection sera dans notre cas : `http://droneci/login`.
Voici à quoi pourrait ressemble le playbook Ansible démarrant notre conteneur
Drone :
<div lang="en-US">
```yaml
- name: Launch drone container
docker_container:
name: droneci
image: drone/drone:1
volumes:
- /var/lib/drone:/data
state: started
restart_policy: unless-stopped
memory: 1G
memory_swap: 1G
networks:
- name: drone
- name: gitea
published_ports:
- "80:80"
env:
DRONE_GITEA_CLIENT_ID: "{{ client.id }}"
DRONE_GITEA_CLIENT_SECRET: "{{ client.secret }}"
DRONE_GITEA_SERVER: "http://gitea:3000"
DRONE_RPC_SECRET: "{{ shared_secret }}"
DRONE_SERVER_HOST: "droneci"
DRONE_SERVER_PROTO: "http"
```
</div>
Une fois lancé, rendez-vous sur l'interface de DroneCI : <http://droneci/>
Vous serez automatiquement redirigé vers la page d'authentification de Gitea,
puis vers l'autorisation OAuth d'accès de Drone à Gitea. Il faut bien
évidemment valider cette demande, afin que Drone ait accès à nos dépôts.
![OAuth Drone](../devops/oauth-drone.png){width=9cm}
### *Runner*
Notre conteneur `droneci` est uniquement une interface graphique qui va
centraliser d'un côté les nouveaux commits à traiter, et de l'autre les
résultats retournés par les agents chargés d'exécuter le code.
Il serait impensable d'exécuter arbitrairement du code en parallèle d'une
application privilégiée (ici, notre conteneur `droneci` a accès aux dépôts
potentiellement privés de Gitea). Les agents qui sont amenés à traiter du code
arbitraire s'exécutent à part et peuvent être de différents types. Dans le
vocabulaire de Drone, on les appelle des ~~blade~~*runners*.
Nous allons lancer un *runner* Docker : il s'agit d'un type d'agent qui va
exécuter nos étapes de compilation dans des conteneurs Docker (oui, quand on
disait que Drone était conçu autour de Docker, c'était pas pour rire !)
Voici à quoi pourrait ressemble le playbook Ansible démarrant notre agent Drone :
<div lang="en-US">
```yaml
- name: Launch drone runer
docker_container:
name: droneci-runner
image: "drone/drone-runner-docker:1"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
state: started
restart_policy: unless-stopped
memory: 2G
memory_swap: 2G
networks:
- drone
env:
DRONE_RPC_PROTO: "http"
DRONE_RPC_HOST: "droneci"
DRONE_RPC_SECRET: "{{ shared_secret }}"
DRONE_RUNNER_CAPACITY: 2
DRONE_RUNNER_NAME: "my-runner"
DRONE_RUNNER_NETWORKS: "drone,gitea"
```
</div>
L'environnement étant prêt, il ne reste plus qu'à nous lancer dans nos projets !

View file

@ -0,0 +1,10 @@
### Pour aller plus loin
Le mouvement DevOps tend à utiliser mettre en avant la CI/CD, ce ne leur est
évidemment pas exclusivement réservé. Toute entreprise ayant une méthodologie
de développement saine dispose d'outils automatisés de construction et de
tests.
Pour en savoir plus sur le DevOps, vous devriez lire la première partie du [TP
des SRS](https://virli.nemunai.re/tutorial-5-srs.pdf), qui traite justement de
ce sujet.

View file

@ -0,0 +1,127 @@
\newpage
Électropcool
============
Bienvenue dans la société Électropcool !
Électropcool est une société française spécialisée dans
l'[immotique](https://fr.wikipedia.org/wiki/Immotique), elle vend des
équipements IoT, principalement à destination des professionels du bâtiment. Le
produit phare est une plate-forme de
[GTB](https://fr.wikipedia.org/wiki/Gestion_technique_de_b%C3%A2timent)
modulaire de suivi de la vie d'un bâtiment où sont regroupés les différents
compteurs, capteurs et actionneurs que l'on retrouve dans les installations.
Les nouveaux bâtiments conçus autour la plate-forme permettent de faire de
sérieuses économies d'entretien (en ne faisant déplacer les techiciens que
lorsque c'est nécessaire) tout en permettant d'anticiper les problèmes (grâce à
un moteur de *machine-learning* capable d'anticiper les pannes) et les besoins
en combustible (liés à la météo)[^HOMEASSISTANT].
[^HOMEASSISTANT]: Si ça vous met l'eau à la bouche, jettez un œil du côté du
projet <https://www.home-assistant.io/> qui fait un peu moins de
*bullshit*, mais est bien réel !
La principale difficulté que rencontre Électropcool est qu'aucun bâtiment ne
dispose des mêmes références de pièces et qu'en dehors des nouveaux bâtiments
pour lesquels la société peut imposer des équipements électroniques
spécifiquement supportés et compatibles avec la plate-forme qu'elle vend, il lui
est bien souvent nécessaire de faire des développements spécifiques pour
s'interfacer avec de l'électronique existant : c'est notamment le cas pour les
chaudières et les
[VMC](https://fr.wikipedia.org/wiki/Ventilation_m%C3%A9canique_contr%C3%B4l%C3%A9e),
qui, compte tenu de leur coût de remplacement prohibitif, nécessitent souvent
de réaliser des interfaces électroniques spécifiques pour s'adapter à
l'existant.
L'entreprise est en train de prendre un tournant historique et
souhaite accélérer ses développements pour faire face à la concurrence
qui arrive sur le marché.
\
L'entreprise utilise principalement de nombreux équipements de la *Raspberry Pi
fundation*, notamment les [Compute Module 3 et
4](https://www.raspberrypi.com/products/compute-module-4/) et les [Raspberry Pi
Zero W](https://www.raspberrypi.com/products/raspberry-pi-zero-w/), ainsi que
de nombreux PCB fait par l'entreprise, à base de micro-contrôleurs AVR,
lorsqu'il est nécessaire de pour s'interfacer avec des équipements
propriétaires non prévu pour l'immotique.
Une grosse partie des travaux est donc réalisé avec un noyau Linux, sur du
matériel très performant, pour de l'embarqué.
\
Tous les modules logiciels qui interragissent avec les capteurs sont
aujourd'hui intégrés dans un système construit à l'aide de
[`bitbake`](https://www.yoctoproject.org/). L'entreprise grossissant à vue d'œil,
il devient de plus en plus difficile de synchroniser les équipes concilier la
stabilité des *releases* avec le besoin de déployer de nouvelles
fonctionnalités chaque semaine.
Vous avez été chargés d'étudier la meilleure façon de déployer les différents
modules, sans qu'il soit nécessaire de reconstruire une image Yocto à chaque
fois, mais tout en assurant la stabilité de la plate-forme.
Le directeur technique vous suggère de regarder du côté des conteneurs
applicatifs, qui sont légers et assurent un cloisonnement suffisant pour ne pas
entraver la stabilité de la plate-forme en cas de déploiement d'un module
défaillant.
Vous êtes également chargés de jeter les bases du système d'intégration continu
des modules. (La partie déploiement continu, sera réalisé plus tard par
l'équipe développant le nouveau système de base, suivant le meilleur outil que
retiendrez.)
\
Le projet qui vous servira de base pour vos tests sera
[`linky2influx`](https://git.nemunai.re/nemunaire/linky2influx) : à partir d'un
compteur [Linky](https://fr.wikipedia.org/wiki/Linky), branché sur les bornes
de [téléinformation client du
compteur](https://hallard.me/demystifier-la-teleinfo/) et [lisant le
protocole](https://www.enedis.fr/media/2035/download) pour enregistrer les
données dans une *Time-series database*, en l'occurrence InfluxDB.
![La prod chez Électropcool](../devops/electropcool.jpg)
Dans un premier temps, on voudra juste compiler notre projet, pour s'assurer
que chaque commit poussé ne contient pas d'erreur de compilation, dans
l'environnement défini comme étant celui de production. Ensuite, on ajoutera
quelques tests automatiques. Puis nous publierons automatiquement le binaire
`linky2influx` comme fichier associé à un tag au sein de l'interface web du
gestionnaire de versions.
Nous testerons enfin différentes solution pour déployer notre binaire, afin
d'établir quelle est la solution adéquate.
## Préparer le terrain
Tous les déploiements sont à faire sur votre machine et la plate-forme de CI
utilisera massivement les conteneurs Docker, qui seront regroupés au sein de
réseaux Docker. Cela vous permettra d'utiliser la résolution de noms entre vos
conteneurs.
Vous devriez dès maintenant créer les deux réseaux suivants sur votre machines :
<div lang="en-US">
```shell
docker network create gitea
docker network create drone
```
</div>
Étant donné que votre machine ne dispose pas de domaine sur Internet et que
l'on va essayer de simplifier au maximum l'installation, vous devriez ajouter
cette ligne à votre fichier `/etc/hosts` (ou
`\Windows\System32\drivers\etc\hosts`) :
<div lang="en-US">
```conf
127.0.0.1 gitea droneci
```
</div>
Cette ligne va vous permettre de résoudre les noms des conteneurs. Cela
permettra aux requêtes OAuth de se faire de manière transparente pour vous
lorsque vous serez dans votre navigateur.

View file

@ -4,19 +4,19 @@ But du TP
========= =========
Nous allons nous mettre aujourd'hui dans la peau d'une équipe DevOps et Nous allons nous mettre aujourd'hui dans la peau d'une équipe DevOps et
réaliser une solution complète de intégration/déploiement continu (le fameux réaliser une solution complète d'intégration/déploiement continu (le fameux
CI/CD, pour *Continuous Integration* et *Continuous Delivery*). CI/CD, pour *Continuous Integration* et *Continuous Delivery*).
Le résultat attendu d'ici la fin du TP sera de mettre en place toutes les Le résultat attendu d'ici la fin de cette partie sera de mettre en place toutes
briques décrite dans la section précédente. les briques décrites dans la section précédente.
\ \
Nous allons commencer par automatiser le projet `youp0m`, plus simple, puis la Nous allons commencer par automatiser le projet `youp0m`, plus simple, ~~puis
plate-forme du FIC dans son ensemble, ce qui représente un petit challenge. la plate-forme du FIC dans son ensemble, ce qui représente un petit challenge~~
(merci Nabih !).
Il est également attendu que vous rendiez un playbook Ansible, permettant de Il est également attendu que vous rendiez un playbook Ansible, permettant de
retrouver un environnement similaire. Car on se reservira de cette installation retrouver un environnement similaire. Car on pourra s'en resservir par la suite.
dans un prochain TP.
\ \
Dans un premier temps, on voudra juste compiler notre projet, pour s'assurer Dans un premier temps, on voudra juste compiler notre projet, pour s'assurer
@ -27,7 +27,7 @@ quelques tests automatiques. Puis nous publierons automatiquement le binaire
gestionnaire de versions. gestionnaire de versions.
Enfin, nous mettrons en place un registre Docker qui nous permettra de publier Enfin, nous mettrons en place un registre Docker qui nous permettra de publier
automatiquement l'image Docker assocciée. C'est à partir de cette image Docker automatiquement l'image Docker associée. C'est à partir de cette image Docker
que l'on va commencer à déployer automatiquement... que l'on va commencer à déployer automatiquement...
@ -50,7 +50,8 @@ Dans votre playbook Ansible, vous pourrez procéder ainsi :
Étant donné que votre machine ne dispose pas de domaine sur Internet et que Étant donné que votre machine ne dispose pas de domaine sur Internet et que
l'on va essayer de simplifier au maximum l'installation, vous devriez ajouter l'on va essayer de simplifier au maximum l'installation, vous devriez ajouter
cette ligne à votre fichier `/etc/hosts` : cette ligne à votre fichier `/etc/hosts` (ou
`\Windows\System32\drivers\etc\hosts`) :
<div lang="en-US"> <div lang="en-US">
```conf ```conf

View file

@ -1,6 +1,6 @@
include ../pandoc-opts.mk include ../pandoc-opts.mk
SOURCES = tutorial.md oci.md runc.md linuxkit.md linuxkit-adlin.md linuxkit-content.md rendu.md SOURCES = tutorial.md oci.md registry.md runc.md linuxkit.md linuxkit-content.md rendu.md
all: tutorial.pdf all: tutorial.pdf

View file

@ -41,19 +41,19 @@ L'image la plus simple que l'on puisse réaliser pourrait être :
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
kernel: kernel:
image: linuxkit/kernel:4.14.80 image: linuxkit/kernel:5.10.76
cmdline: "console=tty0 console=ttyS0" cmdline: "console=tty0 console=ttyS0"
init: init:
- linuxkit/init:c563953a2277eb73a89d89f70e4b6dcdcfebc2d1 - linuxkit/init:eb597ef74d808b5320ad1060b1620a6ac31e7ced
- linuxkit/runc:83d0edb4552b1a5df1f0976f05f442829eac38fe - linuxkit/runc:21dbbda709ae138de0af6b0c7e4ae49525db5e88
- linuxkit/containerd:326b096cd5fbab0f864e52721d036cade67599d6 - linuxkit/containerd:2f0907913dd54ab5186006034eb224a0da12443e
onboot: onboot:
- name: dhcpcd - name: dhcpcd
image: linuxkit/dhcpcd:v0.6 image: linuxkit/dhcpcd:v0.8
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"] command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
services: services:
- name: getty - name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478 image: linuxkit/getty:3c6e89681a988c3d4e2610fcd7aaaa0247ded3ec
env: env:
- INSECURE=true - INSECURE=true
trust: trust:
@ -91,7 +91,7 @@ Il reste possible de se dissocier également de ces namespaces, en précisant :
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
- name: getty - name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478 image: linuxkit/getty:3c6e89681a988c3d4e2610fcd7aaaa0247ded3ec
net: new net: new
``` ```
</div> </div>
@ -101,7 +101,7 @@ Ou inversement, pour persister dans le namespace initial :
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
- name: getty - name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478 image: linuxkit/getty:3c6e89681a988c3d4e2610fcd7aaaa0247ded3ec
pid: host pid: host
``` ```
</div> </div>
@ -118,7 +118,7 @@ On commence donc d'abord par créer le nouveau *namespace*, en prenant soin de
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
- name: getty - name: getty
image: linuxkit/getty:2eb742cd7a68e14cf50577c02f30147bc406e478 image: linuxkit/getty:3c6e89681a988c3d4e2610fcd7aaaa0247ded3ec
net: new net: new
runtime: runtime:
bindNS: /run/netns/mynewnetns bindNS: /run/netns/mynewnetns
@ -132,7 +132,7 @@ réutiliser plus tard ce chemin, en remplacement du mot clef `new` :
<div lang="en-US"> <div lang="en-US">
```yaml ```yaml
- name: xxxx - name: xxxx
image: linuxkit/xxxx:v0.6 image: linuxkit/xxxx:v0.8
net: /run/netns/mynewnetns net: /run/netns/mynewnetns
``` ```
</div> </div>

View file

@ -177,3 +177,9 @@ Hello from Docker!
Pensez également à tester avec d'autres images, comme par exemple Pensez également à tester avec d'autres images, comme par exemple
`nemunaire/youp0m`. Il vous faudra alors extraire plusieurs couches. `nemunaire/youp0m`. Il vous faudra alors extraire plusieurs couches.
Pour gérer les différentes couches, vous pouvez utiliser une stratégie
similaire au driver `vfs` : en extrayant chaque tarball l'une au dessus de
l'autre, en essayant de gérer les *whiteout files*. Ou bien en suivant le
driver `overlayfs`, en montant un système de fichier à chaque couche (dans ce
cas, votre script devra être lancé en `root`).

View file

@ -6,18 +6,23 @@ Rendu
Modalités de rendu Modalités de rendu
------------------ ------------------
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP.
Un service automatique s'occupe de réceptionner vos rendus, de faire des Un service automatique s'occupe de réceptionner vos rendus, de faire des
vérifications élémentaires et de vous envoyer un accusé de réception (ou de vérifications élémentaires et de vous envoyer un accusé de réception (ou de
rejet). rejet).
Ce service écoute sur l'adresse <virli@nemunai.re>, c'est donc à cette adresse Ce service écoute sur l'adresse <virli@nemunai.re>. C'est donc à cette adresse
et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu
envoyé à une autre adresse et/ou non signé et/ou reçu après la correction ne envoyé à une autre adresse et/ou non signé et/ou reçu après la correction ne
sera pas pris en compte. sera pas pris en compte.
Afin d'orienter correctement votre rendu, ajoutez une balise `[TP6]` au sujet
de votre courriel. N'hésitez pas à indiquer dans le corps du courriel votre
ressenti et vos difficultés ou bien alors écrivez votre meilleure histoire
drôle si vous n'avez rien à dire.
Mais n'oubliez pas de répondre au [sondage](https://virli.nemunai.re/quiz/16)
pour me permettre d'améliorer ce cours.
Tarball Tarball
------- -------

View file

@ -1,9 +1,9 @@
--- ---
title: Virtualisation légère -- TP n^o^ 3 title: Virtualisation légère -- TP n^o^ 6
subtitle: Les projets de l'Open Container Initiative subtitle: Les projets de l'Open Container Initiative
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps} author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA institute: EPITA
date: Mercredi 28 octobre 2020 date: Vendredi 19 novembre 2021
abstract: | abstract: |
Après avoir beaucoup parlé de Docker, nous allons voir dans ce TP la Après avoir beaucoup parlé de Docker, nous allons voir dans ce TP la
manière dont les différents projets qu'il utilise dans sa plomberie manière dont les différents projets qu'il utilise dans sa plomberie
@ -11,10 +11,10 @@ abstract: |
\vspace{1em} \vspace{1em}
Les éléments de ce TP constituent du contenu bonus que vous pouvez rendre à **Ce TP est un sujet alternative au TP Kubernetes** que les GISTRE
<virli@nemunai.re> au plus tard le dimanche 22 novembre 2020 à 23 peuvent rendre à la place, à <virli@nemunai.re> au plus tard le
h 42. Consultez la dernière section de chaque partie pour plus d'information vendredi 3 décembre 2021 à 23 h 42. Consultez la dernière section de
sur les éléments à rendre. chaque partie pour plus d'information sur les éléments à rendre.
En tant que personnes sensibilisées à la sécurité des échanges électroniques, En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à

View file

@ -15,27 +15,41 @@ dessus de `curl`.
Obtenir de l'aide Obtenir de l'aide
----------------- -----------------
Commençons par apprivoiser `kubectl` en prenant quelques
renseignements et surtout en apprennant comment obtenir de l'aide :
<div lang="en-US">
```bash ```bash
kubectl describe type/name
kubectl describe type name kubectl describe type name
kubectl explain type kubectl explain type
``` ```
</div>
Les `type`s que vous pouvez découvrir sont ceux que l'on a vu à la
sections précédentes : `node`, `pod`, ...
La commande `describe` permet d'afficher l'état tel qu'il est attendu
et tel qu'il est actuellement (cela permet de se rendre lorsque les
deux divergent).
`get` `get`
----- -----
Une autre manière, moins verbeuse, de récupérer des informations est
d'utiliser `get` :
```bash ```bash
kubectl get node kubectl get node
``` ```
Plus d'infos : On peut ajouter des options pour avoir plus d'infos :
```bash ```bash
kubectl get nodes -o wide kubectl get nodes -o wide
``` ```
Lisible par une machine : ... ou rendre la sortie lisible par une machine :
```bash ```bash
kubectl get no -o yaml kubectl get no -o yaml
@ -91,7 +105,7 @@ conteneurs, gérés par lui-même... notamment :
- `kube-controller-manager` et `kube-scheduler`, deux autres composants - `kube-controller-manager` et `kube-scheduler`, deux autres composants
indispensables, indispensables,
- `coredns` : un composant additionnel pour gérer la résolution de noms internes - `coredns` : un composant additionnel pour gérer la résolution de noms internes
(pour pas avoir à s'embêter avec les IP), (pour ne pas avoir à s'embêter avec les IP),
- `kube-proxy` : 1 par nœud, pour gérer l'ouverture des ports notamment, - `kube-proxy` : 1 par nœud, pour gérer l'ouverture des ports notamment,
- `kindnet`, `weave` : 1 par nœud, le plugin réseau. - `kindnet`, `weave` : 1 par nœud, le plugin réseau.
@ -110,9 +124,9 @@ Nous devons lancer un *pod* (qui ne contiendra qu'un seul conteneur).
kubectl run pingpong --image alpine ping 1.1.1.1 kubectl run pingpong --image alpine ping 1.1.1.1
``` ```
`kubectl` doit nous indiquer nous qu'un *pod* a été créée. `kubectl` doit nous indiquer nous qu'un *pod* a été créé.
Si l'on affiche la liste des pods, vous devriez avoir quelque chose qui Si l'on affiche la liste des *pod*s, vous devriez avoir quelque chose qui
ressemble à cela : ressemble à cela :
``` ```
@ -144,7 +158,7 @@ Notez ici l'option -f qui permet de suivre les logs en direct.
Notre premier test ayant réussi, nous pouvons arrêter de DDos Cloudflare : Notre premier test ayant réussi, nous pouvons arrêter de DDos Cloudflare :
```bash ```bash
kubectl delete deploy/pingpong kubectl delete pods pingpong
``` ```
@ -152,13 +166,13 @@ kubectl delete deploy/pingpong
Bien ... maintenant que nous savons nous débrouiller avec `kubectl`, attaquons Bien ... maintenant que nous savons nous débrouiller avec `kubectl`, attaquons
les choses sérieuses : en temps normal avec Kubernetes, nous ne déploierons pas les choses sérieuses : en temps normal avec Kubernetes, nous ne déploierons pas
de *pod* directement, car cela reviendrait à utiliser Docker, mais des tâches de *pod* directement, car cela reviendrait à utiliser Docker. Nous allons
de déploiement. plutôt créer des tâches de déploiement.
Essayons sans plus attendre de lancer nos `ping` à travers une tâche de déploiement : Essayons sans plus attendre de lancer nos `ping` à travers une tâche de déploiement :
```bash ```bash
kubectl create deployment pingpong --image=alpine -- ping 1.1.1.1 kubectl create deployment pingpong --image=alpine -- ping 8.8.8.8
``` ```
Si l'on regarde maintenant la sortie de `kubectl get all`, on obtient : Si l'on regarde maintenant la sortie de `kubectl get all`, on obtient :
@ -177,19 +191,21 @@ NAME DESIRED CURRENT READY AGE
replicaset.apps/pingpong-98f6d5899 1 1 0 123s replicaset.apps/pingpong-98f6d5899 1 1 0 123s
``` ```
Oula, on a vraiment lancé tout ça ?!
Pas de panique, on peut très facilement le décortiquer : Pas de panique, on peut très facilement le décortiquer :
Les tâches de déploiements (*deployment.apps*) sont des ressources de Les tâches de déploiement (*deployment.apps*) sont des ressources de
haut-niveau et sont là pour s'assurer que les migrations se font en douceur : haut niveau et sont là pour s'assurer que les migrations se font en douceur :
elles vont permettre de basculer progressivement les pods d'une version X à une elles vont permettre de basculer progressivement les *pod*s d'une version X à une
version Y (par exemple si l'on change notre ping d'alpine vers debian), mais version Y (par exemple si l'on change notre ping d'alpine 3.14 vers alpine
éventuellement de revenir sur la version X si besoin, en cours de migration. edge), mais éventuellement de revenir sur la version X si besoin, en cours de
Elles délèguent aux *replicatsets* la gestion des pods. migration. Elles délèguent ensuite aux *replicatsets* la gestion des *pod*s.
Le *replicatset* est là pour indiquer le nombre de pods que l'on désire, et
s'assurer que le nombre de pods actuellement lancé est bien en adéquation avec
le nombre de pods attendu.
Le *replicatset* est là pour indiquer le nombre de *pod*s que l'on désire et
s'assurer que le nombre de *pod*s actuellement lancé est bien en adéquation avec
le nombre de *pod*s attendu.
\
Pour résumer : `kubectl` a créé une tâche de déploiement Pour résumer : `kubectl` a créé une tâche de déploiement
`deploy/pingpong`. Cette tâche de déploiement a créé elle-même un *replicatset* `deploy/pingpong`. Cette tâche de déploiement a créé elle-même un *replicatset*
@ -198,7 +214,7 @@ Pour résumer : `kubectl` a créé une tâche de déploiement
### Passage à l'échelle : facile ? ### Passage à l'échelle : facile ?
Pour lancer 3 ping en parallèle, modifions la tâche de déploiement comme suit : Pour lancer 3 `ping`s en parallèle, modifions la tâche de déploiement comme suit :
```bash ```bash
kubectl scale deploy/pingpong --replicas 3 kubectl scale deploy/pingpong --replicas 3
@ -206,9 +222,10 @@ kubectl scale deploy/pingpong --replicas 3
À ce stade, comme nous ne modifions que le nombre de replicats, Kubernetes va À ce stade, comme nous ne modifions que le nombre de replicats, Kubernetes va
tout simplement propager ce nombre au *replicatset* existant. Puis, le tout simplement propager ce nombre au *replicatset* existant. Puis, le
*replicatset* voyant un décalage entre le nombre de pods attendus et le nombre *replicatset* voyant un décalage entre le nombre de *pod*s attendus et le nombre
de pods en cours d'exécution, il va en lancer de nouveaux, afin de répondre à de *pod*s en cours d'exécution, il va en lancer de nouveaux, afin de répondre à
la demande. la demande.
\
Et que se passe-t-il alors, si l'on tue un *pod* ? Et que se passe-t-il alors, si l'on tue un *pod* ?
@ -216,31 +233,32 @@ Et que se passe-t-il alors, si l'on tue un *pod* ?
kubectl delete pod pingpong-yyyy kubectl delete pod pingpong-yyyy
``` ```
Cela supprime bien un *pod*, mais un autre est relancé instantannément car le Cela supprime bien un *pod*, mais un autre est relancé instantanément car le
*replicatset* constate une différence dans le nombre attendu. *replicatset* constate une différence dans le nombre attendu.
Si nous voulons arrêter de DDoS Cloudflare, il ne s'agit pas de tuer chacun des Si nous voulons arrêter de DDoS Google/Cloudflare, il ne s'agit pas de tuer
pods un par un, car de nouveaux seraient créés par le *replicatset*. Si l'on chacun des *pod*s un par un, car de nouveaux seraient créés par le
supprime le *replicatset*, la tâche de déploiement en rećréera un similaire. *replicatset*. Si l'on supprime le *replicatset*, la tâche de déploiement en
recréera un similaire (avec de nouveaux *pod*s).
Pour arrêter nos conteneurs, il convient donc de supprimer la tâche de Pour arrêter nos conteneurs, il convient donc de supprimer la tâche de
déploiement : déploiement :
```bash ```bash
kubectl delete deploy/pingpong kubectl delete deploy pingpong
``` ```
### Exposer son conteneur ### Exposer son conteneur
Exposer un conteneur revient à créer un nouveau service (une *resource* Exposer un conteneur revient à créer un nouveau service (une ressource
service). Un service est une adresse IP que l'on peut considérer comme stable *service*). Un service est une adresse IP que l'on peut considérer comme stable
pour un *pod* ou un groupe de *pods*. pour un *pod* ou un groupe de *pod*s.
Il est nécessaire de créer un service si l'on veut pouvoir se connecter à un Il est nécessaire de créer un *service* si l'on veut pouvoir se connecter à un
*pod*. *pod*.
Une fois le service créé, le serveur DNS interne va permettre de résoudre le Une fois le *service* créé, le serveur DNS interne va permettre de résoudre le
nom du *pod* depuis les autres conteneurs. nom du *pod* depuis les autres conteneurs.
@ -249,12 +267,12 @@ nom du *pod* depuis les autres conteneurs.
Il y a différents types de services : Il y a différents types de services :
- `ClusterIP` (par défaut) : une adresse IP virtuelle est allouée pour le - `ClusterIP` (par défaut) : une adresse IP virtuelle est allouée pour le
service, elle n'est accessible que depuis le réseau interne (par les pods et service, elle n'est accessible que depuis le réseau interne (par les *pod*s et
les nœuds). Il n'y a pas de translation de port à effectuer. les nœuds). Il n'y a pas de translation de port à effectuer.
- `NodePort` : un port est alloué pour le service, sur tous les nœuds le - `NodePort` : un port est alloué pour le service, sur tous les nœuds le
cluster, et n'importe qui peut alors s'y connecter. Le port est choisi cluster et n'importe qui peut alors s'y connecter. Le port est choisi
aléatoirement. aléatoirement.
- `LoadBalancer` : lorsque l'infrastructure sous-jacente fourni un - `LoadBalancer` : lorsque l'infrastructure sous-jacente fournit un
load-balancer (typiquement AWS, GCE, Azure, ...), un service `NodePort` est load-balancer (typiquement AWS, GCE, Azure, ...), un service `NodePort` est
créé pour utiliser ce load-balancer externe. créé pour utiliser ce load-balancer externe.
- `ExternalName` : une entrée DNS est créée pour avoir un alias. - `ExternalName` : une entrée DNS est créée pour avoir un alias.
@ -262,6 +280,8 @@ Il y a différents types de services :
#### Le retour de `youp0m` #### Le retour de `youp0m`
Déployons maintenant l'image `youp0m` pour voir comment utiliser les *service*s :
```bash ```bash
kubectl create deployment youp0m --image=nemunaire/youp0m kubectl create deployment youp0m --image=nemunaire/youp0m
``` ```
@ -287,7 +307,7 @@ différents nœuds.
Si vous passez par `kind`, vous pouvez constater le bon fonctionnement grâce à : Si vous passez par `kind`, vous pouvez constater le bon fonctionnement grâce à :
```bash ```bash
docker exec -it kind-control-plane curl 10.96.179.154:8080 docker exec -it kind-control-plane curl 10.102.129.233:8080
``` ```
@ -306,11 +326,15 @@ la configuration nécessaire :
kubectl create -f https://virli.nemunai.re/insecure-dashboard.yaml kubectl create -f https://virli.nemunai.re/insecure-dashboard.yaml
``` ```
::::: {.warning}
Notez que le dashboard, avec cette configuration, va s'exécuter sans les Notez que le dashboard, avec cette configuration, va s'exécuter sans les
prérequis minimum de sécurité : pas de certificat TLS, ni prérequis minimum de sécurité : pas de certificat TLS, ni
d'authentification. Ceci est juste pour jouer avec l'interface, en production, d'authentification. Ceci est juste pour jouer avec l'interface, en production,
on n'utilisera pas cette recette. on n'utilisera pas cette recette.
:::::
Regardons où nous pouvons contacter notre dashboard : Regardons où nous pouvons contacter notre dashboard :
```bash ```bash
@ -323,7 +347,7 @@ kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6m51s
Regardons si cela répond : Regardons si cela répond :
```bash ```bash
$ docker exec -it kind-control-plane curl 127.0.0.1:31505 $ docker exec -it kind-control-plane curl 10.96.78.69:80
<p class="browsehappy">You are using an <strong>outdated</strong> browser. <p class="browsehappy">You are using an <strong>outdated</strong> browser.
``` ```
@ -332,10 +356,10 @@ Pas très sympa... il faudrait que l'on puisse le voir dans un navigateur plus
Étant donné que notre cluster ne se trouve pas directement sur notre machine, Étant donné que notre cluster ne se trouve pas directement sur notre machine,
mais dans différents conteneurs Docker, nous ne pouvons pas accéder à mais dans différents conteneurs Docker, nous ne pouvons pas accéder à
`127.0.0.1`. Heureusement, au moment de la création de notre cluster, nous `127.0.0.1`. Heureusement, au moment de la création de notre cluster avec
avons renseigné plusieurs ports redirigés au sein de notre configuration. Il va `kind`, nous avons renseigné plusieurs ports redirigés au sein de notre
donc falloir indiquer à Kubernetes que l'on désire utiliser un port spécifique configuration. Il va donc falloir indiquer à Kubernetes que l'on désire
pour exposer le tableau de bord. utiliser un port spécifique pour exposer le tableau de bord.
Pour ce faire, éditons le fichier `insecure-dashboard.yaml`, pour ajouter, dans Pour ce faire, éditons le fichier `insecure-dashboard.yaml`, pour ajouter, dans
la partie `Service` un *node port* plus spécifique : la partie `Service` un *node port* plus spécifique :

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -3,14 +3,16 @@
Introduction Introduction
============ ============
Notre application du jour
-------------------------
Aujourd'hui, nous allons travailler avec un mineur de pépites ... de chocolat ! Aujourd'hui, nous allons travailler avec un mineur de pépites ... de chocolat !
Alors, on se fait un bon thé, on prend sa boîte de gâteaux pour tenir le coup,
et c'est parti ! <!--Alors, on se fait un bon thé, on prend sa boîte de gâteaux pour tenir le coup,
<!--De véritables cookies sont à gagner pour celles et ceux qui auront amassés le et c'est parti !-->
plus de pépites avant la pause !--> Comme c'est notre dernier cours ensemble, de véritables cookies sont à
gagner pour celles et ceux qui auront amassé le plus de pépites d'ici
la fin du TP[^cookies] ! Vous pouvez suivre votre progression sur
[cette page](https://virli.nemunai.re/scores.html).
[^cookies]: Dans la limite des stocks disponibles.
![ChocoMiner](dockercoins-diagram.svg) ![ChocoMiner](dockercoins-diagram.svg)
@ -34,7 +36,7 @@ Obtenir l'application
<div lang="en-US"> <div lang="en-US">
```shell ```shell
git clone https://gitea.nemunai.re/srs/chocominer.git git clone https://git.nemunai.re/srs/chocominer.git
``` ```
</div> </div>
@ -47,7 +49,7 @@ des conteneurs : un serveur DNS nous permettait de se connecter aux différents
services à partir de leurs noms. services à partir de leurs noms.
Dans Kubernetes, le même principe s'applique : dans aucun cas, nous ne devrions Dans Kubernetes, le même principe s'applique : dans aucun cas, nous ne devrions
coder en dur des adresses IP. Il convient d'utiliser au maximum le système de inscrire en dur des adresses IP. Il convient d'utiliser au maximum le système
DNS, car les IP sont susceptibles de changer ! DNS, car les IP sont susceptibles de changer !
@ -71,7 +73,7 @@ Montée en puissance
docker-compose up -d --scale worker=2 docker-compose up -d --scale worker=2
``` ```
On remarque que le nombre de hash calculés augmente ! Génial ! On remarque que le nombre de hashs calculés augmente ! Génial !
```bash ```bash
docker-compose up -d --scale worker=10 docker-compose up -d --scale worker=10

View file

@ -5,7 +5,7 @@ Vue d'ensemble de Kubernetes
*Kubernetes* est un système open source d'orchestration et de gestion de *Kubernetes* est un système open source d'orchestration et de gestion de
conteneurs. C'est-à-dire qu'il se charge de coller constamment aux conteneurs. C'est-à-dire qu'il se charge de coller constamment aux
spécifications qu'on lui aura demandé. spécifications qu'on lui aura demandées.
Ce projet est l'aboutissement de plus d'une dizaine d'années d'expérience de Ce projet est l'aboutissement de plus d'une dizaine d'années d'expérience de
gestion de conteneurs applicatifs chez Google (rappelons que c'est eux qui ont gestion de conteneurs applicatifs chez Google (rappelons que c'est eux qui ont
@ -13,13 +13,13 @@ poussé de nombreuses technologies dans le noyau Linux, notamment les
*cgroups*, ...). *cgroups*, ...).
Dans Kubernetes, il n'est pas question d'indiquer comment lancer ses Dans Kubernetes, il n'est pas question d'indiquer comment lancer ses
conteneurs, ni même quels cgroups utiliser. On va fournir à l'orchestrateur des conteneurs, ni même quels *cgroups* utiliser. On va fournir à l'orchestrateur
informations, des *spécifications* qui vont altérer l'état du cluster. Et c'est des informations, des *spécifications*, qui vont altérer l'état du cluster. Et
en cherchant à être constamment dans l'état qu'on lui a décrit, qu'il va c'est en cherchant à être constamment dans l'état qu'on lui a décrit, qu'il va
s'adapter pour répondre aux besoins. s'adapter pour répondre aux besoins.
Par exemple, on ne va pas lui expliquer comment lancer des conteneurs ou Par exemple, on ne va pas lui expliquer comment lancer des conteneurs ou
récupérer des images ; mais on va lui demander d'avoir 5 conteneurs youp0m récupérer des images ; mais on va lui demander d'avoir 5 conteneurs `youp0m`
lancés, de placer ces conteneurs derrière un load-balancer ; on pourra lancés, de placer ces conteneurs derrière un load-balancer ; on pourra
également lui demander d'adapter la charge pour absorber les pics de trafic également lui demander d'adapter la charge pour absorber les pics de trafic
(par exemple lors du Black Friday sur une boutique), mais également, il pourra (par exemple lors du Black Friday sur une boutique), mais également, il pourra
@ -34,7 +34,7 @@ Architecture de Kubernetes
Un cluster Kubernetes est composé d'un (ou plusieurs) nœuds *master*, et d'une Un cluster Kubernetes est composé d'un (ou plusieurs) nœuds *master*, et d'une
série de *workers*. série de *workers*.
Sur le master, on retrouve les composants suivants : Sur le(s) *master(s)*, on retrouve les composants suivants :
API HTTP API HTTP
: On distingue plusieurs API, elles sont toutes utilisées pour communiquer avec : On distingue plusieurs API, elles sont toutes utilisées pour communiquer avec
@ -51,16 +51,13 @@ Le contrôleur
**`etcd`** **`etcd`**
: Il s'agit d'une base de données clef/valeur, supportant la : Il s'agit d'une base de données clef/valeur, supportant la
haute-disponibilité, que Kubernetes emploie comme système de stockage haute-disponibilité, que Kubernetes emploie comme système de stockage
persistant pour les objets d'API. persistant pour les objets et ses états.
\
Chaque nœud[^minion] (généralement, le nœud *master* est également *worker*) est utilisé Chaque nœud (généralement, le nœud *master* est également *worker*) est utilisé
via deux composants : via deux composants :
[^minion]: historiquement, avant de parler de *node*, on parlait de
*minion*. Vous êtes susceptibles de rencontrer encore ce terme dans
certaines documentations.
`kubelet` `kubelet`
: C'est l'agent qui va se charger de créer les conteneurs et les manager, afin : C'est l'agent qui va se charger de créer les conteneurs et les manager, afin
de répondre aux spécifications. de répondre aux spécifications.
@ -70,6 +67,7 @@ via deux composants :
Sans oublier le moteur de conteneurs (généralement Docker), qui va Sans oublier le moteur de conteneurs (généralement Docker), qui va
effectivement se charger de lancer les conteneurs demandés par `kubelet`. effectivement se charger de lancer les conteneurs demandés par `kubelet`.
\
Évidemment, chaque élément de l'architecture est malléable à souhait, c'est la Évidemment, chaque élément de l'architecture est malléable à souhait, c'est la
@ -85,11 +83,12 @@ Avec Docker, nous avons eu l'habitude de travailler avec des objets (images,
containers, networks, volumes, secrets, ...). Au sein de Kubernetes, cela containers, networks, volumes, secrets, ...). Au sein de Kubernetes, cela
s'appelle des *resources* et elles sont très nombreuses. s'appelle des *resources* et elles sont très nombreuses.
Parmi les plus courantes, citons les types (désignés *Kind* dans l'API) Parmi les plus courantes, citons les types (désignés *Kind* dans l'API, rien à
suivants : voir avec le projet `kind` au début du sujet) suivants :
node node
: il s'agit d'une machine physique ou virtuelle, de notre cluster. : il s'agit d'une machine de notre cluster (elle peut être physique ou
virtuelle).
pod pod
: un groupe de conteneurs travaillant ensemble. Il s'agit de la ressource que : un groupe de conteneurs travaillant ensemble. Il s'agit de la ressource que
@ -128,8 +127,8 @@ compléter ce schéma...
Chaque plugin implémente la [spécification Chaque plugin implémente la [spécification
CNI](https://github.com/containernetworking/cni/blob/master/SPEC.md#network-configuration) CNI](https://github.com/containernetworking/cni/blob/master/SPEC.md#network-configuration)
(Container Network Interface). On trouve donc autant de plugin qu'il y a de (Container Network Interface). On trouve donc autant de plugins qu'il y a de
besoins en terme de réseau. besoins en termes de réseau.
Ainsi, à la création d'un conteneur, Kubernetes va laisser aux plugins CNI le Ainsi, à la création d'un conteneur, Kubernetes va laisser aux plugins CNI le
loisir d'allouer l'adresse IP, d'ajouter les interfaces réseaux adéquates, de loisir d'allouer l'adresse IP, d'ajouter les interfaces réseaux adéquates, de

View file

@ -20,7 +20,7 @@ de votre courriel. N'hésitez pas à indiquer dans le corps du courriel votre
ressenti et vos difficultés ou bien alors écrivez votre meilleure histoire ressenti et vos difficultés ou bien alors écrivez votre meilleure histoire
drôle si vous n'avez rien à dire. drôle si vous n'avez rien à dire.
Mais n'oubliez pas de répondre au [sondage](https://virli.nemunai.re/quiz/8) Mais n'oubliez pas de répondre au [sondage](https://virli.nemunai.re/quiz/16)
pour me permettre d'améliorer ce cours. pour me permettre d'améliorer ce cours.

View file

@ -13,7 +13,7 @@ allons devoir :
- exposer avec un NodePort l'interface graphique de contrôle. - exposer avec un NodePort l'interface graphique de contrôle.
Lancement des *pods* Lancement des *pod*s
-------------------- --------------------
### Via Helm ### Via Helm
@ -32,7 +32,7 @@ permettant de trouver facilement son bonheur. On va y trouver
va avoir besoin pour la suite. va avoir besoin pour la suite.
Mais d'abord, il va nous falloir [installer Mais d'abord, il va nous falloir [installer
helm](https://helm.sh/docs/intro/install/). Il utilisera la même configuration Helm](https://helm.sh/docs/intro/install/). Il utilisera la même configuration
que `kubectl`, il n'y a rien de plus à configurer. que `kubectl`, il n'y a rien de plus à configurer.
Une fois `helm` installé, et le dépôt `influxdata` ajouté, comme précisé dans Une fois `helm` installé, et le dépôt `influxdata` ajouté, comme précisé dans
@ -40,7 +40,7 @@ la documentation du *chart* d'InfluxDB, nous pouvons le déployer dans notre
cluster : cluster :
```bash ```bash
helm install influxdata/influxdb --generate-name helm install influxdb influxdata/influxdb
``` ```
Les valeurs de configuration indiquées dans le `README` du *chart* se modifient Les valeurs de configuration indiquées dans le `README` du *chart* se modifient
@ -50,7 +50,7 @@ ainsi :
helm upgrade -f values.yml your-influx-name influxdata/influxdb helm upgrade -f values.yml your-influx-name influxdata/influxdb
``` ```
Il vous sera entre-autre nécessaire d'ajouter un administrateur afin de pouvoir Il vous sera entre autres nécessaire d'ajouter un administrateur afin de pouvoir
utiliser la base de données. utiliser la base de données.
Nous pouvons ensuite faire de même avec Nous pouvons ensuite faire de même avec
@ -61,7 +61,7 @@ mixer avec la méthode ci-dessous (en adaptant certaines valeurs).
### Via `kubectl` ### Via `kubectl`
Si vous ne souhaitez pas utiliser `helm`, vous pouvez vous rabattre sur les Si vous ne souhaitez pas utiliser `helm`, vous pouvez vous rabattre sur les
YAML que l'on a utilisé jusqu'à maintenant, et utiliser `kubectl`. Commençons YAML que l'on a utilisés jusqu'à maintenant, et utiliser `kubectl`. Commençons
par lancer `influxdb` : par lancer `influxdb` :
```bash ```bash
@ -89,7 +89,7 @@ done
### Exposer les ports ### Exposer les ports
Pour trois des applications, des ClusterIP font l'affaire, car ils n'ont pas Pour trois des applications, des `ClusterIP` font l'affaire, car ils n'ont pas
besoin d'être exposés en dehors du cluster. besoin d'être exposés en dehors du cluster.
```bash ```bash
@ -98,6 +98,9 @@ kubectl expose deployment rng --port 80
kubectl expose deployment hasher --port 80 kubectl expose deployment hasher --port 80
``` ```
Si vous avez utilisé le *chart* Helm d'InfluxDB, Un `ClusterIP` a été
automatiquement créé.
Par contre, notre Chronograf doit être exposé, on lui alloue donc un NodePort : Par contre, notre Chronograf doit être exposé, on lui alloue donc un NodePort :
```bash ```bash
@ -115,9 +118,9 @@ la base `chocominer.autogen`, puis la table `hashes` et enfin on sélectionne
l'élément `value`. Pour être tout à fait juste, il faut choisir la fonction l'élément `value`. Pour être tout à fait juste, il faut choisir la fonction
`sum`, car nous voulons afficher le nombre total de condensat générés. Un `sum`, car nous voulons afficher le nombre total de condensat générés. Un
second graphique intéressant est celui du nombre de pépites trouvées : il faut second graphique intéressant est celui du nombre de pépites trouvées : il faut
compter (`count`), le nombre d'éléments dans la table `chunks`. compter (`count`) le nombre d'éléments dans la table `chunks`.
![Montée en charge progressive dans Chronograph](nuggets-graph.png) ![Montée en charge progressive dans Chronograph](nuggets-graph.png)
Vous n'avez pas la même courbe de progression ? continuons le TP alors, pour Vous n'avez pas la même courbe de progression ? Continuons le TP alors, pour
augmenter la puissance de notre *rig* ! augmenter la puissance de notre *rig* !

View file

@ -25,7 +25,7 @@ effet, il nous faut répartir les services entre plusieurs machines.
Une ressource *daemon sets* va s'assurer que tous les nœuds (ou une partie) Une ressource *daemon sets* va s'assurer que tous les nœuds (ou une partie)
vont exécuter une instance d'un *pod*. Ainsi, si un nouveau nœud rejoint le vont exécuter une instance d'un *pod*. Ainsi, si un nouveau nœud rejoint le
cluster, le *pod* sera automatiquement lancé dessus. Inversement, lorsqu'un cluster, le *pod* sera automatiquement lancé dessus. Inversement, lorsqu'un
nœud quitte le cluster, le pod est nettoyé. nœud quitte le cluster, le *pod* est nettoyé.
On s'en sert principalement pour exécuter une instance de daemon de stockage On s'en sert principalement pour exécuter une instance de daemon de stockage
(tel que Ceph, `glusterd`, ...) ou pour la collecte de logs (`fluentd`, (tel que Ceph, `glusterd`, ...) ou pour la collecte de logs (`fluentd`,
@ -90,7 +90,7 @@ documentation](https://kubernetes.io/docs/concepts/workloads/controllers/daemons
#### *DaemonSet* `rng` #### *DaemonSet* `rng`
Pour réaliser le *DaemonSet* de notre pod `rng`, le plus simple est de partir Pour réaliser le *DaemonSet* de notre *pod* `rng`, le plus simple est de partir
d'un export de la ressource existante : d'un export de la ressource existante :
```bash ```bash
@ -123,8 +123,8 @@ kubectl apply -f rng.yml --validate=false
#### Trop de *pods* `rng` {-} #### Trop de *pods* `rng` {-}
Après avoir appliqué la nouvelle spec, on constate qu'il y a beaucoup de *pods* Après avoir appliqué la nouvelle spec, on constate qu'il y a beaucoup de *pod*s
`rng`. En effet, l'ancien *pod* déployé avec la resource *deployment* est `rng`. En effet, l'ancien *pod* déployé avec la ressource *deployment* est
toujours là. toujours là.

View file

@ -4,10 +4,10 @@ Mise en place
============= =============
La mise en place d'un cluster Kubernetes ([prononcé La mise en place d'un cluster Kubernetes ([prononcé
Ku-ber-né-tèce](https://github.com/kubernetes/kubernetes/issues/44308) en grec Ku-ber-né-tice](https://github.com/kubernetes/kubernetes/issues/44308) en grec)
ancien) est une opération qui peut s'avérer très longue et complexe, car elle est une opération qui peut s'avérer très longue et complexe, car elle nécessite
nécessite l'installation et la configuration de nombreux composants avant de l'installation et la configuration de nombreux composants avant de pouvoir être
pouvoir être utilisé sereinement. utilisé sereinement.
Cette opération n'étant pas très palpitante (c'est beaucoup de lecture de Cette opération n'étant pas très palpitante (c'est beaucoup de lecture de
documentations et d'heures passées à essayer de faire tomber en marche tous les documentations et d'heures passées à essayer de faire tomber en marche tous les
@ -15,9 +15,9 @@ composants d'un seul coup), nous ne la verrons pas aujourd'hui.
D'ailleurs, dans le milieu professionnel, il est plutôt rare de voir des D'ailleurs, dans le milieu professionnel, il est plutôt rare de voir des
entreprises investir dans la gestion de leur propre cluster Kubernetes. La entreprises investir dans la gestion de leur propre cluster Kubernetes. La
plupart des entreprises qui choisissent d'utiliser Kubernetes pour gérer leurs plupart des entreprises qui font le choix d'utiliser Kubernetes pour gérer leurs
infrastructures, choisissent de passer par un prestataire. L'entreprise délègue infrastructures, choisissent de passer par un prestataire. L'entreprise délègue
donc la gestion de leur cluster à une autre entreprise, dont c'est la cœur de donc la gestion de son/ses cluster(s) à une autre entreprise, dont c'est le cœur de
métier. La plupart du temps, il va s'agir d'Amazon (via [Elastic Kubernetes métier. La plupart du temps, il va s'agir d'Amazon (via [Elastic Kubernetes
Service](https://aws.amazon.com/fr/eks/)), d'Azur ([Kubernetes Service](https://aws.amazon.com/fr/eks/)), d'Azur ([Kubernetes
Service](https://azure.microsoft.com/fr-fr/services/kubernetes-service/)) ou Service](https://azure.microsoft.com/fr-fr/services/kubernetes-service/)) ou
@ -25,18 +25,54 @@ Google ([Kubernetes Engine](https://cloud.google.com/kubernetes-engine/)), mais
d'autres acteurs plus petits existent aussi d'autres acteurs plus petits existent aussi
([OVHcloud](https://www.ovhcloud.com/fr/public-cloud/kubernetes/), ...). ([OVHcloud](https://www.ovhcloud.com/fr/public-cloud/kubernetes/), ...).
::::: {.more}
Pour jouer aujourd'hui, deux solutions s'offrent à nous pour commencer à Pour l'IoT ou l'Edge Computing, sur du matériel léger, il existe le projet
k3s[^k3s] : il s'agit d'une distribution Kubernetes beaucoup plus simple à
déployer, et parfaitement adaptée à la production sur Raspberry Pi et autres.
:::::
[^k3s]: https://k3s.io/
Pour jouer aujourd'hui, plusieurs solutions s'offrent à nous pour commencer à
utiliser Kubernetes facilement : utiliser Kubernetes facilement :
- Kubernetes in Docker (kind) : pour tenter l'aventure sur votre machine, - [Docker Desktop (for Mac ou for Windows) :](#dockerdesktop) si vous êtes sur l'un de ces
- Play With Kubernetes : si vous ne vous en sortez pas avec `kind`. systèmes c'est la solution la plus simple,
- [Kubernetes in Docker (kind) :](#kind) pour tenter l'aventure sur votre machine,
- [Play With Kubernetes :](#pwk) si vous ne vous en sortez pas avec `kind`.
\newpage
Docker for Mac/Windows {#dockerdesktop}
----------------------
*Docker Desktop* pour Mac ou pour Windows intégre Kubernetes directement. Il
n'est pas activé par défaut, pour cela il convient d'activer l'option dans les
préférences de l'application :
![Paramètres de Docker Desktop](docker-desktop-k8s.png)
Une fois l'option activée, vous pouvez passer au chapitre suivant, la commande
`kubectl` devrait marcher directement pour vous. C'est principalement grâce à
cette commande que nous interagirons avec l'API de Kubernetes.
Une fois que tout sera opérationnel, nous devrions obtenir :
<div lang="en-US">
```
42sh$ kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"archive", BuildDate:"2021-11-18T15:50:50Z", GoVersion:"go1.17.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.5+k3s2", GitCommit:"724ef700bab896ff252a75e2be996d5f4ff1b842", GitTreeState:"clean", BuildDate:"2021-10-05T19:59:14Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"}
```
</div>
Kubernetes in Docker (kind) Kubernetes in Docker (kind) {#kind}
--------------------------- ---------------------------
`kind` est un projet permettant de lancer un cluster kubernetes directement via `kind` est un projet permettant de lancer un cluster Kubernetes directement via
Docker. Docker.
Pour commencer, il nous faudra télécharger le binaire (go, donc statique) Pour commencer, il nous faudra télécharger le binaire (go, donc statique)
@ -44,15 +80,28 @@ suivant (il existe pour Linux, macOS et Windows) :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
curl -Lo kind https://github.com/kubernetes-sigs/kind/releases/download/v0.9.0/kind-$(uname)-amd64 curl -Lo kind https://github.com/kubernetes-sigs/kind/releases/download/v0.11.1/kind-$(uname)-amd64
chmod +x kind chmod +x kind
``` ```
</div> </div>
Placez-le dans un endroit où il sera accessible de votre `$PATH`. Placez le binaire dans un endroit où il sera accessible de votre `$PATH`.
::::: {.question}
`uname` est à remplacer par votre système d'exploitation : `darwin` (macOS), `linux`, `windows`.
Il existe également pour d'autres architectures, consultez la [page des
versions](https://github.com/kubernetes-sigs/kind/releases/latest) pour voir
les différents binaires existants.
:::::
Notre prochaine étape est de décrire le cluster que l'on souhaite avoir : 1 Notre prochaine étape est de décrire le cluster que l'on souhaite avoir : 1
master et 2 workers. Avant de lancer leur création. master et 2 workers, ça fera l'affaire. Attention tout de même de ne pas être
trop extravagant, car chaque nœud consomme pas mal de RAM ! Et puis nous
pourrons facilement changer cette configuration plus tard.
<div lang="en-US"> <div lang="en-US">
```bash ```bash
@ -81,12 +130,12 @@ Profitons-en pour télécharger `kubectl` :
<div lang="en-US"> <div lang="en-US">
```bash ```bash
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.19.4/bin/linux/amd64/kubectl curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.22.2/bin/linux/amd64/kubectl
chmod +x kubectl chmod +x kubectl
``` ```
</div> </div>
C'est via cette commande que nous interagirons principalement avec l'API de C'est principalement grâce à cette commande que nous interagirons avec l'API de
Kubernetes. Kubernetes.
Une fois que tout sera opérationnel, nous devrions obtenir : Une fois que tout sera opérationnel, nous devrions obtenir :
@ -94,19 +143,26 @@ Une fois que tout sera opérationnel, nous devrions obtenir :
<div lang="en-US"> <div lang="en-US">
``` ```
42sh$ kubectl version 42sh$ kubectl version
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"archive", BuildDate:"2020-11-18T12:02:06Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"} Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"archive", BuildDate:"2021-11-18T15:50:50Z", GoVersion:"go1.17.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.1", GitCommit:"206bcadf021e76c27513500ca24182692aabd17e", GitTreeState:"clean", BuildDate:"2020-09-14T07:30:52Z", GoVersion:"go1.15", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.5+k3s2", GitCommit:"724ef700bab896ff252a75e2be996d5f4ff1b842", GitTreeState:"clean", BuildDate:"2021-10-05T19:59:14Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"}
``` ```
</div> </div>
Par défaut, `kubectl` va tenter de contacter le port local 2375, `kind` aura Par défaut, `kubectl` va tenter de contacter le port local 2375, `kind` aura
pris soin de l'exposer pour vous au moment de la création du cluster. pris soin de l'exposer pour vous au moment de la création du cluster.
Passez ensuite à la section 2 si vous avez réussi à mettre en place `kind`. Passez ensuite au chapitre suivant si vous avez réussi à mettre en place `kind`.
Play With Kubernetes Play With Kubernetes {#pwk}
-------------------- --------------------
::::: {.warning}
Cette section vous concerne uniquement si vous n'avez pas réussi à créer de
cluster Kubernetes selon les autres méthodes décrites.
:::::
De la même manière que pour les TP utilisant Docker, si vous avez des De la même manière que pour les TP utilisant Docker, si vous avez des
difficultés pour réaliser les exercices sur vos machines, vous pouvez utiliser difficultés pour réaliser les exercices sur vos machines, vous pouvez utiliser
le projet [Play With K8s](https://play-with-k8s.com/) qui vous donnera accès à le projet [Play With K8s](https://play-with-k8s.com/) qui vous donnera accès à
@ -126,7 +182,7 @@ kubeadm init --apiserver-advertise-address $(hostname -i)
``` ```
</div> </div>
Cette action peut prendre quelques minutes, et devrait se finir, si tout se Cette action peut prendre quelques minutes et devrait se finir, si tout se
passe bien, par : passe bien, par :
<div lang="en-US"> <div lang="en-US">
@ -166,15 +222,27 @@ kubectl apply -n kube-system -f \
</div> </div>
Minikube, Docker for Mac/Windows, MicroK8s, ... Minikube, k3d, MicroK8s, ...
----------------------------------------------- ----------------------------
Si les solutions précédentes ne sont pas adaptées à votre usage, de nombreuses Si les solutions précédentes ne sont pas adaptées à votre usage, de nombreuses
autres applications permettent de mettre en place un cluster plus ou moins autres applications permettent de mettre en place un cluster plus ou moins
complet, facilement. complet facilement.
Vous pouvez tenter d'utiliser Vous pouvez tenter d'utiliser
[k3d](https://k3d.io/),
[minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/), [minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/),
[microk8s](https://microk8s.io/), ... Notez également que *Docker for Mac* et [microk8s](https://microk8s.io/), ...
*Docker for Windows* intègrent aussi Kubernetes depuis quelques versions ;
il convient de l'activer dans les préférences de l'application. ##### `k3d` {-}
est un script similaire à `kind`, mais utilise `k3s`, une version plus légère
et compacte de Kubernetes.
Après l'avoir installé, vous pouvez lancer
<div lang="en-US">
```bash
k3d cluster create mycluster --agents 2 --kubeconfig-switch-context
```
</div>

View file

@ -3,13 +3,13 @@ title: Ελαφριά εικονικοποίηση -- Πρακτική δουλ
subtitle: κυβερνήτης subtitle: κυβερνήτης
author: Πιέρ-Ολιβιέ *νεμυναιρε* [ῥαφοπώλης]{.smallcaps} author: Πιέρ-Ολιβιέ *νεμυναιρε* [ῥαφοπώλης]{.smallcaps}
institute: ΣΠκΠΤ institute: ΣΠκΠΤ
date: Πέμπτη 19 Νοεμβρίου 2021 date: Παρασκευή 19 Νοεμβρίου 2021
abstract: | abstract: |
Ο στόχος αυτού του τελευταίου εργαστηρίου είναι να κατανοήσει το κυβερνήτης και την ενορχήστρωση εμπορευματοκιβωτίων. Ο στόχος αυτού του τελευταίου εργαστηρίου είναι να κατανοήσει το κυβερνήτης και την ενορχήστρωση εμπορευματοκιβωτίων.
\vspace{1em} \vspace{1em}
Οι ασκήσεις για αυτό το πρακτικό έργο μπορούν να επιστραφούν στη διεύθυνση <ανδροππήςρε@nemunai.re> το αργότερο την Πέμπτη 26 Νοεμβρίου 2021 στις 11:42 μ.μ., οι ερωτήσεις των μαθημάτων πρέπει επίσης να ολοκληρωθούν πριν από αυτήν την ημερομηνία. Δείτε το τελευταίο μέρος αυτού του εργαστηρίου για λεπτομέρειες. Οι ασκήσεις για αυτό το πρακτικό έργο μπορούν να επιστραφούν στη διεύθυνση <ανδροππήςρε@nemunai.re> το αργότερο την Παρασκευή 3 Δεκεμβρίουz 2021 στις 11:42 μ.μ., οι ερωτήσεις των μαθημάτων πρέπει επίσης να ολοκληρωθούν πριν από αυτήν την ημερομηνία. Δείτε το τελευταίο μέρος αυτού του εργαστηρίου για λεπτομέρειες.
Καθώς οι άνθρωποι γνωρίζουν την ασφάλεια των ηλεκτρονικών ανταλλαγών, πρέπει να μου στείλετε τις υπογεγραμμένες αποδόσεις σας με το κλειδί PGP. Θυμηθείτε να [με](https://keys.openpgp.org/search?q=nemunaire%40nemunai.re) υπογράψετε το κλειδί σας και μην διστάσετε [να υπογράψετε το δικό σας](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/). Καθώς οι άνθρωποι γνωρίζουν την ασφάλεια των ηλεκτρονικών ανταλλαγών, πρέπει να μου στείλετε τις υπογεγραμμένες αποδόσεις σας με το κλειδί PGP. Θυμηθείτε να [με](https://keys.openpgp.org/search?q=nemunaire%40nemunai.re) υπογράψετε το κλειδί σας και μην διστάσετε [να υπογράψετε το δικό σας](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
... ...

View file

@ -3,7 +3,7 @@ title: Virtualisation légère -- TP n^o^ 6
subtitle: Kubernetes subtitle: Kubernetes
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps} author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
institute: EPITA institute: EPITA
date: Jeudi 19 novembre 2021 date: Vendredi 19 novembre 2021
abstract: | abstract: |
Le but de ce dernier TP est d'appréhender Kubernetes et l'orchestration de Le but de ce dernier TP est d'appréhender Kubernetes et l'orchestration de
conteneurs. conteneurs.