Introduction#
Dans l’article précédent, je vous ai présenté comment créer de toute pièce un cluster Kubeadm avec Vagrant et Ansible. Il est maintenant question de rendre accessible ce cluster vers l’extérieur, par exemple, si vous souhaitez évaluer une personne à distance sur ses connaissances sur Kubernetes ou tout simplement pour vous, afin d’avoir accès à votre cluster quel que soit votre lieu.
Dans cet article, le but n’est pas de reprendre ce qui a été fait dans kubeadm-automation, mais bien de le compléter à travers deux playbooks Ansible qui permettent d’en faire un “vrai” simulateur à la manière de killer.sh (mais sans interface graphique).
Tout d’abord, je vous présenterai comment rendre votre cluster Kubeadm accessible à distance de manière sécurisée à travers son API kubeapi-server
sans ouvrir le moindre flux vers l’extérieur, assez pratique quand on travaille en local sur sa machine, par exemple. Et pour finir, je vous montrerai comment alimenter votre cluster de scripts qui permettent d’en faire un vrai simulateur.
L’accès à distance#
Pour de qui est de rendre accessible votre cluster Kubeadm fraichement déployé, il est nécessaire d’utiliser un outil qui permet de créer un tunnel du localhost
de notre machine master afin de l’exposer sur internet via une url générée par l’outil.
J’ai choisi la solution ngrok qui répond à ce besoin. Vous pouvez utiliser l’outil dans sa version gratuite pour réaliser les étapes de cet article, il n’y a aucun problème. Vous aurez tout de même besoin d’un compte à créer au préalable.
Une fois, votre compte créé, il faudra récupérer l’url de votre binaire qui est affichée ici ainsi que le token d’authentification une fois connecté.
Pour exposer notre kubeapi-server
, il est d’abord primordial avant toute chose de créer un proxy sur notre localhost
vers cette API. Ce qui permettra par la suite, de créer notre tunnel avec ngrok en prenant le port de ce proxy.
Notre playbook sera composé de plusieurs étapes :
- Téléchargement du binaire pour ngrok ;
- Vérifier si le proxy vers le
kubeapi-server
s’exécute, si ce n’est pas le cas, le démarrer ; - Vérifier que le ngrok s’exécute, si ce n’est pas le cas, l’initialiser et démarrer le tunnel vers le proxy du
kubeapi-server
qui est sur le port 8081 par défaut ; - Récupérer les informations de ngrok : l’url publique sur laquelle notre tunnel est accessible ;
- Générer la configuration Kubernetes pour accéder à notre cluster via les informations de ngrok.
Tout est bon pour vous ? Je vous présente le playbook Ansible
qui va réaliser ces tâches :
---
- hosts: master
gather_facts: yes
vars:
ngrok_download_url: # L'url de votre binaire ngrok
ngrok_authtoken: # Votre token d'authentification
ngrok_api: http://localhost:4040/api/tunnels
tasks:
# Téléchargement du binaire pour ngrok
- name: Download ngrok
unarchive:
src: "{{ ngrok_download_url }}"
dest: /usr/local/bin
remote_src: yes
become: yes
# Vérifier si le proxy vers le ``kubeapi-server`` s'exécute
- name: Check if proxy is starting
shell: ps aux | grep "kubectl proxy" | grep -v grep
register: check_proxy
changed_when: false
ignore_errors: yes
# Si ce n'est pas le cas, le démarrer
- name: Start proxy
shell: nohup kubectl proxy --disable-filter=true >/dev/null 2>&1 &
when: check_proxy.stdout_lines | length == 0
# Vérifier que le ngrok s'exécute
- name: Check if ngrok is starting
shell: ps aux | grep "ngrok http 8001" | grep -v grep
register: check_ngrok
changed_when: false
ignore_errors: yes
# Si ce n'est pas le cas, l'initialiser
- name: Init ngrok
shell: ngrok authtoken {{ ngrok_authtoken }}
when: check_ngrok.stdout_lines | length == 0
# Et démarrer le tunnel vers le proxy du kubeapi-server qui est sur le port 8081 par défaut
- name: Start ngrok
shell: nohup ngrok http 8001 >/dev/null 2>&1 &
when: check_ngrok.stdout_lines | length == 0
# Récupérer les informations de ngrok : l'url publique sur laquelle notre tunnel est accessible
- name: Get ngrok informations
uri:
url: "{{ ngrok_api }}"
return_content: yes
register: ngrok_api
retries: 3
delay: 5
until: ngrok_api.json.tunnels[0].public_url is defined
# Générer la configuration Kubernetes pour accéder à notre cluster via les informations de ngrok
- name: Get kubeconfig from master
fetch:
src: /home/vagrant/.kube/config
dest: kubeconfig_remote
flat: yes
# Remplacement de l'url avec celle générée par ngrok
- name: Replace localhost by ngrok url
replace:
path: kubeconfig_remote
regexp: 'https://10.0.0.10:6443'
replace: "{{ ngrok_api.json.tunnels[0].public_url }}"
delegate_to: 127.0.0.1
become: no
# Ajout de "insecure-skip-tls-verify: true" car l'url générée par ngrok n'est pas celle qui est autorisée via le certificat CA de Kubernetes
- name: Replace localhost by ngrok url
replace:
path: kubeconfig_remote
regexp: 'certificate-authority-data(.*)'
replace: 'insecure-skip-tls-verify: true'
delegate_to: 127.0.0.1
become: no
Je vous recommande fortement de créer ce playbook dans le répertoire de votre dépôt de code kubeadm-automation
pour avoir accès facilement à l’inventaire de Vagrant
.
Ce qui permet de l’exécuter avec la commande suivante (configure_remote_access.yml
est le nom de mon fichier playbook) :
ansible-playbook configure_remote_access.yml -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory
Comme vous pouvez le remarquer, le playbook génère un fichier à la racine de votre dépôt de code, qui se nomme kubeconfig_remote
et qui contient votre configuration pour piloter votre cluster avec kubectl
via une url publique (*.ngrok.io).
Pour l’utiliser :
export KUBECONFIG=kubeconfig_remote
Et vous pouvez ensuite faire vos commandes kubectl
favorites :
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master Ready control-plane,master 9m14s v1.20.11 10.0.0.10 <none> Ubuntu 20.04.2 LTS 5.4.0-80-generic containerd://1.5.5
k8s-worker1 Ready <none> 7m32s v1.20.11 10.0.0.11 <none> Ubuntu 20.04.2 LTS 5.4.0-80-generic containerd://1.5.5
Et voilà, vous avez votre cluster Kubeadm accessible à distance !
Faire de votre cluster, un simulateur !#
Pour faire de votre cluster Kubeadm un vrai simulateur, il faut avoir une sorte de script qui donne un énoncé et qui est capable de vérifier si l’ensemble de l’énoncé a été réalisé correctement.
On peut donc imaginer un script (pourquoi pas shell ?) qui vient vérifier différents points à travers l’exécution de commandes kubectl
sur les objets à créer.
Je vous propose un exemple de script assez court que j’ai moi-même réalisé pour arriver vers ce but-là. Bien sûr, vous pouvez l’adapter en fonction de vos besoins.
Script commons.sh
:
RED='\033[0;31m' # Rouge
GREEN='\033[0;32m' # Vert
NC='\033[0m' # Sans couleur
# Le but de cette fonction est d'afficher ce que va vérifier notre commande "kubectl" et de l'exécuter pour savoir si le retour de cette commande renvoie quelque chose (OK) ou non (KO).
check_context() {
context=$1
command=$(bash -c "$2" 2>/dev/null)
if [[ ! -z "$command" ]]; then
echo -e "${context} : ${GREEN}OK${NC}"
else
echo -e "${context} : ${RED}KO${NC}"
fi
}
Script check_ex1.sh
:
#!/bin/bash
source ./commons.sh
check_context "Le namespace ex1 a été créé" "kubectl get ns | grep ex1"
check_context "Le déploiement test-k8s a été créé" "kubectl -n ex1 get deploy | grep test-k8s"
check_context "Le déploiement possède 3 replicas" "kubectl -n ex1 get deploy test-k8s -o=jsonpath='{.spec.replicas}' | grep 3"
check_context "Le déploiement a comme image nginx" "kubectl -n ex1 get deploy test-k8s -o=jsonpath='{.spec.template.spec.containers[0].image}' | grep nginx"
Le but de l’exercice est de créer un déploiement test-k8s dans le namespace ex1 qui utilise l’image nginx et qui possède 3 replicas.
Si on exécute le script avant :
$ ./check_ex1.sh
Le namespace ex1 a été créé : KO
Le déploiement test-k8s a été créé : KO
Le déploiement possède 3 replicas : KO
Le déploiement a comme image nginx : KO
Et après avoir réalisé l’exercice :
Le namespace ex1 a été créé : OK
Le déploiement test-k8s a été créé : OK
Le déploiement possède 3 replicas : OK
Le déploiement a comme image nginx : OK
Pour finir, vous pouvez très bien mettre ces exercices sur votre cluster avec le playbook ci-dessous :
- hosts: master
gather_facts: yes
become: yes
tasks:
- name: Copy exercices
copy:
src: ../k8s-simulator/ # Dossier contenant nos exercices
dest: "/home/{{ ansible_user }}/k8s-simulator"
mode: 0755
Le but de cette démarche est d’enrichir au fur et à mesure les exercices et d’ajouter plusieurs vérifications afin de proposer une bibliothèque assez complète de challenge !
Conclusion#
Vous avez maintenant un cluster Kubeadm qui ressemble à un vrai simulateur et où l’API de Kubernetes est accessible vers l’extérieur.
Personnellement, j’utilise cela pour tester les potentiels candidats de l’entreprise dans laquelle je suis, SFEIR, afin de vérifier leurs connaissances sur la création de Pod
, Deployment
, Service
, etc. Ce qui correspond à un niveau de certification plutôt proche de la CKAD.
Si on souhaite aller plus loin et tester des compétences d’administration ou de mise en place de la sécurité, un accès ssh est indispensable afin de réaliser des modifications au niveau des composants clés de Kubernetes comme par exemple le scheduler.