Déployer un cluster K8s avec Kubespray
Publié le :
Pour des besoins professionnels, je dois monter des clusters Kubernetes afin
d’héberger des API. Pour cela, je fais le choix d’utiliser KubeSpray.
KubeSpray est un framework qui permet de provisionner des clusters
Kubernetes sur du bare-metal, mais aussi chez la plupart des clouders,
en utilisant Ansible. Pour tester le tout, je vais utiliser
Ignite que j’ai présenté récemment,
auquel je vais ajouter footloose.
Provisionnement des VM avec Footloose et Ignite
Pour créer rapidement mon cluster de micro-VM je vais utiliser footloose ↗ un autre projet de WeaveWorks qui permet de créer rapidement une série de machines. Je vais créer un cluster kubernetes composés de 3 masters et 2 workers à base de Centos 8.5.
Pour installer footloose je vous renvoie à mon billet sur ignite
Création de l’image CENTOS 8.5
Je vais mettre à jour l’image et l’injecter dans Ignite. Mon Dockerfile :
FROM weaveworks/ignite-centos:8
RUN dnf upgrade -yOn lance le build :
docker build -t weaveworks/ignite-centos:8.5 .On récupère la version et on tague l’image teste rapidement :
docker run --rm -it build -t weaveworks/ignite-centos:8.5 cat /etc/redhat-releaseCentOS Linux release 8.5.2111
docker tag weaveworks/ignite-centos:8.5 weaveworks/ignite-centos:8.5.2111On l’importe dans Ignite :
sudo ignite image import weaveworks/ignite-centos:8.5.2111 --runtime docker
INFO[0000] Starting image import...INFO[0004] Imported OCI image "weaveworks/ignite-centos:8.5.2111" (526.4 MB) to base image with UID "cdc78b581b43346e"INFO[0004] Created image with ID "cdc78b581b43346e" and name "weaveworks/ignite-centos:8.5.2111"Maintenant créons nos 5 VM avec Footloose.
Création du cluster de VM avec Footloose
Footloose permet d’utiliser ignite comme backend pour provisionner des micro-VM. Je vais donc créer un cluster de 5 VM avec 1 CPU / 1.6 GB (le minimum accepté par kubespray) et 5 GO de disque chacune.
Déclarons notre cluster avec ce fichier :
cluster:  name: cluster  privateKey: cluster-keymachines:- count: 5  spec:    image: weaveworks/ignite-centos:8.5.2111    name: node%d    portMappings:    - containerPort: 22    # This is by default "docker". However, just set this to "ignite" and it'll work with Ignite :)    backend: ignite    # Optional configuration parameters for ignite:    ignite:      cpus: 1      memory: 1600MB      diskSize: 5GB      kernel: "weaveworks/ignite-kernel:5.10.51"Lançons le provisionnement en lançant la commande footloose create depuis le
répertoire où se trouve le fichier footloose.yaml :
sudo footloose createIl est possible de créer le cluster en indiquant le nom du fichier avec l’option -c :
sudo footloose create -c mon-cluster.yml
INFO[0000] Creating machine: cluster-node0 ...INFO[0002] Creating machine: cluster-node1 ...INFO[0004] Creating machine: cluster-node2 ...INFO[0006] Creating machine: cluster-node3 ...INFO[0009] Creating machine: cluster-node4 ...On vérifie qu’elles sont bien présentes sous Ignite :
sudo ignite psVM ID                   IMAGE                           KERNEL                           SIZE     CPUS    MEMORY          CREATED STATUS  IPS             PORTS                   NAME054f0119bc87ca0c        weaveworks/ignite-centos:8.5    weaveworks/ignite-kernel:5.10.51 5.0 GB   1       1024.0 MB       52m ago Up 52m  10.61.0.50      0.0.0.0:44567->22/tcp   cluster-node33498ae67c7f695cd        weaveworks/ignite-centos:8.5    weaveworks/ignite-kernel:5.10.51 5.0 GB   1       1024.0 MB       52m ago Up 52m  10.61.0.51      0.0.0.0:43621->22/tcp   cluster-node4714f445ea643ebad        weaveworks/ignite-centos:8.5    weaveworks/ignite-kernel:5.10.51 5.0 GB   1       1024.0 MB       52m ago Up 52m  10.61.0.47      0.0.0.0:45371->22/tcp   cluster-node0d6cf7a17be0368e5        weaveworks/ignite-centos:8.5    weaveworks/ignite-kernel:5.10.51 5.0 GB   1       1024.0 MB       52m ago Up 52m  10.61.0.49      0.0.0.0:33309->22/tcp   cluster-node2f1fcde290a9f3f09        weaveworks/ignite-centos:8.5    weaveworks/ignite-kernel:5.10.51 5.0 GB   1       1024.0 MB       52m ago Up 52m  10.61.0.48      0.0.0.0:35075->22/tcp   cluster-node1Provisionnement d’un cluster avec Kubepsray
Construction de l’environnement
Dans un premier temps, nous allons récupérer le projet et installer les requirements.
git clone https://github.com/kubernetes-incubator/kubespray.gitcd kubespraypyenv virtualenv 3.9.7 kubespraypyenv local kubespray
pip install -r requirements.txtLooking in indexes: https://python:****@artefacts.sa-cim.local/repository/pypi-all/simple/Collecting ansible==3.4.0  Downloading https://artefacts.sa-cim.local/repository/pypi-all/packages/ansible/3.4.0/ansible-3.4.0.tar.gz (31.9 MB)     |████████████████████████████████| 31.9 MB 3.4 MB/s
Installing collected packages: pycparser, six, pyparsing, MarkupSafe, cffi, PyYAML, packaging, jinja2, cryptography, ansible-base, ruamel.yaml.clib, ruamel.yaml, pbr, netaddr, jmespath, ansible    Running setup.py install for ansible-base ... done    Running setup.py install for ansible ... doneSuccessfully installed MarkupSafe-1.1.1 PyYAML-6.0 ansible-3.4.0 ansible-base-2.10.15 cffi-1.15.0 cryptography-2.8 jinja2-2.11.3 jmespath-0.9.5 netaddr-0.7.19 packaging-21.3 pbr-5.4.4 pycparser-2.21 pyparsing-3.0.6 ruamel.yaml-0.16.10 ruamel.yaml.clib-0.2.4 six-1.16.0Éditons le fichier ansible.cfg pour l’adapter à notre besoin. On ajoute
simplement la localisation de la clé SSH et le remote_user (les deux
paramètres avant [inventory]) :
[ssh_connection]pipelining=Truessh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null#control_path = ~/.ssh/ansible-%%r@%%h:%%p[defaults]# https://github.com/ansible/ansible/issues/56930 (to ignore group names with - and .)force_valid_group_names = ignorehost_key_checking=Falsegathering = smartfact_caching = jsonfilefact_caching_connection = /tmpfact_caching_timeout = 7200stdout_callback = defaultdisplay_skipped_hosts = nolibrary = ./librarycallback_whitelist = profile_tasksroles_path = roles:$VIRTUAL_ENV/usr/local/share/kubespray/roles:$VIRTUAL_ENV/usr/local/share/ansible/roles:/usr/share/kubespray/rolesdeprecation_warnings=Falseinventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds, .gpgprivate_key_file = ../cluster-keyremote_user = root[inventory]ignore_patterns = artifacts, credentialsCréation de l’inventaire et modification du paramétrage
On va utiliser les outils de KubeSpray pour générer l’inventaire :
cp -rfp inventory/sample inventory/ignitedeclare -a IPS=(10.61.0.47 10.61.0.48 10.61.0.49 10.61.0.50 10.61.0.51)CONFIG_FILE=inventory/ignite/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]}Vous devriez vous retrouver avec ce fichier inventory/ignite/hosts.yml
    node1:      ansible_host: 10.61.0.47      ip: 10.61.0.47      access_ip: 10.61.0.47    node2:      ansible_host: 10.61.0.48      ip: 10.61.0.48      access_ip: 10.61.0.48    node3:      ansible_host: 10.61.0.49      ip: 10.61.0.49      access_ip: 10.61.0.49    node4:      ansible_host: 10.61.0.50      ip: 10.61.0.50      access_ip: 10.61.0.50    node5:      ansible_host: 10.61.0.51      ip: 10.61.0.51      access_ip: 10.61.0.51  children:    kube_control_plane:      hosts:        node1:        node2:    kube_node:      hosts:        node1:        node2:        node3:        node4:        node5:    etcd:      hosts:        node1:        node2:        node3:    k8s_cluster:      children:        kube_control_plane:        kube_node:    calico_rr:      hosts: {}Testons :
ansible -m ping -i node1, all
node1 | SUCCESS => {    "changed": false,    "ping": "pong"}Ensuite pour Centos il faut modifier le paramétrage de Calico :
sed -i -r 's/^(calico_iptables_backend:).*/\1 "Auto"/g' roles/network_plugin/calico/defaults/main.ymlDans le paramétrage du cluster j’ai désactivé aussi la mise à jour du DNS:
sed -i -r 's/^(dns_mode:).*/\1 none/g' inventory/ignite/group_vars/k8s_cluster/k8s-cluster.ymlInstallation du cluster Kubernetes
Tout est prêt on peut passer à l’installation du cluster.
ansible-playbook -i inventory/ignite cluster.ymlWednesday 15 December 2021  11:48:41 +0000 (0:00:00.131)       0:25:18.294 ****===============================================================================kubernetes/preinstall : Install packages requirements --------------------------------------------------------------------------------- 141.77sdownload : download_container | Download image if required ----------------------------------------------------------------------------- 48.32snetwork_plugin/calico : Start Calico resources ----------------------------------------------------------------------------------------- 44.53sbootstrap-os : Assign inventory name to unconfigured hostnames (non-CoreOS, non-Flatcar, Suse and ClearLinux, non-Fedora) -------------- 41.05sdownload : download_file | Download item ----------------------------------------------------------------------------------------------- 34.31skubernetes/kubeadm : Join to cluster --------------------------------------------------------------------------------------------------- 32.23skubernetes/control-plane : kubeadm | Initialize first master --------------------------------------------------------------------------- 29.68sdownload : download_container | Download image if required ----------------------------------------------------------------------------- 28.06spolicy_controller/calico : Start of Calico kube controllers ---------------------------------------------------------------------------- 25.77skubernetes/control-plane : Joining control plane node to the cluster. ------------------------------------------------------------------ 24.47sdownload : download_container | Download image if required ----------------------------------------------------------------------------- 24.26sbootstrap-os : Gather host facts to get ansible_distribution_version ansible_distribution_major_version -------------------------------- 23.03sbootstrap-os : Gather host facts to get ansible_os_family ------------------------------------------------------------------------------ 22.87spolicy_controller/calico : Create calico-kube-controllers manifests -------------------------------------------------------------------- 22.09sdownload : download_container | Download image if required ----------------------------------------------------------------------------- 21.43sGather necessary facts (hardware) ------------------------------------------------------------------------------------------------------ 20.98setcd : reload etcd --------------------------------------------------------------------------------------------------------------------- 20.96sdownload : download_file | Download item ----------------------------------------------------------------------------------------------- 20.88sGather necessary facts (network) ------------------------------------------------------------------------------------------------------- 20.77sGather minimal facts ------------------------------------------------------------------------------------------------------------------- 20.67sAu bout de 25 minutes notre cluster est prêt. Récupérons sa configuration.
Créons les entrées dans /etc/hosts
Pour accéder plus facilement aux noeuds un petit quick win Ansible pour ajouter les hosts de l’inventaire dans /etc/hosts :
---- hosts: k8s_cluster  gather_facts: true  become: true
  tasks:    - name: update /etc/hosts file      vars:        ansible_python_interpreter: "/usr/bin/python"      blockinfile:        path: /etc/hosts        marker: "# {mark} Node {{ inventory_hostname }}"        block: "{{ ansible_facts.default_ipv4.address }} {{ inventory_hostname }}"      delegate_to: localhostSi vous détruisez votre cluster il faudra le rejouer pour mettre les bonnes IP !
On lance le playbook :
cd ..ansible-playbook -i kubespray/inventory/ignite create-etc-hosts.yml
cat /etc/hosts
# BEGIN Node node110.61.0.62 node1# END Node node1# BEGIN Node node210.61.0.63 node2# END Node node2# BEGIN Node node510.61.0.66 node5# END Node node5# BEGIN Node node410.61.0.65 node4# END Node node4# BEGIN Node node310.61.0.64 node3# END Node node3Configuration de kubectl
Afin de pouvoir utiliser les commandes kubectl depuis notre poste, on va récupérer la configuration du cluster et la déposer dans le répertoire .kube:
ssh -i cluster-key root@node1 cat /etc/kubernetes/admin.conf > ~/.kube/config-igniteRécupérer l’adresse de node1 pour remplacer 127.0.0.1 dans la config :
awk '$2 ~ /node1/ {print $0}' /etc/hosts10.61.0.62 node1Editez le fichier ~/.kube/config-ignite et remplacer 127.0.0.1 par cette adresse. On peut aussi changer le nom du context par ignite :
    server: https://10.61.0.62:6443  name: cluster.localcontexts:- context:    cluster: cluster.local    user: kubernetes-admin  name: igniteUtilisons les contexts :
KUBECONFIG=~/.kube/config-test:~/.kube/config-ignitekubectl config get-contexts
CURRENT   NAME      CLUSTER         AUTHINFO           NAMESPACE*         default   default         default          ignite    cluster.local   kubernetes-adminPour changer de contexte utilisons kubectx :
asdf plugin add kubectxasdf install kubectx latestasdf set --home kubectx latestkubectx igniteSwitched to context "ignite".On vérifie qu’on accède au cluster :
kubectl get pod -ANAMESPACE     NAME                                      READY   STATUS    RESTARTS       AGEkube-system   calico-kube-controllers-5788f6558-c9mv9   1/1     Running   2 (166m ago)   166mkube-system   calico-node-bvcqd                         1/1     Running   0              168mkube-system   calico-node-lnw87                         1/1     Running   2 (167m ago)   168mkube-system   calico-node-nfcj4                         1/1     Running   2 (167m ago)   168mkube-system   calico-node-ptfjj                         1/1     Running   3 (167m ago)   168mkube-system   calico-node-wzqb9                         1/1     Running   2 (167m ago)   168mkube-system   kube-apiserver-node1                      1/1     Running   0              171mkube-system   kube-apiserver-node2                      1/1     Running   0              170mkube-system   kube-controller-manager-node1             1/1     Running   3 (98m ago)    171mkube-system   kube-controller-manager-node2             1/1     Running   3 (53m ago)    170mkube-system   kube-proxy-2shqj                          1/1     Running   0              168mkube-system   kube-proxy-4t96f                          1/1     Running   0              169mkube-system   kube-proxy-fnt65                          1/1     Running   0              169mkube-system   kube-proxy-hxjks                          1/1     Running   0              168mkube-system   kube-proxy-kwmmr                          1/1     Running   0              169mkube-system   kube-scheduler-node1                      1/1     Running   3 (98m ago)    171mkube-system   kube-scheduler-node2                      1/1     Running   3              170mkube-system   nginx-proxy-node3                         1/1     Running   0              169mkube-system   nginx-proxy-node4                         1/1     Running   0              169mkube-system   nginx-proxy-node5                         1/1     Running   0              169mUn petit test :
kubectl create ns testnamespace/test created
kubens testContext "ignite" modified.Active namespace is "test".
kubectl create deployment nginx --image=nginx
Cela confirme que ignite est très bon remplaçant à vagrant. La création des nodes s’est faite en moins d’une minute. Donc à nous la destruction et reconstruction sans perdre de temps. Ça confirme aussi que KubeSpray peut répondre à mon besoin.
Allez on nettoie tout !
sudo footloose deletePlus d’infos sur kubespray ↗.
A la prochaine !
