# 🇫🇷 Kit de survie Kubernetes pour les développeurs avec K3S - Partie 2: Le déploiement
Normalement, vous avez lu la première partie de ce kit de survie Kubernetes pour les devs (opens new window). Vous avez donc un cluster qui tourne sur votre machine. Vous êtes prêt à jouer avec et à déployer votre 1ère webapp.
# Déployer (et redéployer) facilement une webapp NodeJS sur K3S
J'ai une grosse appétence pour le JavaScript, je trouve que c'est simple à mettre en oeuvre. Nous allons donc commencer par une application Express, mais ne vous inquietez pas, dans le futur, nous ferons du Kotlin 🙂
Alors pas besoin de vous taper tous le code, je vous ai préparé un projet ici: https://gitlab.com/learn-k3s/amazing-web-app (opens new window)
Donc il vous suffit de le cloner: git@gitlab.com:learn-k3s/amazing-web-app.git
Cette application est fournie avec un Dockerfile
très simple qui va nous permettre de construire une image et de déployer un container sur notre cluster.
Pré-requis: il vous faut un compte sur le Docker Hub et un client Docker installé
le
Dockerfile
FROM node:12.0-slim
COPY . .
RUN npm install
CMD [ "node", "index.js" ]
# 1er déploiement pas à pas
Nous allons tout d'abord créer un fichier yaml
qui va expliquer à kubectl
comment déployer notre application. Vous pouvez mettre ce fichier n'importe où dans votre projet, mais par convention, on le trouve le plus souvent dans un sous-répertoire kube
. Je vais appeler ce fichier deploy.yaml
(je n'ai pas vérifié si il y avait une convention).
Ce fichier comporte 3 parties (vous pouvez même le splitter en 3 fichiers, mais je préfère avoir tout au même endroit)
Notre application est "représentée" dans Kubernetes par:
- un service
- un déploiement
- un ingress
✋ pas de panique, en général vous ne serez pas seul pour écrire ce type de fichier
# 1ère partie: "Service"
---
# Service
apiVersion: v1
kind: Service
metadata:
name: amazing-web-app
spec:
selector:
app: amazing-web-app
ports:
- port: 80
targetPort: 8080
- Service: "Une manière abstraite d’exposer une application s’exécutant sur un ensemble de Pods en tant que service réseau."
- 📘 Référence: https://kubernetes.io/fr/docs/concepts/services-networking/service/
- Pod: "Un Pod est l’unité d’exécution de base d’une application Kubernetes–l’unité la plus petite et la plus simple dans le modèle d’objets de Kubernetes–que vous créez ou déployez. Un Pod représente des process en cours d’exécution dans votre Cluster."
- 📘 Référence: https://kubernetes.io/fr/docs/concepts/workloads/pods/pod-overview/
🖐 dans notre cas nous aurons un pod qui va encapsuler notre container
Les données importantes à connaître sont:
- le nom de l'application (et du service, car j'ai donné le même au deux):
amazing-web-app
- le port http (dans notre cas) de notre application:
8080
- le port exposé:
80
# 2ème partie: "Deployment"
---
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: amazing-web-app
spec:
replicas: 3
selector:
matchLabels:
app: amazing-web-app
template:
metadata:
labels:
app: amazing-web-app
spec:
containers:
- name: amazing-web-app
image: k33g/amazing-img:0.0.0
ports:
- containerPort: 8080
imagePullPolicy: Always
- Déploiement: "Le déploiement instruit Kubernetes de comment créer et mettre à jour des instances de votre application"
- 📘 Références:
- https://kubernetes.io/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/
- https://kubernetes.io/fr/docs/concepts/workloads/controllers/deployment/
- Réplicas: "Un ReplicaSet (ensemble de réplicas en français) a pour but de maintenir un ensemble stable de Pods à un moment donné. Cet objet est souvent utilisé pour garantir la disponibilité d’un certain nombre identique de Pods."
- 📘 Référence: https://kubernetes.io/fr/docs/concepts/workloads/controllers/replicaset/
🖐 dans notre cas nous aurons un ensemble de 3 réplicas de notre pod (et nous aurns donc un système "automatique" de loadbalancing pour notre application sur ces 3 pods)
Les données importantes à connaître sont:
- le nom de l'application:
amazing-web-app
- le port http (dans notre cas) de notre application:
8080
- le nom de l'image Docker:
k33g/amazing-img:0.0.0
🖐 k33g
c'est mon nom(handle) de user sur le docker hub, donc si le votre c'est bob
, pensez à changer 😉
# 3ème partie: "Ingress"
---
# Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: amazing-web-app
spec:
rules:
- host: amazing-web-app.192.168.64.17.nip.io
http:
paths:
- backend:
serviceName: amazing-web-app
servicePort: 80
- Ingress: "Un Ingress est un objet Kubernetes qui gère l’accès externe aux services dans un cluster, généralement du trafic HTTP. Un Ingress peut fournir un équilibrage de charge, une terminaison TLS et un hébergement virtuel basé sur un nom."
- 📘 Référence: https://kubernetes.io/fr/docs/concepts/services-networking/ingress/
Les données importantes à connaître sont:
- le nom du service (et application):
amazing-web-app
- le port http exposé:
80
- l'url de notre application:
amazing-web-app.192.168.64.17.nip.io
🖐 🤔 Mais c'est quoi cette URL? amazing-web-app.192.168.64.17.nip.io
: nip.io est un service de "DNS wildcard" bien pratique pour du test. Par exemple, un nom comme hello.127.0.0.1.nip.io
vas résoudre/pointer sur 127.0.0.1
. Et nous nous utiliserons l'adresse ip de notre cluster (enfin du noeud master
).
Nous avions appelé notre noeud principal basesar
, donc pour récupérer son adresse IP, vous pouvez utiliser la commande multipass list
ou encore mieux (car très pratique dans un script):
CLUSTER_IP=$(multipass info basestar | grep IPv4 | awk '{print $2}')
echo $CLUSTER_IP
🖐🖐🖐 Pensez bien à changer l'adresse IP dans le fichier YAML avec l'IP de votre cluster
Enregistrez votre fichier deploy.yaml
dans le répertoire kube
de votre projet.
Donc maintenant vous êtes prêt à déployer votre application, voici les étapes:
- lancez K9S dans un terminal pour suivre le déploiement:
export KUBECONFIG=$PWD/k3s.yaml k9s --all-namespaces
- ouvrez un autre terminal
Partie "Docker":
- positionnez vous dans votre projet:
cd amazing-web-app
- connectez vous au Docker hub:
docker login
- construisez votre image:
docker build -t amazing-img .
(🖐 n'oubliez pas le.
à la fin) - taguez votre image:
docker tag amazing-img k33g/amazing-img:0.0.0
- "poussez" votre image sur le Docker Hub:
docker push k33g/amazing-img:0.0.0
🖐 mon repository docker est publique sur Docker Hub, donc accessible par mon cluster sans avoir besoin de credentials pour accéder à l'image
Partie "Kube":
- expliquez à
kubectl
où est le fichier de configuration du cluster:export KUBECONFIG=../create-cluster/k3s.yaml
(🖐 adaptez en fonction de vos besoins) - lancez la commande
kubectl apply -f ./kube/deploy.yaml
Vous devriez obtenir:
service/amazing-web-app created
deployment.apps/amazing-web-app created
ingress.extensions/amazing-web-app created
Et vous pouvez suivre dans K9S le déploiement de vos pods:
Et enfin, allez à http://amazing-web-app.192.168.64.17.nip.io (opens new window) avec votre navigateur:
🎉 vous avez déployé votre première webapp dans un cluster kube (et en local!!!)
Maintenant toujours avec votre navigateur, appelez la "route" http://amazing-web-app.192.168.64.17.nip.io/api/hello (opens new window) et raffraîchissez votre page plusieurs fois:
Vous notez qu'à chaque refresh le message json change. Si vous allez faire un tour dans le code source de l'application (dans index.js
), à chaque lancement de l'application je crée un nom let fancy_name = fancyName()
et je fournis ce nom lors de l'appel de /api/hello
:
app.get('/api/hello', (req, res) => {
res.send({
message: `👋 hello world 🌍`,
pod: fancy_name
})
})
Et comme nous avons 3 pods, que Kube fait du "loadbalancing" sur ces 3 pods, et bien nous avons 3 noms.
👋 Remarque: vous trouverez le fichier deploy.yaml
sur la branche first-steps
du projet https://gitlab.com/learn-k3s/amazing-web-app/-/tree/first-steps (opens new window)
Allez, un dernier petit effort, nous allons voir comment re-déployer après une modification.
# Redéploiement
Si vous faites des modifications dans votre code, par exemple, ajoutez une "route" à votre web app:
app.get('/api/vulcan_salute', (req, res) => {
res.send({
message: `🖖dif-tor heh smusma (live long and prosper)`,
pod: fancy_name
})
})
Il va falloir penser à "re-taguer" votre image et modifier le fichier deploy.yaml
en fonction:
docker build -t amazing-img .
docker tag amazing-img k33g/amazing-img:0.0.1 # 👋 on change le tag
docker push k33g/amazing-img:0.0.1 # 👋 on change le tag
Dans le fichier deploy.yaml
, allez modifier le tag: image: k33g/amazing-img:0.0.1
et enfin:
kubectl apply -f ./kube/deploy.yaml
Vous devriez obtenir:
service/amazing-web-app unchanged
deployment.apps/amazing-web-app configured
ingress.extensions/amazing-web-app unchanged
👋 vous pouvez noter que seul la partie déploiement a été changée
Faites un curl:
curl http://amazing-web-app.192.168.64.17.nip.io/api/vulcan_salute
Vous devriez obtenir un résultat comme celui ci:
{"message":"🖖dif-tor heh smusma (live long and prosper)","pod":"lingering_field"}
👋 bien-sûr, à chaque fois que vous allez relancer un curl, le nom du pod va changer.
🎉 C'est terminé pour ce premier déploiement. Je vous laisse expérimenter dans vore coin. Pendant ce temps, je vous écris une suite.
Ce que nous avons fait s'appelle du "Rolling Update": https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/ (opens new window)
Dans les prochains épisodes nous allons voir comment:
- automatiser un peu son déploiement (et écrire un plugin pour
kubectl
) - déployer un/des microservice(s) Vert-x (en Kotlin)
- créer un service discovery grâce à Redis pour nos microservices
- ... et d'autres petites choses sympas à venir
🖖 J'espère que cela vous a plu. Bien sûr toutes les remarques sont les bienvenues
Last Articles
- 🇫🇷 Type Result en Kotlin | 2020-10-31 | Kotlin
- 🇫🇷 Type Result en Kotlin | 2020-10-31 | Kotlin
- 🇬🇧 Every GitLab Page deserves a real CI/CD | 2020-07-23 | GitLab CI
- 🇫🇷 Lit-Element, commencer doucement | 2020-07-20 | WebComponent
- 🇬🇧 Build quickly and host easily your Docker images with GitLab and GitLab CI | 2020-06-02 | GitLab CI
- 🇬🇧 Deploy quickly on Clever Cloud with GitLab CI | 2020-05-31 | GitLab CI
- 🇫🇷 Borg Collective, mes jouets pour apprendre Knative | 2020-05-30 | Knative
- 🇬🇧 Borg Collective, Toys to learn Knative | 2020-05-30 | Knative
- 🇫🇷 M5Stack, une petit device IOT bien sympathique, programmable en Python | 2020-05-09 | IOT
- 🇫🇷 Knative, l'outil qui rend Kubernetes sympathique | 2020-05-02 | kubernetes