Aller au contenu

Administrer des clusters ETCD

logo kubernetes

Suite à 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) :

Terminal window
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 :

Terminal window
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 :

Terminal window
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 :

Terminal window
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 :

Terminal window
--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.

Terminal window
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) :

Terminal window
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 :

Terminal window
export ETCDCTL_API=3

Contrôle de l’état de santé cluster ETCD

Dans un premier temps listons les membres du cluster ETCD :

Terminal window
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 :

Terminal window
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 noeudsTolérance de défaillance
10
20
31
41
52
62

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 :

Terminal window
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 :

Terminal window
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 :

Terminal window
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 :

Terminal window
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 :

Terminal window
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 :

Terminal window
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.

Terminal window
echo dG90bw== | base64 -d
toto

Pour afficher toutes les clés commençant par le prefix :

Terminal window
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 :

Terminal window
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

Terminal window
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 :

Terminal window
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 :

Terminal window
etcdctl del toto
1

Scruter les changements d’une clé

La commande watch permet de monitorer une clé. Sur le premier nœud :

Terminal window
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 !

Terminal window
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 :

Terminal window
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+.

Sources

kubernetes.io Documentation etcdctl