#+TITLE: Cours de virtualisation avancée: /Kubernetes/, suite
#+OPTIONS: toc:nil date:nil author:nil reveal_single_file:t timestamp:nil
#+LATEX_CLASS: article
#+LATEX_CLASS_OPTIONS: [12pt,a4paper]
#+LATEX_HEADER: \usepackage[a4paper,margin=0.5in]{geometry}
#+LATEX_HEADER: \usepackage[utf8]{inputenc}
#+LATEX_HEADER: \usepackage[inkscapelatex=false]{svg}
#+LATEX_HEADER: \usepackage[sfdefault]{AlegreyaSans}
#+LATEX_HEADER: \usepackage{multicol}
#+LATEX_HEADER: \usepackage{minted}
#+LATEX_HEADER: \usepackage{float}
#+LATEX_HEADER: \usepackage{tikz}
#+LATEX_HEADER: \usetikzlibrary{positioning}
#+LATEX_HEADER: \renewcommand\listingscaption{Exemple de code}

#+REVEAL_THEME: white
#+REVEAL_INIT_OPTIONS: slideNumber:true
#+REVEAL_EXTRA_CSS: ../../common/reveal_custom.css

* Déploiement
** /Rolling Updates/
Permet des mises à jour d'images sans temps de coupure
#+BEGIN_SRC yaml
---
...
spec:
  ...
  strategy: 
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
  ...
#+END_SRC

#+REVEAL: split

- =maxUnavailable=: défini le nombre maximal de /replicas/ indisponibles
- =maxSurge=: défini le nombre maximal de /replicas/ à mettre à jour en même temps

#+REVEAL: split

Ensuite, mettre à jour l'image avec:
#+BEGIN_SRC bash
kubectl set image deployment/<nom déploiement> <nom conteneur>=<nouvelle image:tag>
#+END_SRC

*But*:
- Mettre à jour l'application sans /downtime/

** Déploiement /blue / green/
[[file:./images/blue_green.svg]]

#+REVEAL: split

- On déploie la nouvelle version en parallèle de l'ancienne
- Une fois que tout est déployé on redirige le trafic vers le nouveau déploiement

*But*:
- Tester le déploiement de la nouvelle version avant de la basculer en prod

** Déploiement /canary/
[[file:./images/canary.svg]]

#+REVEAL: split

- On déploie la nouvelle version en parallèle de l'ancienne *avec moins de /replicas/*
- Automatiquement une petite partie des clients tomberont sur la nouvelle version

*But*:
- Faire tester à quelques utilisat(eur|rice)s aléatoires la nouvelle version

* Mise à l'échelle (/scaling/)

- Nécessaire quand la charge augmente
- Par exemple pour suivre l'augmentation du trafic de notre application

** Verticale (/vertical scaling/)
*** Fonctionnement
- On augmente la puissance des nœuds
- Augmente les capacité de l'application existante
- L'application *n'a pas besoin d’être capable de gérer la réplication*

*** Inconvénients
- Augmentation des coûts
- Coûts pas toujours proportionnels à la puissance des nœuds
- Si nœud déjà au max: comment faire ?

** Horizontale (/horizontal scaling/)
*** Fonctionnement
- On ajoute des nœuds (et donc des nouvelles instances) à l'infra
- La charge de travail est donc répartie entre les instances
- L'application *a besoin d’être capable de gérer la réplication*

*** Inconvénients
- Augmentation des coûts
- On peut se retrouver avec beaucoup de nœuds

** /Horizontal scaling/ dans /K8S/
[[https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/][doc]]
[[https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/][doc]]

#+BEGIN_SRC bash
kubectl autoscale deployment <nom déploiement> \
        --cpu-percent=50 --min=1 --max=10
#+END_SRC

#+REVEAL: split

Demande au /cluster/ de créer entre =min= et =max= /replicas/ selon la charge du /CPU/ du nœud

** /Vertical scaling/ dans /K8S/
Compliqué à mettre en place sur sa propre infra étant donné qu'il faut changer les ressources des machines.

* Réseau
** Rappels
[[file:./images/networking.svg]]

** /Ingress/
[[https://kubernetes.io/fr/docs/concepts/services-networking/ingress/][doc]]
[[https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/][doc]]

- Permet d'exposer nos services en dehors du /cluster/
- Assez similaire à un /reverse proxy/ comme vous aviez déjà vu avec /Nginx/

- Nécessite des ressources configurées par les administrat(eur|rice)s du /cluster/

#+REVEAL: split

#+BEGIN_SRC yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
spec:
  defaultBackend:
    service:
      name: testsvc
      port:
        number: 80
#+END_SRC

#+REVEAL: nginx

#+BEGIN_SRC bash
❯ kubectl get ingress test-ingress
NAME           HOSTS     ADDRESS           PORTS     AGE
test-ingress   *         107.178.254.228   80        59s
#+END_SRC

#+REVEAL: split

- Peut aussi servir de *routeur /HTTP/* en dirigeant le trafic des routes vers différents services

#+REVEAL: split

#+BEGIN_SRC yaml
...
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 4200
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 8080  
#+END_SRC

* Sécurité et gestion d'utilisat(eur|rice)s
** Contrôle d'accès basé sur les rôles (/RBAC/)
[[https://kubernetes.io/fr/docs/reference/access-authn-authz/rbac/][doc]]

- Permet de réguler l'accès aux ressources en fonction de *rôles* attribués aux *utilisat(eur|rice)s*

*** /Role/ et /ClusterRole/

Pour créer les rôles (au sens large)

#+BEGIN_SRC yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
#+END_SRC

#+REVEAL: split

- Ce rôle permet de définir un accès en *lecture seule* aux */pods/* de l'espace de noms */default/*
- Le type /Role/ concerne *toujours* l'espace de noms dans lequel il est créé

#+REVEAL: split

#+BEGIN_SRC yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # pas de "namespace"
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]  
#+END_SRC

#+REVEAL: split

- Ce rôle permet de définir un accès en *lecture seule* aux */pods/* dans *n'importe quel* espace de noms

*** /RoleBinding/ et /ClusterRoleBinding/

Pour accorder les rôles (au sens large) à un.e ou des utilisat(eur|rice)s, ou un groupe

#+BEGIN_SRC yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane # sensible à la casse
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
#+END_SRC
  
* Aller plus loin
- https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/
- https://kubernetes.io/fr/docs/concepts/services-networking/ingress/
- https://kubernetes.io/fr/docs/reference/access-authn-authz/rbac/
