Save tuto corrections

This commit is contained in:
nemunaire 2022-02-24 20:43:43 +01:00
parent f5ee6b8534
commit 10448a6c8d
115 changed files with 1425 additions and 1291 deletions

View file

@ -1,6 +1,6 @@
include ../pandoc-opts.mk
SOURCES_TUTO = tutorial-el.md setup.md intro.md overview.md discover.md run.md scaling.md rendu.md
SOURCES_TUTO = tutorial-el.md setup.md intro-srs.md intro.md overview.md discover.md run.md scaling.md rendu.md
all: tutorial.pdf

View file

@ -1,22 +1,21 @@
\newpage
Découverte de `kubectl`
=======================
-----------------------
`kubectl`
([prononcé](https://www.reddit.com/r/kubernetes/comments/5qthoc/how_should_i_pronounce_kubectl/)
'cube C T L', 'cube cuttle', 'kyoob cuddle', 'cube control', ...) est le principal
'cube C T L', 'cube cuttle', 'kyoob cuddle', 'cube control', ...) est le principal
programme que l'on utilise pour interagir avec notre cluster.
Étant donné qu'il s'agit d'un programme client, qui ne fait rien de plus que
discuter avec une API REST HTTP, on peut le considérer comme un gros wrapper au
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 :
renseignements et surtout en apprennant comment obtenir de l'aide :
<div lang="en-US">
```bash
@ -26,44 +25,43 @@ 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`, ...
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` :
d'utiliser `get` :
```bash
kubectl get node
```
On peut ajouter des options pour avoir plus d'infos :
On peut ajouter des options pour avoir plus d'infos :
```bash
kubectl get nodes -o wide
```
... ou rendre la sortie lisible par une machine :
... ou rendre la sortie lisible par une machine :
```bash
kubectl get no -o yaml
kubectl get no -o json
```
On aimera utiliser `jq(1)` avec la sortie `-o json` :
On aimera utiliser `jq(1)` avec la sortie `-o json` :
```bash
kubectl get no -o json | \
jq ".items[] | {name:.metadata.name} + .status.capacity"
```
### Services
#### Services
```bash
kubectl get services
@ -75,15 +73,15 @@ Pour le moment, nous n'avons qu'un seul service, il s'agit de l'API Kubernetes.
`ClusterIP` désigne l'IP d'un service accessible en interne, pour le cluster.
### Conteneurs actifs
#### Conteneurs actifs
Jetons un œil aux conteneurs actifs :
Jetons un œil aux conteneurs actifs :
```bash
kubectl get pods
```
Regardons maintenant les `namespaces` :
Regardons maintenant les `namespaces` :
```bash
kubectl get namespaces
@ -91,34 +89,33 @@ kubectl get namespaces
On l'a vu, les *namespaces* ici désignent des espaces de noms qui n'ont rien à
voir avec les *namespaces* de Linux. Regardons par exemple les conteneurs d'un
autre espace de noms :
autre espace de noms :
```bash
kubectl -n kube-system get pods
```
Eh oui ! De nombreux services de base pour Kubernetes tournent dans des
conteneurs, gérés par lui-même... notamment :
Eh oui ! De nombreux services de base pour Kubernetes tournent dans des
conteneurs, gérés par lui-même... notamment :
- `etcd` : notre base de données clef/valeur,
- `kube-apiserver` : l'API REST avec qui communique `kubectl`,
- `etcd` : notre base de données clef/valeur,
- `kube-apiserver` : l'API REST avec qui communique `kubectl`,
- `kube-controller-manager` et `kube-scheduler`, deux autres composants
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 ne pas avoir à s'embêter avec les IP),
- `kube-proxy` : 1 par nœud, pour gérer l'ouverture des ports notamment,
- `kindnet`, `weave` : 1 par nœud, le plugin réseau.
- `kube-proxy` : 1 par nœud, pour gérer l'ouverture des ports notamment,
- `kindnet`, `weave` : 1 par nœud, le plugin réseau.
Mon premier conteneur
---------------------
### Mon premier conteneur
Prêt à lancer notre premier conteneur ?!
Prêt à lancer notre premier conteneur ?!
Pas si vite ! En fait ... Kubernetes ne permet pas de lancer de conteneur...
Pas si vite ! En fait ... Kubernetes ne permet pas de lancer de conteneur...
Nous devons lancer un *pod* (qui ne contiendra qu'un seul conteneur).
### Mon premier pod
#### Mon premier pod
```bash
kubectl run pingpong --image alpine ping 1.1.1.1
@ -127,7 +124,7 @@ kubectl run pingpong --image alpine ping 1.1.1.1
`kubectl` doit nous indiquer nous qu'un *pod* a été créé.
Si l'on affiche la liste des *pod*s, vous devriez avoir quelque chose qui
ressemble à cela :
ressemble à cela :
```
$ kubectl get pods
@ -135,18 +132,18 @@ NAME READY STATUS RESTARTS AGE
pingpong 1/1 Running 0 123s
```
#### Sortie d'un conteneur
##### Sortie d'un conteneur \
Allons maintenant regarder si nous recevons bien nos PONG.
Pour cela, nous allons utiliser la commande `kubectl logs`. Cette commande
s'utilise d'une manière similaire à `docker logs` :
s'utilise d'une manière similaire à `docker logs` :
```bash
kubectl logs pingpong
```
ou bien :
ou bien :
```bash
kubectl logs -f pingpong
@ -155,27 +152,27 @@ kubectl logs -f pingpong
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
kubectl delete pods pingpong
```
### Déploiement³
#### Déploiement³
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
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
de *pod* directement, car cela reviendrait à utiliser Docker. Nous allons
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
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 :
```
NAME READY STATUS RESTARTS AGE
@ -191,12 +188,12 @@ NAME DESIRED CURRENT READY AGE
replicaset.apps/pingpong-98f6d5899 1 1 0 123s
```
Oula, on a vraiment lancé tout ça ?!
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é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 *pod*s d'une version X à une
version Y (par exemple si l'on change notre ping d'alpine 3.14 vers alpine
edge), mais éventuellement de revenir sur la version X si besoin, en cours de
@ -207,14 +204,14 @@ s'assurer que le nombre de *pod*s actuellement lancé est bien en adéquation av
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*
`rs/pingpong-xxxx`. Ce *replicatset* a créé un *pod* `po/pingpong-yyyy`.
### Passage à l'échelle : facile ?
#### Pasage à l'échelle : facile ?
Pour lancer 3 `ping`s 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
kubectl scale deploy/pingpong --replicas 3
@ -227,7 +224,7 @@ de *pod*s en cours d'exécution, il va en lancer de nouveaux, afin de répondre
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* ?
```bash
kubectl delete pod pingpong-yyyy
@ -242,14 +239,14 @@ chacun des *pod*s un par un, car de nouveaux seraient créés par le
recréera un similaire (avec de nouveaux *pod*s).
Pour arrêter nos conteneurs, il convient donc de supprimer la tâche de
déploiement :
déploiement :
```bash
kubectl delete deploy pingpong
```
### Exposer son conteneur
#### Exposer son conteneur
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
@ -262,37 +259,37 @@ Une fois le *service* créé, le serveur DNS interne va permettre de résoudre l
nom du *pod* depuis les autres conteneurs.
#### Types de services
##### Types de services\
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 *pod*s et
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
aléatoirement.
- `LoadBalancer` : lorsque l'infrastructure sous-jacente fournit un
load-balancer (typiquement AWS, GCE, Azure, ...), un service `NodePort` est
- `LoadBalancer` : lorsque l'infrastructure sous-jacente fournit un
load-balancer (typiquement AWS, GCE, Azure, ...), un service `NodePort` est
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.
#### Le retour de `youp0m`
##### Le retour de `youp0m`\
Déployons maintenant l'image `youp0m` pour voir comment utiliser les *service*s :
Déployons maintenant l'image `youp0m` pour voir comment utiliser les *service*s :
```bash
kubectl create deployment youp0m --image=nemunaire/youp0m
```
Commençons par créer un service `ClusterIP` :
Commençons par créer un service `ClusterIP` :
```bash
kubectl expose deployment youp0m --port 8080
```
Ce qui donne :
Ce qui donne :
```
$ kubectl get service
@ -304,15 +301,14 @@ Depuis un nœud du cluster, on peut donc venir interroger cette IP. Si l'on
essaie avec plusieurs nœuds, on voit alors que les requêtes sont balancées sur
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
docker exec -it kind-control-plane curl 10.102.129.233:8080
```
Kubernetes dashboard
--------------------
### Kubernetes dashboard
L'équipe de Kubernetes propose un tableau de bord assez pratique, qui permet de
voir toutes les *resources*, comme nous l'avons fait avec `kubectl`, mais dans
@ -320,7 +316,7 @@ une interface web.
Ils mettent à disposition un fichier décrivant l'état d'un cluster ayant une
telle application. Nous pouvons demander à ce que notre cluster converge vers
la configuration nécessaire :
la configuration nécessaire :
```bash
kubectl create -f https://virli.nemunai.re/insecure-dashboard.yaml
@ -329,13 +325,13 @@ kubectl create -f https://virli.nemunai.re/insecure-dashboard.yaml
::::: {.warning}
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,
on n'utilisera pas cette recette.
:::::
Regardons où nous pouvons contacter notre dashboard :
Regardons où nous pouvons contacter notre dashboard :
```bash
$ kubectl get svc
@ -344,7 +340,7 @@ dashboard NodePort 10.96.78.69 <none> 80:31505/TCP 3m10s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6m51s
```
Regardons si cela répond :
Regardons si cela répond :
```bash
$ docker exec -it kind-control-plane curl 10.96.78.69:80
@ -362,7 +358,7 @@ configuration. Il va donc falloir indiquer à Kubernetes que l'on désire
utiliser un port spécifique pour exposer le tableau de bord.
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 :
```yaml
- port: 80
@ -371,8 +367,8 @@ la partie `Service` un *node port* plus spécifique :
nodePort: 30002
```
Maintenant, nous n'allons pas recréer un nouveau dashboard : nous allons
simplement « appliquer » la nouvelle configuration :
Maintenant, nous n'allons pas recréer un nouveau dashboard : nous allons
simplement « appliquer » la nouvelle configuration :
```bash
kubectl apply -f my-insecure-dashboard.yaml

View file

@ -0,0 +1,10 @@
\newpage
Présentation du fil rouge
-------------------------
Afin d'évaluer Kubernetes, nous allons travailler avec un mineur de
pépites ... de chocolat !
Alors, on se sert un bon thé, on prend sa boîte de gâteaux pour teniir le coup,
et c'est parti !

16
tutorial/k8s/intro-srs.md Normal file
View file

@ -0,0 +1,16 @@
\newpage
Introduction
------------
Aujourd'hui, nous allons travailler avec un mineur de pépites ... de
chocolat !
<!--Alors, on se sert un bon thé, on prend sa boîte de gâteaux pour tenir le coup,
et c'est parti !-->
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.

View file

@ -1,23 +1,9 @@
\newpage
Introduction
============
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 !-->
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)
Fier de respecter le paradigme des micro-services, notre ChocoMiner fonctionne
ainsi :
ainsi :
* le `worker` demande à `rng` de générer un grand nombre aléatoire,
* le `worker` envoie ce grand nombre au `hasher`, qui lui retourne un hash,
@ -31,8 +17,9 @@ Une interface graphique (`chronograf`) permet d'interroger la base de données
pour afficher des statistiques.
Obtenir l'application
---------------------
### Obtenir l'application
Les micro-services sont regroupés sur le dépôt suivant :
<div lang="en-US">
```shell
@ -41,57 +28,64 @@ git clone https://git.nemunai.re/srs/chocominer.git
</div>
Rappels sur la découverte de services
-------------------------------------
### Rappels sur la découverte de services
Dans Docker, nous avions vu que nous n'avions pas besoin de connaître les IP
des conteneurs : un serveur DNS nous permettait de se connecter aux différents
des conteneurs : un serveur DNS nous permettait de se connecter aux différents
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
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 !
Tester avec `docker-compose`
----------------------------
### Tester avec `docker-compose`
<div lang="en-US">
```bash
docker-compose up
```
</div>
Une fois le docker-compose lancé, nous devrions pouvoir accéder à l'interface
de chronograf pour voir l'avancement de recherche de pépites :
Une fois le `docker-compose` lancé, nous devrions pouvoir accéder à l'interface
de chronograf pour voir l'avancement de recherche de pépites :
<http://localhost:8888/sources/1/dashboards/1>
Montée en puissance
-------------------
### Montée en puissance
Avec `docker-compose`, on peut facilement monter en puissance. Commençons en
augmentant doucement le nombre de `worker`, pour voir si cela a un impact :
<div lang="en-US">
```bash
docker-compose up -d --scale worker=2
```
</div>
On remarque que le nombre de hashs calculés augmente ! Génial !
On remarque que le nombre de hashs calculés augmente ! Génial ! Continuons
d'augmenter alors :
<div lang="en-US">
```bash
docker-compose up -d --scale worker=10
```
</div>
Mais ça atteint un palier au bout d'un moment...
Mais l'augmentation n'est plus aussi nette, on semble atteindre un palier au
bout d'un moment...
Identification du goulot d'étranglement
---------------------------------------
### Identification du goulot d'étranglement
De nombreux outils existent pour réaliser des tests de performance, essayons
`httping` sur nos différents services pour voir si un service ne serait pas
la cause des ralentissements :
la cause des ralentissements :
- Testons `rng` : `httping -c 3 localhost:8001`,
- puis testons `hasher` : `httping -c 3 localhost:8002`.
- Testons `rng` : `httping -c 3 localhost:8001`,
- puis testons `hasher` : `httping -c 3 localhost:8002`.
Il semblerait que notre application `rng` nécessite d'être exécutée en parallèle
! Mais on ne peut pas faire de répartition de charge facilement avec
`docker-compose` !
Il semblerait que notre application `rng` nécessite d'être exécutée en
parallèle ! Mais on ne peut pas faire la répartition de charge facilement avec
`docker-compose` !

View file

@ -1,16 +1,16 @@
\newpage
Vue d'ensemble de Kubernetes
============================
----------------------------
*Kubernetes* est un système open source d'orchestration et de gestion de
*Kubernetes* (prononcé
Ku-ber-né-tice](https://github.com/kubernetes/kubernetes/issues/44308) en grec)
est un système open source d'orchestration et de gestion de
conteneurs. C'est-à-dire qu'il se charge de coller constamment aux
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
gestion de conteneurs applicatifs chez Google (rappelons que c'est eux qui ont
poussé de nombreuses technologies dans le noyau Linux, notamment les
*cgroups*, ...).
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 poussé de nombreuses technologies
dans le noyau Linux, notamment les *cgroups*, ...).
Dans Kubernetes, il n'est pas question d'indiquer comment lancer ses
conteneurs, ni même quels *cgroups* utiliser. On va fournir à l'orchestrateur
@ -18,23 +18,22 @@ des informations, des *spécifications*, qui vont altérer l'état du cluster. E
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.
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`
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
(par exemple lors du Black Friday sur une boutique), mais également, il pourra
gérer les mises à jour des conteneurs selon différentes méthodes, ...
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` 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 (par exemple lors du Black Friday sur une boutique),
mais également, on pourra gérer les mises à jour des conteneurs selon
différentes méthodes ...
Architecture de Kubernetes
--------------------------
### Architecture de Kubernetes
![Architecture de Kubernetes](k8s-archi.png)
Un cluster Kubernetes est composé d'un (ou plusieurs) nœuds *master*, et d'une
série de *workers*.
Un cluster Kubernetes est composé dun (ou plusieurs) nœuds *master*, et dune série de *workers*.
Sur le(s) *master(s)*, on retrouve les composants suivants :
Sur le(s) *master(s)*, on retrouve les composants suivants :
API HTTP
: On distingue plusieurs API, elles sont toutes utilisées pour communiquer avec
@ -56,7 +55,7 @@ Le contrôleur
Chaque nœud (généralement, le nœud *master* est également *worker*) est utilisé
via deux composants :
via deux composants :
`kubelet`
: C'est l'agent qui va se charger de créer les conteneurs et les manager, afin
@ -72,19 +71,18 @@ 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
raison pour laquelle il peut être très difficile de mettre en place une
architecture Kubernetes : avec ou sans haute-disponibilité, un nœud master
architecture Kubernetes : avec ou sans haute-disponibilité, un nœud master
dédié au contrôle, avec un moteur de conteneur exotique (`rkt`, `ctr`, ...).
*Resources*
-----------
### *Resources*
Avec Docker, nous avons eu l'habitude de travailler avec des objets (images,
containers, networks, volumes, secrets, ...). Au sein de Kubernetes, cela
s'appelle des *resources* et elles sont très nombreuses.
Parmi les plus courantes, citons les types (désignés *Kind* dans l'API, rien à
voir avec le projet `kind` au début du sujet) suivants :
voir avec le projet `kind` au début du sujet) suivants :
node
: il s'agit d'une machine de notre cluster (elle peut être physique ou
@ -109,12 +107,11 @@ secret
: comme `docker secret`, il s'agit d'un moyen de passer des données sensibles à
un conteneur.
Pour voir la liste complète des *resources*, on utilise : `kubectl
Pour voir la liste complète des *resources*, on utilise : `kubectl
api-resources`.
Modèle réseau
-------------
### Modèle réseau
Pour Kubernetes, il n'y a qu'un seul gros réseau au sein duquel se retrouve
tous les conteneurs. Il ne doit pas y avoir de NAT, que ce soit entre les
@ -135,8 +132,9 @@ loisir d'allouer l'adresse IP, d'ajouter les interfaces réseaux adéquates, de
configurer les routes, les règles de pare-feu, ...
Pour aller plus loin
--------------------
### Pour aller plus loin
* [Kubernetes Documentation](https://kubernetes.io/docs/)
* [A Reference Architecture for Deploying WSO2 Middleware on Kubernetes](https://medium.com/containermind/a-reference-architecture-for-deploying-wso2-middleware-on-kubernetes-d4dee7601e8e)
* La documentation de Kubernetes : <https://kubernetes.io/docs/>
* A Reference Architecture for Deploying WSO2 Middleware on Kubernetes :\
<https://medium.com/containermind/a-reference-architecture-for-deploying-wso2-middleware-on-kubernetes-d4dee7601e8e>
* Les spécifications CNI : <https://github.com/containernetworking/cni/blob/master/SPEC.md#network-configuration>

View file

@ -30,7 +30,7 @@ Tarball
Tous les exercices de ce TP sont à placer dans une tarball (pas d'archive ZIP,
RAR, ...).
Voici une arborescence type :
Voici une arborescence type :
<div lang="en-US">
```

View file

@ -1,27 +1,26 @@
\newpage
Cookies dans Kube
=================
-----------------
Maintenant que nous en savons un peu plus sur Kubernetes, nous allons commencer
à déployer notre application ChocoMiner dans notre cluster. Pour cela, nous
allons devoir :
allons devoir :
- lancer des déploiements de ces images ;
- lancer des déploiements de ces images ;
- exposer avec un ClusterIP les services qui ont besoin de communiquer
entre-eux ;
entre-eux ;
- exposer avec un NodePort l'interface graphique de contrôle.
Lancement des *pod*s
--------------------
### Lancement des *pod*s
### Via Helm
#### Via Helm
[Helm](https://helm.sh/) est l'équivalent d'un gestionnaire de paquets, mais
pour Kubernetes. Nous avons pu voir dans la section précédente qu'il faut
parfois écrire des fichiers de description YAML assez volumineux (et encore,
celui du tableau de bord est tout petit !) afin de se faire comprendre de
celui du tableau de bord est tout petit !) afin de se faire comprendre de
Kubernetes.
Helm se veut donc, notamment, être un moyen de packager une application, pour
@ -37,14 +36,14 @@ 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
la documentation du *chart* d'InfluxDB, nous pouvons le déployer dans notre
cluster :
cluster :
```bash
helm install influxdb influxdata/influxdb
```
Les valeurs de configuration indiquées dans le `README` du *chart* se modifient
ainsi :
ainsi :
```bash
helm upgrade -f values.yml your-influx-name influxdata/influxdb
@ -58,18 +57,18 @@ Nous pouvons ensuite faire de même avec
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
YAML que l'on a utilisés jusqu'à maintenant, et utiliser `kubectl`. Commençons
par lancer `influxdb` :
par lancer `influxdb` :
```bash
kubectl apply -f https://virli.nemunai.re/influxdb.yaml
```
Pour chronograf, la commande suivante fonctionnerait, mais prenons exemple sur
le fichier YAML d'InfluxDB pour Chronograf :
le fichier YAML d'InfluxDB pour Chronograf :
```bash
kubectl create deployment chronograf --image=chronograf -- chronograf \
@ -78,7 +77,7 @@ kubectl create deployment chronograf --image=chronograf -- chronograf \
--influxdb-password=eBoo8geingie8ziejeeg8bein6Yai1a
```
### Notre application
#### Notre application
```bash
TAG=0.1
@ -87,7 +86,7 @@ for SERVICE in hasher rng worker; do
done
```
### Exposer les ports
#### Exposer les ports
Pour trois des applications, des `ClusterIP` font l'affaire, car ils n'ont pas
besoin d'être exposés en dehors du cluster.
@ -101,26 +100,27 @@ 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
kubectl create service nodeport chronograf --tcp=8888 --node-port=30001
```
À ce stade, nous devrions pouvoir accéder à l'interface de Chronograf !
À ce stade, nous devrions pouvoir accéder à l'interface de Chronograf !
Le port 30001 est exposé par `kind` (cela faisait partie des ports redirigés par
Docker entre le nœud *master* et votre machine !), nous devrions donc pouvoir
nous rendre sur : <http://localhost:30001/> pour y voir Chronograf.
Docker entre le nœud *master* et votre machine !), nous devrions donc pouvoir
nous rendre sur : <http://localhost:30001/> pour y voir Chronograf.
Pour afficher un graphique intéressant, on se rend dans *Explore*, on choisit
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
`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
compter (`count`) le nombre d'éléments dans la table `chunks`.
Pour afficher un graphique intéressant, on se rend dans la partie
*Explore*, puis on choisit 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 `summ`, 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 compter (`count`) le nombre d'éléments dans la table
`chunks`.
![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
augmenter la puissance de notre *rig* !
Vous n'avez pas la même courbe de progression ? Alors continuons pour augmenter
la puissance de notre *rig* !

View file

@ -1,16 +1,15 @@
Montée en charge
----------------
### Montée en charge
Commençons facilement, en augmentant le nombre de `workers` :
Commençons facilement, en augmentant le nombre de `workers` :
```bash
kubectl scale deploy/worker --replicas=10
```
Tout comme cela fonctionnait en partie avec `docker-compose`, on obtient ici le
même résultat. Ouf ... c'était pas trop tôt !
même résultat. Ouf ... c'était pas trop tôt !
Nous pouvons profiter de regarder l'augmentation en direct, via la commande :
Nous pouvons profiter de regarder l'augmentation en direct, via la commande :
```bash
kubectl get pods -w
@ -20,7 +19,7 @@ Par contre, ce ne sera pas aussi simple d'augmenter le nombre de `rng`. En
effet, il nous faut répartir les services entre plusieurs machines.
### Daemon sets
#### Daemon sets
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
@ -31,7 +30,7 @@ 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`,
`logstash`, ...), voire du monitoring (Prometheus, `collectd`, ...)
Pour créer un *daemon sets*, il est nécessaire d'écrire un fichier YAML :
Pour créer un *daemon sets*, il est nécessaire d'écrire un fichier YAML :
```yaml
apiVersion: apps/v1
@ -78,7 +77,7 @@ spec:
path: /var/lib/docker/containers
```
Ensuite, on crée le *DaemonSet* en appliquant la nouvelle spécification :
Ensuite, on crée le *DaemonSet* en appliquant la nouvelle spécification :
```bash
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
@ -88,17 +87,17 @@ Pour plus d'informations, consultez [la
documentation](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/).
#### *DaemonSet* `rng`
##### *DaemonSet* `rng`
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
kubectl get deploy/rng -o yaml > rng.yml
```
La première chose que l'on peut faire, c'est changer le type décrit dans le
champ `kind` :
champ `kind` :
```yaml
kind: DaemonSet
@ -111,24 +110,24 @@ Il vous faudra également retirer le champ `replicas` (qui n'a pas de sens ici,
vu que la réplication est basée sur les nœuds), les champs `strategy`,
`progressDeadlineSeconds`, ainsi que la ligne `status: {}`.
##### Force ! {-}
###### Force ! {-}
En fait, plutôt que de corriger ces erreurs, on aurait aussi très bien pu
désactiver la validation comme ceci :
désactiver la validation comme ceci :
```bash
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 *pod*s
`rng`. En effet, l'ancien *pod* déployé avec la ressource *deployment* est
toujours là.
#### Bootleneck résolu ? {-}
##### Botleneck résolu ? {-}
Admirez maintenant dans Chronograf si vous avez réussi à augmenter votre nombre
de pépites !
de pépites !

View file

@ -3,11 +3,9 @@
Mise en place
=============
La mise en place d'un cluster Kubernetes ([prononcé
Ku-ber-né-tice](https://github.com/kubernetes/kubernetes/issues/44308) en grec)
est une opération qui peut s'avérer très longue et complexe, car elle nécessite
l'installation et la configuration de nombreux composants avant de pouvoir être
utilisé sereinement.
La mise en place d'un cluster Kuernetes est une opération qui peut s'avérer
très longue et complexe, car elle nécessite l'installation et la configuration
de nombreux composants avant de pouvoir être utilisé pleinement.
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
@ -19,7 +17,7 @@ plupart des entreprises qui font le choix d'utiliser Kubernetes pour gérer leur
infrastructures, choisissent de passer par un prestataire. L'entreprise délègue
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
Service](https://aws.amazon.com/fr/eks/)), d'Azur ([Kubernetes
Service](https://aws.amazon.com/fr/eks/)), d'Azure [Kubernetes
Service](https://azure.microsoft.com/fr-fr/services/kubernetes-service/)) ou
Google ([Kubernetes Engine](https://cloud.google.com/kubernetes-engine/)), mais
d'autres acteurs plus petits existent aussi
@ -28,79 +26,63 @@ d'autres acteurs plus petits existent aussi
::::: {.more}
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 à
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/
[^k3s]: Lightweight Kubernetes : <https://k3s.io/>
Pour jouer aujourd'hui, plusieurs solutions s'offrent à nous pour commencer à
utiliser Kubernetes facilement :
- [Docker Desktop (for Mac ou for Windows) :](#dockerdesktop) si vous êtes sur l'un de ces
- [Docker Desktop (for Mac ou for Windows) :](#dockerdesktop) si vous êtes sur l'un de ces
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`.
- [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 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 :
préférences de l'application :
![Paramètres de Docker Desktop](docker-desktop-k8s.png)
![Paramètres de Docker Desktop](../k8s/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 :
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"}
Client Version: version.Info{Major:"1", minor:"22", GitVersion:"v1.22.2", [...]
Server Version: version.Info{Major:"1", minor:"21", GitVersion:"v1.21.5", [...]
```
</div>
Kubernetes in Docker (kind) {#kind}
---------------------------
### Kubernetes in Docker (kind) {#kind}
`kind` est un projet permettant de lancer un cluster Kubernetes directement via
Docker.
Pour commencer, il nous faudra télécharger le binaire (go, donc statique)
suivant (il existe pour Linux, macOS et Windows) :
suivant (il existe pour Linux, macOS et Windows) :
<div lang="en-US">
```bash
curl -Lo kind https://github.com/kubernetes-sigs/kind/releases/download/v0.11.1/kind-$(uname)-amd64
chmod +x kind
```
</div>
<https://github.com/kubernetes-sigs/kind/releases/latest>
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.
:::::
Placez le binaire (`chmod +x {}`) dans un endroit où il sera accessible de
votre `$PATH`.
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, ç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
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">
@ -126,25 +108,19 @@ kind create cluster --config my-cluster.yml
La création du cluster peut prendre quelques minutes.
Profitons-en pour télécharger `kubectl` :
<div lang="en-US">
```bash
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.22.2/bin/linux/amd64/kubectl
chmod +x kubectl
```
</div>
Profitons-en pour télécharger `kubectl` :\
<https://storage.googleapis.com/kubernetes-release/release/v1.22.2/bin/linux/amd64/kubectl>
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 :
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"}
Client Version: Version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", [...]
Server Version: Version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.5", [...]
```
</div>
@ -153,8 +129,7 @@ pris soin de l'exposer pour vous au moment de la création du cluster.
Passez ensuite au chapitre suivant si vous avez réussi à mettre en place `kind`.
Play With Kubernetes {#pwk}
--------------------
### Play With Kubernetes {#pwk}
::::: {.warning}
@ -163,18 +138,18 @@ 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 exercices utilisant Docker, si vous avez des
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 à
un bac à sable avec lequel vous pourrez réaliser tous les exercices de ce TP.
un bac à sable avec lequel vous pourrez réaliser tous les exercices.
Il nous faut créer plusieurs instances, disons 3 : parmi elles, 1 instance sera
Il nous faut créer plusieurs instances, disons 3 : parmi elles, 1 instance sera
la master, nous l'utiliserons principalement, les deux autres ne feront
qu'exécuter des conteneurs, nous pourrons les oublier dès qu'on les aura
connectées au master.
Pour initialiser notre cluster Kubernetes, nous allons devoir créer notre
master. Pour cela, dans notre première instance, nous allons taper :
master. Pour cela, dans notre première instance, nous allons taper :
<div lang="en-US">
```bash
@ -183,7 +158,7 @@ kubeadm init --apiserver-advertise-address $(hostname -i)
</div>
Cette action peut prendre quelques minutes et devrait se finir, si tout se
passe bien, par :
passe bien, par :
<div lang="en-US">
```
@ -202,7 +177,7 @@ Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
You can now join any number of machines by running the following on each node
as root:
kubeadm join --token SOMETOKEN SOMEIPADDRESS --discovery-token-ca-cert-hash SOMESHAHASH
kubeadm join --token TOKEN IPADDRESS --discovery-token-ca-cert-hash SHAHASH
```
</div>
@ -212,18 +187,18 @@ master.
Dernière étape pour la mise en place de notre cluster, il s'agit de définir un
profil de politique réseau, sur le master (nous n'exécuterons plus de commande
sur les autres workers) :
sur les autres workers) :
<div lang="en-US">
```bash
kubectl apply -n kube-system -f \
"https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 |tr -d '\n')"
"https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | \
base64 | tr -d '\n')"
```
</div>
Minikube, k3d, MicroK8s, ...
----------------------------
### Minikube, k3d, MicroK8s, ...
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
@ -239,7 +214,7 @@ Vous pouvez tenter d'utiliser
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
Après l'avoir installé, vous pouvez lancer :
<div lang="en-US">
```bash