Home >> Blog >> k3d + k3s = k8s :match parfait pour le dev et le test

k3d + k3s = k8s :match parfait pour le dev et le test

03 septembre 2019

By Yann Albou.

Ce billet de blog a été initialement publié sur Medium

Perfect

Photo de Jonathan Hoxmark sur Unsplash

MISE À JOUR : Un nouveau billet de blog est disponible avec k3d v3.x

K3d est un wrapper pour lancer facilement un cluster Kubernetes en utilisant la distribution très légère Rancher k3s.
Il s’intègre particulièrement bien dans un environnement de développement lorsque vous souhaitez tester votre application avec les manifestes k8s en conditions réelles ou en tant qu’administrateur pour valider des comportements ou évaluer de nouvelles fonctionnalités k8s.

Dans cet article de blog, j’expliquerai comment l’installer, comment créer un cluster Kubernetes complet avec des nœuds de travail et comment cela fonctionne.


k3s/k3d ?

D’abord un peu d’explication sur k3s. Comme mentionné sur le site Web de Rancher, l’idée derrière k3s est d’obtenir une distribution Kubernetes très efficace et légère entièrement conforme.
L’équipe Rancher a fait un excellent travail en réduisant le binaire à moins de 40 Mo en supprimant tous les composants inutiles (Legacy, alpha, fonctionnalités non par défaut, …)

Les K3 utilisaient les composants suivants :

  • Flannel est un réseau superposé très simple qui répond aux exigences de Kubernetes. Il s’agit d’un plugin CNI (Container Network Interface), tel que Calico, Romana, Weave-net
  • CoreDNS est un serveur DNS flexible et extensible qui peut servir de cluster DNS Kubernetes
  • Traefik est un proxy inverse HTTP moderne et un équilibreur de charge
  • SQLite : les backends de stockage utilisés par défaut (mais prennent également en charge MySQL, Postgres et etcd)
  • Containerd est un conteneur d’exécution comme docker sans la partie de construction d’image. Je reviendrai plus tard sur cette pièce importante…

K3s peut être installé via un simple script qui téléchargera et configurera un binaire linux (moins de 40 Mo) plus un cli ‘k3s’.
Ou, ce qui est ma méthode préférée, via une image docker ou avec un docker-compose préconfiguré. et c’est là que "k3d" entre en jeu.

k3d est un utilitaire conçu pour exécuter facilement k3s dans Docker, il fournit une simple CLI pour créer, exécuter, supprimer un cluster Kubernetes entièrement conforme avec 0 à n nœuds de travail.


Installation

Tout d’abord l’installation (bien sûr, vous devez avoir installé docker et le kubectl cli).
Lancez le script d’installation suivant qui détectera votre architecture de processeur (386, amd64) et votre système d’exploitation (linux, darwin, windows) puis installera l’outil cli :

wget -q -O - https://raw.githubusercontent.com/rancher/k3d/master/install.sh | bash

Créez votre premier cluster :

k3d create --name dev --api-port 6551 --publish 8081:80

‘dev’ est le nom de votre Kubernetes qui expose le port du serveur api à 6551 et publie les ports du nœud k3s à l’hôte sur le port 8081
Une fois créé, vous pouvez vérifier l’état du cluster :

K3d list
+ — — — + — — — — — — — — — — — — — — — + — — — — -+ — — — — -+
| NAME  | IMAGE                         | STATUS   | WORKERS  |
+ — — — + — — — — — — — — — — — — — — — + — — — — -+ — — — — -+
| dev   | docker.io/rancher/k3s:v0.7.0  | running  | 0/0      |
+ — — — + — — — — — — — — — — — — — — — + — — — — -+ — — — — -+

et de s’y connecter (le kubeconfig est stocké dans votre répertoire utilisateur mais il est facilement récupérable avec une simple commande k3d) :

export KUBECONFIG="$(k3d get-kubeconfig --name='dev')"
kubectl cluster-info

kubectl get nodes
NAME            STATUS  ROLES   AGE   VERSION
k3d-dev-server  Ready   master  6d1h  v1.14.4-k3s.1

Une pièce manquante est le serveur de métriques qui est un agrégateur de données d’utilisation des ressources à l’échelle du cluster. Il collecte des métriques telles que la consommation de CPU ou de mémoire pour les conteneurs ou les nœuds, exposées par Kubelet sur chaque nœud.
Donc, si vous voulez utiliser les fonctionnalités de k8s comme l’autoscaler de pod horizontal ou même pour pouvoir utiliser la commande kubectl top, vous devez utiliser le metrics-server (qui remplace Heapster qui a été marqué comme obsolète avec Kubernetes version 1.11 et retiré en 1.13)
Pour l’installer :

git clone https://github.com/kubernetes-incubator/metrics-server.git
kubectl apply -f metrics-server/deploy/1.8+/

Attendez 1 ou 2 minutes, puis vous pouvez maintenant utiliser les commandes suivantes :

kubectl top node
kubectl top pod --all-namespaces

Déployer un serveur nginx

vous pouvez désormais déployer un serveur nginx simple à l’aide d’un déploiement, d’un service et d’un manifeste Ingress.


---

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP

---

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: None
  type: ClusterIP

---

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx
  annotations:
    ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: nginx
          servicePort: 80

J’ai utilisé l’approche déclarative versus impérative (voir mon blog précédent sur l’approche déclarative avec l’état du désir)

kubectl apply -f https://raw.githubusercontent.com/myannou/k3d-demo/master/nginx.yaml

Une fois les pods en cours d’exécution (kubectl get pods), vous pouvez accéder à nginx en utilisant localhost et le port de publication k3d (8081 dans notre cas) :

curl http://localhost:8081

Plusieurs clusters sur 1 machine !

Répétez maintenant ces étapes en créant 2 autres clusters k8s (un avec 1 noeud worker et l’autre avec 2 noeuds worker :

k3d create --name stag --api-port 6552 --publish 8082:80 --workers 1
k3d create --name prod --api-port 6553 --publish 8083:80 --workers 2

puis par exemple vous pouvez scaler jusqu’à 3 pods dans le cluster « prod » :

kubectl scale --replicas=3 deployment/nginx

Attendez!

J’exécute 3 clusters kubernetes sur mon macbook pro local avec respectivement 1 maître, 1 maître avec 1 nœud de travail et 1 maître avec 2 nœuds de travail !

J’ai aussi fait le test avec un vieux MacBook avec moins de mémoire et je n’ai pas pu lancer le troisième cluster mais c’était facile avec la commande k3d d’arrêter les autres clusters :

k3d stop --name=dev
k3d stop --name=stag

et vous pouvez les redémarrer plus tard (k3d start –name=dev) en récupérant le même état qu’avant
Vous pouvez même décider de créer un cluster avec une version spécifique de l’image du docker k3s qui cible une version spécifique de Kubernetes :

k3d create --name dev-0-8-1 --api-port 6554 --publish 8084:80 --version=0.8.1

il ciblera une version 1.14.6 de kubernetes !
voir la version disponible de k3s : https://github.com/rancher/k3s/releases


Mais comment ça marche de tout regrouper dans une image docker ?

Un « docker ps » montre que les seuls conteneurs docker démarrés sont ceux du master et des workers, vous ne voyez aucun conteneur docker pour vos images nginx que nous avons précédemment démarrées :

docker ps

IMAGE                COMMAND                  NAMES
rancher/k3s:v0.7.0   "/bin/k3s agent"         k3d-prod-worker-1
rancher/k3s:v0.7.0   "/bin/k3s agent"         k3d-prod-worker-0
rancher/k3s:v0.7.0   "/bin/k3s server --h…"   k3d-prod-server
rancher/k3s:v0.7.0   "/bin/k3s agent"         k3d-stag-worker-0
rancher/k3s:v0.7.0   "/bin/k3s server --h…"   k3d-stag-server
rancher/k3s:v0.7.0   "/bin/k3s server --h…"   k3d-dev-server

Alors, comment ça marche pour faire docker dans docker sans mapper le socket docker ?
Pour comprendre, exécutez les commandes suivantes dans le conteneur docker k3d-dev-server :

docker exec -it k3d-dev-server crictl imagesIMAGE                             TAG      IMAGE ID       SIZE
docker.io/coredns/coredns         1.3.0    2ee68ed074c6e  12.3MB
docker.io/library/nginx           latest   5a3221f0137be  50.7MB
docker.io/library/traefik         1.7.9    98768a8bf3fed  19.9MB
docker.io/rancher/klipper-helm    v0.1.5   c1e4f72eb6760  27.1MB
docker.io/rancher/klipper-lb      v0.1.1   4a065d8dfa588  2.71MB
k8s.gcr.io/metrics-server-amd64   v0.3.3   c6b5d3e48b43d  10.5MB
k8s.gcr.io/pause                  3.1      da86e6ba6ca19  317kB

docker exec -it k3d-dev-server crictl ps
CONTAINER ID   IMAGE          STATE    NAME          
2796b478f1422  c6b5d3e48b43d  Running  metrics-server
e524745ae7fc9  5a3221f0137be  Running  nginx         
d331d0f08e225  98768a8bf3fed  Running  traefik       
50a618c636f6e  4a065d8dfa588  Running  lb-port-443   
44d89c5d598e2  2ee68ed074c6e  Running  coredns       
444f2b203f128  4a065d8dfa588  Running  lb-port-80

As previously mentioned k3s relies on the « Containerd » runtime container.

Docker, Containerd et CRI-O sont tous des moteurs de conteneurs pour Kubernetes et sont tous compatibles CRI (Container Runtime Interface)

CRI a été introduit dans Kubernetes 1.5 et agit comme un pont entre le kubelet et le runtime du conteneur
Comme toute API, CRI vous offre une couche d’abstraction qui permet théoriquement aux utilisateurs finaux, aux fournisseurs de cloud et même aux distributions Kubernetes de passer de l’implémentation. K3s permet de passer en docker bien que ce ne soit pas recommandé :

k3s inclut et par défaut est containerd. Pourquoi? Parce que c’est tout simplement mieux. Si vous voulez courir avec Docker, arrêtez-vous d’abord et pensez : « Vraiment ? Est-ce que je veux vraiment plus de maux de tête ? Si toujours oui, il vous suffit d’exécuter l’agent avec l’indicateur –docker

Containerd a été initialement développé par Docker mais a été donné en 2017 à la CNCF pour servir de standard de l’industrie pour le démon de gestion des conteneurs. Docker utilise toujours Containerd, mais Containerd est maintenant indépendant et ne nécessite plus du tout Docker (en particulier le démon Docker).

On peut interagir avec un runtime CRI directement à l’aide de l’outil « crictl » (comme le docker cli)

Les adopteurs de Containerd sont Rancher, Google,… tandis que Red Hat investit massivement dans CRI-O.


Conclusion

K3s s’appuie sur des normes avec CRI implémentées via Containerd, ce qui permet de s’exécuter à l’intérieur d’une image Docker sans utiliser d’astuces laides et non sécurisées.

L’équipe Rancher a fait un excellent travail avec k3s et k3d en rendant très facile, simple et efficace l’exécution de plusieurs instances de clusters Kubernetes sur une seule machine.

Les usages sont multiples et très adaptés au développement, aux tests et à la formation de Kubernetes.

  Edit this page