---
title: Howto etcd
categories: databases
...

* Documentation : <https://etcd.io/docs/v3.5/>

[Etcd](https://etcd.io/) est un système de stockage clé-valeur distribué fortement cohérent qui fournit un moyen fiable de stocker des données auxquelles un système distribué ou un cluster de machines doit accéder. Il gère les élections de primaire lors de problème réseau, et peux tolérer les pannes de machines, même sur le nœud primaire.

**ATTENTION : Documentation en cours d'écriture !**

# Installation

En Debian 11 on installe le client et/ou le serveur **etcd** comme ceci :

~~~
# apt install etcd-client etcd-server
~~~ 

Si on doit utiliser etcd via une API en Python, comme pour Patroni par exemple, on peux installer ces paquets supplémentaires :

~~~
# apt install python3-etcd python3-psycopg2
~~~ 

# Configuration

etcd écoute, par défaut, sur deux port bien distincts: `2379` et `2380`.

Le port `2379` sert pour la communication pour les requêtes des clients, et le port `2380` sert pour la communication des nœuds.

Voici la définition des variables d'environnement que nous utilisons le plus souvent :

* `ETCD_NAME` : nom du nœud
* `ETCD_DATA_DIR` : datadir des WAL etcd
* `ETCD_LOG_OUTPUTS` : sortie des logs sur `stdout` ou `stderr`, ça annule la remonté des logs dans journald.
* `ETCD_LISTEN_PEER_URLS` : liste des URLs sur laquelle écoute le trafic des pairs. Seule une adresse IP est valide, si on indique `0.0.0.0:PORT` cela écoute sur toutes les interfaces réseau de la machine. Un nom de domaine n'est pas valide pour l'écoute.
* `ETCD_LISTEN_CLIENT_URLS` : liste des URLs sur laquelle écoute le trafic des clients. Seule une adresse IP est valide, si on indique `0.0.0.0:PORT` cela écoute sur toutes les interfaces réseau de la machine. Un nom de domaine n'est pas valide pour l'écoute.
* `ETCD_INITIAL_ADVERTISE_PEER_URLS` : liste des URLs homologues de ce nœud à annoncer au reste du cluster. Ces adresses sont utilisées pour communiquer les données etcd autour du cluster, et elle peuvent contenir des noms de domaine.
* `ETCD_INITIAL_CLUSTER` : configuration initiale du cluster pour l'amorçage.
* `ETCD_ADVERTISE_CLIENT_URLS` : liste des URL client de ce membre à annoncer au reste du cluster, peux contenir des noms de domaine.
* `ETCD_INITIAL_CLUSTER_TOKEN` : défini le token d'initialisation pour l'amorçage du cluster etcd.
* `ETCD_INITIAL_CLUSTER_STATE` : état initial du cluster, peut être défini sur `new` ou `existing`. Si cette option est définie sur `existing`, etcd tentera de rejoindre le cluster existant. Si la mauvaise valeur est définie, etcd tentera de démarrer mais échouera en toute sécurité.

## Etcd en _stand alone_ sur un seul nœud

Si on veux utiliser etcd sur un seul serveur, et pas en mode cluster, on peut utiliser la configuration suivante dans `/etc/default/etcd` :

~~~
ETCD_NAME="etcd-foo"
ETCD_DATA_DIR="/var/lib/etcd/foo.etcd"
ETCD_LOG_OUTPUTS="stdout"
ETCD_LISTEN_PEER_URLS="http://192.0.1.2:2380"
ETCD_DATA_DIR="/var/lib/etcd/foo.etcd"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://192.0.1.2:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.0.1.2:2380"
ETCD_INITIAL_CLUSTER="etcd-foo=http://192.0.1.2:2380,"
ETCD_ADVERTISE_CLIENT_URLS="http://192.0.1.2:2379"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-foo"
ETCD_INITIAL_CLUSTER_STATE="new"
~~~

Dans cet exemple l'ip `192.0.1.2` est l'ip locale de la machine, on le fait écouter à la fois sur `localhost` et l'ip locale.

## Etcd en mode cluster

Si on veux utiliser etcd en mode cluster, on peut utiliser la configuration suivante :

~~~
ETCD_NAME="etcd-foo1"
ETCD_DATA_DIR="/var/lib/etcd/foo.etcd"
ETCD_LOG_OUTPUTS="stdout"
ETCD_LISTEN_PEER_URLS="http://10.0.0.1:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.1:2380"
ETCD_INITIAL_CLUSTER="etcd-foo1=http://10.0.0.1:2380,etcd-foo2=http://10.0.0.2:2380,etcd-foo3=http://10.0.0.3:2380,"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.1:2379"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-foo"
ETCD_INITIAL_CLUSTER_STATE="new"
~~~

On fait écouter etcd sur le port `2379` sur l'ip publique ou LAN de la machine, et également sur `localhost`.

On défini la variable `ETCD_INITIAL_CLUSTER` vers tous les nœud etcd du cluster, dans cet exemple il y a 3 nœuds sur 3 machines différentes.

On défini la variable `ETCD_NAME` sur chaque nœud avec un nom différent.

La variable `ETCD_INITIAL_CLUSTER_TOKEN` doit avoir un nom commun sur les nœuds du cluster.

On met en place cette configuration sur tous les nœuds, en modifiant les variables `ETCD_LISTEN_PEER_URLS` / `ETCD_LISTEN_CLIENT_URLS` et `ETCD_INITIAL_ADVERTISE_PEER_URLS` sur chaque nœud avec les valeurs spécifiques a ces machines.

# Administration

## Interagir en CLI avec l'API de etcd

On peux utiliser la commande `etcdctl` pour interagir avec l'API de etcd, il faut bien exporter la variable `ETCDCTL_API` en fonction de la version de etcd qu'on utilise, soit v2 ou v3.

En Debian 11 on utilise la v3, donc on exporte la variable comme ceci :

~~~
# export ETCDCTL_API=3
~~~

Voici quelques exemples d'utilisation :

* Lister les membres du cluster et connaitre l'état de chaque nœud :

~~~
# etcdctl --endpoints=http://127.0.0.1:2379 member list
3f4bf14e37c364ce: name=etcd-foo2 peerURLs=http://10.0.0.2:2380 clientURLs=http://10.0.0.2:2379 isLeader=false
48b925a0f1dfc2de: name=etcd-foo1 peerURLs=http://10.0.0.1:2380 clientURLs=http://10.0.0.1:2379 isLeader=false
c9633f5e058d7c36: name=etcd-foo3 peerURLs=http://10.0.0.3:2380 clientURLs=http://:10.0.0.3:2379 isLeader=true
~~~

* Connaitre la version de etcd, exemple en Debian 11 :

~~~
# etcdctl version
etcdctl version: 3.3.25
API version: 3.3
~~~

## Sauvegarde

Pour faire une sauvegarde de etcd dans un fichier on peux utiliser la commande suivante :

~~~
# etcdctl --endpoints=http://127.0.0.1:2379 snapshot save /home/backup/etcd-foo1.db
2022-08-10 15:56:52.128086 I | clientv3: opened snapshot stream; downloading
2022-08-10 15:56:52.147177 I | clientv3: completed snapshot read; closing
Snapshot saved at /home/backup/etcd-foo1.db
~~~

On peux vérifier le contenu de la sauvegarde, pour savoir le nombre de clés quelle contient, sa taille…

~~~
# etcdctl --write-out=table --endpoints=http://127.0.0.1:2379 snapshot status /home/backup/etcd-foo1.db
+----------+----------+------------+------------+
|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| a173f634 |        0 |          6 |      20 kB |
+----------+----------+------------+------------+
~~~