Skip to main content

Initialisation de mon tout premier cluster HA

Architecture

Hostname
RAM
CPU
DISQUE
IP
FONCTION
k8s-master-1
4 go 2 60 SSD + 100 HDD (/opt) 192.168.1.101 etcd + control-plane
k8s-master-2 4 go 2 60 SSD + 100 HDD (/opt) 192.168.1.102 etcd + control-plane
k8s-master-3 4 go 2 60 SSD + 100 HDD (/opt) 192.168.1.103 etcd + control-plane
k8s-worker-1 16 go 4 60 SSD + 100 HDD (/opt) 192.168.1.104
k8s-worker-2 16 go 4 60 SSD + 100 HDD (/opt) 192.168.1.105
k8s-worker-3 16 go 4 60 SSD + 100 HDD (/opt) 192.168.1.106

Tous les noeuds sont sur debian 13.

Plan de déploiement du cluster :

  • Préparation du système
  • installation des prérequits
    • conainer.io
    • kubelet
    • kubeadm
    • kubectl
  • Préparation du cluster HA (KubeVip)
  • Initialisation du cluster
  • Configuration du cluster
  • Ajout des différents noeud au cluster


Préparation du système

Commandes à réaliser sur tous les noeuds

1) Désactivation de la swap
swapoff -a

Désactivation de la swap de manière pérenne : 

sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
2) Configuration du kernel

Chargement au démarage des modules pour k8s : 

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

Chargement immédiat des modules pour k8s : 

modprobe overlay
modprobe br_netfilter

Le module overlay permet le fonctionnement du système de fichier OverlayFS.
Le module br_netfiltrer permet d'appliquer les iptables à un bridge.

Configuration des paramètres réseaux :

cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

Permet aux bridges de faire appel au FW iptables
Permet d'active le routage

Application des paramètres : 

sysctl --system

installation des prérequits

Commandes à réaliser sur tous les noeuds

Installation des packets courrants :
apt-get update 
apt-get install -y ca-certificates curl gnupg lsb-release htop jq tcpdump ethtool
Installation de containerd.io
install -m 0755 -d /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg

chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/debian bookworm stable" \
  | tee /etc/apt/sources.list.d/docker.list > /dev/null

apt update

apt install -y containerd.io

Configuration de containerd : 

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

Activation de containerd : 

systemctl enable containerd

Activation de l'emploie de systemd comme gestionnaire de Cgroup : 

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml

Redémarage de Containerd :

systemctl restart containerd
Installation de kubernet

Installation de kubelet kubeadm et kubectl :

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | gpg --dearmor | sudo tee /etc/apt/keyrings/kubernetes-apt-keyring.gpg > /dev/null
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg

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

sudo apt update

sudo apt install -y kubelet kubeadm kubectl

sudo apt-mark hold kubelet kubeadm kubectl

Préparation du cluster HA (KubeVip)

Sur tous les noeuds master UNIQUEMENT

export VIP="192.168.1.100"
export INTERFACE="ens18"

Ici ens18 correspond à mon interface de prod et 192.168.1.100 correspondra à l'ip qui se "baladera" sur mes noeuds master selon leur disponiblité -> elle n'est pas fixée à un seul endroit.

KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases/latest | jq -r ".name")
echo "Version kube-vip : $KVVERSION"
sudo mkdir -p /etc/kubernetes/manifests/
# Pull de l'image kube-vip
sudo ctr image pull ghcr.io/kube-vip/kube-vip:$KVVERSION
# Génération du manifeste Static Pod
sudo ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:$KVVERSION vip \
/kube-vip manifest pod \
--interface $INTERFACE \
--address $VIP \
--controlplane \
--services \
--arp \
--leaderElection | sudo tee /etc/kubernetes/manifests/kube-vip.yaml

Initialisation du cluster

Sur le noeuds k8s-master-1 UNIQUEMENT

Application "à la main" de l'ip vip le temps qu'elle soit gérée par K8S : 

sudo ip addr add 192.168.1.100/32 dev ens18

Initialisation du cluster :

sudo kubeadm init \
--control-plane-endpoint "192.168.1.100:6443" \
--upload-certs \
--pod-network-cidr=10.10.0.0/16
sudo kubeadm init phase upload-certs --upload-certs

Configurer kubectl pour l'utilisateur courant :

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

 Vérification du bon déploiement du cluster "basique" : 

kubectl get pods -n kube-system
NAME                                   READY   STATUS    RESTARTS   AGE
etcd-k8s-master-1                      1/1     Running   0          4m57s
kube-apiserver-k8s-master-1            1/1     Running   0          4m57s
kube-controller-manager-k8s-master-1   1/1     Running   0          4m57s
kube-scheduler-k8s-master-1            1/1     Running   0          4m57s
kube-vip-k8s-master-1                  1/1     Running   0          4m57s

Déploiement du réseau Calico 

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

Attendre que l'opérateur ait fini :

kubectl rollout status deployment tigera-operator -n tigera-operator

Déployer les ressources Calico :

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/custom-resources.yaml

Définir le sous réseau de K8S : 

kubectl patch installation default --type=merge -p '{"spec": {"calicoNetwork": {"ipPools": [{"cidr": "10.10.0.0/16", "encapsulation": "VXLANCrossSubnet", "natOutgoing": "Enabled", "nodeSelector": "all()"}]}}}'

Suvi des états : 

watch kubectl get pods -n calico-system

Configuration du cluster

Désactivation de l'ip VIP "manuelle" :

sudo ip addr del 192.168.1.100/32 dev ens18

Ajout de l'ip vp dans le configmap de kubeadmin :

kubectl edit configmap kubeadm-config -n kube-system
apiVersion: v1
data:
  ClusterConfiguration: |
    apiServer: {}
    apiVersion: kubeadm.k8s.io/v1beta4
    caCertificateValidityPeriod: 87600h0m0s
    certificateValidityPeriod: 8760h0m0s
    certificatesDir: /etc/kubernetes/pki
    clusterName: kubernetes
    controllerManager: {}
--> controlPlaneEndpoint: "192.168.1.100:6443"

Ici on ajoute uniquement "controlPlaneEndpoint.

kubeadm init phase upload-certs --upload-certs

Application du label control-plane à k8s-master-1

kubectl label node k8s-master-1 node-role.kubernetes.io/control-plane=

Génération de la commande permettant d'ajouter des noeuds masters :

sudo kubeadm token create --print-join-command --certificate-key $(sudo kubeadm init phase upload-certs --upload-certs | tail -1)

Génération de la commande permettant d'ajouter des noeuds worker :

kubeadm token create --print-join-command


Ajout des différents noeuds master au cluster

Commandes à exécuter sur les noeuds k8s-master-2 et k8s-master-3

kubeadm join 192.168.1.100:6443 --token ld3z42.3n2zglgdtoyd2to2 --discovery-token-ca-cert-hash sha256:03d97c70e97b300bb1088fa63f1005d52dcf45d813e6ec535897f2151c8a61c2 --control-plane --certificate-key c9413180b64c612ee58713da91a4d9b77e95bee06b424aa500ebb4b16fb7769d

Ajout des différents noeuds worker au cluster

Commandes à exécuter sur les noeuds k8s-worker-1, k8s-worker-2 et k8s-worker-3

// Envoyer la commande générée par kubeadm token create --print-join-command

Résultat : 

kubectl get nodes
NAME           STATUS   ROLES           AGE     VERSION
k8s-master-1   Ready    control-plane   81m     v1.32.12
k8s-master-2   Ready    control-plane   6m13s   v1.32.12
k8s-master-3   Ready    control-plane   4m8s    v1.32.12
k8s-worker-1   Ready    <none>          2m3s    v1.32.12
k8s-worker-2   Ready    <none>          115s    v1.32.12
k8s-worker-3   Ready    <none>          105s    v1.32.12

Félicitation ! Vous venez de déployer votre tout premier cluster Kubernettes !

Déployer une solution de stockage

Installation des prérequits sur TOUS LES NOEUDS : 

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

Installation de Helm sur le master 1 :

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

Préparation et déploiement de Longhorn :

helm repo add longhorn https://charts.longhorn.io
helm repo update

Dans le fichier : longhorn-values.yaml :

defaultSettings:
  defaultDataPath: "/opt/longhorn"

Déploiement de longhorn : 

helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  -f longhorn-values.yaml

Vérifications : 

watch kubectl get pods -n longhorn-system