virli/tutorial/devops/tools.md

198 lines
6.4 KiB
Markdown

\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 : <https://hub.docker.com/r/gitea/gitea>.
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 !