Skip to content
Snippets Groups Projects
Select Git revision
  • 7f268c377d7fe5bec14c716a9e4231d24dba526e
  • master default protected
2 results

kubernetes

  • Clone with SSH
  • Clone with HTTPS
  • user avatar
    remche authored
    7f268c37
    History

    TP Kubernetes

    Prise en main

    Installation de snap

    Tout d'abord, si ce n'est pas déjà fait, installez snap:

    sudo apt-get update
    sudo apt-get install snapd

    Installation et conf de base

    Puis installez MicroK8s via snap et configurez-le pour l'utilisateur de la VM:

    sudo snap install microk8s --classic
    sudo usermod -a -G microk8s $USER
    sudo chown -f -R $USER ~/.kube
    su - $USER

    Vérifiez que le cluster Kubernetes fonctionne correctement :

    microk8s status --wait-ready

    Vous pouvez récupérer la liste des noeuds (un seul par défaut) :

    microk8s kubectl get nodes

    Afin de faciliter la suite et de rester vanilla, ajouter l'alias suivant :

    alias kubectl='microk8s kubectl'
    echo "alias kubectl='microk8s kubectl'" >> ~/.bashrc

    Ajoutez la complétion de la commande kubectl:

    echo 'source <(kubectl completion bash)' >>~/.bashrc
    bash

    Vous pouvez aussi utiliser les alias pratiques définis par kubectl-aliases.

    Services de base

    MicroK8s est un déploiement minimal de Kubernetes. Vous pouvez lister les pods déployés par défaut :

    kubectl get pods -A

    Il s'agit uniquement des pods Calico, le plugin CNI (Container Network Interface) qui gère le réseau pour les conteneurs.

    Vous allez ajouter deux services importants généralement déployés sur les cluster Kubernetes :

    • metrics-server pour l'accès aux métriques de base ;
    • CoreDNS pour la resolution DNS interne.

    metrics-server

    Actuellement, vous n'avez pas accès aux métriques :

    kubectl top nodes
    kubectl top pods -A

    Déployez metrics-server et vérifiez que le pod correspondant tourne bien :

    microk8s enable metrics-server
    kubectl get pods -A

    Après quelques dizaine de secondes, les métriques devraient être disponibles :

    kubectl top nodes
    kubectl top pods -A

    CoreDNS

    Pour tester le service de DNS (qui est derrière le mécanisme de Service Discovery), lançez un pod nginx et vérifiez qu'il tourne :

    kubectl run --image nginx nginx-pod
    kubectl expose pod nginx-pod --port 80
    kubectl get pods -o wide
    pod_ip=$(kubectl get pod nginx-pod -o jsonpath='{.status.podIP}')
    kubectl get service
    service_ip=$(kubectl get service nginx-pod -o jsonpath='{.spec.clusterIP}')

    Essayez de l'atteindre depuis un autre pod, via son IP, l'IP du service, puis le nom DNS du service :

    kubectl run --rm --restart=Never -it --image busybox test -- wget -O- $pod_ip
    kubectl run --rm --restart=Never -it --image busybox test -- wget -O- $service_ip
    kubectl run --rm --restart=Never -it --image busybox test -- wget -O- nginx-pod

    Déployez CoreDNS, vérifiez qu'il tourne bien et testez à nouveau la résolution DNS :

    microk8s enable dns
    kubectl get pods -A
    kubectl run --rm --restart=Never -it --image busybox test -- wget -O- nginx-pod

    Nettoyage

    kubectl delete service nginx-pod
    kubectl delete pod nginx-pod

    Vapormap

    Nous allons lancer trois pods: un pour Mariadb, un pour l'application Django, et un pour notre frontal NGINX. Ces pods seront contrôlés par des Deployments, ce qui permet de les relancer automatiquement en cas de défaillance.

    Mariadb

    Premier déploiement

    Astuce: pour générer les manifestes yaml facilement, vous pouvez utiliser la commande kubectl avec les options --dry-run -o yaml :

    kubectl create deployment mariadb --image mariadb --dry-run=client -o yaml > mariadb.yml

    Examiner le fichier créé et lancez le déploiement (1 réplicas) :

    less mariadb.yml
    kubectl apply -f mariadb.yml

    Surveillez l'état du pod :

    kubectl get pods -w

    Debug

    Le pod mariadb produit une erreur. Pour la comprendre :

    kubectl describe pod -l app=mariadb

    L'erreur est Back-off restarting failed container, ce qui signifie que le pod redémarre sans cesse. Pour examiner plus précisément l'activité d'un conteneur du pod :

    kubectl logs -l app=mariadb

    On voit qu'il manque des options (variables d'environnement) pour le que conteneur mariadb démarre correctement. Définissez les variables MYSQL_ROOT_PASSWORD, MYSQL_USER, MYSQL_PASSWORD et MYSQL_DATABASE dans le fichier mariadb.yml à l'aide du champ env.

    Dans la suite, nous verrons comment éviter les secrets en clair... Si nous avons le temps ;)

    Une fois les variables définies, réappliquez les changements et vérifiez que le pod tourne :

    kubectl apply -f mariadb.yml
    kubectl get pods -w

    Tests

    Pour tester facilement que le pod mariadb répond correctement, et pour les futurs debug, vous pouvez utiliser la commande kubectl port-forward :

    kubectl port-forward $nom_du_pod_mariadb 3306:3306
    telnet localhost 3306

    Nous avons vu que les pods et leur configuration réseau sont temporaires. Afin de les exposer de manière pérenne, déployez un service comme dans la première partie. Utilisez la même astuce du dry-run pour générer le fichier :

    kubectl expose deployment mariadb --port=3306 --target-port=3306 --dry-run=client -o yaml > mariadb-service.yml
    kubectl apply -f mariadb-service.yml

    Ainsi, le nom DNS mariadb pointera vers le pod correspondant. Vous pouvez créer un pod temporaire afin de vérifier la résolution DNS, et le bon fonctionnement du serveur mariadb.

    kubectl run --rm --restart=Never -i -t --image busybox test /bin/sh
    telnet mariadb 3306

    Vapormap

    Déploiement de vapormap (à vous de jouer)

    Sur l'exemple des manifests mariadb, créez un manifest pour déployer les conteneurs vapormap et nginx, avec 2 replicas pour nginx et 3 pour vapormap.

    Vous pouvez déclarer plusieurs objets dans le même fichier en les séparant par la ligne ---

    Pensez à :

    • Spécifier les images correspondantes, Si vous n'avez pas vos propres images, vous pouvez utiliser les suivantes : registry.plmlab.math.cnrs.fr/resinfo/anf/2019/ada/vapormap/vapormap:master
      registry.plmlab.math.cnrs.fr/resinfo/anf/2019/ada/vapormap/nginx:master
    • Positionner les variables VAPOR_DBNAME, VAPOR_DBUSER, VAPOR_DBPASS, DJANGO_SETTINGS_MODULE et VAPOR_DBHOST pour le conteneur vapormap ;
    • Positionner les variables VAPORMAP_URL et VAPORMAP_PORT pour le conteneur nginx ;
    • Spécifier les ports pour chaque conteneur ;
    • Créer les services correspondants.

    Après avoir appliqué le manifeste, vérifez que vous accédez aux conteneurs avec kubectl port-forward.

    Migration de base

    L'application ne marchera pas en l'état, puisqu'il faut lancer les migrations de base avant de lancer l'application Django. Ajoutez un initContainer au déploiement varpomap, dont le rôle sera d'éxecuter la commande python manage.py makemigrations && python manage.py migrate

    Verifiez le bon fonctionnement de l'application à l'aide de :

    kubectl port-forward svc/nginx 8000:8000

    Ingress

    Maintenant, nous allons exposer l'application au monde extérieur grâce à l'objet Ingress.

    Ajoutons NGINX Ingress Controller, qui est un Ingress Controller très répandu de l'écosystème :

    microk8s.enable ingress
    kubectl get pods --all-namespaces

    Nous pouvons alors définir l'objet Ingress qui va diriger le trafic vers le service nginx :

    cat <<EOF > ingress.yml
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: vapormap
    spec:
      ingressClassName: public
      rules:
      - http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 8000
    EOF
    kubectl apply -f ingress.yml

    Vous n'avez désormais plus besoin de port-forward (qui est un mécanisme prévu pr le debug) pour accéder à votre application :

    firefox http://localhost

    3. Aller plus loin

    Ressources

    Afin de limiter l'usage des ressources par les pods et de faciliter le travail du scheduler, il est fortement conseillé de spécifier des Resources. Vous pouvez par exemple configurer le pod nginx avec 2Mo/10Mo, et le pod vapormap avec 40Mo/80Mo.

    Secrets

    Dans le TP, les secrets sont dans le dépôt, ce qui est évidemment un mauvaise pratique. En pratique, l'API Kubernetes comporte un objet (que l'on a utilisé pour configurer la registry docker) qui permet de séparer les secrets des déploiements : l'objet Secret. Ajouter un secret avec les différentes variables d'environnement nécessaire, et modifier les déploiements mariadb et vapormap afin qu'ils utilisent le secret comme variable d'environnement. Par la suite, on peut utiliser sops pour chiffrer les secrets yaml et les ajouter au dépôt en toute confiance...

    Volume

    Vous aurez remarqué que les données ne sont pas persistantes. En effet, à chaque redémarrage du pod MariaDB, les données sont perdues. Cette problématique est résolue par Kubernetes grâce aux Volumes. Notez que Kubernetes est capable de communiquer avec le cloud sous-jacent (par exemple cinder, dans le cas d'Openstack), mais aussi de tailler des volumes iSCSI, nfs, etc...

    Pour MicroK8s, il s'agit par défaut d'un simple stockage fichier dans un répertoire de la machine hôte. Il faut tout d'abord activer le composant qui gère le stockage persitant :

    microk8s.enable hostpath-storage

    Puis, ajoutez une PersistentVolumeClaim et attachez le volume résultant au pod du déploiement MariaDB (qui stocke ses données dans /var/lib/mysql). Vérifiez ensuite qu'un redémarrage du pod préserve les données.

    NetworkPolicy

    Par défaut, la base mariadb est accessible à tous les pods du cluster. Vous pouvez limiter les pods qui y ont accès à l'aide d'une NetworkPolicy. Utilisez le namespaceSelector qui correspond à votre namespace, et le label app: vapormap.

    Helm

    Vous trouverez dans le repertoire helm un chart qui permet de déployer Vapormap à l'aide de Helm, un gestionnaire de paquets pour Kubernetes. Le chart se base lui-même sur le chart MariaDB de Bitnami.

    Pour cela, il faut installer la version Helm 3 de MicroK8s :

    microk8s.enable helm3
    alias helm='microk8s helm3'
    echo "alias helm='microk8s helm3'" >> ~/.bashrc

    Vous pourrez alors déployer le chart Helm. Les différentes valeurs peuvent être configurées via le fichier values.yaml.

    helm upgrade --install vapormap vapormap -f values.yaml 

    GitOps

    Pour fluidifier les mises en production d'application, nous allons utiliser Argo CD, qui permet de mettre en place des pratiques GitOps. Cet outil va surveiller un dépôt git contenant la définition de votre application et mettre à jour automatiquement à chaque modification.

    Installation d'Argo CD :

    helm repo add argo https://argoproj.github.io/argo-helm
    helm repo update
    helm upgrade --install argocd --create-namespace -n argocd  argo/argo-cd

    Vous pouvez alors déclarer votre application à Argo CD via une Custom Resource Definition :

    kubectl apply -f argocd/vapormap.yaml 

    Après quelques secondes, votre application sera disponible. Une modification du dépôt git spécifié dans le fichier argocd/vapormap.yaml déclenchera alors une mise à jour sur le cluster.