Added 4 tp and cm

main
Evrard Van Espen 11 months ago
parent 8303f01d4f
commit fd35166a82

@ -0,0 +1,247 @@
#+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
** /Service Mesh/
** /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 administrateur.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 utilisateur.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/

@ -0,0 +1,4 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{+w}{ }kubectl\PYG{+w}{ }delete\PYG{+w}{ }pods\PYG{+w}{ }profiles\PYGZhy{}app
pod\PYG{+w}{ }\PYG{l+s+s2}{\PYGZdq{}profiles\PYGZhy{}app\PYGZdq{}}\PYG{+w}{ }deleted
\end{Verbatim}

@ -0,0 +1,8 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{k}{FROM}\PYG{+w}{ }\PYG{l+s}{debian}\PYG{+w}{ }\PYG{k}{as}\PYG{+w}{ }\PYG{l+s}{builder}
\PYG{k}{RUN}\PYG{+w}{ }apt\PYG{+w}{ }install\PYG{+w}{ }\PYGZhy{}y\PYG{+w}{ }nodejs\PYG{+w}{ }npm
\PYG{k}{RUN}\PYG{+w}{ }npm\PYG{+w}{ }install\PYG{+w}{ }\PYG{o}{\PYGZam{}\PYGZam{}}\PYG{+w}{ }npm\PYG{+w}{ }run\PYG{+w}{ }build
\PYG{k}{FROM}\PYG{+w}{ }\PYG{l+s}{nginx}
\PYG{k}{COPY}\PYG{+w}{ }\PYGZhy{}\PYGZhy{}from\PYG{o}{=}builder\PYG{+w}{ }/app/dist/html\PYG{+w}{ }/var/www/html
\end{Verbatim}

@ -0,0 +1,16 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{Pod}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}app}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{containers}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{test\PYGZhy{}container}
\PYG{+w}{ }\PYG{n+nt}{image}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}image}
\PYG{+w}{ }\PYG{n+nt}{env}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{DATABASE\PYGZus{}URI}
\PYG{+w}{ }\PYG{n+nt}{valueFrom}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{configMapKeyRef}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}app\PYGZhy{}config}
\PYG{+w}{ }\PYG{n+nt}{key}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{database\PYGZus{}uri}
\end{Verbatim}

@ -0,0 +1,15 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nn}{\PYGZhy{}\PYGZhy{}\PYGZhy{}}
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{Pod}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} ici le type est \PYGZdq{}pod\PYGZdq{}}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{namespace}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{profiles\PYGZhy{}app\PYGZhy{}ns}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on choisi le namespace}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{profiles\PYGZhy{}app}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} le nom du pod}
\PYG{n+nt}{spec}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} puis ses spécifications}
\PYG{+w}{ }\PYG{n+nt}{containers}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} il contient des conteneurs}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{database}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} nom du conteneur}
\PYG{+w}{ }\PYG{n+nt}{image}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{image:latest}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} l\PYGZsq{}image à utiliser}
\PYG{+w}{ }\PYG{n+nt}{env}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} variables d\PYGZsq{}environnement}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{COULEUR}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} avec un nom}
\PYG{+w}{ }\PYG{n+nt}{value}\PYG{p}{:}\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}rouge\PYGZdq{}}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} et une valeur}
\end{Verbatim}

@ -0,0 +1,5 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{+w}{ }kubectl\PYG{+w}{ }get\PYG{+w}{ }pv\PYG{+w}{ }pv\PYGZhy{}volume
NAME\PYG{+w}{ }CAPACITY\PYG{+w}{ }ACCESSMODES\PYG{+w}{ }...\PYG{+w}{ }STATUS\PYG{+w}{ }STORAGECLASS
pv\PYGZhy{}volume\PYG{+w}{ }10Gi\PYG{+w}{ }RWO\PYG{+w}{ }...\PYG{+w}{ }Available\PYG{+w}{ }manual
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
kubectl\PYG{+w}{ }apply\PYG{+w}{ }\PYGZhy{}f\PYG{+w}{ }\PYGZlt{}fichier.yaml\PYGZgt{}
\end{Verbatim}

@ -0,0 +1,6 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{+w}{ }kubectl\PYG{+w}{ }get\PYG{+w}{ }pvc\PYG{+w}{ }app\PYGZhy{}pv\PYGZhy{}claim
NAME\PYG{+w}{ }STATUS\PYG{+w}{ }VOLUME\PYG{+w}{ }CAPACITY\PYG{+w}{ }ACCESSMODES\PYG{+w}{ }STORAGECLASS\PYG{+w}{ }AGE
app\PYGZhy{}pv\PYGZhy{}claim\PYG{+w}{ }Bound\PYG{+w}{ }pv\PYGZhy{}volume\PYG{+w}{ }10Gi\PYG{+w}{ }RWO\PYG{+w}{ }manual\PYG{+w}{ }30s
\end{Verbatim}

@ -0,0 +1,10 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{k}{FROM}\PYG{+w}{ }\PYG{l+s}{debian}
\PYG{c}{\PYGZsh{} ...}
\PYG{k}{RUN}\PYG{+w}{ }useradd\PYG{+w}{ }test
\PYG{k}{USER}\PYG{+w}{ }\PYG{l+s}{test}
\PYG{c}{\PYGZsh{} CMD / ENTRYPOINT}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
kubectl\PYG{+w}{ }logs\PYG{+w}{ }\PYGZlt{}nom\PYG{+w}{ }pod\PYGZgt{}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
trivy\PYG{+w}{ }k8s\PYG{+w}{ }\PYGZhy{}\PYGZhy{}severity\PYG{o}{=}CRITICAL\PYG{+w}{ }\PYGZhy{}\PYGZhy{}report\PYG{o}{=}all
\end{Verbatim}

@ -0,0 +1,14 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nn}{\PYGZhy{}\PYGZhy{}\PYGZhy{}}
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{PersistentVolumeClaim}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nfs\PYGZhy{}claim}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{accessModes}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{ReadWriteMany}
\PYG{+w}{ }\PYG{n+nt}{storageClassName}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nfs}
\PYG{+w}{ }\PYG{n+nt}{resources}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{requests}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{storage}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{10Gi}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
kubectl\PYG{+w}{ }\PYG{n+nb}{set}\PYG{+w}{ }image\PYG{+w}{ }deployment/\PYGZlt{}nom\PYG{+w}{ }déploiement\PYGZgt{}\PYG{+w}{ }\PYGZlt{}nom\PYG{+w}{ }conteneur\PYGZgt{}\PYG{o}{=}\PYGZlt{}nouvelle\PYG{+w}{ }image:tag\PYGZgt{}
\end{Verbatim}

@ -0,0 +1,4 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{+w}{ }kubectl\PYG{+w}{ }logs\PYG{+w}{ }profiles\PYGZhy{}app
...
\end{Verbatim}

@ -0,0 +1,14 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{+w}{ }kubectl\PYG{+w}{ }\PYGZhy{}n\PYG{+w}{ }profiles\PYGZhy{}app\PYG{+w}{ }describe\PYG{+w}{ }pod\PYG{+w}{ }profiles\PYGZhy{}app
Name:\PYG{+w}{ }profiles\PYGZhy{}app
Namespace:\PYG{+w}{ }profiles\PYGZhy{}app
Priority:\PYG{+w}{ }\PYG{l+m}{0}
Service\PYG{+w}{ }Account:\PYG{+w}{ }default
Node:\PYG{+w}{ }minikube/192.168.49.2
Start\PYG{+w}{ }Time:\PYG{+w}{ }Thu,\PYG{+w}{ }\PYG{l+m}{09}\PYG{+w}{ }May\PYG{+w}{ }\PYG{l+m}{2024}\PYG{+w}{ }\PYG{l+m}{17}:35:54\PYG{+w}{ }+0200
Labels:\PYG{+w}{ }\PYG{n+nv}{run}\PYG{o}{=}profiles\PYGZhy{}app
Annotations:\PYG{+w}{ }\PYGZlt{}none\PYGZgt{}
Status:\PYG{+w}{ }Running
IP:\PYG{+w}{ }\PYG{l+m}{10}.244.0.7
...
\end{Verbatim}

@ -0,0 +1,11 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nn}{\PYGZhy{}\PYGZhy{}\PYGZhy{}}
\PYG{n+nn}{...}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{...}
\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{strategy}\PYG{p+pIndicator}{:}
\PYG{+w}{ }\PYG{n+nt}{type}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{RollingUpdate}
\PYG{+w}{ }\PYG{n+nt}{rollingUpdate}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{maxUnavailable}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{0}
\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{...}
\end{Verbatim}

@ -0,0 +1,5 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{+w}{ }kubectl\PYG{+w}{ }get\PYG{+w}{ }pods
NAME\PYG{+w}{ }READY\PYG{+w}{ }STATUS\PYG{+w}{ }RESTARTS\PYG{+w}{ }AGE
profiles\PYGZhy{}app\PYG{+w}{ }\PYG{l+m}{3}/3\PYG{+w}{ }Running\PYG{+w}{ }\PYG{l+m}{0}\PYG{+w}{ }22s
\end{Verbatim}

@ -0,0 +1,11 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nn}{\PYGZhy{}\PYGZhy{}\PYGZhy{}}
\PYG{n+nt}{clef}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{valeur}
\PYG{n+nt}{liste\PYGZus{}de\PYGZus{}nombres}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{1}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{2}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{3}
\PYG{n+nt}{liste\PYGZus{}de\PYGZus{}clefs\PYGZus{}valeurs}\PYG{p}{:}
\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{titre}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{blade\PYGZus{}runner}
\PYG{+w}{ }\PYG{n+nt}{note}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{10}
\end{Verbatim}

@ -0,0 +1,19 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{Pod}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}app}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{volumes}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}app\PYGZhy{}storage}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} un nom pour le volume}
\PYG{+w}{ }\PYG{n+nt}{persistentVolumeClaim}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{claimName}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{app\PYGZhy{}pv\PYGZhy{}claim}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} le nom du \PYGZdq{}claim\PYGZdq{} à utiliser}
\PYG{+w}{ }\PYG{n+nt}{containers}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}app}
\PYG{+w}{ }\PYG{n+nt}{image}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nginx}
\PYG{+w}{ }\PYG{n+nt}{ports}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{containerPort}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{80}
\PYG{+w}{ }\PYG{n+nt}{volumeMounts}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{mountPath}\PYG{p}{:}\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}/usr/share/nginx/html\PYGZdq{}}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} point de montage dans le /pod/}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}app\PYGZhy{}storage}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} nom du stockage}
\end{Verbatim}

@ -0,0 +1,8 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{ConfigMap}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} un nouveau type}
\PYG{+w}{ }\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}app\PYGZhy{}config}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on lui met un nom}
\PYG{+w}{ }\PYG{n+nt}{data}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} puis une liste de clefs\PYGZhy{}valeurs}
\PYG{+w}{ }\PYG{n+nt}{database\PYGZus{}uri}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{mongodb://localhost:27017}
\end{Verbatim}

@ -0,0 +1,16 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{PersistentVolume}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} un nouveau type}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{pv\PYGZhy{}volume}
\PYG{+w}{ }\PYG{n+nt}{labels}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{type}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{local}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{storageClassName}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{manual}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} la classe du stockage}
\PYG{+w}{ }\PYG{n+nt}{capacity}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{storage}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{10Gi}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} la taille du volume}
\PYG{+w}{ }\PYG{n+nt}{accessModes}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{ReadWriteOnce}
\PYG{+w}{ }\PYG{n+nt}{hostPath}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on veut stocker sur le nœud physique}
\PYG{+w}{ }\PYG{n+nt}{path}\PYG{p}{:}\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}/mnt/data\PYGZdq{}}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} son emplacement sur le nœud}
\end{Verbatim}

@ -0,0 +1,15 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nn}{\PYGZhy{}\PYGZhy{}\PYGZhy{}}
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{Service}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} ici le type est \PYGZdq{}service\PYGZdq{}}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{namespace}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{profiles\PYGZhy{}app\PYGZhy{}ns}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on choisi le namespace}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{my\PYGZhy{}service}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on choisi un nom pour le service}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{selector}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} règles pour sélectionner le pod}
\PYG{+w}{ }\PYG{n+nt}{app.kubernetes.io/name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{profiles\PYGZhy{}app}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} selection par nom}
\PYG{+w}{ }\PYG{n+nt}{ports}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on choisi les ports à exposer}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{protocol}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{TCP}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} le protocole}
\PYG{+w}{ }\PYG{n+nt}{port}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{80}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} le port *CIBLE*}
\PYG{+w}{ }\PYG{n+nt}{targetPort}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{9376}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} le port *DU POD*}
\end{Verbatim}

@ -0,0 +1,23 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{apps/v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{Deployment}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} un nouveau type, \PYGZdq{}Deployment\PYGZdq{}}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nginx\PYGZhy{}deployment}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on lui met un nom}
\PYG{+w}{ }\PYG{n+nt}{labels}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} et des labels}
\PYG{+w}{ }\PYG{n+nt}{app}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nginx}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{replicas}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{3}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} le nombre de réplications voulues}
\PYG{+w}{ }\PYG{n+nt}{selector}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{matchLabels}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{app}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nginx}
\PYG{+w}{ }\PYG{n+nt}{template}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} champs qui seront appliqués aux pods}
\PYG{+w}{ }\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{labels}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{app}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nginx}
\PYG{+w}{ }\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{containers}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} on spécifie les conteneurs}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nginx}
\PYG{+w}{ }\PYG{n+nt}{image}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{nginx:1.7.9}
\PYG{+w}{ }\PYG{n+nt}{ports}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{n+nt}{containerPort}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{80}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
kubectl\PYG{+w}{ }\PYG{n+nb}{exec}\PYG{+w}{ }\PYGZhy{}it\PYG{+w}{ }\PYGZlt{}nom\PYG{+w}{ }pod\PYGZgt{}\PYG{+w}{ }\PYGZhy{}\PYGZhy{}\PYG{+w}{ }/bin/bash
\end{Verbatim}

@ -0,0 +1,13 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{PersistentVolumeClaim}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} un nouveau type}
\PYG{n+nt}{metadata}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{app\PYGZhy{}pv\PYGZhy{}claim}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} un nom}
\PYG{n+nt}{spec}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{storageClassName}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{manual}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} la classe du stockage}
\PYG{+w}{ }\PYG{n+nt}{accessModes}\PYG{p}{:}
\PYG{+w}{ }\PYG{p+pIndicator}{\PYGZhy{}}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{ReadWriteOnce}
\PYG{+w}{ }\PYG{n+nt}{resources}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{requests}\PYG{p}{:}
\PYG{+w}{ }\PYG{n+nt}{storage}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{3Gi}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} la taille demandée}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
trivy\PYG{+w}{ }k8s\PYG{+w}{ }\PYGZhy{}\PYGZhy{}report\PYG{o}{=}summary
\end{Verbatim}

@ -0,0 +1,5 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{+w}{ }kubectl\PYG{+w}{ }get\PYG{+w}{ }services
NAME\PYG{+w}{ }TYPE\PYG{+w}{ }CLUSTER\PYGZhy{}IP\PYG{+w}{ }EXTERNAL\PYGZhy{}IP\PYG{+w}{ }PORT\PYG{o}{(}S\PYG{o}{)}\PYG{+w}{ }AGE
profiles\PYGZhy{}app\PYGZhy{}svc\PYG{+w}{ }LoadBalancer\PYG{+w}{ }\PYG{l+m}{10}.97.188.25\PYG{+w}{ }\PYGZlt{}pending\PYGZgt{}\PYG{+w}{ }\PYG{l+m}{8000}:30487/TCP,8001:32451/TCP\PYG{+w}{ }5s
\end{Verbatim}

@ -0,0 +1,7 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nn}{\PYGZhy{}\PYGZhy{}\PYGZhy{}}
\PYG{n+nt}{apiVersion}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{v1}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} nécessaire pour que K8S comprenne}
\PYG{n+nt}{kind}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{Namespace}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} le type de ressource}
\PYG{n+nt}{metadata}\PYG{p}{:}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} les informations de la ressource}
\PYG{+w}{ }\PYG{n+nt}{name}\PYG{p}{:}\PYG{+w}{ }\PYG{l+lScalar+lScalarPlain}{profiles\PYGZhy{}app}\PYG{+w}{ }\PYG{c+c1}{\PYGZsh{} ici, son nom}
\end{Verbatim}

@ -0,0 +1,102 @@
\makeatletter
\def\PYG@reset{\let\PYG@it=\relax \let\PYG@bf=\relax%
\let\PYG@ul=\relax \let\PYG@tc=\relax%
\let\PYG@bc=\relax \let\PYG@ff=\relax}
\def\PYG@tok#1{\csname PYG@tok@#1\endcsname}
\def\PYG@toks#1+{\ifx\relax#1\empty\else%
\PYG@tok{#1}\expandafter\PYG@toks\fi}
\def\PYG@do#1{\PYG@bc{\PYG@tc{\PYG@ul{%
\PYG@it{\PYG@bf{\PYG@ff{#1}}}}}}}
\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+\PYG@do{#2}}
\@namedef{PYG@tok@w}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}}
\@namedef{PYG@tok@c}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cp}{\def\PYG@tc##1{\textcolor[rgb]{0.61,0.40,0.00}{##1}}}
\@namedef{PYG@tok@k}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kt}{\def\PYG@tc##1{\textcolor[rgb]{0.69,0.00,0.25}{##1}}}
\@namedef{PYG@tok@o}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@ow}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
\@namedef{PYG@tok@nb}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@nf}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@nc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@nn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@ne}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.80,0.25,0.22}{##1}}}
\@namedef{PYG@tok@nv}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@no}{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.00,0.00}{##1}}}
\@namedef{PYG@tok@nl}{\def\PYG@tc##1{\textcolor[rgb]{0.46,0.46,0.00}{##1}}}
\@namedef{PYG@tok@ni}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.44,0.44,0.44}{##1}}}
\@namedef{PYG@tok@na}{\def\PYG@tc##1{\textcolor[rgb]{0.41,0.47,0.13}{##1}}}
\@namedef{PYG@tok@nt}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@nd}{\def\PYG@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
\@namedef{PYG@tok@s}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sd}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@si}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.64,0.35,0.47}{##1}}}
\@namedef{PYG@tok@se}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.67,0.36,0.12}{##1}}}
\@namedef{PYG@tok@sr}{\def\PYG@tc##1{\textcolor[rgb]{0.64,0.35,0.47}{##1}}}
\@namedef{PYG@tok@ss}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@sx}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@m}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@gh}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
\@namedef{PYG@tok@gu}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}}
\@namedef{PYG@tok@gd}{\def\PYG@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}}
\@namedef{PYG@tok@gi}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.52,0.00}{##1}}}
\@namedef{PYG@tok@gr}{\def\PYG@tc##1{\textcolor[rgb]{0.89,0.00,0.00}{##1}}}
\@namedef{PYG@tok@ge}{\let\PYG@it=\textit}
\@namedef{PYG@tok@gs}{\let\PYG@bf=\textbf}
\@namedef{PYG@tok@ges}{\let\PYG@bf=\textbf\let\PYG@it=\textit}
\@namedef{PYG@tok@gp}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
\@namedef{PYG@tok@go}{\def\PYG@tc##1{\textcolor[rgb]{0.44,0.44,0.44}{##1}}}
\@namedef{PYG@tok@gt}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
\@namedef{PYG@tok@err}{\def\PYG@bc##1{{\setlength{\fboxsep}{\string -\fboxrule}\fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}}
\@namedef{PYG@tok@kc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kr}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@bp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@fm}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@vc}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@vg}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@vi}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@vm}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@sa}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sb}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sc}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@dl}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@s2}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sh}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@s1}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@mb}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mf}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mh}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mi}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@il}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mo}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@ch}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cm}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cpf}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@c1}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cs}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\def\PYGZbs{\char`\\}
\def\PYGZus{\char`\_}
\def\PYGZob{\char`\{}
\def\PYGZcb{\char`\}}
\def\PYGZca{\char`\^}
\def\PYGZam{\char`\&}
\def\PYGZlt{\char`\<}
\def\PYGZgt{\char`\>}
\def\PYGZsh{\char`\#}
\def\PYGZpc{\char`\%}
\def\PYGZdl{\char`\$}
\def\PYGZhy{\char`\-}
\def\PYGZsq{\char`\'}
\def\PYGZdq{\char`\"}
\def\PYGZti{\char`\~}
% for compatibility with earlier versions
\def\PYGZat{@}
\def\PYGZlb{[}
\def\PYGZrb{]}
\makeatother

@ -0,0 +1,58 @@
<mxfile host="Electron" modified="2024-06-01T07:51:41.103Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.4.0 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="h0a0V1IMEfZagyl094p_" version="24.4.0" type="device">
<diagram name="Page-1" id="-ReUibY8v-FiZFFb0WlK">
<mxGraphModel dx="1419" dy="860" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="DhV2PLKCl5DcjJhsPUaC-7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-1" target="DhV2PLKCl5DcjJhsPUaC-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-1" value="Client" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="120" y="400" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-2" target="DhV2PLKCl5DcjJhsPUaC-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;dashed=1;dashPattern=12 12;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-2" target="DhV2PLKCl5DcjJhsPUaC-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-2" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="190" y="405" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-3" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;green&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="280" y="295" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-4" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;blue&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="280" y="495" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-8" value="" style="endArrow=none;html=1;rounded=0;strokeWidth=3;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="580" as="sourcePoint" />
<mxPoint x="400" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-10" target="DhV2PLKCl5DcjJhsPUaC-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-10" value="Client" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="420" y="400" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;dashed=1;dashPattern=12 12;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-13" target="DhV2PLKCl5DcjJhsPUaC-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-13" target="DhV2PLKCl5DcjJhsPUaC-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-13" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="490" y="405" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-14" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;green&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="580" y="295" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-15" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;blue&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="580" y="495" width="80" height="70" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

@ -0,0 +1,85 @@
<mxfile host="Electron" modified="2024-06-04T05:37:44.471Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.4.0 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="K5GmfFwrwIsdaKY0CkVW" version="24.4.0" type="device">
<diagram name="Page-1" id="V8JBwLZRFhLfpAQfGiY4">
<mxGraphModel dx="979" dy="593" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="c1WQNr5hsSRt7WhhbX0S-3" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="160" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-5" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="190" y="380" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-6" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="220" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-8" value="" style="endArrow=none;dashed=1;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-24">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="140" y="240" as="sourcePoint" />
<mxPoint x="420" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-9" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="282.5" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-10" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="337.5" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-12" target="c1WQNr5hsSRt7WhhbX0S-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-12" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="165" y="290" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-13" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="285" y="290" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-12" target="c1WQNr5hsSRt7WhhbX0S-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-12" target="c1WQNr5hsSRt7WhhbX0S-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-13" target="c1WQNr5hsSRt7WhhbX0S-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-13" target="c1WQNr5hsSRt7WhhbX0S-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-22" value="" style="endArrow=none;dashed=1;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;curved=1;" edge="1" parent="1" target="c1WQNr5hsSRt7WhhbX0S-21">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="140" y="240" as="sourcePoint" />
<mxPoint x="420" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-21" target="c1WQNr5hsSRt7WhhbX0S-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-21" value="&lt;i&gt;Ingress&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="175" y="230" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-23" target="c1WQNr5hsSRt7WhhbX0S-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-23" target="c1WQNr5hsSRt7WhhbX0S-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-23" value="" style="html=1;verticalLabelPosition=bottom;align=center;labelBackgroundColor=#ffffff;verticalAlign=top;strokeWidth=2;strokeColor=#0080F0;shadow=0;dashed=0;shape=mxgraph.ios7.icons.cloud;" vertex="1" parent="1">
<mxGeometry x="245" y="140" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-25" value="" style="endArrow=none;dashed=1;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-21" target="c1WQNr5hsSRt7WhhbX0S-24">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="255" y="240" as="sourcePoint" />
<mxPoint x="420" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-24" target="c1WQNr5hsSRt7WhhbX0S-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-24" value="&lt;i&gt;Ingress&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="295" y="230" width="80" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

@ -0,0 +1,58 @@
<mxfile host="Electron" modified="2024-06-01T07:53:20.292Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.4.0 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="lQ_ysdZIoFnwl8rdb5vc" version="24.4.0" type="device">
<diagram name="Page-1" id="-ReUibY8v-FiZFFb0WlK">
<mxGraphModel dx="1419" dy="860" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="DhV2PLKCl5DcjJhsPUaC-7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-1" target="DhV2PLKCl5DcjJhsPUaC-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-1" value="Client" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="120" y="400" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-2" target="DhV2PLKCl5DcjJhsPUaC-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;dashed=1;dashPattern=12 12;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-2" target="DhV2PLKCl5DcjJhsPUaC-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-2" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="190" y="405" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-3" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;green&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="280" y="295" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-4" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;blue&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="280" y="495" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-8" value="" style="endArrow=none;html=1;rounded=0;strokeWidth=3;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="400" y="580" as="sourcePoint" />
<mxPoint x="400" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-10" target="DhV2PLKCl5DcjJhsPUaC-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-10" value="Client" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="420" y="400" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;dashed=1;dashPattern=12 12;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-13" target="DhV2PLKCl5DcjJhsPUaC-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-13" target="DhV2PLKCl5DcjJhsPUaC-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-13" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="490" y="405" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-14" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;green&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="580" y="295" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-15" value="Déploiement&lt;div&gt;&lt;b&gt;&lt;i&gt;blue&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="580" y="495" width="80" height="70" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 78 KiB

@ -0,0 +1,31 @@
<mxfile host="Electron" modified="2024-06-01T07:56:27.607Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.4.0 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="lbkReOSzwi5TmBN93y_e" version="24.4.0" type="device">
<diagram name="Page-1" id="-ReUibY8v-FiZFFb0WlK">
<mxGraphModel dx="1419" dy="860" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="DhV2PLKCl5DcjJhsPUaC-7" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-1" target="DhV2PLKCl5DcjJhsPUaC-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-1" value="Client" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="120" y="400" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;strokeWidth=3;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-2" target="DhV2PLKCl5DcjJhsPUaC-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="DhV2PLKCl5DcjJhsPUaC-2" target="DhV2PLKCl5DcjJhsPUaC-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-2" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="190" y="405" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-3" value="Version 1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="320" y="295" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="DhV2PLKCl5DcjJhsPUaC-4" value="Version 2" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="320" y="495" width="80" height="70" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

@ -0,0 +1,90 @@
<mxfile host="Electron" modified="2024-06-04T05:38:24.482Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.4.0 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="0joVvB2Uu3NjnDeO1Urb" version="24.4.0" type="device">
<diagram name="Page-1" id="V8JBwLZRFhLfpAQfGiY4">
<mxGraphModel dx="979" dy="593" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="c1WQNr5hsSRt7WhhbX0S-3" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="160" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-5" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="190" y="380" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-6" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="220" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-8" value="" style="endArrow=none;dashed=1;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-24">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="140" y="240" as="sourcePoint" />
<mxPoint x="440" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-30" value="Coté &lt;i&gt;cluster&lt;/i&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="c1WQNr5hsSRt7WhhbX0S-8">
<mxGeometry x="0.0755" y="2" relative="1" as="geometry">
<mxPoint x="11" y="12" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-9" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="282.5" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-10" value="" style="aspect=fixed;sketch=0;html=1;dashed=0;whitespace=wrap;verticalLabelPosition=bottom;verticalAlign=top;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];shape=mxgraph.kubernetes.icon2;kubernetesLabel=1;prIcon=pod" vertex="1" parent="1">
<mxGeometry x="337.5" y="360" width="50" height="48" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-12" target="c1WQNr5hsSRt7WhhbX0S-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-12" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="165" y="290" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-13" value="&lt;i&gt;Service&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="285" y="290" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-12" target="c1WQNr5hsSRt7WhhbX0S-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-12" target="c1WQNr5hsSRt7WhhbX0S-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-13" target="c1WQNr5hsSRt7WhhbX0S-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-13" target="c1WQNr5hsSRt7WhhbX0S-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-22" value="" style="endArrow=none;dashed=1;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;curved=1;" edge="1" parent="1" target="c1WQNr5hsSRt7WhhbX0S-21">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="140" y="240" as="sourcePoint" />
<mxPoint x="420" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-21" target="c1WQNr5hsSRt7WhhbX0S-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-21" value="&lt;i&gt;Ingress&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="175" y="230" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-23" target="c1WQNr5hsSRt7WhhbX0S-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-23" target="c1WQNr5hsSRt7WhhbX0S-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-23" value="" style="html=1;verticalLabelPosition=bottom;align=center;labelBackgroundColor=#ffffff;verticalAlign=top;strokeWidth=2;strokeColor=#0080F0;shadow=0;dashed=0;shape=mxgraph.ios7.icons.cloud;" vertex="1" parent="1">
<mxGeometry x="245" y="140" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-25" value="" style="endArrow=none;dashed=1;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-21" target="c1WQNr5hsSRt7WhhbX0S-24">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="255" y="240" as="sourcePoint" />
<mxPoint x="420" y="240" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="c1WQNr5hsSRt7WhhbX0S-24" target="c1WQNr5hsSRt7WhhbX0S-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="c1WQNr5hsSRt7WhhbX0S-24" value="&lt;i&gt;Ingress&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="295" y="230" width="80" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1,245 @@
#+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/

Binary file not shown.

@ -0,0 +1,127 @@
% Intended LaTeX compiler: pdflatex
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{rotating}
\usepackage[normalem]{ulem}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{capt-of}
\usepackage{hyperref}
\usepackage{minted}
\usepackage[a4paper,margin=0.5in]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[inkscapelatex=false]{svg}
\usepackage[sfdefault]{AlegreyaSans}
\usepackage{multicol}
\usepackage{minted}
\usepackage{float}
\usepackage{tikz}
\usetikzlibrary{positioning}
\renewcommand\listingscaption{Exemple de code}
\date{}
\title{Cours de virtualisation avancée: \emph{Kubernetes}, suite}
\hypersetup{
pdfauthor={Evrard Van Espen},
pdftitle={Cours de virtualisation avancée: \emph{Kubernetes}, suite},
pdfkeywords={},
pdfsubject={},
pdfcreator={Emacs 30.0.50 (Org mode 9.6.15)},
pdflang={English}}
\begin{document}
\maketitle
\section{\emph{Rolling Updates}}
\label{sec:org16f1979}
Permet des mises à jour d'images sans temps de coupure
\begin{minted}[]{yaml}
---
...
spec:
...
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
...
\end{minted}
\begin{itemize}
\item \texttt{maxUnavailable}: défini le nombre maximal de \emph{replicas} indisponibles
\item \texttt{maxSurge}: défini le nombre maximal de \emph{replicas} à mettre à jour en même temps
\end{itemize}
Ensuite, mettre à jour l'image avec:
\begin{minted}[]{bash}
kubectl set image deployment/<nom déploiement> <nom conteneur>=<nouvelle image:tag>
\end{minted}
\textbf{But}:
\begin{itemize}
\item Mettre à jour l'application sans \emph{downtime}
\end{itemize}
\section{Déploiement \emph{blue / green}}
\label{sec:org12d4e94}
\begin{center}
\includesvg[width=.9\linewidth]{./images/blue_green}
\end{center}
\begin{itemize}
\item On déploie la nouvelle version en parallèle de l'ancienne
\item Une fois que tout est déployé on redirige le trafic vers le nouveau déploiement
\end{itemize}
\textbf{But}:
\begin{itemize}
\item Tester le déploiement de la nouvelle version avant de la basculer en prod
\end{itemize}
\section{Déploiement \emph{canary}}
\label{sec:orga83dd0b}
\begin{center}
\includesvg[width=.9\linewidth]{./images/canary}
\end{center}
\begin{itemize}
\item On déploie la nouvelle version en parallèle de l'ancienne \textbf{avec moins de \emph{replicas}}
\item Automatiquement une petite partie des clients tomberont sur la nouvelle version
\end{itemize}
\textbf{But}:
\begin{itemize}
\item Faire tester à quelques utilisateurs aléatoires la nouvelle version
\end{itemize}
\section{Mise à l'échelle (\emph{scaling})}
\label{sec:orge0f2cfb}
\begin{itemize}
\item Nécessaire quand la charge augmente
\item Par exemple pour suivre l'augmentation du trafic de notre application
\end{itemize}
\subsection{Verticale (\emph{vertical scaling})}
\label{sec:org42b7a6d}
\subsubsection{Fonctionnement}
\label{sec:orgc206495}
\begin{itemize}
\item On augmente la puissance des nœuds
\item Augmente les capacité de l'application existante
\item L'application n'a pas besoin dêtre capable de gérer la réplication
\end{itemize}
\subsubsection{Inconvénients}
\label{sec:org3049ea8}
\begin{itemize}
\item Coûts pas toujours proportionnels à la puissance des nœuds
\item Si nœud déjà au max: comment faire ?
\end{itemize}
\section{Aller plus loin}
\label{sec:org39d2766}
\end{document}

@ -0,0 +1,5 @@
\begin{Verbatim}[commandchars=\\\{\}]
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Ridley Scott\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{1982}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2021}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune 2\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2024}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
curl\PYG{+w}{ }http://192.168.49.2:30000
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
git\PYG{+w}{ }clone\PYG{+w}{ }https://codefirst.iut.uca.fr/git/evrard.van\PYGZus{}espen/cours\PYGZus{}virtualisation\PYGZus{}avancee\PYGZus{}ETUD.git
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
curl\PYG{+w}{ }http://10.109.243.202:30000
\end{Verbatim}

@ -0,0 +1,6 @@
\begin{Verbatim}[commandchars=\\\{\}]
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Ridley Scott\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{1982}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner 2049\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2017}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2021}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune 2\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2024}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
./kubectl\PYG{+w}{ }get\PYG{+w}{ }namespaces
\end{Verbatim}

@ -0,0 +1,6 @@
\begin{Verbatim}[commandchars=\\\{\}]
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Ridley Scott\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{1982}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner 2049\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2017}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2021}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune 2\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2024}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
vdn\PYGZhy{}ssh\PYG{+w}{ }test@debian\PYGZhy{}1
\end{Verbatim}

@ -0,0 +1,6 @@
\begin{Verbatim}[commandchars=\\\{\}]
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Ridley Scott\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{1982}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner 2049\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2017}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2021}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune 2\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2024}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
./minikube\PYG{+w}{ }tunnel
\end{Verbatim}

@ -0,0 +1,8 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{c+c1}{\PYGZsh{} Installation de minikube}
curl\PYG{+w}{ }\PYGZhy{}Lo\PYG{+w}{ }minikube\PYG{+w}{ }https://storage.googleapis.com/minikube/releases/latest/minikube\PYGZhy{}linux\PYGZhy{}amd64
chmod\PYG{+w}{ }+x\PYG{+w}{ }minikube
\PYG{c+c1}{\PYGZsh{} Initialisation de minikube}
./minikube\PYG{+w}{ }start\PYG{+w}{ }\PYGZhy{}\PYGZhy{}driver\PYG{o}{=}docker
\end{Verbatim}

@ -0,0 +1,4 @@
\begin{Verbatim}[commandchars=\\\{\}]
git\PYG{+w}{ }clone\PYG{+w}{ }\PYG{l+s+se}{\PYGZbs{}}
\PYG{+w}{ }https://codefirst.iut.uca.fr/git/evrard.van\PYGZus{}espen/cours\PYGZus{}virtualisation\PYGZus{}avancee\PYGZus{}ETUD.git
\end{Verbatim}

@ -0,0 +1,5 @@
\begin{Verbatim}[commandchars=\\\{\}]
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Ridley Scott\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{1982}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2021}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}ext\PYG{+w}{ }ip\PYGZgt{}:4000/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune 2\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2024}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
vdn\PYGZhy{}start\PYG{+w}{ }\PYGZhy{}t\PYG{+w}{ }\PYGZhy{}n\PYG{+w}{ }docker\PYG{+w}{ }debian\PYGZhy{}1
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
curl\PYG{+w}{ }http://\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
./minikube\PYG{+w}{ }status
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{n+nb}{export}\PYG{+w}{ }\PYG{n+nv}{no\PYGZus{}proxy}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}127.0.0.1,.vdn,localhost,192.168.49.1/24\PYGZdq{}}
\end{Verbatim}

@ -0,0 +1,6 @@
\begin{Verbatim}[commandchars=\\\{\}]
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Ridley Scott\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{1982}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Blade Runner 2049\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2017}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2021}
http\PYG{+w}{ }POST\PYG{+w}{ }\PYGZlt{}external\PYG{+w}{ }ip\PYGZgt{}:\PYGZlt{}port\PYGZgt{}/\PYG{+w}{ }\PYG{n+nv}{title}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Dune 2\PYGZdq{}}\PYG{+w}{ }\PYG{n+nv}{director}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}Denis Villeneuve\PYGZdq{}}\PYG{+w}{ }release\PYGZus{}year:\PYG{o}{=}\PYG{l+m}{2024}
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
passwd\PYG{+w}{ }\PYG{n+nb}{test}
\end{Verbatim}

@ -0,0 +1,4 @@
\begin{Verbatim}[commandchars=\\\{\}]
git\PYG{+w}{ }clone\PYG{+w}{ }\PYG{l+s+se}{\PYGZbs{}}
https://codefirst.iut.uca.fr/git/evrard.van\PYGZus{}espen/cours\PYGZus{}virtualisation\PYGZus{}avancee\PYGZus{}ETUD.git
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
vdn\PYGZhy{}ssh\PYG{+w}{ }root@debian\PYGZhy{}1
\end{Verbatim}

@ -0,0 +1,3 @@
\begin{Verbatim}[commandchars=\\\{\}]
minikube\PYG{+w}{ }status
\end{Verbatim}

@ -0,0 +1,4 @@
\begin{Verbatim}[commandchars=\\\{\}]
http\PYG{+w}{ }\PYG{l+m}{192}.168.49.2.nip.io/
http\PYG{+w}{ }\PYG{l+m}{192}.168.49.2.nip.io/api
\end{Verbatim}

@ -0,0 +1,102 @@
\makeatletter
\def\PYG@reset{\let\PYG@it=\relax \let\PYG@bf=\relax%
\let\PYG@ul=\relax \let\PYG@tc=\relax%
\let\PYG@bc=\relax \let\PYG@ff=\relax}
\def\PYG@tok#1{\csname PYG@tok@#1\endcsname}
\def\PYG@toks#1+{\ifx\relax#1\empty\else%
\PYG@tok{#1}\expandafter\PYG@toks\fi}
\def\PYG@do#1{\PYG@bc{\PYG@tc{\PYG@ul{%
\PYG@it{\PYG@bf{\PYG@ff{#1}}}}}}}
\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+\PYG@do{#2}}
\@namedef{PYG@tok@w}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}}
\@namedef{PYG@tok@c}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cp}{\def\PYG@tc##1{\textcolor[rgb]{0.61,0.40,0.00}{##1}}}
\@namedef{PYG@tok@k}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kt}{\def\PYG@tc##1{\textcolor[rgb]{0.69,0.00,0.25}{##1}}}
\@namedef{PYG@tok@o}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@ow}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
\@namedef{PYG@tok@nb}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@nf}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@nc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@nn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@ne}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.80,0.25,0.22}{##1}}}
\@namedef{PYG@tok@nv}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@no}{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.00,0.00}{##1}}}
\@namedef{PYG@tok@nl}{\def\PYG@tc##1{\textcolor[rgb]{0.46,0.46,0.00}{##1}}}
\@namedef{PYG@tok@ni}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.44,0.44,0.44}{##1}}}
\@namedef{PYG@tok@na}{\def\PYG@tc##1{\textcolor[rgb]{0.41,0.47,0.13}{##1}}}
\@namedef{PYG@tok@nt}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@nd}{\def\PYG@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
\@namedef{PYG@tok@s}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sd}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@si}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.64,0.35,0.47}{##1}}}
\@namedef{PYG@tok@se}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.67,0.36,0.12}{##1}}}
\@namedef{PYG@tok@sr}{\def\PYG@tc##1{\textcolor[rgb]{0.64,0.35,0.47}{##1}}}
\@namedef{PYG@tok@ss}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@sx}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@m}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@gh}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
\@namedef{PYG@tok@gu}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}}
\@namedef{PYG@tok@gd}{\def\PYG@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}}
\@namedef{PYG@tok@gi}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.52,0.00}{##1}}}
\@namedef{PYG@tok@gr}{\def\PYG@tc##1{\textcolor[rgb]{0.89,0.00,0.00}{##1}}}
\@namedef{PYG@tok@ge}{\let\PYG@it=\textit}
\@namedef{PYG@tok@gs}{\let\PYG@bf=\textbf}
\@namedef{PYG@tok@ges}{\let\PYG@bf=\textbf\let\PYG@it=\textit}
\@namedef{PYG@tok@gp}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
\@namedef{PYG@tok@go}{\def\PYG@tc##1{\textcolor[rgb]{0.44,0.44,0.44}{##1}}}
\@namedef{PYG@tok@gt}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
\@namedef{PYG@tok@err}{\def\PYG@bc##1{{\setlength{\fboxsep}{\string -\fboxrule}\fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}}
\@namedef{PYG@tok@kc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@kr}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@bp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\@namedef{PYG@tok@fm}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\@namedef{PYG@tok@vc}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@vg}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@vi}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@vm}{\def\PYG@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\@namedef{PYG@tok@sa}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sb}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sc}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@dl}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@s2}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@sh}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@s1}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\@namedef{PYG@tok@mb}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mf}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mh}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mi}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@il}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@mo}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\@namedef{PYG@tok@ch}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cm}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cpf}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@c1}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\@namedef{PYG@tok@cs}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.24,0.48,0.48}{##1}}}
\def\PYGZbs{\char`\\}
\def\PYGZus{\char`\_}
\def\PYGZob{\char`\{}
\def\PYGZcb{\char`\}}
\def\PYGZca{\char`\^}
\def\PYGZam{\char`\&}
\def\PYGZlt{\char`\<}
\def\PYGZgt{\char`\>}
\def\PYGZsh{\char`\#}
\def\PYGZpc{\char`\%}
\def\PYGZdl{\char`\$}
\def\PYGZhy{\char`\-}
\def\PYGZsq{\char`\'}
\def\PYGZdq{\char`\"}
\def\PYGZti{\char`\~}
% for compatibility with earlier versions
\def\PYGZat{@}
\def\PYGZlb{[}
\def\PYGZrb{]}
\makeatother

@ -0,0 +1,77 @@
<mxfile host="Electron" modified="2024-05-29T09:05:34.205Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.4.0 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="3NsCfkjfPwW3kj2nquoN" version="24.4.0" type="device">
<diagram name="Page-1" id="hoiwMJw63AIcIbihmxe5">
<mxGraphModel dx="264" dy="491" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="AQB66iktjeJtlIeZ2JHQ-1" value="Réseau exterieur" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;shadow=1;" vertex="1" parent="1">
<mxGeometry x="120" y="50" width="120" height="80" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-2" value="&lt;i&gt;LoadBalancer&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;shadow=1;" vertex="1" parent="1">
<mxGeometry x="120" y="170" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-3" value="Déploiement &quot;application&quot;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;verticalAlign=top;align=left;shadow=1;" vertex="1" parent="1">
<mxGeometry x="60" y="230" width="240" height="60" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-4" value="&lt;i&gt;Pod&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;shadow=1;" vertex="1" parent="1">
<mxGeometry x="65" y="260" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-5" value="&lt;i&gt;Pod&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;shadow=1;" vertex="1" parent="1">
<mxGeometry x="145" y="260" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-6" value="&lt;i&gt;Pod&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;shadow=1;" vertex="1" parent="1">
<mxGeometry x="225" y="260" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-8" value="Déploiement &quot;base de données&quot;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;verticalAlign=top;align=left;shadow=1;" vertex="1" parent="1">
<mxGeometry x="60" y="390" width="240" height="60" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-9" value="&lt;i&gt;Pod&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;shadow=1;" vertex="1" parent="1">
<mxGeometry x="65" y="420" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-10" value="&lt;i&gt;Pod&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;shadow=1;" vertex="1" parent="1">
<mxGeometry x="145" y="420" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-11" value="&lt;i&gt;Pod&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;shadow=1;" vertex="1" parent="1">
<mxGeometry x="225" y="420" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-12" value="&lt;i&gt;LoadBalancer&lt;/i&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;shadow=1;" vertex="1" parent="1">
<mxGeometry x="120" y="330" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.498;exitY=0.927;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-1" target="AQB66iktjeJtlIeZ2JHQ-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-2" target="AQB66iktjeJtlIeZ2JHQ-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-2" target="AQB66iktjeJtlIeZ2JHQ-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-2" target="AQB66iktjeJtlIeZ2JHQ-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-4" target="AQB66iktjeJtlIeZ2JHQ-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-5">
<mxGeometry relative="1" as="geometry">
<mxPoint x="180" y="330" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-6">
<mxGeometry relative="1" as="geometry">
<mxPoint x="180" y="330" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-12" target="AQB66iktjeJtlIeZ2JHQ-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-12" target="AQB66iktjeJtlIeZ2JHQ-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="AQB66iktjeJtlIeZ2JHQ-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="AQB66iktjeJtlIeZ2JHQ-12" target="AQB66iktjeJtlIeZ2JHQ-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

@ -0,0 +1,180 @@
#+TITLE: TP1 - Cours de virtualisation avancée - /Kubernetes/, dernier TP
#+OPTIONS: toc:nil date:nil author: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}
#+LATEX_HEADER: \usepackage[tikz]{bclogo}
#+LATEX_HEADER: \usepackage{tcolorbox}
#+LATEX_HEADER: \tcbuselibrary{skins}
#+LATEX_HEADER: \usepackage{ragged2e}
#+LATEX_HEADER: \usepackage{environ}
#+BEGIN_EXPORT latex
\NewEnviron{warning}%
{\begin{center}%
\begin{tcolorbox}[notitle,
colback=orange!5!white,
colbacklower=white,
frame hidden,
boxrule=0pt,
bicolor,
sharp corners,
borderline west={4pt}{0pt}{orange!50!black},
fontupper=\sffamily]
\textcolor{orange!50!black}{
\sffamily
\textbf{Attention:\\}%
}%
\BODY
\end{tcolorbox}
\end{center}%
}
\NewEnviron{good}%
{\begin{center}%
\begin{tcolorbox}[notitle,
colback=green!5!white,
colbacklower=white,
frame hidden,
boxrule=0pt,
bicolor,
sharp corners,
borderline west={4pt}{0pt}{green!50!black},
fontupper=\sffamily]
\textcolor{green!50!black}{
\sffamily
}%
\BODY
\end{tcolorbox}
\end{center}%
}
#+END_EXPORT
#+BEGIN_warning
Comme pour les autres TPs, vous allez travailler dans une machine virtuelle VDN.
\medskip
N'oubliez pas de lancer \\
~export no_proxy="127.0.0.1,.vdn,localhost,10.96.0.0/12,192.168.49.2.nip.io"~ \\
à chaque connexion =ssh= !
\medskip
Pour lancer /Minikube/, lancez la commande =./minikube start= (attention vous aviez probablement laissé les binaires =minikube= et =kubectl= dans le dossier du TP2).
\medskip
N'oubliez pas aussi de laisser un autre terminal tourner avec la commande =minikube tunnel= ;)
#+END_warning
#+BEGIN_warning
Installez l'outil =httpie=: =sudo apt install -y httpie=.
Il s'agit d'un outil similaire à =curl= mais plus agréable à utiliser
#+END_warning
L'objectif de ce TP est de finir le travail commencé la semaine dernière et de tester de nouvelles choses.
La base de données que vous avez déployé est une simple /API REST/ qui reçoit et retourne une liste de films au format /json/.
Voici une commande permettant d'ajouter quelques films à la base:
#+BEGIN_SRC bash
http POST <ext ip>:<port>/ title="Blade Runner" director="Ridley Scott" release_year:=1982
http POST <ext ip>:<port>/ title="Dune" director="Denis Villeneuve" release_year:=2021
http POST <ext ip>:<port>/ title="Dune 2" director="Denis Villeneuve" release_year:=2024
#+END_SRC
* Une base de données sans stockage
Déployez le fichier =without_storage.yaml=.
Il contient les déploiements et services de la base de données et de l'application.
Une fois le fichier déployé, vérifier que les /pods/ sont bien en cours dexécution.
Ensuite, lancez la commande =http <external ip>:4000=.
Vous devriez avoir une sortie telle que :
#+BEGIN_EXAMPLE
HTTP/1.1 200 OK
content-length: 2
content-type: application/json
date: Wed, 05 Jun 2024 07:21:34 GMT
x-servedby: database-85bddd5ddc-c4fm7
[]
#+END_EXAMPLE
Notez que la valeur de =x-servedby= change d'une requête à l'autre.
Cela montre que le /Service/ /LoadBalancer/ redirige bien le trafic vers les différents /pods/.
La sortie =[]= indique que la liste est vide.
Maintenant, lancez les commandes :
#+BEGIN_SRC bash
http POST <ext ip>:4000/ title="Blade Runner" director="Ridley Scott" release_year:=1982
http POST <ext ip>:4000/ title="Dune" director="Denis Villeneuve" release_year:=2021
http POST <ext ip>:4000/ title="Dune 2" director="Denis Villeneuve" release_year:=2024
#+END_SRC
Cela va ajouter des films dans la base de données.
Maintenant, relancez la commande =http <external ip>:4000= plusieurs fois.
Vous verrez que les films ne sont pas présents dans toutes les réponses car les requêtes =POST= ont été dirigées vers différents /pods/.
* Votre travail de la semaine dernière
Si vous aviez fini le TP la semaine dernière, passez à la partie suivante.
Sinon continuez le.
Si vous le souhaitez, vous pouvez vous baser le fichier =without_storage.yaml= et y ajouter :
- /ConfigMap/
- /PersistentVolume/
- /PersistentVolumeClaim/
- montage du /PVC/ dans les /pods/ du déploiement
* /Ingress/
#+BEGIN_warning
Avant tout, lancez la commande =minikube addons enable ingress= qui permet l'utilisation des /Ingress/ dans /minikube/.
N'oubliez pas aussi \\
~export no_proxy="127.0.0.1,.vdn,localhost,10.96.0.0/12,192.168.49.2.nip.io"~ \\
*Attention à ne pas utiliser la commande des précédents TPs car elle ne contient pas l'exclusion pour =192.168.49.2.nip.io=*.
#+END_warning
Déployez maintenant un /Ingress/ permettant l'accès à l'application.
Configurez votre /Ingress/ pour que le chemin =/= arrive sur l'application et le chemin =/api= arrive sur la base de données.
Lors de la configuration de l'/Ingress/, utilisez =192.168.49.2.nip.io= *comme nom de domaine*.
Il s'agit d'un domaine résolvant vers l'adresse =192.168.49.2=, qui est l'adresse de /minikube/ dans votre machine virtuelle.
Vérifiez le fonctionnement avec ces commandes :
#+BEGIN_SRC bash
http 192.168.49.2.nip.io/
http 192.168.49.2.nip.io/api
#+END_SRC
* Déploiement /Canary/
Créez maintenant un déploiement identique à celui de l'application mais qui utilise l'image \\
=evanespen/application:claque= et un nombre de /replicas/ à 1.
Ne changez pas les valeurs de =template.metadata.labels.app= sinon ce nouveau déploiement ne sera pas géré par le /LoadBalancer/.
Ouvrez =192.168.49.2.nip.io= dans un navigateur *dans la machine virtuelle* (donc en vous connectant avec =ssh -X=).
Rechargez la page plusieurs fois, *avec =Ctrl+Shift+R=* pour ignorer le cache, et constatez !
* Aide
Référez vous au cours et à ces documentations pour y parvenir (ce sont bien des liens):
- [[https://kubernetes.io/fr/docs/concepts/services-networking/service/][/Service/]]
- [[https://kubernetes.io/docs/concepts/workloads/pods/][/Pod/]]
- [[https://kubernetes.io/docs/concepts/workloads/controllers/deployment/][/Deployment/]]
- [[https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/][/PV/ et /PVC/]]
- [[https://kubernetes.io/fr/docs/concepts/services-networking/ingress/][/Ingress/]]
Amusez vous bien ;)

Binary file not shown.

@ -0,0 +1,210 @@
% Created 2024-06-05 mer. 10:04
% Intended LaTeX compiler: pdflatex
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{rotating}
\usepackage[normalem]{ulem}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{capt-of}
\usepackage{hyperref}
\usepackage{minted}
\usepackage[a4paper,margin=0.5in]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[inkscapelatex=false]{svg}
\usepackage[sfdefault]{AlegreyaSans}
\usepackage{multicol}
\usepackage{minted}
\usepackage{float}
\usepackage{tikz}
\usetikzlibrary{positioning}
\renewcommand\listingscaption{Exemple de code}
\usepackage[tikz]{bclogo}
\usepackage{tcolorbox}
\tcbuselibrary{skins}
\usepackage{ragged2e}
\usepackage{environ}
\date{}
\title{TP1 - Cours de virtualisation avancée - \emph{Kubernetes}, dernier TP}
\hypersetup{
pdfauthor={Evrard Van Espen},
pdftitle={TP1 - Cours de virtualisation avancée - \emph{Kubernetes}, dernier TP},
pdfkeywords={},
pdfsubject={},
pdfcreator={Emacs 30.0.50 (Org mode 9.6.15)},
pdflang={English}}
\begin{document}
\maketitle
\NewEnviron{warning}%
{\begin{center}%
\begin{tcolorbox}[notitle,
colback=orange!5!white,
colbacklower=white,
frame hidden,
boxrule=0pt,
bicolor,
sharp corners,
borderline west={4pt}{0pt}{orange!50!black},
fontupper=\sffamily]
\textcolor{orange!50!black}{
\sffamily
\textbf{Attention:\\}%
}%
\BODY
\end{tcolorbox}
\end{center}%
}
\NewEnviron{good}%
{\begin{center}%
\begin{tcolorbox}[notitle,
colback=green!5!white,
colbacklower=white,
frame hidden,
boxrule=0pt,
bicolor,
sharp corners,
borderline west={4pt}{0pt}{green!50!black},
fontupper=\sffamily]
\textcolor{green!50!black}{
\sffamily
}%
\BODY
\end{tcolorbox}
\end{center}%
}
\begin{warning}
Comme pour les autres TPs, vous allez travailler dans une machine virtuelle VDN.
\medskip
N'oubliez pas de lancer \\[0pt]
\texttt{export no\_proxy="127.0.0.1,.vdn,localhost,10.96.0.0/12,192.168.49.2.nip.io"} \\[0pt]
à chaque connexion \texttt{ssh} !
\medskip
Pour lancer \emph{Minikube}, lancez la commande \texttt{./minikube start} (attention vous aviez probablement laissé les binaires \texttt{minikube} et \texttt{kubectl} dans le dossier du TP2).
\medskip
N'oubliez pas aussi de laisser un autre terminal tourner avec la commande \texttt{minikube tunnel} ;)
\end{warning}
\begin{warning}
Installez l'outil \texttt{httpie}: \texttt{sudo apt install -y httpie}.
Il s'agit d'un outil similaire à \texttt{curl} mais plus agréable à utiliser
\end{warning}
L'objectif de ce TP est de finir le travail commencé la semaine dernière et de tester de nouvelles choses.
La base de données que vous avez déployé est une simple \emph{API REST} qui reçoit et retourne une liste de films au format \emph{json}.
Voici une commande permettant d'ajouter quelques films à la base:
\begin{minted}[]{bash}
http POST <ext ip>:<port>/ title="Blade Runner" director="Ridley Scott" release_year:=1982
http POST <ext ip>:<port>/ title="Dune" director="Denis Villeneuve" release_year:=2021
http POST <ext ip>:<port>/ title="Dune 2" director="Denis Villeneuve" release_year:=2024
\end{minted}
\section{Une base de données sans stockage}
\label{sec:orge95a53d}
Déployez le fichier \texttt{without\_storage.yaml}.
Il contient les déploiements et services de la base de données et de l'application.
Une fois le fichier déployé, vérifier que les \emph{pods} sont bien en cours dexécution.
Ensuite, lancez la commande \texttt{http <external ip>:4000}.
Vous devriez avoir une sortie telle que :
\begin{verbatim}
HTTP/1.1 200 OK
content-length: 2
content-type: application/json
date: Wed, 05 Jun 2024 07:21:34 GMT
x-servedby: database-85bddd5ddc-c4fm7
[]
\end{verbatim}
Notez que la valeur de \texttt{x-servedby} change d'une requête à l'autre.
Cela montre que le \emph{Service} \emph{LoadBalancer} redirige bien le trafic vers les différents \emph{pods}.
La sortie \texttt{[]} indique que la liste est vide.
Maintenant, lancez les commandes :
\begin{minted}[]{bash}
http POST <ext ip>:4000/ title="Blade Runner" director="Ridley Scott" release_year:=1982
http POST <ext ip>:4000/ title="Dune" director="Denis Villeneuve" release_year:=2021
http POST <ext ip>:4000/ title="Dune 2" director="Denis Villeneuve" release_year:=2024
\end{minted}
Cela va ajouter des films dans la base de données.
Maintenant, relancez la commande \texttt{http <external ip>:4000} plusieurs fois.
Vous verrez que les films ne sont pas présents dans toutes les réponses car les requêtes \texttt{POST} ont été dirigées vers différents \emph{pods}.
\section{Votre travail de la semaine dernière}
\label{sec:org59acb8b}
Si vous aviez fini le TP la semaine dernière, passez à la partie suivante.
Sinon continuez le.
Si vous le souhaitez, vous pouvez vous baser le fichier \texttt{without\_storage.yaml} et y ajouter :
\begin{itemize}
\item \emph{ConfigMap}
\item \emph{PersistentVolume}
\item \emph{PersistentVolumeClaim}
\item montage du \emph{PVC} dans les \emph{pods} du déploiement
\end{itemize}
\section{\emph{Ingress}}
\label{sec:orgc44da1d}
\begin{warning}
Avant tout, lancez la commande \texttt{minikube addons enable ingress} qui permet l'utilisation des \emph{Ingress} dans \emph{minikube}.
N'oubliez pas aussi \\[0pt]
\texttt{export no\_proxy="127.0.0.1,.vdn,localhost,10.96.0.0/12,192.168.49.2.nip.io"} \\[0pt]
\textbf{Attention à ne pas utiliser la commande des précédents TPs car elle ne contient pas l'exclusion pour \texttt{192.168.49.2.nip.io}}.
\end{warning}
Déployez maintenant un \emph{Ingress} permettant l'accès à l'application.
Configurez votre \emph{Ingress} pour que le chemin \texttt{/} arrive sur l'application et le chemin \texttt{/api} arrive sur la base de données.
Lors de la configuration de l'\emph{Ingress}, utilisez \texttt{192.168.49.2.nip.io} \textbf{comme nom de domaine}.
Il s'agit d'un domaine résolvant vers l'adresse \texttt{192.168.49.2}, qui est l'adresse de \emph{minikube} dans votre machine virtuelle.
Vérifiez le fonctionnement avec ces commandes :
\begin{minted}[]{bash}
http 192.168.49.2.nip.io/
http 192.168.49.2.nip.io/api
\end{minted}
\section{Déploiement \emph{Canary}}
\label{sec:org485e115}
Créez maintenant un déploiement identique à celui de l'application mais qui utilise l'image \\[0pt]
\texttt{evanespen/application:claque} et un nombre de \emph{replicas} à 1.
Ne changez pas les valeurs de \texttt{template.metadata.labels.app} sinon ce nouveau déploiement ne sera pas géré par le \emph{LoadBalancer}.
Ouvrez \texttt{192.168.49.2.nip.io} dans un navigateur \textbf{dans la machine virtuelle} (donc en vous connectant avec \texttt{ssh -X}).
Rechargez la page plusieurs fois, \textbf{avec \texttt{Ctrl+Shift+R}} pour ignorer le cache, et constatez !
\section{Aide}
\label{sec:orgdbe80a5}
Référez vous au cours et à ces documentations pour y parvenir (ce sont bien des liens):
\begin{itemize}
\item \href{https://kubernetes.io/fr/docs/concepts/services-networking/service/}{\emph{Service}}
\item \href{https://kubernetes.io/docs/concepts/workloads/pods/}{\emph{Pod}}
\item \href{https://kubernetes.io/docs/concepts/workloads/controllers/deployment/}{\emph{Deployment}}
\item \href{https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/}{\emph{PV} et \emph{PVC}}
\item \href{https://kubernetes.io/fr/docs/concepts/services-networking/ingress/}{\emph{Ingress}}
\end{itemize}
Amusez vous bien ;)
\end{document}

@ -0,0 +1,11 @@
FROM rust as builder
WORKDIR /build
COPY . .
RUN cargo build --release
RUN apt update && \
apt install -y toto toto toto toto toto && \
compile && \
apt remove toto toto toto toto toto

@ -0,0 +1 @@
evrardve@orion.1250:1717489275

@ -0,0 +1,3 @@
Dockerfile
storage
target

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/database.iml" filepath="$PROJECT_DIR$/.idea/database.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,15 @@
[package]
name = "database"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4"
serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.117"
anyhow = "1.0.86"
env_logger = "0.11.3"
log = "0.4.21"
gethostname = "0.4.3"

@ -0,0 +1,22 @@
FROM rust as builder
WORKDIR /build
COPY . .
RUN pwd
RUN ls
RUN cargo build --release
RUN pwd
RUN ls
FROM debian
WORKDIR /root
COPY --from=builder /build/target/release/database .
RUN ls -lh
ENV PORT=''
ENV STORAGE_DIR=''
CMD ["./database"]

@ -0,0 +1,125 @@
use log::{info};
use std::env;
use std::fs;
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, middleware::Logger};
use actix_web::error::HttpError;
use serde::{Deserialize, Serialize};
use serde_json;
use gethostname::gethostname;
#[derive(Serialize, Deserialize, Debug)]
struct Movie {
title: String,
director: String,
release_year: u16,
}
fn gen_error_message(error: &str) -> String {
let hostname = gethostname().into_string().unwrap();
format!("[served by {}], {}", hostname, error)
}
fn get_storage_file() -> String {
let storage_dir: String = match env::var("STORAGE_DIR") {
Ok(storage_dir) => storage_dir,
Err(_) => panic!("You must set STORAGE_DIR env var")
};
// fs::create_dir_all(storage_dir).expect("unable to create storage directory");
match storage_dir.chars().last().unwrap() {
'/' => storage_dir + "storage.json",
_ => storage_dir + "/storage.json",
}
}
fn get_all_from_storage() -> anyhow::Result<Vec<Movie>> {
let raw_data = match fs::read_to_string(get_storage_file()) {
Ok(raw_data) => raw_data,
Err(e) => {
fs::write(get_storage_file(), "[]").expect("Unable to write file");
"[]".to_string()
}
};
let movies: Vec<Movie> = serde_json::from_str(&raw_data)?;
Ok(movies)
}
fn write_to_storage(movies: Vec<Movie>) -> anyhow::Result<()> {
let data = serde_json::to_string_pretty(&movies).expect("Failed to serialize movies.");
fs::write(get_storage_file(), data).expect("Unable to write file");
Ok(())
}
#[get("/")]
async fn get_all() -> Result<impl Responder, HttpError> {
let hostname = gethostname().into_string().unwrap();
match get_all_from_storage() {
Ok(movies) => return Ok(HttpResponse::Ok().insert_header(("X-ServedBy", hostname)).json(movies)),
Err(_) => return Ok(HttpResponse::InternalServerError().body(gen_error_message("storage file not found at 'storage/storage.json'")))
}
}
#[get("/{title}")]
async fn get_one(title: web::Path<String>) -> Result<impl Responder, HttpError> {
let hostname = gethostname().into_string().unwrap();
return match get_all_from_storage() {
Ok(movies) => {
for movie in movies {
if movie.title.to_lowercase().replace(' ', "") == title.to_string().to_lowercase().replace(' ', "") {
return Ok(HttpResponse::Ok().insert_header(("X-ServedBy", hostname)).json(movie));
}
}
Ok(HttpResponse::NotFound().insert_header(("X-ServedBy", hostname)).body(format!("Movie '{}' not found", title)))
},
Err(_) => return Ok(HttpResponse::InternalServerError().body(gen_error_message("storage file not found at 'storage/storage.json'")))
}
}
#[post("/")]
async fn insert(new_movie: web::Json<Movie>) -> Result<impl Responder, HttpError> {
let hostname = gethostname().into_string().unwrap();
let mut movies: Vec<Movie>;
match get_all_from_storage() {
Ok(_movies) => movies = _movies,
Err(_) => movies = vec!()
};
for movie in &movies {
if movie.title.to_lowercase().replace(' ', "") == new_movie.title.to_string().to_lowercase().replace(' ', "") {
return Ok(HttpResponse::BadRequest().body(gen_error_message(format!("Movie '{}' already exists", new_movie.title).as_str())))
}
}
movies.push(new_movie.into_inner());
write_to_storage(movies);
Ok(HttpResponse::Created().insert_header(("X-ServedBy", hostname)).body("Created"))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
let port: u16 = match env::var("PORT") {
Ok(port) => port.parse().unwrap(),
Err(_) => panic!("You must set PORT env var")
};
info!("App started on port {}", port);
HttpServer::new(|| {
App::new()
.wrap(Logger::new("%a \"%r\" %s b %T"))
.service(get_all)
.service(get_one)
.service(insert)
})
.bind(("0.0.0.0", port))?
.run()
.await
}

@ -0,0 +1,12 @@
[
{
"title": "toto3",
"director": "toto",
"release_year": 2020
},
{
"title": "toto2",
"director": "toto",
"release_year": 2020
}
]

@ -0,0 +1,3 @@
Dockerfile
storage
target

File diff suppressed because it is too large Load Diff

@ -0,0 +1,17 @@
[package]
name = "application"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4"
serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.117"
anyhow = "1.0.86"
env_logger = "0.11.3"
log = "0.4.21"
tera = "1.19.1"
awc = "3.5.0"
gethostname = "0.4.3"

@ -0,0 +1,23 @@
FROM rust as builder
WORKDIR /build
COPY . .
RUN pwd
RUN ls
RUN cargo build --release
RUN pwd
RUN ls
FROM debian
WORKDIR /root
COPY --from=builder /build/target/release/application ./
COPY ./templates/ ./
RUN mkdir templates && mv index.html templates/
ENV PORT=''
ENV DATABASE_URL=''
CMD ["./application"]

@ -0,0 +1,161 @@
use log::{info, error};
use std::env;
use std::fs;
use anyhow::bail;
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder, middleware::Logger, http::header::ContentType};
use actix_web::error::HttpError;
use awc::Client;
use serde::{Deserialize, Serialize};
use serde_json;
use tera::{Tera, Context};
use gethostname::gethostname;
#[derive(Serialize, Deserialize, Debug)]
struct Movie {
title: String,
director: String,
release_year: u16,
}
fn gen_error_message(error: &str) -> String {
let hostname = gethostname().into_string().unwrap();
format!("[served by {}], {}", hostname, error)
}
fn parse_database_url() -> String {
let mut database_url: String = match env::var("DATABASE_URL") {
Ok(database_url) => database_url.to_string(),
Err(_) => panic!("You must set DATABASE_URL env var")
};
if !database_url.contains("http://") {
database_url = "http://".to_owned() + database_url.as_str();
}
database_url = match database_url.chars().last().unwrap() {
'/' => database_url,
_ => database_url + "/",
};
database_url
}
async fn render(is_ok: bool, error_message: &str) -> anyhow::Result<String> {
let hostname = gethostname().into_string().unwrap();
let client = Client::default();
let movies = match client.get(parse_database_url()).send().await {
Ok(mut res) => match res.json::<Vec<Movie>>().await {
Ok(movies) => movies,
Err(e) => {
error!("{}", e.to_string());
bail!(e.to_string());
},
},
Err(e) => {
error!("{}", e.to_string());
bail!(e.to_string());
},
};
let tera = match Tera::new("templates/*.html") {
Ok(t) => t,
Err(e) => {
println!("Parsing error(s): {}", e);
::std::process::exit(1);
}
};
let mut context = Context::new();
context.insert("hostname", &hostname);
context.insert("movies", &movies);
context.insert("error_message", &error_message);
context.insert("is_ok", &is_ok);
return match tera.render("index.html", &context) {
Ok(page) => Ok(page),
Err(e) => {
error!("{}", e.to_string());
bail!(e.to_string());
},
}
}
#[get("/")]
async fn index() -> Result<impl Responder, HttpError> {
match render(true, "").await {
Ok(page) => Ok(HttpResponse::Ok()
.content_type(ContentType::plaintext())
.insert_header(("Content-Type", "text/html"))
.body(page)),
Err(e) => {
if e.to_string() == "Failed to connect to host: Connection refused (os error 111)".to_string() {
Ok(HttpResponse::InternalServerError().body(gen_error_message("Cannot connect to database")))
} else {
Ok(HttpResponse::InternalServerError().body(gen_error_message(e.to_string().as_str())))
}
}
}
}
#[post("/")]
async fn insert(new_movie: web::Form<Movie>) -> Result<impl Responder, HttpError> {
println!("{:?}", new_movie);
let client = Client::default();
match client.post(parse_database_url()).send_json(&new_movie).await {
Ok(mut res) => match res.status().is_success() {
true => {
match render(true, "Film ajouté").await {
Ok(page) => return Ok(HttpResponse::Ok()
.content_type(ContentType::plaintext())
.insert_header(("Content-Type", "text/html"))
.body(page)),
Err(e) => return Ok(HttpResponse::InternalServerError().body(e.to_string()))
}
}
false => match render(false, "Erreur lors de l'ajout").await {
Ok(page) => return Ok(HttpResponse::Ok()
.content_type(ContentType::plaintext())
.insert_header(("Content-Type", "text/html"))
.body(page)),
Err(e) => return Ok(HttpResponse::InternalServerError().body(e.to_string()))
}
}
Err(e) => return Ok(HttpResponse::InternalServerError().body(e.to_string()))
};
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
let port: u16 = match env::var("PORT") {
Ok(port) => port.parse().unwrap(),
Err(_) => panic!("You must set PORT env var")
};
let database_url = match env::var("DATABASE_URL") {
Ok(database_url) => database_url,
Err(_) => panic!("You must set DATABASE_URL env var")
};
info!("App started on port {} using DATABASE_URL {}", port, database_url);
HttpServer::new(|| {
App::new()
.wrap(Logger::new("%a \"%r\" %s b %T"))
.service(index)
.service(insert)
})
.bind(("0.0.0.0", port))?
.run()
.await
}

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Films</title>
<link rel="stylesheet" href="./style.css">
<link rel="icon" href="./favicon.ico" type="image/x-icon">
<style>
* {
font-family: sans;
color: white;
}
body {
background-color: #202020;
}
.message {
padding: 10px 20px;
border-radius: 10px;
}
.ok {
background-color: #81C784;
color: #2E7D32;
}
.error {
background-color: #E57373;
color: #C62828;
}
main {
width: 80vw;
margin-left: 10vw;
background-color: #202020;
}
.movie {
background-color: #505050;
padding: 10px 20px;
border-radius: 10px;
margin-bottom: 20px;
background: hsla(197, 100%, 63%, 1);
background: linear-gradient(45deg, hsla(197, 100%, 63%, 1) 0%, hsla(294, 100%, 55%, 1) 100%);
}
.title {
font-variant: small-caps;
font-size: 2em;
}
form {
margin-top: 20px;
background-color: #505050;
padding: 10px 20px;
border-radius: 10px;
margin-bottom: 20px;
display: flex;
flex-direction: column;
}
input {
margin-bottom: 10px;
border-radius: 5px;
border: none;
outline: none;
background-color: #707070;
}
input[type="submit"] {
background-color: #388E3C;
color: white;
font-size: 1.5em;
}
</style>
</head>
<body>
<main>
{% if error_message != "" %}
{% if is_ok %}
<div class="message ok">{{error_message}}</div>
{% else %}
<div class="message error">{{error_message}}</div>
{% endif %}
{% endif %}
<h1>Films - Version qui claque !</h1>
<h2>Servi par <code>{{hostname}}</code></h2>
<div id="movies">
{% for movie in movies %}
<div class="movie">
<p class="title">{{movie.title}}</p>
<div class="director">Réalisateur: {{movie.director}}</div>
<div class="year">Année de sortie: {{movie.release_year}}</div>
</div>
{% endfor %}
</div>
<hr/>
<form method="POST" action="/">
<label for="title">Titre</label>
<input name="title" type="text" value="" required/>
<label for="director">Réalisateur</label>
<input name="director" type="text" value="" required/>
<label for="release_year">Année de sortie</label>
<input name="release_year" type="number" value="" required/>
<input name="submit" type="submit" value="Valider"/>
</form>
</main>
<script src="index.js"></script>
</body>
</html>

@ -0,0 +1,78 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: database
spec:
replicas: 3
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
spec:
containers:
- name: database
image: evanespen/database:latest
env:
- name: PORT
value: "4000"
- name: STORAGE_DIR
value: "/root/"
ports:
- containerPort: 4000
---
apiVersion: v1
kind: Service
metadata:
name: database-service
spec:
type: LoadBalancer
ports:
- port: 4000
targetPort: 4000
selector:
app: database
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: application
spec:
replicas: 3
selector:
matchLabels:
app: application
template:
metadata:
labels:
app: application
spec:
containers:
- name: application
image: evanespen/application:latest
env:
- name: PORT
value: "4001"
- name: DATABASE_URL
value: "http://database-service:4000"
ports:
- containerPort: 4001
---
apiVersion: v1
kind: Service
metadata:
name: application-service
spec:
type: LoadBalancer
ports:
- port: 4001
targetPort: 4001
selector:
app: application
Loading…
Cancel
Save