Nous allons découvrir quelques types de plugins permettant d’étendre Kubernetes. La volonté de ces extensions est de permettre à des tiers de contribuer à des fonctions de Kubernetes sans impacter son cœur. L’objectif de la communauté Kubernetes à présent est avant tout à se stabiliser au travers d’une cure d’amaigrissement et de modularisation. Tout ce qui relève d’une implémentation spécifique se voit progressivement remplacé par une interface permettant de brancher différentes implémentations out-of-tree, c’est à dire en dehors du code source de Kubernetes.
Probablement un des mécanismes les plus connus de Kubernetes, CNI permet d’interfacer plusieurs solutions d’interconnexion réseau, parmi lesquelles : Flannel, Calico, Weave .
Nous n’allons pas nous éterniser sur cette interface, car son utilisation est relativement connue, puisque quasiment indispensable pour obtenir un cluster fonctionnel.
Deux fonctions principales sont implémentées dans CNI :
Ce mécanisme d’extension permet de remplacer le moteur d’exécution de conteneurs. Historiquement réservé à Docker, Kubernetes a par la suite été capable de faire tourner des conteneurs rkt.
L’arrivée de la couche d’abstraction CRI permet tout une famille d’implémentations allant jusqu’à de la virtualisation pour ceux qui n’aurait pas une grande confiance dans la conteneurisation. Une autre des motivations derrière cette interface était de pouvoir s’abstraire du démon Docker (devenu trop gros et avec des API mouvantes) en utilisant directement containerd ou cri-o.
Aujourd’hui, la plupart des clusters Kubernetes que nous rencontrons n’utilisent pas encore cette interface et pilotent Docker en direct, à l’ancienne.
Dernier né de la famille des C*I, CSI vient donc offrir une abstraction sur les stockages. À nouveau, différentes implémentations vont pouvoir venir proposer les fonctions de création, redimensionnement, attachement, montage […] des volumes qui peuvent être utilisés dans nos chers conteneurs. Cette initiative vient remplacer les FlexVolumes, première tentative de modularisation des solutions de volumes de stockage.
Le suivi des différentes implémentations et de leur maturité se trouve ici. La bascule du mode de gestion des volumes actuel vers CSI va se faire probablement au fur et à mesure de la stabilisation des nouvelles implémentations.
L’apparition du cloud-controller-manager vise à extraire de notre bon vieux controller-manager toutes les fonctions relatives aux interactions spécifiques aux cloud providers.
À nouveau, l’objectif est double : décorréler les cycles de vie du moteur Kubernetes de la logique de synchronisation des load-balancers, routetables et aux objets cloud et maintenir une taille raisonnable pour le controller-manager.
Les implémentations cloud dans le cloud-controller deviennent progressivement obsolètes pour une bascule officielle avec la version 1.14 de Kubernetes. Le cloud-controller-manager devient un simple pod qui peut être lancé après le bootstrap du cluster. Il peut alors embarquer uniquement la logique du cloud que l’on utilise plutôt que tous comme c’était historiquement le cas. Pour les déploiements statiques qui n’utilisent pas d’intégration cloud, inutile de le démarrer.
Derrière ces termes se cache un moyen d’extension de plus en plus populaire. Les CRD consistent à déclarer des nouveaux types de ressources qui ne sont pas natives à Kubernetes contrairement aux pods, services, replicasets …
Devant la recrudescence des implémentations à tout vent des sites se sont spécialisés dans leur référencement et surtout le suivi de leur maturité. On trouve en vrac des ressources permettant de :
Le champ des possible est très vaste. L’intérêt de développer ses propres CRD réside dans l’utilisation native de fonctions Kubernetes : authentification et autorisations, traçabilité…
Des SDK permettent de coder rapidement des opérateurs, en charge de s’abonner aux événements relatifs à ces nouveaux types de ressources. Libre aux développeurs de coder ce qu’ils souhaitent pour implémenter la logique derrière ces ressources personnalisées.
À noter que si une CRD n’a que peu d’intérêt sans son opérateur, l’inverse n’est pas forcément vrai. On peut tout à fait développer des opérateurs qui s’appuient sur des ressources existantes. Exemple : créer des enregistrements DNS en fonction des services ou des ingresses présents dans les clusters Kubernetes.
Encore plus puissant que les CRD, l’API aggregation permet de créer de nouvelles portions de l’API Kubernetes, mais plus largement que les CRD pour lesquelles la liste des actions (verbes) est limitées aux classiques (get, list, watch, create, delete, use…). Ici, c’est tout un pan de l’arbre des URL qui peut être externalisé sur une application tierce : la vôtre, que vous aurez codée à façon.
Il existe un exemple concret pour illustrer l’usage de l’API aggregation : le kube-metrics-server. Remplaçant de Heapster, cet outil est en charge de collecter des métriques de base des pods et des nœuds (cpu, mémoire) et ainsi permettre les commandes kubectl top po, kubectl top no et surtout le fonctionnement des horizontalPodAutoscallers.
L’installation de kube-metrics-server passe par la déclaration d’un APIservice, l’objet qui représente les portions de l’API qui sont présentes dans le cluster.
En plus des APIservices standards, nous venons ajouter une nouvelle entrée :
--- apiVersion: apiregistration.k8s.io/v1beta1 kind: APIService metadata: name: v1beta1.metrics.k8s.io spec: service: name: metrics-server namespace: kube-system group: metrics.k8s.io version: v1beta1 insecureSkipTLSVerify: true groupPriorityMinimum: 100 versionPriority: 100
Celle-ci pointe sur un service metrics-server dans le namespace kube-system, service fourni par un pod qui implémente la nouvelle API. Une fois l’APIservice déclaré et le pod démarré, l’APIserver répond à une nouvelle route que l’on peut tester avec la commande suivante :
$ kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" {"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/metrics.k8s.io/v1beta1/nodes"},"items":[{"metadata":{"name":"minikube","selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/minikube","creationTimestamp":"2018-12-17T13:52:09Z"},"timestamp":"2018-12-17T13:51:46Z","window":"30s","usage":{"cpu":"567925956n","memory":"6380384Ki"}}]}