Installation de Kubernetes


Prérequis

Machines :

Sur les Load Balancer :

Sur les Master (Control Plane) :

Sur les Nodes :

Préparation et Installation

Préparation : 

A Faire sur toutes les machines / VMs

pour plus de simplicité je vais egalement ajouter les hotes dans le fichier hosts afin de faire de la résolution par nom et eviter les problème en cas de soucis de DNS : 

fichier /etc/hosts (pensez a l'adapter en fonction de chaque hote) :

#Cluster Kubernetes
192.168.20.240      k8s-m1
192.168.20.241      k8s-m2
192.168.20.242      k8s-m3
192.168.20.243      k8s-w1
192.168.20.244      k8s-w2
192.168.20.245      k8s-w3

Désactivation du SWAP :

Pour ce faire il faut executer nano /etc/fstab

Ensuite il faut trouver la ligne ou le "SWAP" est mentionné et la commenté en mettant un # devant cette ligne. Suite a ça enregistré et redémarrer la machine.

Régalge de la Timezone :

timedatectl set-timezone "Europe/Paris"

Installation de l'agent QEMU

apt install qemu-guest-agent

Installation de Kubernetes

Mise a jour des paquets : 

apt update && apt dist-upgrade -y

Installation des dépendances : 

apt-get install curl pgp -y

Penser bien a changer le numéro de version avec la version actuelle que vous pouvez retrouver sur ce site : https://kubernetes.io/fr/releases/

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

apt install containerd curl -y

systemctl enable --now containerd

apt update

configuration de quelques fichier de containerd

Suppression de config.toml (Si nécessaire)

rm /etc/containerd/config.toml
systemctl restart containerd

Ensuite on crée le dossier containerd dans etc si il n'existe pas déjà :

sudo mkdir -p /etc/containerd

Une fois cela fait ont crée la configuration :

containerd config default | sudo tee /etc/containerd/config.toml

On edite la configuration pour modifié ce paramètres de "false" à "true" :

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

vous pouvez également taper cette commande qui fait directement la modifications (c'est plus rapide) : sudo sed -i -E 's/^([[:space:]]*SystemdCgroup[[:space:]]*=[[:space:]]*)false/\1true/' /etc/containerd/config.toml

puis on redémarre containerd :

systemctl restart containerd

Ensuite on fait les deux manipulations suivantes :

cat <<'EOF' | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter

la deuxième :

cat <<'EOF' | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sudo sysctl --system

Puis on redémarre une nouvelle fois containerd : systemctl restart containerd

Pour plus d'inforamtions voici la procédure que j'ai suivi : https://sayakm.me/deploying-a-ha-kubernetes-cluster-on-raspberry-pi-using-kubeadm/?utm_source=chatgpt.com

Installation de Kubernetes (Kubelet - Kubeadm - Kubectl) :  

 

apt-get update && apt-get install kubelet kubeadm kubectl -y && apt-mark hold kubelet kubeadm kubectl

La commande apt-mark permet de fixer la version a celle actuelle de cette manière si quelqu'un vient faire un upgrade du système ce paquet ne se mettra pas à jour.

pour vérifier l'installation vous pouvez taper la commande kubectl et vérifié les noeuds qui sont normalement au nombre de 1 actuellement en tapant : kubectl get nodes

Dernière vérifications (a vérifé si il faut le faire ?) :

On va vérifié si les "cgroups mémoire" sont activer pour ce faire faire la commande : cat /proc/cgroups si enable est egal a "memory" ou à "1" alors c'est bon sinon editer le fichier /boot/firmware/cmdline.txt et ajouter : cgroup_enable=memory puis redémarrer votre hote.

Installation via un Script :

Attention la configuration et le script est a vérifié et a adapter a votre besoin

wget https://gitlab.antoninpomies.fr/antoninpomies/kubernetes/-/raw/main/get_k8s.sh
chmod +x get_k8s.sh
sudo ./get_k8s.sh

Load-Balancer et Initialisation (Keepalived et HAProxy) [OK]

Installation et Configuration de HAProxy :

Sur chaque master node

Installation

sudo apt -y install haproxy
sudo systemctl enable --now haproxy

Configuration :

mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak && sudo nano /etc/haproxy/haproxy.cfg

global
  maxconn 4096
  log /dev/log local0
  daemon
  stats socket /var/lib/haproxy/stats

defaults
  mode                    http
  log                     global
  option                  httplog
  option                  dontlognull
  option http-server-close
  option forwardfor       except 127.0.0.0/8
  option                  redispatch
  retries                 3
  timeout http-request    10s
  timeout queue           1m
  timeout connect         10s
  timeout client          1m
  timeout server          1m
  timeout http-keep-alive 10s
  timeout check           10s
  maxconn                 3000

listen stats
  bind *:9000
  stats enable
  stats uri /stats
  stats refresh 2s
  stats auth admin:statspasswordforhaproxy


# API Kubernetes : 6443 en TCP (TLS passthrough)
listen kubernetes-apiserver-https
  bind *:6443
  mode tcp
  option log-health-checks
  timeout client 10m
  timeout server 10m
  balance roundrobin
  server k8s-m1 192.168.20.240:6443 check
  server k8s-m2 192.168.20.241:6443 check
  server k8s-m3 192.168.20.242:6443 check

Redémarrage de HAProxy pour appliquer les changements sudo systemctl restart haproxy

Test si on écoute bien sur le port 6443 sudo ss -lntp | grep 6443

Installation et Configuration de Keepalived :

Sur chaque master node

Installation

sudo apt -y install keepalived

Configuration

Pensez a adapter la configuration en fonction de l'hote en baissant la priorité et en modifiant le nom de l'interface si nécéssaire.

sudo nano /etc/keepalived/keepalived.conf

vrrp_script chk_haproxy {
  script "pidof haproxy"
  interval 2
  weight -50
}

vrrp_instance VI_API {
  state BACKUP
  interface ens18               # <-- remplace par ton NIC
  virtual_router_id 51
  priority 150                  # M1:150, M2:120, M3:100
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass changeMe
  }
  virtual_ipaddress {
    192.168.20.100/24 dev ens18 # <-- ton VIP
  }
  track_script { chk_haproxy }

  # Bascules ARP propres (options documentées dans le man keepalived)
  garp_master_delay 1
  garp_master_repeat 5
  garp_lower_prio_no_advert
}

Activation et vérification de l'installation :

sudo systemctl enable --now keepalived
journalctl -u keepalived -n 50 --no-pager
ip a | grep -A2 192.168.20.100

Ont peut également vérifié que le port fonctionne bien :

nc -vz 192.168.20.100 6443

Initialisation du Cluster Kubernetes :

sudo kubeadm init \
  --control-plane-endpoint 192.168.20.100:6443 \
  --pod-network-cidr 10.244.0.0/16 \
  --upload-certs

Une fois le conteneur initialisé, mettez vous avec votre utilisateur classique et executer ça (comme recommandé suite a l'installation) :

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Et si vous êtes en "root" alors cette commande ci : export KUBECONFIG=/etc/kubernetes/admin.conf

Installation de Calico

Installation :

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/tigera-operator.yaml

suite a cette commande vous devriez avoir un résultat dans ce genre là :

namespace/tigera-operator created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator-secrets created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
rolebinding.rbac.authorization.k8s.io/tigera-operator-secrets created
deployment.apps/tigera-operator created

suite a ça ont va télécharger le YAML :

wget https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/custom-resources.yaml

Puis on édite le YAML pour spécifié notre sous réseau dans mon cas "10.244.0.0/16".

Une fois cela fait on peut appliquer la configuration :

kubectl apply -f custom-resources.yaml

On peut ensuite surveiller le déployment des conteneur avec la commande suivante :

watch kubectl get tigerastatus

Le résultat attendu est le suivant :

NAME                            AVAILABLE   PROGRESSING   DEGRADED   SINCE
apiserver                       True        False         False      4m9s
calico                          True        False         False      3m29s
goldmane                        True        False         False      3m39s
ippools                         True        False         False      6m4s
whisker                         True        False         False      3m19s

Une fois que tout est "True" ont peut vérifié l'etat du cluster kubectl get nodes et ont doit avoir un résultat comme ça :

NAME     STATUS   ROLES           AGE   VERSION
k8s-m1   Ready    control-plane   90m   v1.34.1
k8s-m2   Ready    control-plane   82m   v1.34.1
k8s-m3   Ready    control-plane   80m   v1.34.1
k8s-w1   Ready    <none>          70m   v1.34.1
k8s-w2   Ready    <none>          69m   v1.34.1
k8s-w3   Ready    <none>          69m   v1.34.1

Ont peut ensuite vérifié l'etat du réseau avec l'outil intégré a calico avec la commande suivante :

kubectl port-forward -n calico-system service/whisker 8081:8081 --address 0.0.0.0

Une fois cette commmande lancé rendez vous sur votre naviguateur et aller a l'adresse du master 1 avec le port 8081 : http://192.168.20.240:8081

Il est normal que la commande n'aboutisse pas car c'est temporaire suite a la vérification vous pouvez annulé la redirection de port en faisant ^C.

Ressources supplémentaires

Liens intéressant :

Installation a combiné avec la procédure précédente : https://github.com/jaiswaladi246/HA-K8-Cluster

Problèmes :

Problème de CRI (Version etc...)

Solution :

rm /etc/containerd/config.toml
systemctl restart containerd
kubeadm init

lien : https://k21academy.com/docker-kubernetes/container-runtime-is-not-running/

Amélioration de l'installation

Cette page va permettre d'améliorer l'installation actuelle afin de ce simplifier la vie dans le futur de l'administration du cluster.

L'Autocomplétion

Installation

apt install bash-completion

Configuration

echo "source <(kubectl completion bash)" >> /home/kube/.bashrc

ensuite ont source la .bashrc :

source /home/kube/.bashrc

Une fois cela fait quand on tape kubectl et qu'on fait la touche tabulation alors toutes les possibilité apparaisse ce qui facilite la rédaction de commande.

sources : https://www.youtube.com/watch?v=jnJfBAdujjE&list=PLn6POgpklwWqfzaosSgX2XEKpse5VY2v5&index=8

Alias

Les alias vont permettre de définir des genre de raccourcis. Par exemple au lieu de taper kubectl systématiquement ont défini k comme alias. Dans votre terminal k aura le meme effet que kubectl ce qui peut facilité la vie. un bon exemple est "kubectl get nodes" qu'on peut raccourcir en "kgn" par exemple.

Pour définir des alias utiliser ce "template" et modifié le a votre besoin et mettez le dans votre .bashrc :

alias k='kubectl'
alias kgn='kubectl get nodes'

Administration a distance

Pour l'administration a distance cela signifie que vous pouvez installer kubectl sur votre terminal de pc et administrer votre cluster depuis celui ci sans passer par ssh par exmeple.

Pour ce faire vous allez installer kubectl sur votre equipement.

Ensuite vous allez copier le contenu de /etc/kubernetes/admin.conf dans un fichier config que vous allez placer dans un dossier .kube qui sera a la racine de votre session.

Une fois cela fait si vous faites un kubectl get nodes dans le terminal de votre PC vous devrier voir un résultat comme celui-ci :

NAME     STATUS   ROLES           AGE     VERSION
k8s-m1   Ready    control-plane   3h23m   v1.34.1
k8s-m2   Ready    control-plane   3h15m   v1.34.1
k8s-m3   Ready    control-plane   3h13m   v1.34.1
k8s-w1   Ready    <none>          3h3m    v1.34.1
k8s-w2   Ready    <none>          3h2m    v1.34.1
k8s-w3   Ready    <none>          3h2m    v1.34.1

Préparation de l'environnement de gestion de Kubernetes

Pour manager efficacement et rapidement son/ses cluster Kubernetes, quelques outils peuvent être mis en place.

Je travaille sur MacOS, donc mes instructions seront sur cet environnement-là.

Autocomplétion

Pour installer l'autocomplétion, nous allons utiliser "Homebrew”.

brew install bash-completion@2

Une fois l'installation terminée, alors l'autocomplétion devrait fonctionner immédiatement. Vous pouvez donc faire un kubectl puis tab pour compléter la commande.

Alias

Les alias vont permettre de faire des raccourcis pour les commandes Kubernetes. Ils sont complètement personnalisables, je vais en mettre quelques-uns que j'utilise régulièrement. Ces alias vont se mettre dans votre .zshrc / .bashrc sous cette forme :

alias k='kubectl'
alias kgn='kubectl get nodes'
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kga='kubectl get all'
alias kap='kubectl apply -f'
alias kg='kubectl get'
alias kn='kubens'

Kubens / Kubectx

Ces deux outils sont très intéressants car ils ont deux usages très intéressants. Pour installer les deux outils : brew install kubectx

Kubens

Kubens est dans mon cas le plus utile. Il permet de naviguer dans les différents namespaces de votre cluster Kubernetes. Cela évite à chaque utilisation de kubectl de spécifier le -n mais à la manière d'un cd de venir se placer dans le namespace.

Pour son utilisation, je vais vous donner quelques commandes utiles et classiques pour l'utilisation de ces outils.

kubens <namespace> Cette commande permet de se déplacer de namespace.

kubens - permet de revenir au namespace par défaut.

Vous pouvez également ajouter des alias pour cet outil. En général, l'alias kn est utilisé.

Kubectx

Kubectx est très utile pour les administrateurs de cluster Kubernetes car il permet de switcher de contexte. En effet, dans le cas où vous avez une configuration multi-cluster, alors vous pouvez modifier grâce à la commande kubectx.

Pour son utilisation, je vais vous donner quelques commandes utiles et classiques pour l'utilisation de cet outil.

kubectx <contexte> permet de changer de contexte.

kubectx - permet de revenir au contexte par défaut.

Vous pouvez également ajouter des alias pour cet outil. En général, l'alias kx est utilisé.

Agent SSH

Afin de simplifier les connexion ssh au hote du cluster notamment pour l'utilisation de ansible il est possible de configurer efficacement son client ssh.

On va commencer par ajouter les hote au /etc/hosts par exemple :

# Cluster k8s #
192.168.20.238      k8s-lb1
192.168.20.239      k8s-lb2
192.168.20.240      k8s-m1
192.168.20.241      k8s-m2
192.168.20.242      k8s-m3
192.168.20.243      k8s-w1
192.168.20.244      k8s-w2
192.168.20.245      k8s-w3

de cette manière ont peut retenir les nom au lieu des adresses ip des autres.

Ensuite nous allons configurer l'agent SSH pour qu'il soit permanent ce qui va nous permettre de simplifier la connexion. Pour ce faire nous allons installer keychain sur le mac : brew install keychain

Une fois installé nous allons crée un agent et charger la clé privée et saisir son mot de passe:

ssh-add --apple-use-keychain ~/.ssh/id_ecdsa

Une fois cela fait nous allons modifier ou crée le fichier ssh config : nano ~/.ssh/config

Puis nous ajoutons le contenu suivant en l'adaptant a la configuration :

Host *
  User kube
  UseKeychain yes
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ecdsa

Et enfin nous ajoutons une ligne a la fin du fichier .zshrc :

echo "ssh-add --apple-load-keychain -q" >> ~.zshrc

Pour finir je ne sais pas si c'est nécéssaire mais on source le fichier zshrc :

source ~.zshrc

Script de configuration

brew install bash-completion@2
echo "alias k='kubectl'" >> $HOME/.zshrc
echo "alias kgn='kubectl get nodes'" >> $HOME/.zshrc
echo "alias kgp='kubectl get pods'" >> $HOME/.zshrc
echo "alias kgs='kubectl get svc'" >> $HOME/.zshrc
echo "alias kga='kubectl get all'" >> $HOME/.zshrc
echo "alias kg='kubectl get'" >> $HOME/.zshrc
echo "alias kn='kubens'" >> $HOME/.zshrc
brew install kubectx`

Installation de HELM

HELM est un similaire a un gestionnaire de paquet comme APT il utilise des repositories pour aller chercher des configuration de logiciel et/ou de services pour un cluster Kubernetes. Voici comment l'installer.

L'installation se fait a l'endroit ou vous administrer votre cluster kubernetes uniquement. Pas besoin de l'installer sur tout les hotes.

Installation via le Script [OK]

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

Installation via APT [?]

curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm

Installation de Metallb

Installation :

A faire sur un noeuds de management

Vérifé la commande a jour sur le site : https://metallb.universe.tf/installation/

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.2/config/manifests/metallb-native.yaml

Configuration de la plage IP pour l'attribution :

Pensez bien a modifié la plage ip et eventuellement le nom au besoin

nano metallb.yaml

---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: k8s-lb-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.20.10-192.168.20.99
  autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: k8s-lb-adv
  namespace: metallb-system
spec:
  ipAddressPools:
    - k8s-lb-pool

Une fois le fichier crée on peut maintenant l'appliquer : kubectl apply -f metallb.yaml

Sources :

Lien 1 : https://www.youtube.com/watch?v=Yl8JKffmhuE

Lien 2 : https://www.youtube.com/watch?v=AsYEYoLW-Uk

Test :

Pour tester l'installation de metallb, nous allons deployer un conteneur nginx et essayer d'y acceder.

kubectl create deploy nginx --image nginx:latest

On vérifie le déploiment du conteneur

kubectl get all

Puis ont crée le services pour exposer le port :

kubectl expose deploy nginx --port 80 --type LoadBalancer

Une fois cela fait ont peut faire un kubectl get all et récupéré l'adresse ip fourni par "Metallb" et aller sure votre naviguateur en mettant l'adresse ip et le port que vous avez spécifié dans votre services.

Installation de Longhorn

Longhorn est un utilitaire qui permet de gérer le stockage sur un cluster Kubernetes.

Pour l'installer nous allons nous servir de HELM :

Prérequis :

sudo apt update
sudo apt -y install open-iscsi nfs-common
sudo systemctl enable --now iscsid

Il faut que vous ajoutiez un disque dédié a longhorn sur votre VMs et ensuite suivre ces commandes pour configurer le disque :

sudo parted -s /dev/sdb mklabel gpt
sudo parted -s /dev/sdb mkpart longhorn 0% 100%
sudo mkfs.ext4 -F /dev/sdb1
sudo mkdir -p /var/lib/longhorn
echo '/dev/sdb1 /var/lib/longhorn ext4 defaults 0 2' | sudo tee -a /etc/fstab
systemctl daemon-reload
sudo mount -a

Installation :

Pour l'installation suivre ces commandes :

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.10.0/deploy/longhorn.yaml

Ont peut ensuite vérifié que les pods ont bien été crée et que il y a bien un stokage "longhorn" qui à été crée et qui est par défaut :

kubectl -n longhorn-system get pods
kubectl get sc

Ont va ensuite exposer l'interface web de Longhorn pour ce faire nous allons editer le service longhorn crée lors de l'installation :

KUBE_EDITOR="nano" kubectl edit svc longhorn-frontend -n longhorn-system

Une fois dans l'edition nous allons modifié "ClusterIP" par "LoadBalancer"

Quitter et enregistrer le service et récupéré le numéro de port : kubectl get svc longhorn-frontend -n longhorn-system

Rendez vous sur votre naviguateur saisissez l'ip du service fourni par Metallb et le numéro de port (normalement 80) et vous devriez tombé sur l'interface de longhorn.

Démontage du volume en cas de problème si vous faites de la haute disponibilité :

Allez dans les settings > Général et trouver le paramètre : Pod Deletion Policy When Node is Down et configurer le sur : delete-both-statefulset-and-deployment-pod

Load-Balancer et Initialisation (KUBE-VIP) [KO]

Commande pour une seule fois : sudo ctr images pull ghcr.io/kube-vip/kube-vip:v1.0.1 alias kube-vip="sudo ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:v1.0.1 vip /kube-vip"

Commande pour que l'alias soit permanent : echo alias kube-vip="sudo ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:v0.4.0 vip /kube-vip" | tee -a ~/.bash_aliases

. ~/.bashrc

génération du manifest (configuration dans kubernetes) :

Certaines inforamtions sont a modifier comme l'interface la vip par exemple

kube-vip manifest pod \
    --interface ens18 \
    --vip 192.168.20.100 \
    --controlplane \
    --services \
    --arp \
    --leaderElection \
    --enableLoadBalancer | sudo tee /etc/kubernetes/manifests/kube-vip.yaml

Une fois cela fait ont initialise le cluster :

Dans cette partie il faut également adapter les inforamtions en mettant l'ip du load balancer choisi ou modifié la plage réseau au besoin

sudo kubeadm init --control-plane-endpoint "192.168.0.150:6443" --upload-certs --pod-network-cidr=10.244.0.0/16