2021 tuto

This commit is contained in:
nemunaire 2021-09-11 14:41:43 +02:00
commit c4bb727cd4
29 changed files with 422 additions and 257 deletions

View file

@ -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).