Kubernetes - Administrer des clusters ETCD
Publié le : 3 janvier 2022 | Mis à jour le : 27 juin 2023Suite à l'introduction de Kubernetes où j’ai décrit le fonctionnement d’un cluster Kubernetes, je vais expliquer comment administrer le composant ETCD.
Etcd, qu’est-ce-que-c’est ?
Rappel : ETCD est une base de données distribuée de type clé-valeur, qui a été développée en “Go”, le langage de programmation de Google. Dans un cluster Kubernetes, ETCD est chargé de stocker la configuration et les informations nécessaires au fonctionnement du cluster, c’est-à-dire de tous ses composants : les nœuds, les pods, les configs, les secrets, les rôles, les comptes, …
Création d’un cluster Kubernetes avec Kind
Je vais utiliser des clusters [Kubernetes créés avec l’utilitaire
Kind
](nc un
parfait candidat pour se préparer aux certifications CKA. En effet, kind
intègre tous les composants contrairement à d’autres solutions comme minikube ou
k3s.
En premier créer un fichier de config pour configurer un cluster avec trois master nodes et un worker. Pourquoi trois nodes et pas deux ? Parce qu’il est fortement conseiller de mettre en place des clusters avec un nombre impair de serveurs.
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
Maintenant lançons la création du cluster avec la dernière version de Kubernetes (voir le lien ci-dessus) :
kind create cluster --config=cluster.yaml --name cluster-1 --image kindest/node:latest
✓ Ensuring node image (kindest/node:v1.23.1) 🖼
✓ Preparing nodes 📦 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-cluster-1"
You can now use your cluster with:
kubectl cluster-info --context kind-cluster-1
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
Contrôlons nos nodes :
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
cluster-1-control-plane Ready control-plane,master 83m v1.23.1 172.18.0.4 <none> Ubuntu 21.04 4.18.0-348.2.1.el8_5.x86_64 containerd://1.5.2
cluster-1-control-plane2 Ready control-plane,master 83m v1.23.1 172.18.0.5 <none> Ubuntu 21.04 4.18.0-348.2.1.el8_5.x86_64 containerd://1.5.2
cluster-1-control-plane3 Ready control-plane,master 82m v1.23.1 172.18.0.6 <none> Ubuntu 21.04 4.18.0-348.2.1.el8_5.x86_64 containerd://1.5.2
cluster-1-worker Ready <none> 82m v1.23.1 172.18.0.3 <none> Ubuntu 21.04 4.18.0-348.2.1.el8_5.x86_64 containerd://1.5.
Contrôlons que nous avons bien un cluster ETCD :
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-64897985d-6wznk 1/1 Running 0 84m 10.244.0.2 cluster-1-control-plane <none> <none>
kube-system coredns-64897985d-95x8p 1/1 Running 0 84m 10.244.0.3 cluster-1-control-plane <none> <none>
kube-system etcd-cluster-1-control-plane 1/1 Running 0 84m 172.18.0.4 cluster-1-control-plane <none> <none>
kube-system etcd-cluster-1-control-plane2 1/1 Running 0 84m 172.18.0.5 cluster-1-control-plane2 <none> <none>
kube-system etcd-cluster-1-control-plane3 1/1 Running 0 83m 172.18.0.6 cluster-1-control-plane3 <none> <none>
kube-system kindnet-fw86t 1/1 Running 0 84m 172.18.0.4 cluster-1-control-plane <none> <none>
kube-system kindnet-k9mrt 1/1 Running 0 83m 172.18.0.6 cluster-1-control-plane3 <none> <none>
kube-system kindnet-m4k22 1/1 Running 0 84m 172.18.0.5 cluster-1-control-plane2 <none> <none>
kube-system kindnet-wmnp8 1/1 Running 0 83m 172.18.0.3 cluster-1-worker <none> <none>
kube-system kube-apiserver-cluster-1-control-plane 1/1 Running 0 84m 172.18.0.4 cluster-1-control-plane <none> <none>
kube-system kube-apiserver-cluster-1-control-plane2 1/1 Running 0 84m 172.18.0.5 cluster-1-control-plane2 <none> <none>
kube-system kube-apiserver-cluster-1-control-plane3 1/1 Running 1 (83m ago) 83m 172.18.0.6 cluster-1-control-plane3 <none> <none>
kube-system kube-controller-manager-cluster-1-control-plane 1/1 Running 1 (84m ago) 84m 172.18.0.4 cluster-1-control-plane <none> <none>
kube-system kube-controller-manager-cluster-1-control-plane2 1/1 Running 0 84m 172.18.0.5 cluster-1-control-plane2 <none> <none>
kube-system kube-controller-manager-cluster-1-control-plane3 1/1 Running 0 82m 172.18.0.6 cluster-1-control-plane3 <none> <none>
kube-system kube-proxy-68hlh 1/1 Running 0 83m 172.18.0.3 cluster-1-worker <none> <none>
kube-system kube-proxy-9ns2b 1/1 Running 0 84m 172.18.0.5 cluster-1-control-plane2 <none> <none>
kube-system kube-proxy-gzfwh 1/1 Running 0 83m 172.18.0.6 cluster-1-control-plane3 <none> <none>
kube-system kube-proxy-hwljt 1/1 Running 0 84m 172.18.0.4 cluster-1-control-plane <none> <none>
kube-system kube-scheduler-cluster-1-control-plane 1/1 Running 1 (84m ago) 84m 172.18.0.4 cluster-1-control-plane <none> <none>
kube-system kube-scheduler-cluster-1-control-plane2 1/1 Running 0 84m 172.18.0.5 cluster-1-control-plane2 <none> <none>
kube-system kube-scheduler-cluster-1-control-plane3 1/1 Running 0 83m 172.18.0.6 cluster-1-control-plane3 <none> <none>
local-path-storage local-path-provisioner-d6d9f7ffc-jznc9 1/1 Running 0 84m 10.244.1.2 cluster-1-control-plane2 <none> <none>
Etcd est bien installé sur les 3 nodes masters !
Affichons la configuration du cluster etcd :
kubectl describe pod etcd-cluster-1-control-plane -n kube-system
Name: etcd-cluster-1-control-plane
Namespace: kube-system
Priority: 2000001000
Priority Class Name: system-node-critical
Node: cluster-1-control-plane/172.18.0.4
Start Time: Mon, 03 Jan 2022 09:42:25 +0000
Labels: component=etcd
tier=control-plane
Annotations: kubeadm.kubernetes.io/etcd.advertise-client-urls: https://172.18.0.4:2379
kubernetes.io/config.hash: a6b006f7d9d8f4eb0ad9ccd08c1722ed
kubernetes.io/config.mirror: a6b006f7d9d8f4eb0ad9ccd08c1722ed
kubernetes.io/config.seen: 2022-01-03T09:42:03.405878931Z
kubernetes.io/config.source: file
seccomp.security.alpha.kubernetes.io/pod: runtime/default
Status: Running
IP: 172.18.0.4
IPs:
IP: 172.18.0.4
Controlled By: Node/cluster-1-control-plane
Containers:
etcd:
Container ID: containerd://3b604561e0d1b49f05dc124361d8e4f7ac3403f3d6326ddccc8a6da3701ecfe3
Image: k8s.gcr.io/etcd:3.5.1-0
Image ID: sha256:25f8c7f3da61c2a810effe5fa779cf80ca171afb0adf94c7cb51eb9a8546629d
Port: <none>
Host Port: <none>
Command:
etcd
--advertise-client-urls=https://172.18.0.4:2379
--cert-file=/etc/kubernetes/pki/etcd/server.crt
--client-cert-auth=true
--data-dir=/var/lib/etcd
--initial-advertise-peer-urls=https://172.18.0.4:2380
--initial-cluster=cluster-1-control-plane=https://172.18.0.4:2380
--key-file=/etc/kubernetes/pki/etcd/server.key
--listen-client-urls=https://127.0.0.1:2379,https://172.18.0.4:2379
--listen-metrics-urls=http://127.0.0.1:2381
--listen-peer-urls=https://172.18.0.4:2380
--name=cluster-1-control-plane
--peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
--peer-client-cert-auth=true
--peer-key-file=/etc/kubernetes/pki/etcd/peer.key
--peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
--snapshot-count=10000
--trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
State: Running
Started: Mon, 03 Jan 2022 09:42:07 +0000
Ready: True
Restart Count: 0
Requests:
cpu: 100m
memory: 100Mi
Liveness: http-get http://127.0.0.1:2381/health delay=10s timeout=15s period=10s #success=1 #failure=8
Startup: http-get http://127.0.0.1:2381/health delay=10s timeout=15s period=10s #success=1 #failure=24
Environment: <none>
Mounts:
/etc/kubernetes/pki/etcd from etcd-certs (rw)
/var/lib/etcd from etcd-data (rw)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
etcd-certs:
Type: HostPath (bare host directory volume)
Path: /etc/kubernetes/pki/etcd
HostPathType: DirectoryOrCreate
etcd-data:
Type: HostPath (bare host directory volume)
Path: /var/lib/etcd
HostPathType: DirectoryOrCreate
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: :NoExecute op=Exists
Events: <none>
Les informations importantes à retenir dont nous aurons besoin avec la commande etcdctl :
--cert-file=/etc/kubernetes/pki/etcd/server.crt
--key-file=/etc/kubernetes/pki/etcd/server.key
--trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
Connexion au serveur du Control-Plane
Ici comme utilisons kind, nous nous connecterons aux nodes non pas en SSH mais avec la commande docker. En effet, les conteneurs etcd sont vraiment léger et ne possède que peu de commandes.
docker exec -it cluster-1-control-plane bash
root@cluster-1-control-plane:/#
Quelques commandes pour démarrer avec ETCD
Installation de la CLI etcdctl
Nous devons installer la CLI etcdctl sur le master node (Toutes les commandes seront lancées depuis ce node) :
docker exec -it cluster-1-control-plane bash
apt update
apt install etcd-client
etcdctl --version
etcdctl version: 3.3.25
Nous utiliserons la version 3 de l’API d’ETCD :
export ETCDCTL_API=3
Contrôle de l’état de santé cluster ETCD
Dans un premier temps listons les membres du cluster ETCD :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt member list --write-out=table
+------------------+---------+--------------------------+-------------------------+-------------------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
+------------------+---------+--------------------------+-------------------------+-------------------------+
| 26aead55408e4ad0 | started | cluster-1-control-plane2 | https://172.18.0.5:2380 | https://172.18.0.5:2379 |
| 5320353a7d98bdee | started | cluster-1-control-plane | https://172.18.0.4:2380 | https://172.18.0.4:2379 |
| 983acdc6eb33276f | started | cluster-1-control-plane3 | https://172.18.0.6:2380 | https://172.18.0.6:2379 |
+------------------+---------+--------------------------+-------------------------+-------------------------+
Nous retrouvons bien nos trois nœuds qui sont en bonne santé. Pour connaître le
leader nous allons plutôt utiliser la commande endpoint status
:
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt endpoint status --write-out=table
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| 172.18.0.4:2379 | 5320353a7d98bdee | 3.5.1 | 3.2 MB | true | 3 | 28711 |
| 172.18.0.5:2379 | 26aead55408e4ad0 | 3.5.1 | 3.2 MB | false | 3 | 28712 |
| 172.18.0.6:2379 | 983acdc6eb33276f | 3.5.1 | 3.2 MB | false | 3 | 28712 |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
Le node 1 est le leader !
Si nous arrêtons un noeud le cluster etcd sera toujours fonctionnel. En effet, avec l’algorithme Raft nous avons droit à une défaillance sur les 3 serveurs. Si deux sont inaccessibles, le cluster passe en read-only et du coup le cluster kubernetes devient instable !
Nombre de noeuds | Tolérance de défaillance |
---|---|
1 | 0 |
2 | 0 |
3 | 1 |
4 | 1 |
5 | 2 |
6 | 2 |
Promouvoir un nœud
Il est possible à tout moment de promouvoir un nœud comme leader dans le cas ou vous devriez intervenir sur le noeud master actuel :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt move-leader 26aead55408e4ad0
Leadership transferred from 5320353a7d98bdee to 26aead55408e4ad0
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt endpoint status --write-out=table
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| 172.18.0.4:2379 | 5320353a7d98bdee | 3.5.1 | 3.2 MB | false | 4 | 34709 |
| 172.18.0.5:2379 | 26aead55408e4ad0 | 3.5.1 | 3.2 MB | true | 4 | 34709 |
| 172.18.0.6:2379 | 983acdc6eb33276f | 3.5.1 | 3.2 MB | false | 4 | 34709 |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
Faire des backups/restaurations d’etcd
Parfois en développement, nous n’utiliserons pas forcément des manifests pour gérer nos déploiements. Donc pour revenir en arrière nous pouvons utiliser des sauvegardes de la base ETCD.
Il suffit d’utiliser les commandes snapshot save
pour le backup et snapshot restore
pour la restauration :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt snapshot save /tmp/snapshot-etcd-1.db
Pour restaurer :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt snapshot restore /tmp/snapshot-etcd-1.db
Jouer avec les clés/valeurs
Ajout de clé/valeur
La commande pour ajout une clé/valeur est put
:
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt put toto test
OK
Afficher une clé/valeur
La commande pour ajout une clé/valeur est get
:
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt get toto
toto
test
Par afficher que la valeur on peut ajouter --print-value-only
et pour que la
clé --keys-only
. De même on peut demander l’affichage en json :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt get toto -w json
{
"header": {
"cluster_id": 13122874208970910000,
"member_id": 2787355801055808000,
"revision": 25139,
"raft_term": 3
},
"kvs": [
{
"key": "dG90bw==",
"create_revision": 8610,
"mod_revision": 24658,
"version": 2,
"value": "dGVzdA=="
}
],
"count": 1
}
Les valeurs sont codées en base64.
echo dG90bw== | base64 -d
toto
Pour afficher toutes les clés commençant par le prefix :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt get --prefix tot
toto
titi
Pour afficher tous les objets Kubernetes de la base :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt get / --prefix --keys-only
...
/registry/services/specs/default/kubernetes
/registry/services/specs/kube-system/kube-dns
/registry/storageclasses/standard
Créer/Détruire un dossier
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt mkdir /newpath
Lister toutes les clés
Il est possible d’afficher toutes les clés d’une base avec la commande suivante :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt get / --prefix --keys-only
Effacer une clé/valeur
La commande pour ajout une clé/valeur est del
:
etcdctl del toto
1
Scruter les changements d’une clé
La commande watch
permet de monitorer une clé. Sur le premier nœud :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt watch toto
Dans une seconde session modifier la valeur ou détruisez-la !
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt put toto titi
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt del toto
Vous devriez voir apparaître des messages dans la première session :
etcdctl --endpoints 172.18.0.4:2379,172.18.0.5:2379,172.18.0.6:2379 --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --cacert=/etc/kubernetes/pki/etcd/ca.crt watch toto
PUT
toto
titi
DELETE
toto
Quelques Conseils
Les performances et la stabilité du cluster sont liés aux performances E/S réseau et disque des serveurs. Toute pénurie de ressources peut entraîner une expiration du délai de pulsation, provoquant une instabilité du cluster. Un etcd instable est un cluster ou aucun master n’est élu. Dans de telles circonstances, un cluster ne peut apporter aucune modification à son état actuel.
Il est conseillé d’installer les clusters etcd sur des machines dédiées ou des environnements isolés pour garantir les besoins en ressources.
La version minimale recommandée d’etcd à exécuter en production est 3.2.10+.