---
# System prepended metadata

title: Untitled

---

kubernetes
----------

```shell
microk8s.kubectl cluster info
alias mk=microk8s.kubectl

mk get nodes

mk get po
mk -n kube-system get po

mk create

mk get no # get the version
```

1 pod = conteneur (sauf cas bizarre)
unité de base = pod

k8s reference: https://kubernetes.io/fr/docs/reference/

Comment écrire en yaml
--------------------
```yaml
cle: valeur
naliste:
    - it1
    - it2
    - it3
    
madeuxliste: [a, b, c]

mondico:
    key1: a
    key2: b
    
malistededico:
    - name: "jegfkajsef fe"
      age: 42
    - name: jean-pierre
      age: 51
```

Normalement commence par "---" et finit par "..."

---
Choses manipulées = ressources
yaml manipulé = manifest
"Je suis en train d'écrire le manifest des ressources de mon pod"

```yaml
---
apiVersion: v1
kind: Pod
metadata:
    name: canard

spec:
    containers:
        - name: printer
          image: alpine
          command: ["/bin/sh"]
          args: ["-c", "while true; do echo 'COINCOIN'; sleep 10; done"]
status:
...
```
manifest commence toujours pareil
seul champs de metadata obligatoire = name
chaque `kind` a un champs spec, mais chacun a sa propre définition
c'est kubernetes qui remplit le champ status, c'est comme ça qu'il m'informe (pas la peine de l'écrire)
pod = sac de conteners

(alpine = mini distrib linux)

donner le yaml:
```shell
42sh$ mk apply -f <fichier.yaml>
pod/<name> created
42sh$ mk get po
NAME     READY    STATUS    RESTARTS    AGE
<name>   1/1      Running   0           <time>
42sh$ mk get po/canard
42sh$ mk get po/canard -o yaml
# rajoute des trucs automatiquement, remplit le status
42sh$ mk logs
# prints du pod
42sh$ mk logs -f po/<name>
# suit en live le pod
42sh$ mk delete -f <fichier.yaml> # kill le pod
pod "<name>" deleted
42sh$ mk delete po/<name> #equivalent
```

Personne en pratique n'utilise les pods directement
Grandes majorités des conteneurs = serveurs (on veut qu'il tourne éternellement) ou job (execute ponctuellement des trucs puis je m'en vais)

replica set = 1er abstraction: est ce que tu peux me lancer n instances de ce pod
workload: lance des pods automatiquement
replica set = un workload

```yaml
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: canard

spec:
    replicas: 3
    selector:
        matchLabels:
            app: canard
    template:
        metadata:
            labels:
                app: canard
                version: first-latest
        spec:
            containers:
                - name: printer
                  image: alpine
                  command: ["/bin/sh"]
                  args: ["-c", "while true; do echo 'COINCOIN'; sleep 10; done"]
status:
...
```
voir la doc pour apiVersion et spec
replicationController: il faut qu'il ait la capacité de compter les pod (si il doit en supprimer, en recréer, etc, quels pods m'interessent
label = association clé-valeur (peut etre ce qu'on veut),
    super importants: demande au replicaset de regarder les pod qui ont un certain label
dans les metadata du template de pod: donne le label du pod
dans les spec de replica: label qu'on veut suivre

```shell
42sh$ mk apply -f <fichier.yaml>
42sh$ mk get po # affiche 3 lignes de pod
42sh$ mk get rs
NAME    DESIRED    CURRENT    READY    AGE
canard  3          3          3        <time>
42sh$ mk get po -l 'app=canard'
42sh$ mk delete po/canard-poi
42sh$ mk get po -l 'app=canard'
NAME        READY    STATUS        RESTARTS    AGE
canard-kjn  1/1      Running       0           <time>
canard-poi  1/1      Terminating   0           <time>
canard-min  1/1      Running       0           <time>
canard-bmn  1/1      Running       0           <time> # il a créé un nouveau pod automatiquement
```

daemonSet = pour faire du système
Personne n'écrit de replicaSet à la main

Je veux un niveau d'abstraction en plus (mise à jour, cycle de vie, déploiement, rollback)

Deployment: lance des replicaSet qui lancent des pods

```yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
    name: canard

spec:
    replicas: 3
    selector:
        matchLabels:
            app: canard
    template:
        metadata:
            labels:
                app: canard
                version: first-latest
        spec:
            containers:
                - name: printer
                  image: alpine
                  command: ["/bin/sh"]
                  args: ["-c", "while true; do echo 'COINCOIN'; sleep 10; done"]
status:
...
```

```shell
42sh$ mk apply -f <fichier.yaml>
Deployment.apps/canard created
42sh$ mk get po
42sh$ mk get rs
42sh$ mk get deploy
NAME    READY    UP-TO-DATE    AVAILABLE    AGE
canard  3/3      3             3            <time>
```

on change le yaml
```shell
42sh$ mk apply -f <fichier.yaml>
deployment.apps/canard configured
42sh$ mk rollout status deploy/canard
42sh$ mk rollout history deploy/canard
42sh$ mk rollout undo deploy/canard # rollback 1 mise a jour
deployment.apps/canard rolled back
```
On peut faire un `undo` à l'envers, revenir vers la dernière mise a jour (avec --to-revision et le numero de la revision, à voir avec history)

```shell
42sh$ mk rollout restart deploy/canard # restart all
deployment.apps/canard restarted
```

On veut un loadbalancer interne pour mes pods (pour la backend)
Nouveau concept: le service

addon à installer pour microk8s (pas besoin pour k3s): dns
```shell
42sh$ microk8s.enable dns
```

```shell
42sh$ mk get ns
42sh$ mk -n .....................

```

```yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
    name: spider

spec:
    replicas: 3
    selector:
        matchLabels:
            app: spider
    template:
        metadata:
            labels:
                app: spider
                version: first-latest
        spec:
            containers:
                - name: nginx
                  image: nginx
                  ports:
                      - containerPort: 80
                        name: Web
status:
...
```

```shell
42sh$ mk apply -f <fichier.yaml>
42sh$ mk get po -l app=spider # seulement ceux avec le label "app=spider"
42sh$ mk describe po/spider-cjhvkjn # utile pour debug
42sh$ mk run -it --rm busy --image=busybox
# -it = interactif
# --rm = remove a la fin
# busy = name
> wget -O- 
# -O- = print à l'écran
```

```yaml
---
apiVersion: v1
kind: Service
metadata:
    name: spider

spec:
    selector:
        matchLabels:
            app: spider
    ports:
        - name: Web # on peut ne pas le nommer
          port: 80   # sur lequel faut écouter
          targetPort: Web  # celui du deployment # sur lequel il redirige, entier ou string: le nom
...
```

```shell
42sh$ mk apply -f <fichier.yaml>
42sh$ mk get svc
NAME        TYPE        CLUSTER-IP    EXTERNAL-IP    PORT(S)    AGE
kubernetes  ClusterIP   <..>          <none>         443/TCP    <time>
spider      ClusterIP   <..>          <none>         80/TCP     <time>
42sh$ mk run -it --rm busy --image=busybox
> env
SPIDER_SERVICE_PORT=80
SPIDER_PORT=.....
> wget -0- spider
# it works
> ping spider
# it works
```
Service discovery et loadbalancing

"Donc les services c'est la vie"
Pour l'instant les services ça n'existe que dans le cluster
traffic à l'intérieur du cluster = traffic Est-Ouest
là on a fait que du Est-Ouest

dans la vraie vie: sur un cloud

```shell
42sh$ mk get svc/spider -oyaml
```
Ne jamais changé les adresses IP (il les prend au pif)
Truc qu'on peut changer: le type
ClusterIP = que pour Est-Ouest

si AWS, call amazon pour créer machin, pareil pour Azure, etc
metallb: addon pour le faire meme sans cloud
```shell
# pour microk8s
microk8s.enable metallb
# pour k3s voir la doc de metallb
```

(apply -f peut prendre une url)

```shell
42sh$ mk -n metallb-system get po
```

```yaml
---
apiVersion: v1
kind: Service
metadata:
    name: spider

spec:
    type: Loadbalancer
    selector:
        matchLabels:
            app: spider
    ports:
        - name: Web # on peut ne pas le nommer
          port: 80   # sur lequel faut écouter
          targetPort: Web  # celui du deployment # sur lequel il redirige, entier ou string: le nom
...
```

```shell
42sh$ mk apply -f <fichier.yaml>
42sh$ mk get svc
# spider gagne un EXTERNAL-IP
# dans navigateur: EXTERNAL-IP: atterit sur la page
```



ingress = ce qui rentre
egress = ce qui sort

reverse proxy = ingress
donc 1 seul adresse IP pour plusieurs sites/services

ingress controller = regarde les services ingress et update le reverse proxy

nginx: reverse proxy le plus populaire
dans la vraie vie, ce sont les sysadmin et les ops qui installent ça

```shell
42sh$ microk8s.enable ingress
```


```yaml
---
apiVersion: v1
kind: Service
metadata:
    name: spider

spec:
    type: ClusterIP
    selector:
        matchLabels:
            app: spider
    ports:
        - name: Web # on peut ne pas le nommer
          port: 80   # sur lequel faut écouter
          targetPort: Web  # celui du deployment # sur lequel il redirige, entier ou string: le nom
...
```

Par défaut sur le port 80 => localhost

dns menteur: utiliser pour du dev, pas pour de la prod: xip.io (wildcard dns)
dans la vraie vie: sysadmin vous ont donné le wildcard du dns
```yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
    name: spider
spec:
    rules:
    - host: spider
      http:
          paths:
          - backend:
              serviceName: spider
              servicePort: web # nom du port du service
```

```shell
42sh$ mk apply -f <fichier.yaml>
42sh$ mk get ing

# spider.172.0.0.1.xip.io exists !
# others = Error404
```

addon:
- registry: pour tester les pipelines

---

stateless

*Kerlsey Hightower: "Kubernetes support statefull workload I don't" (grand monsieur du Kubernetes)*

**Avancé**: opérateurs dans Kubernetes: créer des ressources custom

statefullset = trop low level => passer par un opérateur

cluster ceph à l'intérieur de Kubernetes: rook.io

postgres dans Kubernetes: ça passe si on passe par PostGresOperator (PGO) (github Crunchydata)

cluster pour etcd (externe): coreos/etcd-operator


> Execute the app as one or more stateless processes
-- 12factor

besoin de stocker ? sur un S3 (toujours un truc sur étagère)

---

prochain cour:
ci pour du deploiement sur kubernetes