Aller au contenu

Mon second déploiement avec Kompose

Nous devons recréer un cluster k3d d'une maniere que le port interne 80 (ou le contrôleur ingress traefik écoute) soit exposé au système. Nous allons aussi configurer le cluster avec deux noeuds "worker" virtuels.

k3d cluster delete mycluster 
k3d cluster create mycluster-lb -p "8180:80@loadbalancer" --agents 2

Puis changer de contexte et de namespace comme au début du tutoriel :

kubectx k3d-mycluster-lb &&\
k create ns tuto &&\
kubens tuto

De Docker à k8s avec Kompose

Maintenant que nous avons vu toutes les étapes qui mènent au déploiement complet d'une application Jupyter, nous reprenons les 3 fichiers générés avec Kompose dans la partie du tutoriel sur Docker qui sont un déploiement, un service de type ClusterIP et un PersistentVolumeClaim. Nous les plaçons dans un répertoire à part afin de les appliquer ensemble :

jupyter-service.yaml
jupyter-deployment.yaml
jupyter-claim0-persistentvolumeclaim.yaml

Pour appliquer tous au cluster k8s :

k apply -f .

Et vous devez obtenir :

NAME                           READY   STATUS         RESTARTS   AGE
pod/jupyter-7b8bbbf8b7-brpjq   0/1     ErrImagePull   0          14s

NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/jupyter   ClusterIP   10.43.169.51   <none>        8888/TCP   14s

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/jupyter   0/1     1            0           14s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/jupyter-7b8bbbf8b7   1         1         0       14s

Il y a une erreur de type ErrImagePull dans le pod cela est due au nom de l'image qu'il faut changer dans le yaml (nous utilisons l'image de base de Jupyter).

...
    spec:
      containers:
        - image: jupyter/base-notebook # <-- modifié
          name: jupyter
          env:
            - name: JUPYTER_PORT
              value: "8888"

...

!!! info Variable d'environnement Il faut ajouter la variable d'environnement JUPYTER_PORT pour que le conteneur fonctionne. L'initialisation standard y mettre mauvais valeur dans un cluster multi-node.

Ensuite réappliquer les manifests.

k apply -f .

Comme lors du premier déploiement, il y a des ReplicaSet associé au déploiement. Il est possible de voir l'historique des updates de pod via :

k rollout history deployment jupyter
deployment.apps/jupyter
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

Volumes

Nous avons utilisé des nouveaux objets que sont les volumes/persistentVolumeClaim pour garder les données entre redémarrages de pod. Il est possible de les afficher avec :

k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-8bb4749f-5b6c-45ab-b1a5-ef850ea39353   100Mi      RWO            Delete           Bound    tuto/jupyter-claim0   local-path     <unset>                          10s

Ce volume est créé à partir d'un PersistentVolumeClaim qui déclare des caractéristiques d'un Volume (il est possible de créer le volume manuellement, mais c'est peu pratique et n'est pas souvent utilisé)

k get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
jupyter-claim0   Bound    pvc-901b9698-5ee0-47e6-b465-4bf5dabb448a   100Mi      RWO            local-path     <unset>                 16m
cat jupyter-claim0-persistentvolumeclaim.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    io.kompose.service: jupyter-claim0
  name: jupyter-claim0
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi

L'option clé de PVC est StorageClass (on utilise StorageClass par défaut si manqué)

k get sc
NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path (default)   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  177m

Ici le seul SC fournie avec k3d est de type local-path. Les données de ces volumes sont stockés dans un dossier local de noeud. On peut avoir les SCs différents en fonction d'installation particulaire de k8s.

Autre option important est AccessMode. Avec ReadWriteOnce (RWO) le volume peut être attache à un seul noeud en mode read-write, ReadOnlyMany (ROX) permet d'attacher le volume aux quelques noeuds en mode readonly et ReadWriteMany (RWX) est utilisé si on a besoin d'écrire sur le volume à partir des différents noeuds en façon concourante.

Configmap

Les configmaps permettent de configurer les applications via des fichiers textes ou des paramètres.

k create configmap my-config --from-file=13-1-my-config.txt --from-literal=extra-param=extra-value --from-literal=another-param=another-value &&\
k get cm

Il est possible de vérifier où sont stockés les config maps :

 k exec pod/jupyter -- ls /config
 ```

### Secret

Les **Secrets** sont stockés en mémoire alors que les configmap sont sur disque.

## Autres spécificités

### Stratégies de rolling

```yaml
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate

Sondes

Les sondes sont de plusieurs types :

  • vie :
    • /healthy : implementation d'un url dans l'app pour tester en plus de la socket
    • équivalent à nagios
    • redémarre le conteneur
  • ready :
    • conteneur plus exposé sur le réseau
    • fini sa tache mais plus de requête

Ajouter une sonde de vie à l'application :

  livenessProbe:
    httpGet:
      path: /healthy
      port: 8888
    initialDelaySeconds: 5
    timeoutSeconds: 1
    periodSeconds: 10
    failureThreshold: 3
k create deployment jupyter --image=jupyter/base-notebook

Puis crée un service de type ClusterIP :

k create service clusterip jupyter --tcp=8888:80

Puis créer un objet de type Ingress avec le fichier myjupyter-lb.yaml :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jupyter
  annotations:
    ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: jupyter
            port:
              number: 80

Et l'appliquer :

k apply -f myjupyter-lb.yaml

Nous pouvons accéder à l'ingress :

k describe ingress jupyter
Name:             jupyter
Labels:           <none>
Namespace:        tuto
Address:          172.19.0.3
Ingress Class:    traefik
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /     jupyter:80 (10.42.0.11:80)
Annotations:  ingress.kubernetes.io/ssl-redirect: false
Events:       <none>
Authors: Cécile Cavet