Best-of FOSDEM 2020

Quelques consultants d’Objectif Libre se sont rendus au FOSDEM à Bruxelles au début du mois de Février. Voici un condensé de ce qui les a marqués :

Un voyage de VMware à Kubernetes

Le dimanche 2 février, Marek Libra, ingénieur logiciel senior de Red Hat, nous présente comment migrer des machines virtuelles depuis VMware vers un environnement Kubernetes.

Comme beaucoup le savent, Kubernetes est un orchestrateur de conteneurs. Mais il existe aussi la possibilité d’exploiter des machines virtuelles au sein de Kubernetes et ce, au moyen de KubeVirt. La question qui se pose alors est la suivante : Pourquoi mélanger des conteneurs et des machines virtuelles au sein d’un environnement unifié ?

Plusieurs réponses sont admissibles et parmi celles-ci :

  • Pour migrer d’un environnement applicatif classique vers une architecture conteneurisée avec plus de souplesse.
  • Pour conserver des applications critiques dites legacy.
  • Pour isoler plus efficacement, afin de contrôler la sécurité et la stabilité du cluster.
  • Pour scale horizontalement.

KubeVirt implémente la création de machines virtuelles au moyen de CRD ou Custom Resource Definition.

La fonctionnalité d’import de machines virtuelles est en cours de développement dans OKD, la distribution communautaire de Kubernetes qui sert de base à Red Hat OpenShift.

Un formulaire multi-étapes d’import de machines virtuelle est disponible dans la console OKD. La validation de ce premier déclenche la création de plusieurs ressources interconnectées de manière à reproduire la machine virtuelle d’un vCenter dans OKD. L’une de ces ressources est la machine virtuelle elle-même, d’autres sont pour les volumes persistants.

Une autre de ces ressources est le pod de conversion. Lui-même voué à télécharger les données émanant du vCenter en les plaçant ensuite dans un volume persistant de Kubernetes.

L’état de la migration est visualisable sur l’interface web d’OKD. Une fois terminée, l’utilisateur peut se servir d’une machine virtuelle prête à l’emploi sur Kubernetes.

Les fonctionnalités suivantes sont toujours en cours d’implémentation :

  • L’ajout d’autres providers.
  • L’import en groupe ou bulk import de machines virtuelles.

Un appel à contributions est lancé.

Liens utiles : Dépôt OpenShift Cluster Console UI https://github.com/openshift/console
Site officiel de KubeVirt https://kubevirt.io/
Architecture de KubeVirt https://github.com/kubevirt/kubevirt/blob/master/docs/architecture.md
Pourquoi KubeVirt n’est pas une CRI ? https://github.com/kubevirt/kubevirt/issues/49
Vidéo de la conférence: https://ftp.fau.de/fosdem/2020/H.1309/vai_vm_journey_from_vmware_to_k8s.webm

Debug de cluster Kubernetes

Le débug d’une application dans Kubernetes peut être un vrai problème, surtout si l’application est répliquée sur plusieurs nœuds. Pendant le Fosdem, deux conférences ont traité ce problème.

Debug d’apps dans Kubernetes

Par: Jeff Knurek

Note : Les outils présentés ne sont pas recommandés pour l’environnement de production

La conférence a présenté quelques outils qui peuvent être utilisés par les développeurs pour dépanner leurs applications en phase de développement, ces outils sont les suivants :

  • Ksync : est un outil qui permet de monter le système de fichiers d’un pod sur le système de fichiers local, l’outil permet de tester les changements en quelques secondes et de ne pas attendre plusieurs minutes pour un petit changement, pour résumer on peut dire que ksync est le -v de Kubernetes.
  • Telepresence : est un outil qui peut être utilisé pour dépanner une application mais contrairement à ksync, Telepresence permet d’exécuter l’application sur le système local et de mandater la communication vers le cluster kubernetes si l’application a besoin d’autres microservices.
  • Skaffold : ou Local Kubernetes Development, est un autre outil pour aider les développeurs à construire leurs microservices dans un environnement Kubernetes, l’outil surveille principalement les changements sur les fichiers locaux, dans ce cas il va construire l’image et la lancer sur Kubernetes, l’outil peut être utile si l’application a besoin d’autres applications tournant sur Kubernetes.
  • Squash : Squash permet de modifier le code des conteneurs à la volée et de consulter leurs logs, tout cela à partir de l’IDE local. Au delà du débug des pods, Squash peut également être utilisé pour débug les services de Kubernetes.

Pour plus d’informations, voir les liens ci-dessous :

Video + Slides: https://fosdem.org/2020/schedule/event/debugging_kubernetes/ ksync: https://github.com/ksync/ksync Telepresence: https://www.telepresence.io/ skaffold: https://github.com/GoogleContainerTools/skaffold Squash: https://github.com/solo-io/squash

Inspektor Gadget et traceloop

Par: Alban Crequy

Le stracing d’un pod dans Kubernetes ou d’un container n’est pas du tout pratique, la raison principale est que le strace utilisant le numéro PID comme filtre, dans le monde des containers, peut être limité. traceloop résout ce problème en traçant les containers au niveau du cgroup. Contrairement à strace, traceloop enregistre les appels système dans un buffer ring, qui peut être consulté après le crash d’un conteneur. Le traçage des appels système sur les conteneurs est une bonne fonctionnalité mais dans Kubernetes les développeurs n’ont pas accès aux workers et les conteneurs sont répartis sur plusieurs workers, pour surmonter ces problèmes Inspektor a été ajouté. Le rôle d’Inspektor est d’exécuter une trace loop sur les workers et de collecter les syscalls en utilisant des labels et les métadonnées de Kubernetes au lieu des cgroups. Pour plus d’informations sur le projet, voir l’enregistrement de la présentation.

Video: https://video.fosdem.org/2020/UD2.208/containers_bpf_tracing.mp4

Falco : le chaînon manquant de la sécurité Kubernetes

par Kris Nova, lead-maintainer de Falco

Dans le domaine de la sécurité, il y a deux approches complémentaires, la prévention et la détection.

La prévention, c’est verrouiller la porte, empêcher les actions indésirables de vos utilisateurs, de n’importe qui sur Internet, etc.

La détection intervient lorsque la prévention a échoué ; afin de de ne pas réitérer cet échec, il est nécessaire de savoir comment il est advenu, ce qu’a fait l’attaquant, pourquoi et comment elle ou il a été capable de le faire ; et donc, ce que l’on peut faire pour l’empêcher.

La détection est essentielle car il n’y pas de système parfaitement sécurisé.

Dans un contexte Kubernetes, les outils qui assurent la prévention sont les Pod Security Policies, les Network Policies, ou bien encore Open Policy Agent.

Kris Nova nous présente Falco, qui remplit le rôle de détection dans ce contexte.

Falco combine le Kernel Tracing [1], le contexte du container (fourni par le moteur de container) et les metadatas Kubernetes. Il fait correspondre cela avec des règles définies par l’utilisateur. On peut ensuite l’interroger de plusieurs manières : logs standards, interface gRPC, ou un système de webhooks.

Combiner ces trois niveaux d’information permet d’appréhender le schéma général sans perdre de vue les détails clés. Ainsi comme l’explique Kris Nova dans sa présentation, le kernel tracing est important parce qu’en définitive, c’est le kernel qui exécute toutes les opérations sur un système et qu’il n’est donc pas possible, par exemple, de cacher l’accès à un fichier au niveau du kernel, alors qu’au niveau userspace, des moyens détournés pourraient dissimuler cet accès. Les données fournies par le moteur de container et Kubernetes permettent quant à elles de donner un contexte à cette action.

En dernier point, notons que l’observabilité d’un système vient souvent au détriment de sa performance. Selon Kris Nova, Falco a un impact négligeable sur la performance, grâce à son implémentation en C++.

Le projet est actuellement en phase d’incubation à la CNCF, et semble assez prometteur.

Fosdem recording Falco Internals

SELinux et conteneurs

SELinux: les bases

SELinux est un outil complexe. La plupart des utilisateurs Linux vous diront que leur seule aventure avec SELinux se résume à sestatus suivi de setenforce Permissive (d’après les suggestions Google).

Ne vous inquiétez pas, si vous n’êtes pas familier avec SELinux, nous allons reprendre les bases. Vous pouvez le considérer comme une couche de sécurité supplémentaire qui vient augmenter les ACLs Linux classiques via un système de contrôle d’accès obligatoire (MAC). Son but est d’empêcher les élévations de privilèges en limitant l’accès aux ressources système. Avec Linux, toutes les ressources système ont l’avantage d’être représenté sous forme de fichier. SELinux fonctionne donc en assignant des labels aux processus et aux fichiers, stockés dans les attributs étendus du système de fichier (la plupart des fs sont compatibles). Viennent ensuite les politiques SELinux qui décrivent les interactions possibles entre les processus et les ressources. Tout est refusé par défaut, il faut donc explicitement définir chaque accès requis pour chaque application et chaque ressource. SELinux fonctionne aussi avec des conteneurs auxquels il est possible d’assigner des labels, particulièrement utile pour les conteneurs qui nécessitent des privilèges ou des capabilities.

Pour faciliter la vie des utilisateurs, une politique SELinux par défaut est présente pour les conteneurs. Les conteneurs ne peuvent lire/exécuter uniquement dans /usr et ne peuvent qu’écrire dans les fichiers conteneurs. Les conteneurs ont par défaut le label container_t et les fichiers des volumes auront le label container_file_t lorsque que l’option Z est précisée dans les volumes. Cela protège l’hôte des conteneurs, mais pas les conteneurs entre eux. Pour cette raison existent les catégories en plus des labels par défaut:

Cette politique par défaut est suffisante pour la plupart des utilisations, mais elle présente quelques désavantages:

  • Pas de restriction réseau: les conteneurs peuvent se bind sur tous les ports réseaux
  • Pas de contrôle des capabilities
  • Trop strict pour des applications ayant besoin d’un accès au filesystem de l’hôte
  • Trop dangereux de rajouter le label container_file_t à tous les dossiers hôte (et peut causer des conflits avec d’autres applications)

Il vous faudra donc écrire des politiques adaptées à vos besoins pour que SELinux soit véritablement utile, ou simplement pour rendre votre application fonctionnelle. C’est là l’un des plus gros obstacles à l’adoption de SELinux: la nécessité et complexité d’écrire des politiques pour juste voir son application fonctionner. Mais SELinux est terriblement efficace: toutes les vulnérabilités des runtime de conteneurs permettant de compromettre l’hôte passaient par le filesystem, et toutes ont été mitigées par SELinux.

Udica: générez des politiques

Donnez un poisson à un homme, il mangera un jour; donnez-lui une canne à pêche et il mangera toute sa vie. Ici, le poisson est une politique SELinux et la canne à pêche est Udica, un outil permettant de générer des politiques SELinux pour conteneurs. Prenez un conteneur avec SELinux temporairement désactivé, récupérez ses caractéristiques et donnez cela en entrée à Udica: vous obtiendrez une politique SELinux basée sur les bind réseaux et filesystem ainsi que les capabilities attribuées au conteneur (docker inspect <container> | udica my_container). Chargez les politiques SELinux générées puis lancez votre conteneur avec son label --security-opt label=type:my_container.process. Udica est compatible avec plusieurs système de conteneurs: CRI-O, Docker et Podman. Vous pouvez l’utiliser en tant que paquet python ou via un conteneur.

Udica est pratique en tant que tel pour les utilisateurs de conteneurs sur des systèmes SELinux, mais pas uniquement. Au-delà de cette utilisation, Udica peut également générer des politiques pour tout un cluster Kubernetes. Avec un un opérateur dédié, vous pouvez déployer SELinux sur vos clusters entiers !

Support et enregistrement: https://fosdem.org/2020/schedule/event/security_using_selinux_with_container_runtimes/

[1] Trace les appels système et leurs paramètres, au moyen soit d’un module kernel, soit d’une sonde ePBF (cette seconde option étant à privilégier, puisqu’elle fonctionne en userspace et ne peut crasher le kernel).