S'installer facilement un environnement Docker et Kubernetes sur la même machine, tout en gardant un certain cloisonnement entre les deux, peut parfois s'avérer très utile pour réaliser des tests.
Cette opération est très simple à mettre en œuvre sous Windows, puisque l'outil Docker Desktop
vous propose plus ou moins de réaliser cela out-of-the-box ( il s'agit tout de même de conteneur ... ). Mais quand est-il sous Linux ?
Je vais aujourd'hui vous expliquer comment réaliser cette installation sous Ubuntu 20.04 à l'aide de l'outil Multipass. Cette solution n'est pas la seule envisageable, il existe par exemple le projet k3d
qui peut permettre d'installer un environnement k3s dans Docker ou encore Minikube
.
Commençons ce tutoriel par l'installation de multipass
. Mais au fait multipass c'est quoi ?
Multipass
C'est un outil en ligne de commande, qui permet de gérer des machines virtuelles lightweight. L'outil se veut très simple d'utilisation et permet en quelques minutes d'obtenir des machines virtuelles tournant sous Ubuntu :
Multipass is a mini-cloud on your workstation
Disponible sous Windows, macOS and Linux, il vous permettra également d'initialiser ces instances à l'aide de cloud-init lors du démarrage de celle-ci.
Installons donc l'outil :
$ sudo snap install multipass --classic
Enfin regardons les images disponibles pour lancer une instance :
$ multipass find
Provisionons une première instance qui va nous servir par la suite pour l'installation de K3S
afin d'avoir un environnement Kubernetes.
$ multipass launch --name k3s --cpus 4 --mem 2048M --disk 5G
Comme vous pouvez le voir, il est possible de paramétrer certaines caractéristiques physiques ( mémoires, CPU ). De base 1G de mémoire seront alloués, 1 CPU et 5G d'espace disque.
Vous pouvez lister les instances disponible avec la commande :
$ multipass list
Ou encore arrêter ou démarrer vos instances avec :
$ multipass stop my-instance
$ multipass start my-instance
Il est bien sûr possible d’exécuter un shell
dans votre instance :
$ multipass shell my-instance
ou
$ multipass exec k3s -- bash
Nous allons donc pouvoir installer toute de suite notre environnement Kubernetes !
K3S
Si vous souhaitez en apprendre plus sur K3S, je vous invite à relire cet article :
L'installation est toujours aussi simple :
$ multipass exec k3s -- bash -c "curl -sfL https://get.k3s.io | sh -s - --no-deploy=traefik"
[INFO] Finding release for channel stable
[INFO] Using v1.17.4+k3s1 as release
[INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v1.17.4+k3s1/sha256sum-amd64.txt
[INFO] Downloading binary https://github.com/rancher/k3s/releases/download/v1.17.4+k3s1/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Creating /usr/local/bin/ctr symlink to k3s
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO] systemd: Starting k3s
Vous pouvez bien évidemment vérifier le bon fonctionnement :
$ multipass exec k3s -- sudo kubectl get nodes
Souhaitant optimiser mon temps, je n'ai pas envie de lancer en permanence des commandes exec
sur mon instance pour gérer le tout.
Je vais donc installer la CLI kubectl
sur mon hôte :
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
On rend le binaire exécutable :
$ chmod +x ./kubectl
Et je le déplace dans mon $PATH
:
$ sudo mv ./kubectl /usr/local/bin/kubectl
On teste le bon fonctionnement :
$ kubectl version --client
Je vais récupérer le fichier de configuration présent sur mon instance :
$ sudo mkdir ~/.kube
$ multipass exec k3s -- bash -c "sudo cat /etc/rancher/k3s/k3s.yaml" > ~/.kube/k3s.yaml
Enfin il est nécessaire de changer l'adresse IP présente dans ce fichier :
$ K3S_SERVER=`multipass info k3s | grep "IPv4" | awk -F ' ' '{print 2}'`
$ sed -ie s/127.0.0.1/${K3S_SERVER}/g ~/.kube/k3s.yaml
Enfin je peux exporter ma configuration :
$ export KUBECONFIG=${HOME}/.kube/k3s.yaml
Je n'ai plus qu'à essayer :
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s Ready master 16m v1.17.4+k3s1
Il est bien sûr possible de créer un mini-cluster en créant quelques nodes supplémentaires ! Mais je vais de mon côté, me lancer dans l'installation de Docker !
Docker
Si votre machine possède déjà un environnement Docker, alors cette partie n'est pas utile. Si ce n'est pas le cas :
$ sudo apt install docker.io
Je m'assure que Docker se lance au démarrage :
$ sudo systemctl enable --now docker
Optionnel mais pratique :
$ sudo usermod -aG docker $USER
Enfin il ne reste qu'à valider !
$ docker --version
J'en profiter pour également pour installer docker-compose
, vous pouvez suivre cet article :
Vous voila maintenant avec Docker et Kubernetes sur la même machine, tout ceci gérable depuis votre hôte 😛
Ok mais je bosse sur 2 ou 3 applications webs en même temps et franchement j'aimerais bien gérer mes deux environnements avec un seul reverse-proxy !
Bonus stage 👍
Forcément si on parle reverse-proxy ...
Je vais utiliser Traefik afin d’accéder à deux instances whoami
.
- Ma première instance sur
Docker
devra répondre sur le port 80 avec le chemin /docker-whoami, - Enfin ma seconde instance sur
Kubernetes
répondra elle sur le chemin /k3s-whoami.
Avant de commencer, deux solutions s'offrent à moi, démarrer Traefik sur Docker ou sur Kubernetes.
Je vais choisir d'instancier mon reverse-proxy sur Kubernetes. Pourquoi ?
Il faut être honnête, une installation depuis Docker serait plus complexe ( le certificat auto-signé de K3S, la gestion des droits RBAC, etc ). Cette installation mérite sûrement un post à part entière 😂
Préparons Docker !
Traefik va devoir se connecter au endpoint de Docker au travers du réseau.
Une nouvelle fois, deux possibilités :
- Depuis la 2.2, Traefik me donne la possibilité d'utiliser le endpoint au travers de
ssh
. - Ou avec une connexion
tcp
direct.
La deuxième solution n'est clairement pas sécurisée ( en tout cas si je n'utilise pas de certificat, filtrage IP, etc ). Mais je vais partir sur cette solution.
Je vais utiliser - encore - la solution simple car je souhaite garder ce tutoriel simple et dans l'esprit "fun devops". Complexifier une installation qui n'a rien de production ready n'aurait ici aucun intérêt !
Je vais donc faire écouter l'API docker sur le port 2376, pour cela je vais simplement modifier le fichier systemd de Docker :
/etc/systemd/system/multi-user.target.wants/docker.service
Modifiez la ligne 15 :
$ ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376 --containerd=/run/containerd/containerd.sock
Vous pouvez valider votre modification avec la commande :
$ docker -H tcp://127.0.0.1:2376 ps
Je vais donc maintenant déployer Traefik sur mon installation de K3S. J'utilise la base présente sur mon dépôt Git :
$ git clone https://github.com/lfache/awesome-traefik-kubernetes
Enfin dans le dossier awesome-traefik-kubernetes/traefik-kustomize-sample/development
, je vais modifier ma configuration statique ( traefik-configmap.yaml ) :
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-config-static
namespace: default
labels:
app: traefik
data:
traefik.yml: |
entryPoints:
web:
address: :80
api:
insecure: true
providers:
kubernetesCRD: {}
docker:
endpoint: tcp://HOSTIP:2376
Remplacez HOSTIP
par l'adresse IP de votre hôte.
Je peux ensuite appliquer ma configuration :
$ kubectl apply -k ./
Récupérez l'adresse IP de votre K3S :
$ multipass info k3s | grep "IPv4" | awk -F ' ' '{print $2}'
Et connectez vous au dashboard de Traefik avec cette adresse :
Déployons notre première instance de Whoami, je vais créer un simple fichier de déploiement, deployment.yaml
:
kind: Service
apiVersion: v1
metadata:
name: whoami
spec:
ports:
- port: 80
name: web
protocol: TCP
selector:
app: whoami
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 3
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: containous/whoami
imagePullPolicy: Always
ports:
- containerPort: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami-web
spec:
entryPoints:
- web
routes:
- kind: Rule
match: PathPrefix(`/whoami`)
services:
- name: whoami
port: 80
Enfin j'applique ce fichier :
$ kubectl apply -f ./deployment.yaml
Et je vérifie que tout fonctionne :
$ curl http://10.72.232.47/k3s-whoami
Hostname: whoami-5b4bb9c787-ttr97
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.13
IP: fe80::dc35:c6ff:fe1a:df8f
RemoteAddr: 10.42.0.9:58440
GET /k3s-whoami HTTP/1.1
Host: 10.72.232.47
User-Agent: curl/7.68.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: 10.72.232.47
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-66b8f478c6-pf5pj
X-Real-Ip: 10.42.0.1
Je n'ai plus qu'à déployer une instance whoami sur Docker !
Mon fichier docker-compose.yaml
:
version: '3.7'
services:
backend:
image: containous/whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.go.rule=Path(`/docker-whoami`)"
- "traefik.http.services.go.loadbalancer.server.port=80"
Et je vérifie :
$ curl http://10.72.232.47/docker-whoami
Hostname: 2bb14832f7b3
IP: 127.0.0.1
IP: 172.18.0.2
RemoteAddr: 172.18.0.1:64199
GET /docker-whoami HTTP/1.1
Host: 10.72.232.47
User-Agent: curl/7.68.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: 10.72.232.47
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-66b8f478c6-pf5pj
X-Real-Ip: 10.42.0.1
Sur le dashboard de Traefik :
Au travers de cet article, nous avons pu mettre en place sur notre hôte Ubuntu 20.04 :
- Une installation de docker, avec docker-compose.
- Un environnement Kubernetes avec K3S grâce à multipass.
- Une unique instance de Traefik pour piloter mon trafic web !
Multipass est déjà un outil très sympathique, virtualisation ultra-légère et très simple d'utilisation. Même si on pourrait se demander ce qu'il apporte de plus qu'un outil déjà existant comme Vagrant par exemple.
Il manque notamment pour l'instant quelques options réseaux ( bridge network par exemple ) qui peuvent parfois limiter son utilisation. Mais cela ne devrait plus tarder !
Cet environnement est devenu pour le moment ma base, dont je me sers pour réaliser mes démos. J'ai quelques scripts supplémentaires pour ajouter des nodes à mon cluster K3S et Docker en mode Swarm.
Mais on en parlera dans un prochain article avec sûrement quelques changements ( sécurité ? ) à cette installation 😄
En tout cas n'hésitez pas à m'apporter des remarques ou des commentaires sur Twitter ! C'est toujours un plaisir d'avoir des retours ! 😘