Split docker-orchestration into docker-advanced and docker-orchestration

This commit is contained in:
nemunaire 2018-10-17 19:31:33 +02:00
commit 4e107e631d
16 changed files with 238 additions and 154 deletions

View file

@ -0,0 +1,25 @@
SOURCES = tutorial.md setup.md what.md manual.md compose.md rendu.md
PANDOCOPTS = --latex-engine=xelatex \
--standalone \
--normalize \
--number-sections \
--smart \
-M lang=fr-FR \
-M fontsize=12pt \
-M papersize=a4paper \
-M mainfont="Linux Libertine O" \
-M monofont="FantasqueSansMono-Regular" \
-M sansfont="Linux Biolinum O" \
-M colorlinks=true \
-M linkcolor="black" \
-M urlcolor="[rgb]{0.2,0.6,0.4}" \
--include-in-header=../header.tex
all: tutorial.pdf
tutorial.pdf: ${SOURCES}
pandoc ${PANDOCOPTS} -o $@ $+
clean::
rm tutorial.pdf

141
tutorial/docker-advanced/check.sh Executable file
View file

@ -0,0 +1,141 @@
#!/bin/sh
note_init() {
NOTE=0
echo -n $@
}
note() {
NOTE=$(($NOTE + $1))
echo -n ,$@
}
for LOGIN in $@
do
note_init $LOGIN
pushd $LOGIN > /dev/null
# Questions
if grep -i "go" questions.txt 2> /dev/null > /dev/null; then
note 1
else
note 0
fi
if grep -E -i "(linkage|static|statique|liaison)" questions.txt 2> /dev/null > /dev/null; then
note 1
else
note 0
fi
# Exercice InfluxDB
DOCKERFILE_influxdb="influxdb/Dockerfile"
if ! [ -f "${DOCKERFILE_influxdb}" ] && [ -f "influxdb/dockerfile" ]; then
DOCKERFILE_influxdb="influxdb/dockerfile"
fi
NBRUN=$(grep -E -i ^RUN "${DOCKERFILE_influxdb}" 2> /dev/null | wc -l)
if [ $NBRUN -le 2 ] && [ $NBRUN -gt 0 ]; then
note 1
else
note 0
fi
if grep -E -i '^EXPOSE.*8083' "${DOCKERFILE_influxdb}" 2> /dev/null > /dev/null && grep -E -i '^EXPOSE.*8086' "${DOCKERFILE_influxdb}" 2> /dev/null > /dev/null && \
grep -i ^EXPOSE "${DOCKERFILE_influxdb}" 2> /dev/null | sed "s/ 8083//g;s/ 8086//g" | grep -E '^EXPOSE[[:space:]]*$' > /dev/null; then
note 1
else
note 0
fi
if grep -E -i '^MAINTAINER[[:space:]]' "${DOCKERFILE_influxdb}" 2> /dev/null > /dev/null; then
note 1
else
note 0
fi
if grep -E -i '^(ADD|COPY)[[:space:]]' "${DOCKERFILE_influxdb}" 2> /dev/null > /dev/null; then
CONFIGFILE=$(grep -E -i '^(ADD|COPY)[[:space:]]' "${DOCKERFILE_influxdb}" | sed -r 's/^(COPY|ADD)[[:space:]]+([^[:space:]]*).*$/\2/')
if [ -f "influxdb/${CONFIGFILE}" ]; then
note 1
else
note 0
fi
else
note 0
fi
# Exercice mymonitoring
DOCKERFILE_mymonitoring="mymonitoring/Dockerfile"
if grep -E -i '^FROM[[:space:]]' "${DOCKERFILE_mymonitoring}" 2> /dev/null > /dev/null; then
note 1
else
note 0
fi
if grep -E -i '^ENV[[:space:]]' "${DOCKERFILE_mymonitoring}" 2> /dev/null > /dev/null; then
note 1
else
note 0
fi
CONFIGFILE=$(grep -E -i '^(ADD|COPY)[[:space:]]' "${DOCKERFILE_mymonitoring}" 2> /dev/null | grep -vi "influx" | grep -vi "chrono" | sed -r 's/^(COPY|ADD)[[:space:]]+([^[:space:]]*).*$/\2/')
if ! [ -f "mymonitoring/${CONFIGFILE}" ]; then
CONFIGFILE="mymonitoring/supervisor.conf"
fi
if [ -f "mymonitoring/${CONFIGFILE}" ]; then
ERRS=0
if grep -E -i "command=.*service.*start" "mymonitoring/${CONFIGFILE}" > /dev/null; then
ERRS=$(($ERRS + 1))
fi
note $((2 - $ERRS))
else
note 0
fi
# Exercice docker-compose
DOCKERCOMPOSE="docker-compose.yml"
NBBUILD=$(grep -E -i "build[[:space:]]*:" "${DOCKERCOMPOSE}" 2> /dev/null | wc -l)
if [ $NBBUILD -ge 2 ]; then
note 2
elif [ $NBBUILD -ge 1 ]; then
note 1
else
note 0
fi
NBVOLS=$(grep -E -i "volumes[[:space:]]*:" "${DOCKERCOMPOSE}" 2> /dev/null | wc -l)
if [ $NBVOLS -ge 2 ]; then
note 2
elif [ $NBVOLS -ge 1 ]; then
note 1
else
note 0
fi
NBNET=$(grep -E -i "networks[[:space:]]*:" "${DOCKERCOMPOSE}" 2> /dev/null | wc -l)
NBLINK=$(grep -E -i "networks[[:space:]]*:" "${DOCKERCOMPOSE}" 2> /dev/null | wc -l)
if [ $NBNET -ge 2 ]; then
note 2
elif [ $NBNET -ge 1 ]; then
note 1
elif [ $NBLINK -ge 1 ]; then
note 2
else
note 0
fi
echo #" = $NOTE"
popd > /dev/null
done

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

View file

@ -0,0 +1 @@
../dockerfiles/chronograf_setup.png

View file

@ -0,0 +1,160 @@
\newpage
Composition de conteneurs
=========================
## Automatiser la construction et le lancement
Au lieu de faire un script pour construire et lancer tous vos conteneurs, nous
allons définir à la racine de notre projet un fichier `docker-compose.yml` qui
contiendra les paramètres d'exécution (et éventuellement les méthodes de
construction).
<div lang="en-US">
```yaml
version: '3'
services:
influxdb:
...
chronograf:
build: grafana/
image: nginx
ports:
- "3000:3000"
volumes:
- ./:/tmp/toto
links:
- influxdb
```
</div>
Ce fichier est un condensé des options que nous passons habituellement au
`docker container run`.
### `version`
Notons toutefois la présence d'une ligne `version` ; il ne s'agit pas de la
version de vos conteneurs, mais de la version du format de fichier
`docker-compose` qui sera utilisé. Sans indication de version, la version
originale sera utilisée.
### `services`
Cette section énumère la liste des services (ou conteneurs) qui seront gérés
par `docker-compose`.
Il peuvent dépendre d'une image à construire localement, dans ce cas ils auront
un fils `build`. Ou ils peuvent utiliser une image déjà existante, dans ce cas
ils auront un fils `image`.
Les autres fils sont les paramètres classiques que l'on va passer à `docker
run`.
### `volumes`
Cette section est le pendant de la commandes `docker volume`.
On déclare les volumes simplement en leur donnant un nom et un driver comme
suit :
<div lang="en-US">
```yaml
volumes:
mysql-data:
driver: local
```
</div>
Pour les utiliser avec un conteneur, on référence le nom ainsi que
l'emplacement à partager :
<div lang="en-US">
```yaml
[...]
mysql:
[...]
volumes:
- mysql-data:/var/lib/mysql
```
</div>
### `network`
Cette section est le pendant de la commandes `docker network`.
Par défaut, Docker relie tous les conteneurs sur un bridge et fait du NAT pour
que les conteneur puisse accéder à l'Internet. Mais ce n'est pas le seul mode
possible !
De la même manière que pour les `volumes`, cette section déclare les réseaux
qui pourront être utilisés par les `services`. On pourrait donc avoir :
<div lang="en-US">
```yaml
networks:
knotdns-slave-net:
driver: bridge
```
</div>
#### Driver `host`
Le driver `host` réutilise la pile réseau de la machine hôte. Le conteneur
pourra donc directement accéder au réseau, sans NAT et sans redirection de
port. Les ports alloués par le conteneur ne devront pas entrer en conflits avec
les ports ouverts par la machine hôte.
#### Driver `null`
Avec le driver `null`, la pile réseau est recréée et aucune interface (autre
que l'interface de loopback) n'est présente. Le conteneur ne peut donc pas
accéder à Internet, ni aux autres conteneur, ...
Lorsque l'on exécute un conteneur qui n'a pas besoin d'accéder au réseau, c'est
le driver à utiliser. Par exemple pour un conteneur dont le but est de vérifier
un backup de base de données.
#### Driver `bridge`
Le driver `bridge` crée un nouveau bridge qui sera partagée entre tous les
conteneurs qui la référencent.
Avec cette configuration, les conteneurs ont accès à une résolution DNS des
noms de conteneurs qui partagent leur bridge. Ainsi, sans avoir à utiliser la
fonctionnalité de `link` au moment du `run`, il est possible de se retrouvé
lié, même après que l'on ait démarré. La résolution se fera dynamiquement.
### Utiliser le `docker-compose.yml`
Consultez
[la documentation](https://docs.docker.com/compose/compose-file/) pour
une liste exhaustive des options que nous pouvons utiliser.
Une fois que votre `docker-compose.yml` est prêt, lancez tout d'abord
`docker-compose build` pour commencer la phase de build de tous les conteneurs
listés dans le fichier.
Une fois le build terminé, nous pouvons lancer la commande suivante et admirer
le résultat :
<div lang="en-US">
```shell
docker-compose up
```
</div>
Encore une fois, testez la bonne connexion entre chronograf (accessible sur
<http://localhost:8888>) et influxdb.
## Rendu
Pour cette partie, vous devrez rendre la dernière itération de votre
`docker-compose.yml`.

View file

@ -0,0 +1,155 @@
\newpage
Lier des conteneurs
===================
Avant de voir des méthodes plus automatiques pour déployer toute notre pile
logicielle TICK, nous allons commencer par mettre en place et lier les
conteneurs manuellement, de la même manière que nous avons pu le faire avec
Owncloud et MySQL.
## Conteneur central : la base de données
Le premier conteneur qui doit être lancé est la base de données orientée séries
temporelles :
[InfluxDB](https://www.influxdata.com/time-series-platform/influxdb/).
En effet, tous les autres conteneurs on besoin de cette base de données pour
fonctionner correctement : il serait impossible à *Chronograf* d'afficher les
données sans base de données, tout comme *Telegraf* ne pourrait écrire les
métriques dans une base de données à l'arrêt.
Afin d'interagir avec les données, InfluxDB expose une
[API REST](https://fr.wikipedia.org/wiki/Representational_state_transfer)
sur le port 8086. Pour éviter d'avoir plus de configuration à réaliser, nous
allons tâcher d'utiliser ce même port pour tester localement :
<div lang="en-US">
```
docker container run -p 8086:8086 -d --name mytsdb influxdb
```
</div>
Comme il s'agit d'une API REST, nous pouvons vérifier le bon fonctionnement de
notre base de données en appelant :
<div lang="en-US">
```
42sh$ curl -f http://localhost:8086/ping
42sh$ echo $?
0
```
</div>
Si votre influxdb répond, vous pouvez vous y connecter en utilisant directement
le client fourni :
<div lang="en-US">
```
42sh$ docker container run --rm -it --link mytsdb:influxdb \
--entrypoint "/usr/bin/influx" influxdb -host influxdb
Connected to http://influxdb:8086 version 1.6.3
InfluxDB shell version: 1.6.3
> show databases
name: databases
name
---------------
_internal
```
</div>
Si vous aussi vous voyez la table `_internal`, bravo ! vous pouvez passer à la
suite.
Notez que comme nous avons lancé le conteneur en mode détaché (option `-d`),
nous ne voyons pas les logs qui sont écrits par le daemon. Pour les voir, il
faut utiliser la commande `docker container logs` :
<div lang="en-US">
```
docker container logs mytsdb
```
</div>
\hspace{2em}**Exercice :** Ajoutez à la ligne de commande de lancement du
conteneur les bon(s) volume(s) qui permettront de ne pas perdre les données
d'influxDB si nous devions redémarrer le conteneur.
## Collecter les données locales
Tentons maintenant de remplir notre base de données avec les métriques du
système. Pour cela, on commence par télécharger *Telegraf* :
<div lang="en-US">
```shell
curl https://dl.influxdata.com/telegraf/releases/telegraf-1.8.1-static_linux_amd64.tar.gz | \
tar xzv -C /tmp
```
</div>
Puis, lançons *Telegraf* :
<div lang="en-US">
```shell
cd /tmp/telegraf
./telegraf --config telegraf.conf
```
</div>
**Remarque :** La configuration par défaut va collecter les données de la
machine locale et les envoyer sur le serveur situé à
`http://localhost:8086`. Ici, cela fonctionne parce que l'on a fait en sorte de
rediriger le port de notre conteneur sur notre machine locale (option `-p`).
Et observons ensuite :
<div lang="en-US">
```shell
42sh$ docker container run --rm -it --link mytsdb:influxdb \
--entrypoint "/usr/bin/influx" influxdb -host influxdb
Connected to http://influxdb:8086 version 1.6.3
InfluxDB shell version: 1.6.3
> show databases
name: databases
name
---------------
_internal
telegraf
> use telegraf
Using database telegraf
> show measurements
name: measurements
name
------------------
cpu
disk
diskio
kernel
mem
processes
swap
system
```
</div>
La nouvelle base a donc bien été créé et tant que nous laissons *Telegraf*
lancé, celui-ci va régulièrement envoyer des métriques de cette machine.
## Afficher les données collectées
\hspace{2em}**Exercice :** À vous de jouer pour lancer le conteneur
[*Chronograf*](https://store.docker.com/images/chronograf).
L'interface de *Chronograf* est disponible sur le port 8888.
Consultez la [documentation du conteneur](https://hub.docker.com/_/chronograf)
si besoin.
![Résultat obtenu](chronograf_latest.png)

View file

@ -0,0 +1,34 @@
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
vérifications élémentaires et de vous envoyer un accusé de réception (ou de
rejet).
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
envoyé à une autre adresse et/ou non signé et/ou reçu après la correction ne
sera pas pris en compte.
Par ailleurs, n'oubliez pas de répondre à
[l'évaluation du cours](https://www.epitaf.fr/moodle/mod/quiz/view.php?id=33).
Tarball
-------
Tous les fichiers identifiés comme étant à rendre pour ce TP sont à
placer dans une tarball (pas d'archive ZIP, RAR, ...).
Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires,
cela dépendra de votre avancée dans le projet) :
<div lang="en-US">
```
login_x-TP2/tp/docker-compose.yml
login_x-TP2/tp/mymonitoring-stack.yml
```
</div>

View file

@ -0,0 +1,70 @@
\newpage
Mise en place
=============
Durant le premier TP, nous avons installé l'environnement Docker principal, qui
inclut le client, le daemon et toute sa machinerie. Mais le projet Docker
propose de nombreuses autres ressources, souvent directement trouvée dans les
usages de la communauté, et parfois même approprié par Docker.
## `docker-compose`
Pour ce TP, nous allons également avoir besoin de `docker-compose`.
Ce projet ne bénéficie pas d'une intégration au sein du projet Docker et doit
être téléchargé séparément, car originellement, le projet était développé par
une équipe indépendante[^fig]. Il constitue aujourd'hui une brique de
l'écosystème Docker, presque indispensable !
[^fig]: Le site du projet initial est toujours en ligne :
<https://www.fig.sh/>.
### Par le gestionnaire de paquets
Les distributions à jour vous proposeront un paquet `docker-compose` qui
fonctionnera avec la version de Docker qu'ils fournissent.
### Par la distribution binaire
L'équipe en charge de Docker compose met à disposition un exécutable contenant
tous les scripts. Nous pouvons l'installer en suivant la procédure suivante :
<div lang="en-US">
```shell
curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-Linux-x86_64 \
> /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
```
</div>
### `pip`
Le projet étant écrit en Python, il est également disponible via `pip`, si vous
préférez cette méthode. N'oubliez pas de préciser une version compatible avec
votre version de Docker.
### Vérification du fonctionnement
Comme avec Docker, nous pouvons vérifier le bon fonctionnement de
`docker-compose` en exécutant la commande :
<div lang="en-US">
```
42sh$ docker-compose --version
docker-compose version: 1.16.1
```
</div>
Si vous obtenez une réponse similaire, c'est que vous êtes prêt à commencer le
TP ! Alors n'attendons pas, partons à l'aventure !
## Play With Docker
Tout comme pour le TP précédent, si vous avez des difficultés pour réaliser les
exercices sur vos machines, vous pouvez utiliser le projet
[Play With Docker](https://play-with-docker.com/) qui vous donnera accès à un
bac à sable avec lequel vous pourrez réaliser tous les exercices de ce TP.

View file

@ -0,0 +1,22 @@
---
title: Virtualisation légère -- TP n^o^ 2.2
subtitle: Aller plus loin avec Docker
author: Pierre-Olivier *Nemunaire* Mercier
institute: EPITA
date: Jeudi 18 octobre 2017
...
Dans cette deuxième partie du TP, nous allons approfondir l'utilisation de Docker !
Tous les éléments de ce TP (exercices et projet) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 24 octobre 2017 à 0 h 42. Consultez la
dernière section de chaque partie pour plus d'information sur les éléments à
rendre.
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 à
[me](https://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96) faire
signer votre clef et n'hésitez pas à
[faire signer votre clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
\tableofcontents

View file

@ -0,0 +1,29 @@
\newpage
But du TP
=========
Aujourd'hui, nous allons réaliser un système de monitoring, prêt à être déployé
chez un fournisseur de cloud.
Le résultat attendu d'ici la fin du TP, est un groupe de conteneurs
indépendants les uns des autres, réutilisables en fonction de besoins
génériques et pouvant facilement être mis à l'échelle.
Nous collecterons les données d'utilisation de votre machine avec
[Telegraf](https://www.influxdata.com/time-series-platform/telegraf/). Ces
données seront envoyés vers
[InfluxDB](https://www.influxdata.com/time-series-platform/influxdb/), puis
elles seront affichées sous forme de graphique grâce à
[Chronograf](https://www.influxdata.com/time-series-platform/chronograf/).
![Dashboard de l'utilisation CPU et mémoire sur Chronograf](chronograf.png)
L'installation que nous allons réaliser est celle d'une plate-forme TICK. Il
s'agit d'un mécanisme de séries temporelles (*Time Series*) moderne, que l'on
peut utiliser pour stocker toute sorte de données liées à un indice temporel.
La pile logicielle TICK propose de collecter des métriques, en les enregistrant
dans une base de données adaptées et permet en suite de les ressortir sous
forme de graphiques ou de les utiliser pour faire des alertes intelligentes.