Gérer des clusters Kubernetes avec kubeadm
Familiarisez-vous avec l'architecture et les composants de Kubernetes. Découvrez comment exécuter des clusters Kubernetes sur des machines Linux à l'aide de kubeadm. Figer la version du cluster et effectuez des mises à niveau à tout moment sans interruption de service.
Architecture des clusters Kubernetes
Vue d'ensemble
Les composants des clusters Kubernetes peuvent être organisés en deux groupes :
Les composants du plan de contrôle et des nœuds de travail peuvent être déployés sur n’importe quel nœud du cluster Kubernetes, mais il est préférable de disposer de nœuds dédiés au plan de contrôle et aux nœuds de travail pour une gestion plus facile.
Composants des nœuds de travail
Sur les nœuds de travail, nous avons :
-
kubelet :
- responsable de l'exécution des conteneurs des Pods
- reçoit des instructions d'exécution à partir du plan de contrôle (où exécuter un conteneur de Pods spécifique, avec quelle configuration…)
- transmet les statuts des pods au plan de contrôle via le composant kube-apiserver
-
kube-proxy (optionnel) :
- responsable de la création et de la maintenance des règles réseau nécessaires aux communications avec les Pods, à l'intérieur ou depuis l'extérieur du cluster (atteindre les Pods à partir de services avec des IP externes...)
-
Logiciel d'exécution de conteneur (container runtime) :
- un logiciel qui exécute des conteneurs (containerd, cri-o…)
Composants des nœuds du plan de contrôle
Sur les nœuds du plan de contrôle, nous avons :
-
kube-apiserver :
- une API REST utilisée par kubectl, les nœuds de travail et d'autres composants externes pour communiquer avec le plan de contrôle
-
kube-scheduler :
- décide sur quel nœud de travail un pod nouvellement créé doit s'exécuter
- la décision de planification est basée sur des facteurs tels que :
- besoins en ressources
- spécifications d'affinité et d'anti-affinité
- localité des données
- taints et tolérations
-
etcd :
- une base de données de stockage clés/valeurs pour le système Kubernetes
- dans la plateforme Kubernetes, tout (Pods, Services…) est représenté comme un objet stocké dans cette base de données
-
kube-controller-manager :
- exécute des processus de contrôleur qui surveillent en permanence certains des composants/objets Kubernetes
- apporte les modifications nécessaires pour les amener à répondre aux états souhaités définis par les utilisateurs ou le système lui-même :
- créer des comptes de service et des jetons pour les nouveaux espaces de noms
- créer des pods pour exécuter des tâches (jobs)
- créer des pods pour répondre au nombre de replicas des ReplicaSet
- ...
- chaque contrôleur est logiquement un processus unique, mais tous sont compilés dans un seul binaire et exécutés dans un seul processus
- Voici quelques exemples de contrôleurs pour la mise à l'échelle automatique verticale et horizontale des nœuds et pods de cluster Kubernetes :
-
cloud-controller-manager :
- regroupe les contrôleurs qui interagissent avec les API des fournisseurs de cloud
Configuration du plan de contrôle et des nœuds de travail
Ressources des nœuds de cluster Kubernetes
- 1 nœud de plan de contrôle (2 CPU, 2 Go de RAM)
- 2 nœuds de travail (2 CPU, 2 Go de RAM)
- Ubuntu 22.04 LTS pour tous les nœuds
Prérequis
À exécuter sur les nœuds du plan de contrôle et nœuds de travail (copier/coller ok) :
# Disable swap. By default Kubelet won't start when swap is enabled
sudo swapoff -a && \
# To make kubelet start properly and make Kubernetes use swap,
# have a look at this:
# https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#swap-configuration
# Make sure the br_netfilter and overlay kernels
# modules are automatically loaded at boot
echo "overlay" | sudo tee /etc/modules-load.d/k8s.conf && \
echo "br_netfilter" | sudo tee -a /etc/modules-load.d/k8s.conf && \
# Load the overlay and br_netfilter kernels modules
sudo modprobe br_netfilter && \
sudo modprobe overlay && \
# To verify, run:
# lsmod | egrep "overlay|br_netfilter"
# Result:
# overlay 151552 0
# br_netfilter 32768 0
# bridge 311296 1 br_netfilter
# Make sure IPv4 packets forwarding (routing)
# is always enabled on the machine (even after reboot)
echo "net.ipv4.ip_forward = 1" |
sudo tee -a /etc/sysctl.d/k8s.conf && \
# Make preceding changes effective
sudo systemctl restart procps.service && \
# To verify, run:
# sysctl net.ipv4.ip_forward
# Result:
# net.ipv4.ip_forward = 1
# Install pre-requisite packages
sudo apt update && sudo apt install -y socat software-properties-common curl
Installer un logiciel d'exécution de conteneur
Nous devons installer un logiciel d'exécution de conteneur qui sera responsable de l'exécution de nos conteneurs de pods du clusters Kubernetes. Tout logiciel / environnement d'exécution de conteneur implémentant la norme d' Interface d'exécution de conteneur (CRI) de Kubernetes devrait fonctionner avec Kubernetes.
Nous utiliserons CRI-O comme logiciel / environnement d'exécution de conteneur. Pour obtenir une liste des versions disponibles, consultez Versions CRI-O.
Installons et configurons CRI-O sur les nœuds du plan de contrôle et les nœuds de travail (copier/coller ok) :
# Set the version of CRI-O to install
CRIO_VERSION=v1.29 && \
# Get required GPG key for verifying CRI-O packages signature
curl -fsSL https://pkgs.k8s.io/addons:/cri-o:/stable:/$CRIO_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg && \
# Add CRI-O deb packages repository
echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/stable:/$CRIO_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/cri-o.list && \
# Install CRI-O
sudo apt update && sudo apt install -y cri-o && \
# Start CRI-O systemd service
sudo systemctl start crio.service
Notez que le pilote cgroups utilisé par l'environnement d'exécution de conteneur doit être le même que celui utilisé par kubelet que nous installerons ensuite. CRI-O utilise le pilote cgroups systemd par défaut. Pour afficher ce paramètre à partir de la configuration CRI-O, utilisez :
$ crio config | grep cgroup_manager
Pour modifier un paramètre de configuration, ajoutez un nouveau fichier de configuration à l'intérieur du répertoire /etc/crio/crio.conf.d. Utilisez crio config | less pour explorer les paramètres de configuration disponibles et leurs valeurs par défaut.
Installer kubelet, kubeadm et kubectl
Pour obtenir une liste des versions de Kubernetes disponibles, consultez Versions Kubernetes.
Nous allons installer kubelet, kubeadm et kubectl sur les nœuds du plan de contrôle et nœuds de travail (copier/coller ok) :
KUBERNETES_REPO_VERSION=v1.29 && \
# Get required GPG key for verifying Kubernetes packages signature
curl -fsSL https://pkgs.k8s.io/core:/stable:/$KUBERNETES_REPO_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \
# Add Kubernetes deb packages repository
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/$KUBERNETES_REPO_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/kubernetes.list && \
KUBERNETES_INSTALL_VERSION=1.29.9 && \
sudo apt update && sudo apt install -y kubelet=$KUBERNETES_INSTALL_VERSION* kubeadm=$KUBERNETES_INSTALL_VERSION* kubectl=$KUBERNETES_INSTALL_VERSION*
Vérifier:
$ apt policy kubelet kubeadm kubectl
kubelet:
Installed: 1.29.9-1.1
Candidate: 1.29.9-1.1
Version table:
*** 1.29.9-1.1 500
500 https://pkgs.k8s.io/core:/stable:/v1.29/deb Packages
100 /var/lib/dpkg/status
kubeadm:
Installed: 1.29.9-1.1
Candidate: 1.29.9-1.1
Version table:
*** 1.29.9-1.1 500
500 https://pkgs.k8s.io/core:/stable:/v1.29/deb Packages
100 /var/lib/dpkg/status
kubectl:
Installed: 1.29.9-1.1
Candidate: 1.29.9-1.1
Version table:
*** 1.29.9-1.1 500
500 https://pkgs.k8s.io/core:/stable:/v1.29/deb Packages
100 /var/lib/dpkg/status
Étant donné que kubeadm gère kubelet en tant que service systemd, le pilote cgroups systemd est recommandé par rapport au pilote cgroupfs, utilisé par défaut par kubelet. À partir de la version 1.22, kubeadm définit le pilote cgroups kubelet par défaut sur systemd.
Le pilote cgroups utilisé par kubelet est systemd, le même pilote cgroups utilisé par notre logiciel / environnement d'exécution de conteneur CRI-O précédemment configuré, donc tout va bien.
Assurons-nous maintenant que nos packages d’installation Kubernetes ne sont pas mis à niveau automatiquement car nous souhaitons le faire manuellement.
$ sudo apt-mark hold kubelet kubeadm kubectl
kubelet set on hold.
kubeadm set on hold.
kubectl set on hold.
Initialiser le cluster sur le nœud du plan de contrôle
Mise en réseau des pods
Le CIDR réseau que nous allons utiliser pour les pods du cluster correspond au CIDR réseau par défaut du Plugin réseau que nous allons utiliser. En effet, les réseaux de pods Kubernetes sont fournis par modules complémentaires/plugins tiers et les nœuds du cluster ne seront pas prêts jusqu'à ce qu'un plugin réseau soit installé.
Notre runtime de conteneur CRI-O est fourni avec une configuration réseau par défaut, qui sera utilisée par le cluster Kubernetes, si nous n'installons pas de module complémentaire/plugin réseau spécifique. Cette configuration par défaut obligera nos pods Kubernetes à utiliser le sous-réseau suivant :
(k8s-control)$ cat /etc/cni/net.d/11-crio-ipv4-bridge.conflist | grep subnet
[{ "subnet": "10.85.0.0/16" }]
Malheureusement, cette configuration par défaut ne convient pas aux clusters comportant plus d'un nœud. Pour notre cluster à 3 nœuds, nous devrons donc installer un plugin réseau prenant en charge les clusters multi-nœuds. Nous utiliserons Flanelle pour ce cas d'utilisation.
Pour éviter les problèmes avec Flannel, nous devons désactiver la configuration par défaut du plugin CNI de pont réseau fournie par CRI-O :
(k8s-control)$ cd /etc/cni/net.d/
(k8s-control)$ mv 11-crio-ipv4-bridge.conflist 11-crio-ipv4-bridge.conflist.disabled
Notes sur la haute disponibilité
Comme nous prévoyons d'ajouter davantage de nœuds de plan de contrôle à l'avenir (pour une haute disponibilité), nous utiliserons l'option « --control-plane-endpoint », indiquant l'adresse IP ou le nom de domaine du ou des équilibreurs de charge qui seront en amont des nœuds du plan de contrôle.
Pour l'instant, comme nous n'avons pas encore d'équilibreur(s) de charge ni de nœuds multiples pour le plan de contrôle, nous utiliserons, pour ce point de terminaison, un nom de domaine ('api-servers.k8s.local') pointant vers l'adresse IP de notre nœud de plan de contrôle unique.
Pour que les futurs nœuds du cluster résolvent correctement ce nom de domaine, ajoutez ce qui suit dans le fichier « /etc/hosts » sur chaque machine :
<control_plane_node_ip_address> api-servers.k8s.local
Après avoir ajouté davantage de nœuds de plan de contrôle à l'avenir, nous devrons simplement faire en sorte que ce nom de domaine pointe vers l'adresse IP du ou des équilibreurs de charge qui seront en amont des nœuds du plan de contrôle, afin d'atteindre les serveurs API du cluster.
Initialisation du cluster
Nous allons initialiser le cluster Kubernetes en utilisant le CIDR réseau Flannel par défaut ('10.244.0.0/16') pour les pods du cluster, puis déployer Flannel.
L'option '--cri-socket=container_runtime_unix_socket_path' peut également être utilisée dans le cas où plusieurs environnements d'exécution de conteneurs sont installés, pour indiquer celui qui doit être utilisé.
Utilisez la commande suivante pour initialiser le cluster :
(k8s-control)$ sudo kubeadm init --pod-network-cidr 10.244.0.0/16 --control-plane-endpoint api-servers.k8s.local --kubernetes-version v1.29.9
[init] Using Kubernetes version: v1.29.9
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api-servers.k8s.local k8s-control kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 172.27.36.172]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-control localhost] and IPs [172.27.36.172 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-control localhost] and IPs [172.27.36.172 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "super-admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 7.001927 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-control as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8s-control as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: 9rrzpt.b53urwsvxkrzqw4i
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join api-servers.k8s.local:6443 --token 9rrzpt.b53urwsvxkrzqw4i \
--discovery-token-ca-cert-hash sha256:0e70caff86cbda4341e7072756835402dd79b9b9be0940dc81c6cb0fd8956f4a \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join api-servers.k8s.local:6443 --token 9rrzpt.b53urwsvxkrzqw4i \
--discovery-token-ca-cert-hash sha256:0e70caff86cbda4341e7072756835402dd79b9b9be0940dc81c6cb0fd8956f4a
Créons maintenant le fichier kubeconfig requis pour s’authentifier et communiquer avec le cluster :
mkdir -p $HOME/.kube && \
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && \
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Nous pouvons maintenant utiliser « kubectl » pour mettre à jour ou lire certaines des ressources du cluster :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control NotReady control-plane 41s v1.29.9
(k8s-control)$ kubectl get namespaces
NAME STATUS AGE
default Active 46s
kube-node-lease Active 46s
kube-public Active 46s
kube-system Active 46s
# The control plane components
(k8s-control)$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-76f75df574-sd4sj 0/1 Pending 0 52s
coredns-76f75df574-w7f54 0/1 Pending 0 52s
etcd-k8s-control 1/1 Running 0 68s
kube-apiserver-k8s-control 1/1 Running 0 70s
kube-controller-manager-k8s-control 1/1 Running 0 64s
kube-proxy-slpcs 1/1 Running 0 52s
kube-scheduler-k8s-control 1/1 Running 0 68s
Comme nous pouvons le voir, le nœud du plan de contrôle n'est pas prêt et les pods du module complémentaire coredns sont dans un état d'attente. C'est parce qu'il n'y a pour l'instant pas de plugin réseau installé.
Installons Flanelle:
(k8s-control)$ kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
Vérifions que le nœud est maintenant prêt et que les pods coredns sont en cours d'exécution :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready control-plane 5m18s v1.29.9
(k8s-control)$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-76f75df574-sd4sj 1/1 Running 0 5m25
coredns-76f75df574-w7f54 1/1 Running 0 5m23
(...)
Faire en sorte que les nœuds de travail rejoignent le cluster
Pour obtenir la commande « kubeadm join » qui doit être exécutée sur les nœuds de travail pour faire en sorte qu'ils rejoignent le cluster, exécutez la commande suivante sur le nœud du plan de contrôle :
(k8s-control)$ kubeadm token create --print-join-command
Ensuite, exécutez la commande join affichée, en utilisant sudo, sur les nœuds de travail pour faire en sorte qu'ils rejoignent le cluster Kubernetes :
(k8s-worker1)$ sudo kubeadm join api-servers.k8s.local:6443 --token nhunxq.1owm513wkij8as6e --discovery-token-ca-cert-hash sha256:0e70caff86cbda4341e7072756835402dd79b9b9be0940dc81c6cb0fd8956f4a
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
Nous avons également fait en sorte que « k8s-worker2 » rejoigne le cluster en utilisant la même commande join.
Vérifions que les nœuds de travail précédemment ajoutés font désormais partie du cluster en exécutant la commande suivante sur le nœud du plan de contrôle :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready control-plane 8m6s v1.29.9
k8s-worker1 Ready <none> 24s v1.29.9
k8s-worker2 Ready <none> 16s v1.29.9
Nous avons ajouté avec succès des nœuds de travail au cluster.
Exécutons quelques pods et vérifions que le DNS, l'accès Internet et la communication entre les pods fonctionnent correctement :
(k8s-control)$ kubectl run nginx --image=nginx
pod/nginx created
(k8s-control)$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 7s 10.244.1.2 k8s-worker1 <none> <none>
(k8s-control)$ kubectl run -it busybox --image=busybox -- sh
If you don't see a command prompt, try pressing enter.
/ #
/ # cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local mshome.net
nameserver 10.96.0.10 # IP address of the coredns service
options ndots:5
/ #
/ # nslookup hackerstack.org # DNS resolution is working
Server: 10.96.0.10
Address: 10.96.0.10:53
Non-authoritative answer:
Name: hackerstack.org
Address: 172.67.200.204
Name: hackerstack.org
Address: 104.21.36.232
(...)
/ #
/ # nc -vz hackerstack.org 443 # internet access is working
hackerstack.org (104.21.36.232:443) open
/ #
/ # nc -vz 10.244.1.2 80 # communication with the nginx pod is working
10.244.1.2 (10.244.1.2:80) open
Très bien... les choses fonctionnent comme prévu. L'adresse IP '10.96.0.10' utilisée pour la résolution DNS par les conteneurs des pods correspond au service DNS du cluster Kubernetes dont les backends sont des pods coredns :
(k8s-control)$ kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 66m
(k8s-control)$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-76f75df574-sd4sj 1/1 Running 0 35m
(...)
Mettre à niveau le cluster
Contraintes de versions
Voici les contraintes de versions des composants des clusters Kubernetes par rapport à kubeadm :
- Kubelet par rapport à kubeadm :
- même version ou trois versions plus anciennes
- Ex : kubeadm est à 1.31.x => kubelet à 1.31.x 1.30.x 1.29.x 1.28.x
- Autres composants Kubernetes (kube-apiserver, kube-proxy, kube-controller-manager, kube-scheduler) par rapport à kubeadm :
- même version ou une version plus ancienne
- Ex : kubeadm à 1.31.x => composants Kubernetes à 1.31.x ou 1.30.x
- La version cible des composants Kubernetes est spécifiée à l'aide de l'option kubeadm '--kubernetes-version'
Étapes de mise à niveau
Nous commençons par mettre à niveau le nœud du plan de contrôle, puis les nœuds de travail :
-
Mise à niveau du nœud du plan de contrôle :
- drainer le nœud
- mettre à niveau kubeadm
- planifier la mise à niveau :
kubeadm plan upgrade - appliquer la mise à niveau :
kubeadm apply upgrade - mettre à niveau kubelet et kubectl
- rendre le nœud disponible
-
Mise à niveau des nœuds de travail :
- drainer le nœud (à partir du nœud du plan de contrôle)
- mettre à niveau kubeadm
- mettre à niveau la configuration de kubelet, kubelet et kubectl :
kubeadm upgrade node - rendre le nœud disponible
Mise à niveau du nœud du plan de contrôle
Voici l’état des nœuds du cluster avant la mise à niveau :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready control-plane 31h v1.29.9
k8s-worker1 Ready <none> 31h v1.29.9
k8s-worker2 Ready <none> 31h v1.29.9
Nous allons mettre à niveau le nœud du plan de contrôle vers la version 1.30.x de Kubernetes.
Ajouter le dépôt de paquets de la version cible de Kubernetes
Pour obtenir une liste des versions de Kubernetes disponibles, consultez Versions Kubernetes.
KUBERNETES_REPO_VERSION=v1.30 && \
# Get required GPG key for verifying Kubernetes packages signature
curl -fsSL https://pkgs.k8s.io/core:/stable:/$KUBERNETES_REPO_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \
# Add Kubernetes deb packages repository
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/$KUBERNETES_REPO_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/kubernetes.list
Drain du nœud et mise à niveau kubeadm
# Drain the node
(k8s-control)$ kubectl drain k8s-control --ignore-daemonsets
node/k8s-control cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-mlzcd
node/k8s-control drained
# Verify
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready,SchedulingDisabled control-plane 2d7h v1.29.9
k8s-worker1 Ready <none> 2d7h v1.29.9
k8s-worker2 Ready <none> 23h v1.29.9
# Upgrade kubeadm
KUBERNETES_INSTALL_VERSION=1.30.5 && \
sudo apt update && sudo apt install -y --allow-change-held-packages \
kubeadm=$KUBERNETES_INSTALL_VERSION*
Planifier et appliquer la mise à niveau
Procédez comme suit pour mettre à niveau les composants Kubernetes (kube-apiserver, kube-proxy, kube-controller-manager, kube-scheduler) vers la version 1.30.5 ainsi que etcd et CoreDNS vers leurs dernières versions.
- Voir la planification de la mise à niveau
(k8s-control)$ sudo kubeadm upgrade plan v1.30.5
[preflight] Running pre-flight checks.
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[upgrade] Running cluster health checks
[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: 1.29.9
[upgrade/versions] kubeadm version: v1.30.5
[upgrade/versions] Target version: v1.30.5
[upgrade/versions] Latest version in the v1.29 series: v1.30.5
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT NODE CURRENT TARGET
kubelet k8s-control v1.29.9 v1.30.5
kubelet k8s-worker1 v1.29.9 v1.30.5
kubelet k8s-worker2 v1.29.9 v1.30.5
Upgrade to the latest version in the v1.29 series:
COMPONENT NODE CURRENT TARGET
kube-apiserver k8s-control v1.29.9 v1.30.5
kube-controller-manager k8s-control v1.29.9 v1.30.5
kube-scheduler k8s-control v1.29.9 v1.30.5
kube-proxy 1.29.9 v1.30.5
CoreDNS v1.11.1 v1.11.3
etcd k8s-control 3.5.15-0 3.5.15-0
You can now apply the upgrade by executing the following command:
kubeadm upgrade apply v1.30.5
_____________________________________________________________________
The table below shows the current state of component configs as understood by this version of kubeadm.
Configs that have a "yes" mark in the "MANUAL UPGRADE REQUIRED" column require manual config upgrade or
resetting to kubeadm defaults before a successful upgrade can be performed. The version to manually
upgrade to is denoted in the "PREFERRED VERSION" column.
API GROUP CURRENT VERSION PREFERRED VERSION MANUAL UPGRADE REQUIRED
kubeproxy.config.k8s.io v1alpha1 v1alpha1 no
kubelet.config.k8s.io v1beta1 v1beta1 no
_____________________________________________________________________
- Effectuer la mise à niveau
(k8s-control)$ sudo kubeadm upgrade apply v1.30.5
[preflight] Running pre-flight checks.
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[upgrade] Running cluster health checks
[upgrade/version] You have chosen to change the cluster version to "v1.30.5"
[upgrade/versions] Cluster version: v1.29.9
[upgrade/versions] kubeadm version: v1.30.5
[upgrade] Are you sure you want to proceed? [y/N]: y
[upgrade/prepull] Pulling images required for setting up a Kubernetes cluster
[upgrade/prepull] This might take a minute or two, depending on the speed of your internet connection
[upgrade/prepull] You can also perform this action in beforehand using 'kubeadm config images pull'
[upgrade/apply] Upgrading your Static Pod-hosted control plane to version "v1.30.5" (timeout: 5m0s)...
[upgrade/etcd] Upgrading to TLS for etcd
[upgrade/staticpods] Preparing for "etcd" upgrade
[upgrade/staticpods] Current and new manifests of etcd are equal, skipping upgrade
[upgrade/etcd] Waiting for etcd to become available
[upgrade/staticpods] Writing new Static Pod manifests to "/etc/kubernetes/tmp/kubeadm-upgraded-manifests2733535561"
[upgrade/staticpods] Preparing for "kube-apiserver" upgrade
[upgrade/staticpods] Renewing apiserver certificate
[upgrade/staticpods] Renewing apiserver-kubelet-client certificate
[upgrade/staticpods] Renewing front-proxy-client certificate
[upgrade/staticpods] Renewing apiserver-etcd-client certificate
[upgrade/staticpods] Moved new manifest to "/etc/kubernetes/manifests/kube-apiserver.yaml" and backed up old manifest to "/etc/kubernetes/tmp/kubeadm-backup-manifests-2024-09-28-08-07-04/kube-apiserver.yaml"
[upgrade/staticpods] Waiting for the kubelet to restart the component
[upgrade/staticpods] This can take up to 5m0s
[apiclient] Found 1 Pods for label selector component=kube-apiserver
[upgrade/staticpods] Component "kube-apiserver" upgraded successfully!
[upgrade/staticpods] Preparing for "kube-controller-manager" upgrade
[upgrade/staticpods] Renewing controller-manager.conf certificate
[upgrade/staticpods] Moved new manifest to "/etc/kubernetes/manifests/kube-controller-manager.yaml" and backed up old manifest to "/etc/kubernetes/tmp/kubeadm-backup-manifests-2024-09-28-08-07-04/kube-controller-manager.yaml"
[upgrade/staticpods] Waiting for the kubelet to restart the component
[upgrade/staticpods] This can take up to 5m0s
[apiclient] Found 1 Pods for label selector component=kube-controller-manager
[upgrade/staticpods] Component "kube-controller-manager" upgraded successfully!
[upgrade/staticpods] Preparing for "kube-scheduler" upgrade
[upgrade/staticpods] Renewing scheduler.conf certificate
[upgrade/staticpods] Moved new manifest to "/etc/kubernetes/manifests/kube-scheduler.yaml" and backed up old manifest to "/etc/kubernetes/tmp/kubeadm-backup-manifests-2024-09-28-08-07-04/kube-scheduler.yaml"
[upgrade/staticpods] Waiting for the kubelet to restart the component
[upgrade/staticpods] This can take up to 5m0s
[apiclient] Found 1 Pods for label selector component=kube-scheduler
[upgrade/staticpods] Component "kube-scheduler" upgraded successfully!
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upgrade] Backing up kubelet config file to /etc/kubernetes/tmp/kubeadm-kubelet-config1684861658/config.yaml
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.30.5". Enjoy!
[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
Mettre à jour kubelet et kubectl
# Installation
KUBERNETES_INSTALL_VERSION=1.30.5 && \
sudo apt update && sudo apt install -y --allow-change-held-packages \
kubelet=$KUBERNETES_INSTALL_VERSION* kubectl=$KUBERNETES_INSTALL_VERSION* && \
# Ensure new systemd unit files are loaded
sudo systemctl daemon-reload && \
# Restart kubelet
sudo systemctl restart kubelet
Finaliser la mise à niveau du nœud du plan de contrôle
Vérifions maintenant la version du plan de contrôle :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready,SchedulingDisabled control-plane 2d7h v1.30.5
k8s-worker1 Ready <none> 2d7h v1.29.9
k8s-worker2 Ready <none> 23h v1.29.9
Comme nous pouvons le voir à partir de la sortie de la commande précédente, le nœud du plan de contrôle « k8s-control » a été mis à niveau avec succès vers la version 1.30.5 de Kubernetes.
Nous pouvons maintenant rendre le nœud disponible pour mettre à jour son statut sur Prêt et nous assurer que kubeadm, kubelet et kubectl ne sont pas automatiquement mis à niveau :
kubectl uncordon k8s-control && \
sudo apt-mark hold kubeadm kubelet kubectl
Étapes de vérification finales :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready control-plane 2d7h v1.30.5
k8s-worker1 Ready <none> 2d7h v1.29.9
k8s-worker2 Ready <none> 24h v1.29.9
(k8s-control)$ apt-mark showhold
kubeadm
kubectl
kubelet
Mise à niveau des nœuds de travail
Ajouter le dépôt de paquets pour la version future de Kubernetes
Pour obtenir une liste des versions de Kubernetes disponibles, consultez Versions Kubernetes.
KUBERNETES_REPO_VERSION=v1.30 && \
# Get required GPG key for verifying Kubernetes packages signature
curl -fsSL https://pkgs.k8s.io/core:/stable:/$KUBERNETES_REPO_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \
# Add Kubernetes deb packages repository
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/$KUBERNETES_REPO_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/kubernetes.list
Drain du nœud de travail et mise à niveau kubeadm
# Drain the worker node from the control plane node
(k8s-control)$ kubectl drain k8s-worker1 --ignore-daemonsets --force
node/k8s-worker1 cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-h7f2q; deleting Pods that declare no controller: default/busybox, default/nginx, default/ubuntu
evicting pod default/ubuntu
evicting pod default/busybox
evicting pod default/nginx
pod/nginx evicted
pod/busybox evicted
pod/ubuntu evicted
node/k8s-worker1 drained
# Upgrade kubeadm on the worker node
KUBERNETES_INSTALL_VERSION=1.30.5 && \
sudo apt update && sudo apt install -y --allow-change-held-packages \
kubeadm=$KUBERNETES_INSTALL_VERSION*
Mettre à jour la configuration de kubelet, kubelet et kubectl
- Mettre à jour la configuration de kubelet
(k8s-worker1)$ sudo kubeadm upgrade node
[upgrade] Reading configuration from the cluster...
[upgrade] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Running pre-flight checks
[preflight] Skipping prepull. Not a control plane node.
[upgrade] Skipping phase. Not a control plane node.
[upgrade] Backing up kubelet config file to /etc/kubernetes/tmp/kubeadm-kubelet-config1488552398/config.yaml
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[upgrade] The configuration for this node was successfully updated!
[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.
- Mettre à jour kubelet et kubectl
KUBERNETES_INSTALL_VERSION=1.30.5 && \
sudo apt update && sudo apt install -y --allow-change-held-packages \
kubelet=$KUBERNETES_INSTALL_VERSION* kubectl=$KUBERNETES_INSTALL_VERSION* && \
# Ensure new systemd unit files are loaded
sudo systemctl daemon-reload && \
# Restart kubelet
sudo systemctl restart kubelet
Finaliser la mise à niveau du nœud de travail
Vérifions maintenant la version du nœud de travail :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready control-plane 2d10h v1.30.5
k8s-worker1 Ready,SchedulingDisabled <none> 2d10h v1.30.5
k8s-worker2 Ready <none> 26h v1.29.9
Comme nous pouvons le voir à partir de la sortie de la commande précédente, le nœud de travail « k8s-worker1 » a été mis à niveau avec succès vers la version 1.30.5 de Kubernetes.
Nous pouvons maintenant rendre le nœud disponible pour mettre à jour son statut sur Prêt et nous assurer que kubeadm, kubelet et kubectl ne sont pas automatiquement mis à niveau :
(k8s-control)$ kubectl uncordon k8s-worker1
node/k8s-worker1 uncordoned
(k8s-worker1)$ sudo apt-mark hold kubeadm kubelet kubectl
kubeadm set on hold.
kubelet set on hold.
kubectl set on hold.
Étapes de vérification finales :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready control-plane 2d10h v1.30.5
k8s-worker1 Ready <none> 2d10h v1.30.5
k8s-worker2 Ready <none> 27h v1.29.9
(k8s-worker1)$ apt-mark showhold
kubeadm
kubectl
kubelet
Après avoir répété les étapes de mise à niveau du nœud de travail précédent sur le nœud de travail « k8s-worker2 » restant, notre cluster Kubernetes est entièrement mis à niveau :
(k8s-control)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control Ready control-plane 2d23h v1.30.5
k8s-worker1 Ready <none> 2d23h v1.30.5
k8s-worker2 Ready <none> 39h v1.30.5
Liens vers de la documentation supplémentaire
- Considérations sur la haute disponibilité
- Architecture de cluster Kubernetes détaillée
- Installation de kubeadm
- Cluster kubeadm K8s
- Que se passe-t-il lors de la mise à niveau du cluster
- Reconfiguration du cluster
- Se remettre des échecs
- Politique des versions
- Mise à niveau du cluster
- Considérations relatives au cluster de production
- Architecture réseau du cluster
- Modules complémentaires tiers pour des fonctionnalités supplémentaires
- Renouvellement manuel des certificats K8s
- Sauvegarde/restauration Etcd