2021 tuto
This commit is contained in:
parent
ba77aca73b
commit
c4bb727cd4
29 changed files with 422 additions and 257 deletions
|
|
@ -1,6 +1,6 @@
|
|||
include ../pandoc-opts.mk
|
||||
|
||||
SOURCES_TUTO = tutorial.md setup.md intro.md overview.md discover.md run.md scaling.md rendu.md
|
||||
SOURCES_TUTO = tutorial-el.md setup.md intro.md overview.md discover.md run.md scaling.md rendu.md
|
||||
|
||||
|
||||
all: tutorial.pdf
|
||||
|
|
|
|||
|
|
@ -84,13 +84,13 @@ kubectl -n kube-system get pods
|
|||
```
|
||||
|
||||
Eh oui ! De nombreux services de base pour Kubernetes tournent dans des
|
||||
conteneurs, géré par lui-même... notamment :
|
||||
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`,
|
||||
- `kube-controller-manager` et `kube-scheduler`, deux autres composants
|
||||
indispensables,
|
||||
- `coredns` : un composant additionnel pour gérer la résolution de noms interne
|
||||
- `coredns` : un composant additionnel pour gérer la résolution de noms internes
|
||||
(pour 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.
|
||||
|
|
@ -110,87 +110,98 @@ Nous devons lancer un *pod* (qui ne contiendra qu'un seul conteneur).
|
|||
kubectl run pingpong --image alpine ping 1.1.1.1
|
||||
```
|
||||
|
||||
Outre un avertissement, `kubectl` doit indiquer nous qu'une tâche de
|
||||
déploiement a été créée.
|
||||
`kubectl` doit nous indiquer nous qu'un *pod* a été créée.
|
||||
|
||||
Si l'on affiche la liste des pods, vous devriez avoir quelque chose qui
|
||||
ressemble à cela :
|
||||
|
||||
```
|
||||
$ kubectl get pods
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pingpong-7d49d9bc9-k8fpg 1/1 Running 0 123s
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pingpong 1/1 Running 0 123s
|
||||
```
|
||||
|
||||
#### Déploiement³
|
||||
#### Sortie d'un conteneur
|
||||
|
||||
Si l'on affiche davantage d'informations, on obtient :
|
||||
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` :
|
||||
|
||||
```bash
|
||||
kubectl logs pingpong
|
||||
```
|
||||
|
||||
ou bien :
|
||||
|
||||
```bash
|
||||
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 :
|
||||
|
||||
```bash
|
||||
kubectl delete deploy/pingpong
|
||||
```
|
||||
|
||||
|
||||
### 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
|
||||
de *pod* directement, car cela reviendrait à utiliser Docker, mais des tâches
|
||||
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 1.1.1.1
|
||||
```
|
||||
|
||||
Si l'on regarde maintenant la sortie de `kubectl get all`, on obtient :
|
||||
|
||||
```
|
||||
$ kubectl get all
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/pingpong-7d49d9bc9-k8fpg 1/1 Running 0 123s
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/pingpong-98f6d5899-5wsrm 0/1 ContainerCreating 0 123s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2m3s
|
||||
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 123h
|
||||
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/pingpong 1/1 1 1 123s
|
||||
deployment.apps/pingpong 0/1 1 0 123s
|
||||
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
replicaset.apps/pingpong-7d49d9bc9 1 1 1 123s
|
||||
replicaset.apps/pingpong-98f6d5899 1 1 0 123s
|
||||
```
|
||||
|
||||
Pas de panique, on peut très facilement le décortiquer :
|
||||
|
||||
Les tâches de déploiements (*deployment.apps*) sont des ressources de
|
||||
haut-niveau et sont là pour 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
|
||||
version Y (par exemple si l'on change notre ping d'alpine vers debian), mais
|
||||
éventuellement de revenir sur la version X si besoin, en cours de migration.
|
||||
Elles délèguent aux *replicatsets* la gestion des pods.
|
||||
|
||||
Le *replicatset* est là pour indiquer le nombre de pods que l'on désire, et
|
||||
s'assure que le nombre de pods actuellement lancé est bien en adéquation avec
|
||||
le nombre de pods attendus.
|
||||
s'assurer que le nombre de pods actuellement lancé est bien en adéquation avec
|
||||
le nombre de pods attendu.
|
||||
|
||||
|
||||
Pour résumer : `kubectl run` 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`.
|
||||
|
||||
|
||||
#### Sortie d'un conteneur
|
||||
### Passage à l'échelle : facile ?
|
||||
|
||||
Bref ... 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` :
|
||||
Pour lancer 3 ping en parallèle, modifions la tâche de déploiement comme suit :
|
||||
|
||||
```bash
|
||||
kubectl logs deploy/pingpong
|
||||
```
|
||||
|
||||
Cette ligne est la plus simple, et nous affichera la sortie du premier pod de
|
||||
la tâche de déploiement.
|
||||
|
||||
Pour afficher un pod en particulier, il faut indiquer son nom en entier, en
|
||||
remplaçant `yyyy` par son identifiant :
|
||||
|
||||
```bash
|
||||
kubectl logs -f pingpong-yyyy
|
||||
```
|
||||
|
||||
Notez ici l'option -f qui permet de suivre les logs en direct.
|
||||
|
||||
|
||||
#### Mise à l'échelle : facile ?
|
||||
|
||||
Bien ... maintenant que nous savons nous débrouiller avec `kubectl`, attaquons
|
||||
les choses sérieuses.
|
||||
|
||||
Pour lancer 8 ping en parallèle, modifions la tâche de déploiement comme suit :
|
||||
|
||||
```bash
|
||||
kubectl scale deploy/pingpong --replicas 8
|
||||
kubectl scale deploy/pingpong --replicas 3
|
||||
```
|
||||
|
||||
À ce stade, comme nous ne modifions que le nombre de replicats, Kubernetes va
|
||||
|
|
@ -199,55 +210,18 @@ tout simplement propager ce nombre au *replicatset* existant. Puis, le
|
|||
de pods 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
|
||||
```
|
||||
|
||||
Cela supprime bien un *pod*, mais un autre est relancé instantannément car le
|
||||
*replicatset* constate une différence dans le nombre attendu.
|
||||
|
||||
#### Autres usages de `run`
|
||||
|
||||
Si l'on veut des tâche qui ne redémarrent pas systématiquement, on peut
|
||||
utiliser : `kubectl run --restart=OnFailure` ou `kubectl run --restart=Never`,
|
||||
... au lieu de créer des tâches de déploiement, cela va créer des *jobs* ou des
|
||||
*pods*. On peut même créer l'équivalent de tâches cron avec : `kubectl run
|
||||
--schedule=...`.
|
||||
|
||||
Comme nous venons de le voir, actuellement `kubectl run` sert un peu à tout et
|
||||
n'importe quoi, la ressource créée n'est pas évidente, c'est pour cela que
|
||||
l'avertissement nous recommande d'utiliser `kubectl create` :
|
||||
|
||||
- `kubectl create deployment` pour créer une tâche de déploiement,
|
||||
- `kubectl create job` pour créer un *job*.
|
||||
|
||||
Dans le futur, `kubectl run` servira à lancer un *pod* à usage unique, sans
|
||||
tâche de déploiement ni réplicat.
|
||||
|
||||
|
||||
En fait, `kubectl run` génère une nouvelle spécification, qu'il envoie à l'API
|
||||
de Kubernetes. On peut voir le fichier généré avec la ligne de commande
|
||||
suivante :
|
||||
|
||||
```bash
|
||||
kubectl run --dry-run -o yaml pingpong --image alpine ping 1.1.1.1
|
||||
```
|
||||
|
||||
Le fichier YAML récupéré peut s'utiliser comme suit :
|
||||
|
||||
```bash
|
||||
kubectl apply -f my-specs.yml
|
||||
```
|
||||
|
||||
|
||||
#### Arrêter de flooder 1.1.1.1
|
||||
|
||||
Ok, on s'est bien amusé à ping Cloudflare, pour ne pas être trop méchants, nous
|
||||
pouvons maintenant arrêter nos pods.
|
||||
|
||||
Comme nous l'avons vu juste avant, il ne s'agit pas de tuer chacun des pods un
|
||||
par un, car de nouveaux seraient créés par le *replicatset*. Si l'on supprime
|
||||
le *replicatset*, la tâche de déploiement en rećréera un similaire.
|
||||
Si nous voulons arrêter de DDoS Cloudflare, il ne s'agit pas de tuer chacun des
|
||||
pods un par un, car de nouveaux seraient créés par le *replicatset*. Si l'on
|
||||
supprime le *replicatset*, la tâche de déploiement en rećréera un similaire.
|
||||
|
||||
Pour arrêter nos conteneurs, il convient donc de supprimer la tâche de
|
||||
déploiement :
|
||||
|
|
@ -276,13 +250,13 @@ Il y a différents types de services :
|
|||
|
||||
- `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
|
||||
les nœuds). Il n'y a pas de translation de port a 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
|
||||
cluster, et n'importe qui peut alors s'y connecter. Le port est choisi
|
||||
aléatoirement.
|
||||
- `LoadBalancer` : lorsque l'infrastructure sous-jacente fourni un
|
||||
load-balancer (typiquement AWS, GCE, Azure, ...), un service `NodePort` est
|
||||
créé pour utiiser ce load-balancer externe.
|
||||
créé pour utiliser ce load-balancer externe.
|
||||
- `ExternalName` : une entrée DNS est créée pour avoir un alias.
|
||||
|
||||
|
||||
|
|
@ -309,3 +283,86 @@ youp0m ClusterIP 10.102.129.233 <none> 8080/TCP 42s
|
|||
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 à :
|
||||
|
||||
```bash
|
||||
docker exec -it kind-control-plane curl 10.96.179.154:8080
|
||||
```
|
||||
|
||||
|
||||
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
|
||||
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 :
|
||||
|
||||
```bash
|
||||
kubectl create -f https://virli.nemunai.re/insecure-dashboard.yaml
|
||||
```
|
||||
|
||||
Notez que le dashboard, avec cette configuration, va s'exécuter sans les
|
||||
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 :
|
||||
|
||||
```bash
|
||||
$ kubectl get svc
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
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 :
|
||||
|
||||
```bash
|
||||
$ docker exec -it kind-control-plane curl 127.0.0.1:31505
|
||||
<p class="browsehappy">You are using an <strong>outdated</strong> browser.
|
||||
```
|
||||
|
||||
Pas très sympa... il faudrait que l'on puisse le voir dans un navigateur plus
|
||||
... moderne alors.
|
||||
|
||||
É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 à
|
||||
`127.0.0.1`. Heureusement, au moment de la création de notre cluster, nous
|
||||
avons renseigné plusieurs ports redirigés au sein de notre 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 :
|
||||
|
||||
```yaml
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 80
|
||||
nodePort: 30002
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
En voyant la divergence entre la réalité et la configuration demandée,
|
||||
Kubernetes va tout mettre en œuvre pour se conformer à nos directives. En
|
||||
l'occurrence, il s'agit de changer le port qui expose le service au sein du
|
||||
cluster.
|
||||
|
||||
En fait, on pourra faire exactement la même chose lors d'un changement de
|
||||
version. Kubernetes verra la différence et appliquera une politique de
|
||||
migration déterminée.
|
||||
|
||||
Une fois que c'est fait, nous pouvons fièrement utiliser notre navigateur pour
|
||||
aller sur <http://localhost:30002/> (vous pouvez *Skip* l'authentification,
|
||||
dans cette configuration d'exemple, elle n'est pas nécessaire).
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@ Notre application du jour
|
|||
-------------------------
|
||||
|
||||
Aujourd'hui, nous allons travailler avec un mineur de pépites ... de chocolat !
|
||||
De véritables cookies sont à gagner pour celles et ceux qui auront amassés le
|
||||
plus de pépites avant la pause !
|
||||
Alors, on se fait un bon thé, on prend sa boîte de gâteaux pour tenir le coup,
|
||||
et c'est parti !
|
||||
<!--De véritables cookies sont à gagner pour celles et ceux qui auront amassés le
|
||||
plus de pépites avant la pause !-->
|
||||
|
||||

|
||||
|
||||
|
|
@ -32,7 +34,7 @@ Obtenir l'application
|
|||
|
||||
<div lang="en-US">
|
||||
```shell
|
||||
git clone https://git.nemunai.re/chocominer.git
|
||||
git clone https://gitea.nemunai.re/srs/chocominer.git
|
||||
```
|
||||
</div>
|
||||
|
||||
|
|
@ -62,8 +64,8 @@ de chronograf pour voir l'avancement de recherche de pépites :
|
|||
<http://localhost:8888/sources/1/dashboards/1>
|
||||
|
||||
|
||||
Monté en puissance
|
||||
------------------
|
||||
Montée en puissance
|
||||
-------------------
|
||||
|
||||
```bash
|
||||
docker-compose up -d --scale worker=2
|
||||
|
|
@ -88,6 +90,6 @@ la cause des ralentissements :
|
|||
- 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é en parallèle
|
||||
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` !
|
||||
|
|
|
|||
BIN
tutorial/k8s/nuggets-graph.png
Normal file
BIN
tutorial/k8s/nuggets-graph.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
|
|
@ -9,13 +9,13 @@ spécifications qu'on lui aura demandé.
|
|||
|
||||
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és de nombreuses technologies dans le noyau Linux, notamment les
|
||||
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 des
|
||||
informations, des *spécifications* qui vont altérer l'état du cluster. Et c'est
|
||||
en cherchant à être constamment dans l'état que l'on lui a décrit, qu'il va
|
||||
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
|
||||
|
|
@ -94,7 +94,7 @@ node
|
|||
pod
|
||||
: un groupe de conteneurs travaillant ensemble. Il s'agit de la ressource que
|
||||
l'on déploie sur un *node*. Les conteneurs au sein d'un *pod* ne peuvent pas
|
||||
être séparés pour travailler sur deux *nodes* différent.
|
||||
être séparés pour travailler sur deux *nodes* différents.
|
||||
|
||||
service
|
||||
: c'est un point de terminaison (*endpoint*), stable dans le temps, sur lequel
|
||||
|
|
@ -128,8 +128,8 @@ compléter ce schéma...
|
|||
|
||||
Chaque plugin implémente la [spécification
|
||||
CNI](https://github.com/containernetworking/cni/blob/master/SPEC.md#network-configuration)
|
||||
(Container Network Interface). On trouve donc autant de plugin qu'il n'y a de
|
||||
besoin en terme de réseau.
|
||||
(Container Network Interface). On trouve donc autant de plugin qu'il y a de
|
||||
besoins en terme de réseau.
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -3,8 +3,41 @@
|
|||
Rendu
|
||||
=====
|
||||
|
||||
Il n'y a rien à rendre pour ce TP. Profitez-en pour avancer sur le projet !
|
||||
Modalités de rendu
|
||||
------------------
|
||||
|
||||
Mais n'oubliez pas de répondre au
|
||||
[sondage](https://www.epitaf.fr/moodle/mod/feedback/view.php?id=305) pour me
|
||||
permettre d'améliorer ce cours.
|
||||
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 <ανδροππήςρε@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.
|
||||
|
||||
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/8)
|
||||
pour me permettre d'améliorer ce cours.
|
||||
|
||||
|
||||
Tarball
|
||||
-------
|
||||
|
||||
Tous les exercices de ce TP sont à placer dans une tarball (pas d'archive ZIP,
|
||||
RAR, ...).
|
||||
|
||||
Voici une arborescence type :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
login_x-TP6/my-cluster.yml
|
||||
login_x-TP6/my-dashboard.yaml
|
||||
login_x-TP6/influxdb.yml # values.yml avec Helm ou le fichier passé à kubectl -f
|
||||
login_x-TP6/chronograph.yml
|
||||
login_x-TP6/daemonset-rng.yml
|
||||
```
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,94 +7,87 @@ 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 :
|
||||
|
||||
- construire les images de notre application ;
|
||||
- publier ces images dans un registre ;
|
||||
- lancer des déploiements de ces images ;
|
||||
- exposer avec un ClusterIP les services qui ont besoin de communiquer
|
||||
entre-eux ;
|
||||
- exposer avec un NodePort l'interface graphique de contrôle.
|
||||
|
||||
|
||||
Rappels sur les registres
|
||||
-------------------------
|
||||
Lancement des *pods*
|
||||
--------------------
|
||||
|
||||
Pour rappel, lorsque l'on exécute un `docker run alpine`, Docker va étendre le
|
||||
nom de l'image en `library/alpine` puis `index.docker.io/library/alpine`. Pour
|
||||
interroger `index.docker.io` au sujet d'une image `library/alpine:latest`.
|
||||
### Via Helm
|
||||
|
||||
Si l'on souhaite utiliser un autre registre que le Docker Hub, il faut alors
|
||||
préciser le domaine à utiliser : `registry.mycompany.io:5000/myimage:awesome`,
|
||||
...
|
||||
[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
|
||||
Kubernetes.
|
||||
|
||||
Helm se veut donc, notamment, être un moyen de packager une application, pour
|
||||
que ce soit plus simple de l'ajouter à son cluster k8s. L'[artifact
|
||||
hub](https://artifacthub.io/) est une agrégation de différents dépôts,
|
||||
permettant de trouver facilement son bonheur. On va y trouver
|
||||
[`influxdb`](https://artifacthub.io/packages/helm/influxdata/influxdb) dont on
|
||||
va avoir besoin pour la suite.
|
||||
|
||||
Sur la route du registre auto-hébergé
|
||||
-------------------------------------
|
||||
Mais d'abord, il va nous falloir [installer
|
||||
helm](https://helm.sh/docs/intro/install/). Il utilisera la même configuration
|
||||
que `kubectl`, il n'y a rien de plus à configurer.
|
||||
|
||||
Profitons d'avoir notre cluster Kubernetes pour y installer un registre Docker
|
||||
!
|
||||
|
||||
Nous allons déployer l'image officielle de registre Docker : `registry` et
|
||||
faire en sorte que celle-ci stocke les couches des images en local.
|
||||
|
||||
La subtilité à ne pas oublier, est que Docker nécessite d'avoir une connexion
|
||||
chiffrée avec ses registres, à moins qu'il ne soit lancé avec le flag
|
||||
`--insecure-registry`, ou que le registre soit sur `127.0.0.0/8`.
|
||||
|
||||
L'idée sera donc de publier notre registre via un `NodePort`, afin qu'il soit
|
||||
disponible sur un port `127.0.0.1:xxxxx` de chaque nœud :
|
||||
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 :
|
||||
|
||||
```bash
|
||||
kubectl create deployment registry --image=registry
|
||||
kubectl expose deploy/registry --port=5000 --type=NodePort
|
||||
helm install influxdata/influxdb --generate-name
|
||||
```
|
||||
|
||||
Pour tester, vous pouvez :
|
||||
Les valeurs de configuration indiquées dans le `README` du *chart* se modifient
|
||||
ainsi :
|
||||
|
||||
```bash
|
||||
NODEPORT=$(kubectl get svc/registry -o json | jq .spec.ports[0].nodePort)
|
||||
REGISTRY=127.0.0.1:$NODEPORT
|
||||
curl $REGISTRY/v2/_catalog
|
||||
helm upgrade -f values.yml your-influx-name influxdata/influxdb
|
||||
```
|
||||
|
||||
```bash
|
||||
docker pull busybox
|
||||
docker tag busybox $REGISTRY/busybox
|
||||
docker push $REGISTRY/busybox
|
||||
```
|
||||
Il vous sera entre-autre nécessaire d'ajouter un administrateur afin de pouvoir
|
||||
utiliser la base de données.
|
||||
|
||||
Nous pouvons ensuite faire de même avec
|
||||
[Chronograf](https://artifacthub.io/packages/helm/influxdata/chronograf) ou
|
||||
mixer avec la méthode ci-dessous (en adaptant certaines valeurs).
|
||||
|
||||
|
||||
Utiliser les images du Docker Hub
|
||||
---------------------------------
|
||||
### Via `kubectl`
|
||||
|
||||
Si vous n'avez pas réussi à déployer votre propre registre (ou si on n'est pas
|
||||
en avance pour avoir le temps de regarder ça !), utilisez les images mises à
|
||||
disposition sur le Docker Hub :
|
||||
|
||||
- `nemunaire/worker:v0.1`
|
||||
- `nemunaire/rng:v0.1`
|
||||
- `nemunaire/hasher:v0.1`
|
||||
|
||||
|
||||
Lançons les images standards
|
||||
----------------------------
|
||||
|
||||
#### `influxdb` et `chronograf`
|
||||
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
|
||||
par lancer `influxdb` :
|
||||
|
||||
```bash
|
||||
kubectl create deployment chronograf --image=chronograf
|
||||
kubectl apply -f https://virli.nemunai.re/influxdb.yaml
|
||||
```
|
||||
|
||||
#### Notre application
|
||||
Pour chronograf, la commande suivante fonctionnerait, mais prenons exemple sur
|
||||
le fichier YAML d'InfluxDB pour Chronograf :
|
||||
|
||||
```bash
|
||||
TAG=v0.1
|
||||
kubectl create deployment chronograf --image=chronograf -- chronograf \
|
||||
--influxdb-url=http://influxdb:8086 \
|
||||
--influxdb-username=chronograf \
|
||||
--influxdb-password=eBoo8geingie8ziejeeg8bein6Yai1a
|
||||
```
|
||||
|
||||
### Notre application
|
||||
|
||||
```bash
|
||||
TAG=0.1
|
||||
for SERVICE in hasher rng worker; do
|
||||
kubectl create deployment $SERVICE --image=nemunaire/$SERVICE:$TAG
|
||||
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.
|
||||
|
|
@ -112,3 +105,19 @@ kubectl create service nodeport chronograf --tcp=8888 --node-port=30001
|
|||
```
|
||||
|
||||
À 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.
|
||||
|
||||
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`.
|
||||
|
||||

|
||||
|
||||
Vous n'avez pas la même courbe de progression ? continuons le TP alors, pour
|
||||
augmenter la puissance de notre *rig* !
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
\newpage
|
||||
|
||||
Montée en charge
|
||||
================
|
||||
----------------
|
||||
|
||||
Commençons facilement, en augmentant le nombre de `workers` :
|
||||
|
||||
|
|
@ -22,8 +20,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
|
||||
|
|
@ -91,13 +88,13 @@ 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 :
|
||||
|
||||
```bash
|
||||
kubectl get deploy/rng -o yaml --export > rng.yml
|
||||
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
|
||||
|
|
@ -108,13 +105,13 @@ kind: DaemonSet
|
|||
```
|
||||
|
||||
Vous pouvez essayer d'appliquer cette spec, pour voir et essayer de tâtonner
|
||||
grâce aux erreurs renvoyés par l'API.
|
||||
grâce aux erreurs renvoyées par l'API.
|
||||
|
||||
Il vous faudra également retirer le champ `replicas` (qui n'a pas de sens ici,
|
||||
vu que la réplication est basé sur les nœuds), les champs `strategy`,
|
||||
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 :
|
||||
|
|
@ -124,14 +121,14 @@ 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*
|
||||
`rng`. En effet, l'ancien *pod* déployé avec la resource *deployment* est
|
||||
toujours là.
|
||||
|
||||
|
||||
### Bootleneck résolu ?
|
||||
#### Bootleneck résolu ? {-}
|
||||
|
||||
Admirez maintenant dans Chronograf si vous avez réussi à augmenter votre nombre
|
||||
de pépites !
|
||||
|
|
|
|||
|
|
@ -3,12 +3,35 @@
|
|||
Mise en place
|
||||
=============
|
||||
|
||||
La mise en place d'un cluster Kubernetes est une opération très longue, car
|
||||
elle nécessite l'installation et la configuration de nombreux composants.
|
||||
Cette opération n'étant pas très palpitante, nous ne la verrons pas
|
||||
aujourd'hui.
|
||||
La mise en place d'un cluster Kubernetes ([prononcé
|
||||
Ku-ber-né-tèce](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
|
||||
nécessite l'installation et la configuration de nombreux composants avant de
|
||||
pouvoir être utilisé sereinement.
|
||||
|
||||
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
|
||||
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
|
||||
entreprises investir dans la gestion de leur propre cluster Kubernetes. La
|
||||
plupart des entreprises qui choisissent d'utiliser Kubernetes pour gérer leurs
|
||||
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
|
||||
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://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
|
||||
([OVHcloud](https://www.ovhcloud.com/fr/public-cloud/kubernetes/), ...).
|
||||
|
||||
|
||||
Pour jouer aujourd'hui, deux solutions s'offrent à nous pour commencer à
|
||||
utiliser Kubernetes facilement :
|
||||
|
||||
- Kubernetes in Docker (kind) : pour tenter l'aventure sur votre machine,
|
||||
- Play With Kubernetes : si vous ne vous en sortez pas avec `kind`.
|
||||
|
||||
Pour jouer aujourd'hui, deux solutions s'offrent à nous :
|
||||
|
||||
Kubernetes in Docker (kind)
|
||||
---------------------------
|
||||
|
|
@ -17,11 +40,11 @@ Kubernetes in Docker (kind)
|
|||
Docker.
|
||||
|
||||
Pour commencer, il nous faudra télécharger le binaire (go, donc statique)
|
||||
suivant :
|
||||
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.6.0/kind-$(uname)-amd64
|
||||
curl -Lo kind https://github.com/kubernetes-sigs/kind/releases/download/v0.9.0/kind-$(uname)-amd64
|
||||
chmod +x kind
|
||||
```
|
||||
</div>
|
||||
|
|
@ -35,9 +58,16 @@ master et 2 workers. Avant de lancer leur création.
|
|||
```bash
|
||||
cat > my-cluster.yml <<EOF
|
||||
kind: Cluster
|
||||
apiVersion: kind.sigs.k8s.io/v1alpha3
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
nodes:
|
||||
- role: control-plane
|
||||
extraPortMappings:
|
||||
- containerPort: 8080
|
||||
hostPort: 12345
|
||||
- containerPort: 30001
|
||||
hostPort: 30001
|
||||
- containerPort: 30002
|
||||
hostPort: 30002
|
||||
- role: worker
|
||||
- role: worker
|
||||
EOF
|
||||
|
|
@ -51,7 +81,7 @@ Profitons-en pour télécharger `kubectl` :
|
|||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.16.3/bin/linux/amd64/kubectl
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.19.4/bin/linux/amd64/kubectl
|
||||
chmod +x kubectl
|
||||
```
|
||||
</div>
|
||||
|
|
@ -64,11 +94,15 @@ Une fois que tout sera opérationnel, nous devrions obtenir :
|
|||
<div lang="en-US">
|
||||
```
|
||||
42sh$ kubectl version
|
||||
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.3", GitCommit:"b3cbbae08ec52a7fc73d334838e18d17e8512749", GitTreeState:"archive", BuildDate:"2019-11-26T02:51:51Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}
|
||||
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.3", GitCommit:"b3cbbae08ec52a7fc73d334838e18d17e8512749", GitTreeState:"clean", BuildDate:"2019-11-16T01:01:59Z", GoVersion:"go1.12.12", Compiler:"gc", Platform:"linux/amd64"}
|
||||
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"}
|
||||
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"}
|
||||
```
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
||||
Passez ensuite à la section 2 si vous avez réussi à mettre en place `kind`.
|
||||
|
||||
Play With Kubernetes
|
||||
--------------------
|
||||
|
|
@ -135,12 +169,12 @@ kubectl apply -n kube-system -f \
|
|||
Minikube, Docker for Mac/Windows, MicroK8s, ...
|
||||
-----------------------------------------------
|
||||
|
||||
Si les solutions précédentes ne sont pas adaptés à 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
|
||||
complet, facilement.
|
||||
|
||||
Vous pouvez tenter d'utiliser
|
||||
[minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/),
|
||||
[microk8s](https://microk8s.io/), ... Notez également que *Docker for Mac* et
|
||||
*Docker for Windows* intègrent également Kubernetes depuis quelques versions ;
|
||||
*Docker for Windows* intègrent aussi Kubernetes depuis quelques versions ;
|
||||
il convient de l'activer dans les préférences de l'application.
|
||||
|
|
|
|||
15
tutorial/k8s/tutorial-el.md
Normal file
15
tutorial/k8s/tutorial-el.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
title: Ελαφριά εικονικοποίηση -- Πρακτική δουλειά αριθμός 6
|
||||
subtitle: κυβερνήτης
|
||||
author: Πιέρ-Ολιβιέ *νεμυναιρε* [ῥαφοπώλης]{.smallcaps}
|
||||
institute: ΣΠκΠΤ
|
||||
date: Πέμπτη 19 Νοεμβρίου 2020
|
||||
abstract: |
|
||||
Ο στόχος αυτού του τελευταίου εργαστηρίου είναι να κατανοήσει το κυβερνήτης και την ενορχήστρωση εμπορευματοκιβωτίων.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
Οι ασκήσεις για αυτό το πρακτικό έργο μπορούν να επιστραφούν στη διεύθυνση <ανδροππήςρε@nemunai.re> το αργότερο την Πέμπτη 26 Νοεμβρίου 2020 στις 11:42 μ.μ., οι ερωτήσεις των μαθημάτων πρέπει επίσης να ολοκληρωθούν πριν από αυτήν την ημερομηνία. Δείτε το τελευταίο μέρος αυτού του εργαστηρίου για λεπτομέρειες.
|
||||
|
||||
Καθώς οι άνθρωποι γνωρίζουν την ασφάλεια των ηλεκτρονικών ανταλλαγών, πρέπει να μου στείλετε τις υπογεγραμμένες αποδόσεις σας με το κλειδί PGP. Θυμηθείτε να [με](https://keys.openpgp.org/search?q=nemunaire%40nemunai.re) υπογράψετε το κλειδί σας και μην διστάσετε [να υπογράψετε το δικό σας](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
|
||||
...
|
||||
|
|
@ -1,24 +1,23 @@
|
|||
---
|
||||
title: Virtualisation légère -- TP n^o^ 5
|
||||
title: Virtualisation légère -- TP n^o^ 6
|
||||
subtitle: Kubernetes
|
||||
author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps}
|
||||
institute: EPITA
|
||||
date: Mercredi 27 novembre 2019
|
||||
date: Jeudi 19 novembre 2020
|
||||
abstract: |
|
||||
Le but de ce dernier TP est d'appréhender Kubernetes et l'orchestration de
|
||||
conteneurs.
|
||||
|
||||
\vspace{1em}
|
||||
|
||||
Les exercices de ce TP peuvent être rendus à <virli@nemunai.re> au
|
||||
plus tard le mercredi 11 décembre 2019 à 23 h 42, des questions de
|
||||
cours sont également à compléter avant cette date sur
|
||||
Epitaf. Consultez la dernière partie de ce TP pour les modalités.
|
||||
Les exercices de ce TP peuvent être rendus à <virli@nemunai.re> au plus tard
|
||||
le jeudi 26 novembre 2020 à 23 h 42, des questions de cours sont également à
|
||||
compléter avant cette date. Consultez la dernière partie de ce TP pour les
|
||||
modalités.
|
||||
|
||||
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://keys.openpgp.org/search?q=nemunaire%40nemunai.re)
|
||||
faire signer votre clef et n'hésitez pas à [faire signer la
|
||||
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://keys.openpgp.org/search?q=nemunaire%40nemunai.re) faire signer
|
||||
votre clef et n'hésitez pas à [faire signer la
|
||||
votre](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/).
|
||||
...
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue