*L'auteur a choisi Wikimedia Foundation pour recevoir un don dans le cadre du programme Write for Donations.*

Introduction

etcd est un magasin de valeurs clés distribué qui repose sur de nombreuses plateformes et outils, dont Kubernetes , Vulcand et Doorman . Dans Kubernetes, etcd est utilisé comme magasin de configuration globale qui stocke l'état du cluster. Savoir administrer etcd est essentiel pour administrer un cluster Kubernetes. Bien qu'il existe de nombreuses offres Kubernetes gérées, également connues sous le nom de _Kubernetes-as-a-Service_ , qui vous déchargent de cette charge administrative, de nombreuses entreprises choisissent encore de gérer des clusters Kubernetes autogérés sur site en raison de la flexibilité qu'ils apportent.

La première moitié de cet article vous guidera dans la mise en place d'un cluster de 3 nœuds etcd sur les serveurs Ubuntu 18.04. La seconde moitié se concentrera sur la sécurisation du cluster en utilisant la _Transport Layer Secutiry_ (Sécurité de la couche transport), ou _TLS_  Pour exécuter chaque installation de manière automatisée, nous utiliserons Ansible tout au long de ce tutoriel. Ansible est un outil de _gestion de configuration_ similaire à Puppet , Chef , et SaltStack ; il nous permet de définir chaque étape de configuration de manière déclarative, dans des fichiers appelés _playbooks_ .

À la fin de ce tutoriel, vous disposerez d'un cluster sécurisé de 3 nœuds etcd fonctionnant sur vos serveurs.  Vous disposerez également d'un playbook Ansible qui vous permettra de recréer de manière répétée et cohérente la même configuration sur un nouvel ensemble de serveurs.

Conditions préalables

etcd illustration for: Conditions préalables

Avant de commencer ce guide, vous aurez besoin des éléments suivants :

  • Trois serveurs Ubuntu 18.04 sur le même réseau local, avec au moins 2 Go de RAM et un accès SSH root.  Vous devez également configurer les serveurs pour qu'ils aient les noms d'hôtes etcd1 , etcd2 , et etcd3 . Les étapes décrites dans cet article fonctionneraient sur n'importe quel serveur générique, pas nécessairement cloud servers. Cependant, si vous souhaitez héberger vos serveurs sur the cloud provider, vous pouvez suivre le guide Comment créer un droplet du panneau de contrôle de the cloud provider pour remplir cette condition. Notez que vous devez activer l'option Private Networking lors de la création de votre droplet.  Pour activer la mise en réseau privée sur les droplets existants, reportez-vous à la section Comment activer la mise en réseau privée sur les droplets .

[warning]

Avertissement : Le but de cet article étant de fournir une introduction à la mise en place d'un cluster etcd sur un réseau privé, les trois serveurs Ubuntu 18.04 de cette configuration n'ont pas été testés avec un pare-feu et sont accessibles en tant que root user Dans une installation de production, tout nœud exposé à l'internet public nécessiterait un pare-feu et un sudo user pour adhérer aux meilleures pratiques de sécurité. Pour plus d'informations, consultez le tutoriel Configuration initiale du serveur avec Ubuntu 18.04.

  • Ansible installé sur votre machine locale. Par exemple, si vous utilisez Ubuntu 18.04, vous pouvez installer Ansible en suivant l'étape 1 de l'article Comment installer et configurer Ansible sur Ubuntu 18.04. Les commandes ansible et ansible-playbook seront ainsi disponibles sur votre machine. Vous pouvez également conserver ce mode d'emploi Comment utiliser Ansible : Un guide de référence à portée de main. Les commandes de ce tutoriel devraient fonctionner avec Ansible v2.x ; nous l'avons testé sur Ansible v2.9.7 sous Python v3.8.2.

Etape 1 - Configuration d'Ansible pour le nœud de contrôle

Ansible est un outil utilisé pour gérer les serveurs.  Les serveurs qu'Ansible gère sont appelés les _nœuds gérés_, et la machine qui fait tourner Ansible est appelée le _nœud de contrôle_. Ansible fonctionne en utilisant les clés SSH sur le nœud de contrôle pour accéder aux nœuds gérés. Une fois qu'une session SSH est établie, Ansible exécute un ensemble de scripts pour fournir et configurer les nœuds gérés. Dans cette étape, nous allons tester que nous sommes capables d'utiliser Ansible pour nous connecter aux nœuds gérés et exécuter la commande hostname .

Une journée typique pour un administrateur système peut impliquer la gestion de différents ensembles de nœuds. Par exemple, vous pouvez utiliser Ansible pour mettre à disposition de nouveaux serveurs, mais l'utiliser ensuite pour reconfigurer un autre ensemble de serveurs. Pour permettre aux administrateurs de mieux organiser l'ensemble des nœuds gérés, Ansible propose le concept d'_inventaire sur les hôtes_ (ou _inventaire_ en abrégé). Vous pouvez définir chaque nœud que vous souhaitez gérer avec Ansible à l'intérieur d'un _fichier d'inventaire_ et les organiser en _groupes_. Ensuite, lorsque vous exécutez les commandes ansible et ansible-playbook, vous pouvez spécifier à quels hôtes ou groupes la commande s'applique.

Par défaut, Ansible lit le fichier d'inventaire à partir de /etc/ansible/hosts ; cependant, nous pouvons spécifier un fichier d'inventaire différent en utilisant le drapeau --inventory (ou -i en abrégé).

Pour commencer, créez un nouveau répertoire sur votre machine locale (le nœud de contrôle) pour y placer tous les fichiers de ce tutoriel :

				
					
mkdir -p $HOME/playground/etcd-ansible

				
			

Ensuite, entrez dans le répertoire que vous venez de créer :

				
					
cd $HOME/playground/etcd-ansible

				
			

À l'intérieur du répertoire, créez et ouvrez un fichier d'inventaire vierge nommé hosts à l'aide de votre éditeur :

				
					
nano $HOME/playground/etcd-ansible/hosts

				
			

Dans le fichier hosts, listez chacun de vos nœuds gérés selon le format suivant, en remplaçant les adresses IP publiques mises en évidence par les adresses IP publiques réelles de vos serveurs :

				
					
[label ~/playground/etcd-ansible/hosts]

[etcd]

etcd1 ansible_host=<^>etcd1_public_ip<^> ansible_user=root

etcd2 ansible_host=<^>etcd2_public_ip<^> ansible_user=root

etcd3 ansible_host=<^>etcd3_public_ip<^> ansible_user=root

				
			

La ligne [etcd] définit un groupe appelé etcd . Dans la définition du groupe, nous énumérons tous les nœuds que nous gérons. Chaque ligne commence par un alias (par exemple, etcd1 ), ce qui nous permet de nous référer à chaque hôte en utilisant un nom facile à retenir au lieu d'une longue adresse IP. Les _variables_ ansible_host et ansible_user sont des variables Ansible . Dans ce cas, elles sont utilisées pour fournir à Ansible les adresses IP publiques et les noms d'utilisateur SSH à utiliser lors de la connexion via SSH.

Pour s'assurer qu'Ansible est capable de se connecter à nos nœuds gérés, nous pouvons tester la connectivité en utilisant Ansible pour exécuter la commande hostname sur chacun des hôtes du groupe etcd :

				
					
ansible etcd -i hosts -m command -a hostname

				
			

Décomposons cette commande pour apprendre ce que chaque partie signifie :

  • etcd : spécifie le _modèle d'hôte_ à utiliser pour déterminer quels hôtes de l'inventaire sont gérés avec cette commande.  Ici, nous utilisons le nom du groupe comme modèle d'hôte.
  • -i hosts : spécifie le fichier d'inventaire à utiliser.
  • Commande -m : la fonctionnalité derrière Ansible est fournie par des _modules_ . Le module de commande prend l'argument transmis et l'exécute comme une commande sur chacun des nœuds gérés. Ce tutoriel introduira quelques autres modules Ansible au fur et à mesure de notre progression.
  • -a hostname : l'argument à passer dans le module. Le nombre et les types d'arguments dépendent du module.

Après avoir exécuté la commande, vous trouverez la sortie suivante, ce qui signifie qu'Ansible est configuré correctement :

				
					
[secondary_label Output]

etcd2 | CHANGED | rc=0 >>

etcd2



etcd3 | CHANGED | rc=0 >>

etcd3



etcd1 | CHANGED | rc=0 >>

etcd1

				
			

Chaque commande qu'Ansible exécute est appelée une _tâche _. L'utilisation d'ansible sur la ligne de commande pour exécuter des tâches est appelée exécution de commandes _ad hoc_. L'avantage des commandes ad hoc est qu'elles sont rapides et ne nécessitent que peu de réglages ; l'inconvénient est qu'elles fonctionnent manuellement et ne peuvent donc pas être confiées à un système de contrôle de version comme Git .

Une légère amélioration serait d'écrire un script shell et d'exécuter nos commandes en utilisant le module de script d'Ansible .  Cela nous permettrait d'enregistrer les étapes de configuration que nous avons suivies pour le contrôle de version. Cependant, les scripts shell sont _impératifs_, ce qui signifie que nous sommes responsables de la détermination des commandes à exécuter (les « comment ») pour configurer le système dans l'état souhaité. Ansible, d'autre part, préconise une approche _déclarative_, où nous définissons « quel » état souhaité de notre serveur doit se trouver à l'intérieur des fichiers de configuration, et Ansible est responsable d'amener le serveur à cet état souhaité.

L'approche déclarative est préférable parce que l'intention du fichier de configuration est immédiatement communiquée, ce qui signifie qu'il est plus facile à comprendre et à maintenir. De plus, il incombe à Ansible, et non plus à l'administrateur, de traiter les cas marginaux, ce qui nous épargne beaucoup de travail.

Maintenant que vous avez configuré le nœud de contrôle Ansible pour communiquer avec les nœuds gérés, nous vous présenterons, dans une prochaine étape, les _playbooks_ Ansible, qui vous permettent de spécifier des tâches de manière déclarative.

Étape 2 - Obtenir les noms d'hôte des nœuds gérés à l'aide de playbooks Ansible

Au cours de cette étape, nous reproduirons ce qui a été fait à l'étape 1 en imprimant les noms d'hôte des nœuds gérés, mais au lieu d'exécuter des tâches ad hoc, nous définirons chaque tâche de manière déclarative comme un playbook ansible et nous l'exécuterons. L'objectif de cette étape est de démontrer comment fonctionnent les playbooks Ansible ; nous réaliserons des tâches beaucoup plus substantielles avec des playbooks dans des étapes ultérieures.

Dans le répertoire de votre projet, créez un nouveau fichier nommé playbook.yaml en utilisant votre éditeur :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

À l'intérieur de playbook.yaml, ajoutez les lignes suivantes :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 tasks:

 - name: "Retrieve hostname"

 command: hostname

 register: output

 - name: "Print hostname"

 debug: var=output.stdout_lines

				
			

Fermez et enregistrez le fichier playbook.yaml en appuyant sur CTRL+X, puis sur Y.

Le playbook contient une liste de _plays_ ; chaque play contient une liste de tâches qui doivent être exécutées sur tous les hôtes correspondant au modèle d'hôte spécifié par la clé d'hôtes. Dans ce playbook, nous avons un play qui contient deux tâches. La première tâche exécute la commande hostname en utilisant le module de commande et enregistre la sortie dans une variable nommée output . Dans la deuxième tâche, nous utilisons le module debug pour imprimer la propriété stdout_lines de la variable output.

Nous pouvons maintenant exécuter ce playbook en utilisant la commande ansible-playbook :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Vous trouverez la sortie suivante, ce qui signifie que votre playbook fonctionne correctement :

				
					
[secondary_label Output]

PLAY [etcd] ***********************************************************************************************************************



TASK [Gathering Facts] ************************************************************************************************************

ok: [etcd2]

ok: [etcd3]

ok: [etcd1]



TASK [Retrieve hostname] **********************************************************************************************************

changed: [etcd2]

changed: [etcd3]

changed: [etcd1]



TASK [Print hostname] *************************************************************************************************************

ok: [etcd1] => {

 "output.stdout_lines": [

 "etcd1"

 ]

}

ok: [etcd2] => {

 "output.stdout_lines": [

 "etcd2"

 ]

}

ok: [etcd3] => {

 "output.stdout_lines": [

 "etcd3"

 ]

}



PLAY RECAP ************************************************************************************************************************

etcd1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

etcd2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

etcd3 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

				
			

Note : ansible-playbook utilise parfois cowsay comme moyen ludique d'imprimer les titres. Si vous trouvez beaucoup de vaches en ASCII imprimées sur votre terminal, vous savez maintenant pourquoi. Pour désactiver cette fonctionnalité, réglez la variable d'environnement ANSIBLE_NOCOWS sur 1 avant de lancer ansible-playbook en exécutant export ANSIBLE_NOCOWS=1 dans votre shell.

Dans cette étape, nous sommes passés de l'exécution de tâches ad hoc impératives à l'exécution de playbooks déclaratifs. Dans la prochaine étape, nous remplacerons ces deux tâches de démonstration par des tâches qui mettront en place notre cluster etcd.

Étape 3 - Installation d'etcd sur les nœuds gérés

Dans cette étape, nous vous montrerons les commandes pour installer etcd manuellement et nous vous montrerons comment traduire ces mêmes commandes en tâches à l'intérieur de notre playbook Ansible.

etcd et son client etcdctl sont disponibles sous forme de binaires, que nous allons télécharger, extraire et déplacer dans un répertoire qui fait partie de la variable d'environnement PATH. Lorsqu'ils sont configurés manuellement, voici les étapes que nous suivons pour chacun des nœuds gérés :

				
					
[environment second]

mkdir -p /opt/etcd/bin

cd /opt/etcd/bin

wget -qO- https://storage.googleapis.com/etcd/v<^>3.3.13<^>/etcd-v<^>3.3.13<^>-linux-amd64.tar.gz | tar --extract --gzip --strip-components=1

echo 'export PATH="$PATH:/opt/etcd/bin"' >> ~/.profile

echo 'export ETCDCTL_API=3" >> ~/.profile

				
			

Les quatre premières commandes permettent de télécharger et d'extraire les binaires dans le répertoire /opt/etcd/bin/. Par défaut, le client etcdctl utilisera l'API v2 pour communiquer avec le serveur etcd. Puisque nous utilisons etcd v3.x, la dernière commande fixe la variable d'environnement ETCDCTL_API à 3 .

Note : Ici, nous utilisons etcd v3.3.13 construit pour une machine avec des processeurs qui utilisent le jeu d'instructions AMD64. Vous pouvez trouver des binaires pour d'autres systèmes et d'autres versions sur la page officielle des versions de GitHub.

Pour reproduire les mêmes étapes dans un format standardisé, nous pouvons ajouter des tâches à notre playbook. Ouvrez le fichier playbook.yaml dans votre éditeur :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Remplacez la totalité du fichier playbook.yaml par le contenu suivant :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 become: True

 tasks:

 - name: "Create directory for etcd binaries"

 file:

 path: /opt/etcd/bin

 state: directory

 owner: root

 group: root

 mode: 0700

 - name: "Download the tarball into the /tmp directory"

 get_url:

 url: https://storage.googleapis.com/etcd/v<^>3.3.13<^>/etcd-v<^>3.3.13<^>-linux-amd64.tar.gz

 dest: /tmp/etcd.tar.gz

 owner: root

 group: root

 mode: 0600

 force: True

 - name: "Extract the contents of the tarball"

 unarchive:

 src: /tmp/etcd.tar.gz

 dest: /opt/etcd/bin/

 owner: root

 group: root

 mode: 0600

 extra_opts:

 - --strip-components=1

 decrypt: True

 remote_src: True

 - name: "Set permissions for etcd"

 file:

 path: /opt/etcd/bin/etcd

 state: file

 owner: root

 group: root

 mode: 0700

 - name: "Set permissions for etcdctl"

 file:

 path: /opt/etcd/bin/etcdctl

 state: file

 owner: root

 group: root

 mode: 0700

 - name: "Add /opt/etcd/bin/ to the $PATH environment variable"

 lineinfile:

 path: /etc/profile

 line: export PATH="$PATH:/opt/etcd/bin"

 state: present

 create: True

 insertafter: EOF

 - name: "Set the ETCDCTL_API environment variable to 3"

 lineinfile:

 path: /etc/profile

 line: export ETCDCTL_API=3

 state: present

 create: True

 insertafter: EOF

				
			

Chaque tâche utilise un module ; pour cet ensemble de tâches, nous utilisons les modules suivants :

  • file : pour créer le répertoire /opt/etcd/bin, et pour définir plus tard les permissions des fichiers pour les binaires etcd et etcdctl.
  • get_url : pour télécharger le tarball gzippé sur les nœuds gérés.
  • unarchive : pour extraire et déballer les binaires etcd et etcdctl du tarball gzippé.
  • lineinfile : pour ajouter une entrée dans le fichier .profile.

Pour appliquer ces changements, fermez et enregistrez le fichier playbook.yaml en appuyant sur CTRL+X suivi de Y . Ensuite, sur le terminal, exécutez à nouveau la même commande ansible-playbook :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

La section PLAY RECAP de la sortie n'affichera que ok et changed :

				
					
[secondary_label Output]

...

PLAY RECAP ************************************************************************************************************************

etcd1 : ok=8 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

etcd2 : ok=8 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

etcd3 : ok=8 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

				
			

Pour confirmer une installation correcte d'etcd, il faut lancer manuellement SSH dans l'un des nœuds gérés et exécuter etcd et etcdctl :

				
					
ssh root@<^>etcd1_public_ip<^>

				
			

<^>etcd1_public_ip<^> sont les adresses IP publiques du serveur nommé etcd1 . Une fois que vous avez obtenu un accès SSH, lancez etcd --version pour imprimer la version d'etcd installée :

				
					
[environment second]

etcd --version

				
			

Vous trouverez une sortie similaire à ce qui est montré dans la suite, ce qui signifie que le binaire etcd est installé avec succès :

				
					
[environment second]

[secondary_label Output]

etcd Version: &lt;^&gt;3.3.13&lt;^&gt;

Git SHA: 98d3084

Go Version: go1.10.8

Go OS/Arch: linux/amd64

				
			

Pour confirmer qu'etcdctl est installé avec succès, lancez la version d'etcdctl :

				
					
[environment second]

etcdctl version

				
			

Vous recevrez un résultat similaire à celui qui suit :

				
					
[environment second]

[secondary_label Output]

etcdctl version: &lt;^&gt;3.3.13&lt;^&gt;

API version: 3.3

				
			

Notez que la sortie indique API version: 3.3, ce qui confirme également que notre variable d'environnement ETCDCTL_API a été définie correctement.

Sortez du serveur etcd1 pour revenir à votre environnement local.

Nous avons maintenant installé avec succès etcd et etcdctl sur tous nos nœuds gérés. Dans la prochaine étape, nous ajouterons d'autres tâches à notre play pour faire fonctionner etcd comme un service de fond.

Etape 4 - Création d'un fichier d'unité pour etcd

La façon la plus rapide d'exécuter etcd avec Ansible peut être d'utiliser le module command pour exécuter /opt/etcd/bin/etcd . Cependant, cela ne fonctionnera pas car cela fera fonctionner etcd comme un processus de premier plan. L'utilisation du module command entraînera le blocage d'Ansible en attendant le retour de la commande etcd, ce qu'il ne fera jamais. Dans cette étape, nous allons donc mettre à jour notre playbook afin d'utiliser notre binaire etcd en tant que _service_ de fond à la place.

Ubuntu 18.04 utilise _systemd_ comme _système d'initialisation_, ce qui signifie que nous pouvons créer de nouveaux services en écrivant des _fichiers unitaires_ et en les plaçant dans le répertoire /etc/systemd/system/.

Tout d'abord, dans le répertoire de notre projet, créez un nouveau répertoire nommé files/ :

				
					
mkdir files

				
			

Ensuite, à l'aide de votre éditeur, créez un nouveau fichier nommé etcd.service dans ce répertoire :

				
					
nano files/etcd.service

				
			

Ensuite, copiez le bloc de code suivant dans le fichier files/etcd.service :

				
					
[label ~/playground/etcd-ansible/files/etcd.service]

[Unit]

Description=etcd distributed reliable key-value store



[Service]

Type=notify

ExecStart=/opt/etcd/bin/etcd

Restart=always

				
			

Ce fichier d'unité définit un service qui exécute l'exécutable dans /opt/etcd/bin/etcd , notifie à systemd la fin de l'initialisation, et redémarre toujours s'il se termine.

Note : Si vous souhaitez en savoir plus sur les fichiers systemd et les fichiers d'unité, ou si vous voulez adapter le fichier d'unité à vos besoins, lisez le guide Comprendre les unités et les fichiers d'unité systemd.

Fermez et enregistrez le fichier files/etcd.service en appuyant sur CTRL+X suivi de Y .

Ensuite, nous devons ajouter une tâche à l'intérieur de notre playbook qui copiera le fichier local files/etcd.service dans le répertoire /etc/systemd/system/etcd.service pour chaque noeud géré. Nous pouvons le faire en utilisant le module copy.

Ouvrez votre playbook :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ajoutez la tâche surlignée suivante à la fin de nos tâches existantes :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 become: True

 tasks:

 ...

 - name: "Set the ETCDCTL_API environment variable to 3"

 lineinfile:

 path: /etc/profile

 line: export ETCDCTL_API=3

 state: present

 create: True

 insertafter: EOF

 &lt;^&gt;- name: "Create a etcd service"&lt;^&gt;

 &lt;^&gt;copy:&lt;^&gt;

 &lt;^&gt;src: files/etcd.service&lt;^&gt;

 &lt;^&gt;remote_src: False&lt;^&gt;

 &lt;^&gt;dest: /etc/systemd/system/etcd.service&lt;^&gt;

 &lt;^&gt;owner: root&lt;^&gt;

 &lt;^&gt;group: root&lt;^&gt;

 &lt;^&gt;mode: 0644&lt;^&gt;

				
			

En copiant le fichier unitaire dans le fichier /etc/systemd/system/etcd.service , un service est maintenant défini.

Sauvegardez et quittez le playbook.

Exécutez à nouveau la même commande ansible-playbook pour appliquer les nouveaux changements :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Pour confirmer que les changements ont bien été appliqués, il faut d'abord faire entrer les SSH dans l'un des nœuds gérés :

				
					
ssh &lt;^&gt;root&lt;^&gt;@&lt;^&gt;etcd1_public_ip&lt;^&gt;

				
			

Ensuite, lancez systemctl status etcd pour interroger systemd sur l'état du service etcd :

				
					
[environment second]

systemctl status etcd

				
			

Vous trouverez la sortie suivante, qui indique que le service est chargé :

				
					
[secondary_label Output]

[environment second]

● etcd.service - etcd distributed reliable key-value store

 Loaded: loaded (/etc/systemd/system/etcd.service; static; vendor preset: enabled)

 Active: inactive (dead)

...

				
			

Note : La dernière ligne ( Active : inactive (dead)) de la sortie indique que le service est inactif, ce qui signifie qu'il ne sera pas exécuté automatiquement au démarrage du système. Cela est prévu et n'est pas une erreur.

Appuyez sur q pour revenir au shell, puis exécutez exit pour sortir du nœud géré et revenir à votre shell local :

				
					
[environment second]

exit

				
			

Dans cette étape, nous avons mis à jour notre playbook pour faire fonctionner le binaire etcd comme un service systemd. Dans la prochaine étape, nous continuerons à mettre en place etcd en lui fournissant un espace pour stocker ses données.

Étape 5 - Configurer le répertoire de données

etcd est un magasin de données à valeur clé, ce qui signifie que nous devons lui fournir de l'espace pour stocker ses données. Dans cette étape, nous allons mettre à jour notre playbook afin de définir un répertoire de données dédié à l'usage d'etcd.

Ouvrez votre playbook :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ajoutez la tâche suivante à la fin de la liste des tâches :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 become: True

 tasks:

 ...

 - name: "Create a etcd service"

 copy:

 src: files/etcd.service

 remote_src: False

 dest: /etc/systemd/system/etcd.service

 owner: root

 group: root

 mode: 0644

 &lt;^&gt;- name: "Create a data directory"&lt;^&gt;

 &lt;^&gt;file:&lt;^&gt;

 &lt;^&gt;path: /var/lib/etcd/{{ inventory_hostname }}.etcd&lt;^&gt;

 &lt;^&gt;state: directory&lt;^&gt;

 &lt;^&gt;owner: root&lt;^&gt;

 &lt;^&gt;group: root&lt;^&gt;

 &lt;^&gt;mode: 0755&lt;^&gt;

				
			

Ici, nous utilisons /var/lib/etcd/<^>hostname<^>.etcd comme répertoire de données, où <^>hostname<^> est le nom d'hôte du nœud géré actuel. inventory_hostname est une variable qui représente le nom d'hôte du nœud géré actuel ; sa valeur est automatiquement alimentée par Ansible. La syntaxe des accolades (c'est-à-dire {{ inventory_hostname }} ) est utilisée pour la _substitution de variables_, supportée par le moteur de modèle Jinja2, qui est le moteur de modèle par défaut pour Ansible.

Fermez l'éditeur de texte et enregistrez le fichier.

Ensuite, nous devons demander à etcd d'utiliser ce répertoire de données. Nous le faisons en passant le point terminal data-dir à etcd. Pour définir les points terminaux etcd, nous pouvons utiliser une combinaison de variables d'environnement, de drapeaux de ligne de commande et de fichiers de configuration. Pour ce tutoriel, nous utiliserons un fichier de configuration, car il est beaucoup plus judicieux d'isoler toutes les configurations dans un fichier, plutôt que d'avoir la configuration éparpillée dans notre playbook.

Dans le répertoire de votre projet, créez un nouveau répertoire nommé templates/ :

				
					
mkdir templates

				
			

Ensuite, à l'aide de votre éditeur, créez un nouveau fichier nommé etcd.conf.yaml.j2 dans le répertoire :

				
					
nano templates/etcd.conf.yaml.j2

				
			

Ensuite, copiez la ligne suivante et collez-la dans le fichier :

				
					
[label ~/playground/etcd-ansible/templates/etcd.conf.yaml.j2]

data-dir: /var/lib/etcd/{{ inventory_hostname }}.etcd

				
			

Ce fichier utilise la même syntaxe de substitution de variables Jinja2 que notre playbook. Pour substituer les variables et télécharger le résultat sur chaque hôte géré, nous pouvons utiliser le module template. Il fonctionne de la même manière que la copie, sauf qu'il effectue une substitution variable avant le téléchargement.

Sortez d'etcd.conf.yaml.j2 , puis ouvrez votre playbook :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ajoutez les tâches suivantes à la liste des tâches pour créer un répertoire et y télécharger le fichier de configuration modèle :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 become: True

 tasks:

 ...

 - name: "Create a data directory"

 file:

 ...

 mode: 0755

 &lt;^&gt;- name: "Create directory for etcd configuration"&lt;^&gt;

 &lt;^&gt;file:&lt;^&gt;

 &lt;^&gt;path: /etc/etcd&lt;^&gt;

 &lt;^&gt;state: directory&lt;^&gt;

 &lt;^&gt;owner: root&lt;^&gt;

 &lt;^&gt;group: root&lt;^&gt;

 &lt;^&gt;mode: 0755&lt;^&gt;

 &lt;^&gt;- name: "Create configuration file for etcd"&lt;^&gt;

 &lt;^&gt;template:&lt;^&gt;

 &lt;^&gt;src: templates/etcd.conf.yaml.j2&lt;^&gt;

 &lt;^&gt;dest: /etc/etcd/etcd.conf.yaml&lt;^&gt;

 &lt;^&gt;owner: root&lt;^&gt;

 &lt;^&gt;group: root&lt;^&gt;

 &lt;^&gt;mode: 0600&lt;^&gt;

				
			

Enregistrez et fermez le fichier.

Comme nous avons effectué ce changement, nous devons mettre à jour le fichier d'unité de notre service pour lui transmettre l'emplacement de notre fichier de configuration (c'est-à-dire /etc/etcd/etcd.conf.yaml ).

Ouvrez le fichier de service etcd sur votre machine locale :

				
					
nano files/etcd.service

				
			

Mettez à jour le fichier files/etcd.service en ajoutant l'indicateur --config-file mis en évidence dans ce qui suit :

				
					
[label ~/playground/etcd-ansible/files/etcd.service]

[Unit]

Description=etcd distributed reliable key-value store



[Service]

Type=notify

ExecStart=/opt/etcd/bin/etcd &lt;^&gt;--config-file /etc/etcd/etcd.conf.yaml&lt;^&gt;

Restart=always

				
			

Enregistrez et fermez le fichier.

Dans cette étape, nous avons utilisé notre playbook pour fournir un répertoire de données à etcd afin de stocker ses données. Dans l'étape suivante, nous ajouterons quelques tâches supplémentaires pour redémarrer le service etcd et le lancer au démarrage.

Étape 6 - Activation et démarrage du service etcd

Chaque fois que nous apportons des modifications au fichier d'unité d'un service, nous devons redémarrer le service pour qu'elles prennent effet. Nous pouvons le faire en exécutant la commande systemctl restart etcd. En outre, pour que le service etcd démarre automatiquement au démarrage du système, nous devons exécuter systemctl enable etcd . Dans cette étape, nous allons exécuter ces deux commandes en utilisant le playbook.

Pour exécuter les commandes, nous pouvons utiliser le module de commande :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ajoutez les tâches suivantes à la fin de la liste des tâches :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 become: True

 tasks:

 ...

 - name: "Create configuration file for etcd"

 template:

 ...

 mode: 0600

 &lt;^&gt;- name: "Enable the etcd service"&lt;^&gt;

 &lt;^&gt;command: systemctl enable etcd&lt;^&gt;

 &lt;^&gt;- name: "Start the etcd service"&lt;^&gt;

 &lt;^&gt;command: systemctl restart etcd&lt;^&gt;

				
			

Enregistrez et fermez le fichier.

Exécutez ansible-playbook -i hosts playbook.yaml une fois de plus :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Pour vérifier que le service etcd est maintenant redémarré et activé, SSH dans l'un des nœuds gérés :

				
					
ssh &lt;^&gt;root&lt;^&gt;@&lt;^&gt;etcd1_public_ip&lt;^&gt;

				
			

Ensuite, lancez systemctl status etcd pour vérifier l'état du service etcd :

				
					
[environment second]

systemctl status etcd

				
			

Vous trouverez enabled and active (en cours) comme mis en surbrillance ci-dessous ; cela signifie que les modifications que nous avons apportées à notre playbook ont pris effet :

				
					
[environment second]

[secondary_label Output]

● etcd.service - etcd distributed reliable key-value store

 Loaded: loaded (/etc/systemd/system/etcd.service; static; vendor preset: &lt;^&gt;enabled&lt;^&gt;)

 Active: &lt;^&gt;active (running)&lt;^&gt;

 Main PID: 19085 (etcd)

 Tasks: 11 (limit: 2362)

				
			

Dans cette étape, nous avons utilisé le module command pour exécuter des commandes systemctl qui redémarrent et activent le service etcd sur nos nœuds gérés. Maintenant que nous avons mis en place une installation etcd, nous allons, dans la prochaine étape, tester sa fonctionnalité en effectuant quelques opérations de base de création, lecture, mise à jour et suppression (CRUD).

Étape 7 - Tester etcd

Bien que nous disposions d'une installation etcd en état de marche, elle n'est pas sûre et n'est pas encore prête à être utilisée pour la production. Mais avant de sécuriser notre installation etcd dans les étapes ultérieures, il faut d'abord comprendre ce qu'etcd peut faire en termes de fonctionnalités. Dans cette étape, nous allons envoyer manuellement des demandes à etcd pour ajouter, récupérer, mettre à jour et supprimer des données.

Par défaut, etcd expose une API qui écoute sur le port 2379 pour la communication avec les clients. Cela signifie que nous pouvons envoyer des requêtes API brutes à etcd en utilisant un client HTTP. Cependant, il est plus rapide d'utiliser le client officiel etcd (etcdctl), qui permet de créer/mettre à jour, de récupérer et de supprimer des paires clé-valeur en utilisant respectivement les sous-commandes put , get et del.

Assurez-vous que vous êtes toujours à l'intérieur du nœud géré par etcd1, et exécutez les commandes etcdctl suivantes pour confirmer que votre installation etcd fonctionne.

D'abord, créez une nouvelle entrée en utilisant la sous-commande put.

La sous-commande put a la syntaxe suivante :

				
					
etcdctl put &lt;^&gt;key&lt;^&gt; &lt;^&gt;value&lt;^&gt;

				
			

Sur etcd1 , lancez la commande suivante :

				
					
[environment second]

etcdctl put foo "bar"

				
			

La commande que nous venons d'exécuter demande à etcd d'écrire la valeur « bar » dans la clé foo du magasin.

Vous trouverez alors OK imprimé dans la sortie, ce qui indique que les données ont persisté :

				
					
[environment second]

[secondary_label Output]

OK

				
			

Nous pouvons ensuite récupérer cette entrée en utilisant la sous-commande get, qui a la syntaxe etcdctl get <^>key<^> :

				
					
[environment second]

etcdctl get foo

				
			

Vous trouverez ce résultat, qui indique la clé sur la première ligne et la valeur que vous avez insérée plus tôt sur la deuxième ligne :

				
					
[environment second]

[secondary_label Output]

foo

bar

				
			

Nous pouvons supprimer l'entrée en utilisant la sous-commande del, qui a la syntaxe etcdctl del <^>key<^> :

				
					
[environment second]

etcdctl del foo

				
			

Vous trouverez la sortie suivante, qui indique le nombre d'entrées supprimées :

				
					
[environment second]

[secondary_label Output]

1

				
			

Maintenant, lançons à nouveau la sous-commande get pour tenter de récupérer une paire clé-valeur supprimée :

				
					
[environment second]

etcdctl get foo

				
			

Vous ne recevrez pas de sortie, ce qui signifie qu'etcdctl n'est pas en mesure de récupérer la paire clé-valeur. Cela confirme qu'une fois l'entrée supprimée, elle ne peut plus être récupérée.

Maintenant que vous avez testé les opérations de base d'etcd et d'etcdctl, sortons de notre nœud géré et retournons à votre environnement local :

				
					
[environment second]

exit

				
			

Dans cette étape, nous avons utilisé le client etcdctl pour envoyer des demandes à etcd. À ce stade, nous gérons trois instances distinctes d'etcd, chacune agissant indépendamment des autres. Cependant, etcd est conçu comme un magasin de valeurs clés distribué, ce qui signifie que plusieurs instances d'etcd peuvent se regrouper pour former un seul _groupe_ ; chaque instance devient alors un _membre_ du groupe. Après avoir formé un cluster, vous pourrez récupérer une paire clé-valeur insérée à partir d'un autre membre du cluster. Dans la prochaine étape, nous utiliserons notre playbook pour transformer nos trois clusters à un seul nœud en un seul cluster à trois nœuds.

Étape 8 - Formation d'un cluster à l'aide de la découverte statique

Pour créer un cluster à 3 nœuds au lieu de trois clusters à 1 nœud, nous devons configurer ces installations etcd pour qu'elles communiquent entre elles. Cela signifie que chacun doit connaître les adresses IP des autres. Ce processus est appelé _découverte_. La découverte peut se faire soit par _configuration statique_, soit par _découverte dynamique de services_. Dans cette étape, nous discuterons de la différence entre les deux, et nous mettrons à jour notre playbook pour créer un cluster etcd en utilisant la découverte statique.

La découverte par configuration statique est la méthode qui nécessite le moins de configuration ; c'est là que les points terminaux de chaque membre sont passés dans la commande etcd avant qu'elle ne soit exécutée. Pour utiliser la configuration statique, les conditions suivantes doivent être remplies avant l'initialisation du cluster :

  • le nombre de membres est connu
  • les points terminaux de chaque membre sont connus
  • les adresses IP de tous les points terminaux sont statiques

Si ces conditions ne peuvent être remplies, vous pouvez alors utiliser un service de découverte dynamique. Avec le service de découverte dynamique, toutes les instances s'enregistreraient auprès du service de découverte, qui permet à chaque membre de récupérer des informations sur la localisation des autres membres.

Comme nous savons que nous voulons un cluster à 3 nœuds etcd, et que tous nos serveurs ont des adresses IP statiques, nous utiliserons la découverte statique. Pour lancer notre cluster en utilisant la découverte statique, nous devons ajouter plusieurs points terminaux à notre fichier de configuration. Utilisez un éditeur pour ouvrir le fichier modèle templates/etcd.conf.yaml.j2 :

				
					
nano templates/etcd.conf.yaml.j2

				
			

Ajoutez les lignes en surbrillance suivantes :

				
					
[label ~/playground/etcd-ansible/templates/etcd.conf.yaml.j2]

data-dir: /var/lib/etcd/{{ inventory_hostname }}.etcd

&lt;^&gt;name: {{ inventory_hostname }}&lt;^&gt;

&lt;^&gt;initial-advertise-peer-urls: http://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2380&lt;^&gt;

&lt;^&gt;listen-peer-urls: http://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2380,http://127.0.0.1:2380&lt;^&gt;

&lt;^&gt;advertise-client-urls: http://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2379&lt;^&gt;

&lt;^&gt;listen-client-urls: http://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2379,http://127.0.0.1:2379&lt;^&gt;

&lt;^&gt;initial-cluster-state: new&lt;^&gt;

&lt;^&gt;initial-cluster: {% for host in groups['etcd'] %}{{ hostvars[host]['ansible_facts']['hostname'] }}=http://{{ hostvars[host]['ansible_facts']['eth1']['ipv4']['address'] }}:2380{% if not loop.last %},{% endif %}{% endfor %}&lt;^&gt;

				
			

Fermez et enregistrez le fichier templates/etcd.conf.yaml.j2 en appuyant sur CTRL+X suivi de Y .

Voici une brève explication de chaque point terminal :

  • nom – un nom lisible pour le membre. Par défaut, etcd utilise un identifiant unique, généré de manière aléatoire, pour identifier chaque membre ; cependant, un nom lisible par l'utilisateur nous permet de le référencer plus facilement à l'intérieur des fichiers de configuration et sur la ligne de commande. Ici, nous utiliserons les noms d'hôtes comme noms de membres (c'est-à-dire, etcd1 , etcd2 , et etcd3 ).
  • initial-advertise-peer-urls – une liste d'adresses IP/combinaisons de ports que les autres membres peuvent utiliser pour communiquer avec ce membre. En plus du port API (2379), etcd expose également le port 2380 pour la communication entre les membres d'etcd, qui leur permet de s'envoyer des messages et d'échanger des données. Notez que ces URL doivent être accessibles par ses pairs (et ne pas être une adresse IP locale).
  • listen-peer-urls – une liste d'adresses IP/combinaisons de ports où le membre actuel écoutera les communications des autres membres. Cela doit inclure toutes les URL du drapeau -initial-advertise-peer-urls, mais aussi les URL locales comme 127.0.0.1:2380 . L'adresse IP de destination/le port des messages de pairs entrants doit correspondre à l'une des URL énumérées ici.
  • advertise-client-urls – une liste des combinaisons Adresse IP/port que les clients doivent utiliser pour communiquer avec ce membre. Ces URL doivent être accessibles par le client (et ne pas être une adresse locale). Si le client accède au cluster via l'Internet public, il doit s'agir d'une adresse IP publique.
  • listen-client-urls – une liste des combinaisons Adresses IP/ports où le membre actuel écoutera les communications des clients. Cela doit inclure toutes les URL du drapeau --advertise-client-urls, mais aussi les URL locales comme 127.0.0.1:2379 L'adresse IP de destination/le port des messages clients entrants doit correspondre à l'une des URL énumérées ici.
  • groupe initial – une liste de points terminaux pour chaque membre du groupe. Chaque point terminal doit correspondre aux URL initial-advertise-peer-urls du membre correspondant.
  • initial-cluster-state soi new ou existing.

Pour assurer la cohérence, etcd ne peut prendre de décisions que lorsque la majorité des nœuds marche bien. C'est ce qu'on appelle établir le _quorum_. En d'autres termes, dans un groupe de trois membres, le quorum est atteint si deux ou plusieurs des membres fonctionnent bien.

Si le paramètre initial-cluster-state est réglé sur new,etcd saura qu'il s'agit d'un nouveau cluster en cours de démarrage et permettra aux membres de commencer en parallèle, sans attendre que le quorum soit atteint. Plus concrètement, après l'entrée en fonction du premier membre, le quorum ne sera pas atteint car un tiers (33,33%) est inférieur ou égal à 50%. Normalement, etcd s'arrêtera et refusera d'engager d'autres actions et le cluster ne sera jamais formé. Cependant, comme initial-cluster-state a été fixé comme new, il ignorera le manque initial de quorum.

S'il est fixé comme existing, le membre essaiera de rejoindre un groupe existant, et s'attend à ce que le quorum soit déjà établi.

Note : Vous pouvez trouver plus de détails sur tous les drapeaux de configuration pris en charge dans la section Configuration de la documentation d'etcd.

Dans le fichier modèle mis à jour templates/etcd.conf.yaml.j2, on trouve quelques exemples de hostvars .  Lorsque Ansible s'exécute , il recueillera des variables auprès d'une variété sources. Nous avons déjà utilisé la variable inventory_hostname auparavant, mais il y en a beaucoup d'autres disponibles. Ces variables sont disponibles sous hostvars [inventory_hostname]['ansible_facts'] . Ici, nous extrayons les adresses IP privées de chaque nœud et les utilisons pour construire la valeur de notre point terminal.

Note : Comme nous avons activé l'option Private Networking lors de la création de nos serveurs, chaque serveur serait associé à trois adresses IP :

  • Une adresse IP de_bouclage_ – une adresse qui n'est valable qu'à l'intérieur de la même machine. Elle est utilisée pour que la machine se réfère à elle-même, par exemple, 127.0.0.1
  • Une adresse IP _publique_ – une adresse qui peut être acheminée sur l'Internet public, par exemple, 178.128.169.51
  • Une adresse IP _privée_ – une adresse qui n'est routable qu'au sein du réseau privé ; dans le cas de cloud servers, il y a un réseau privé au sein de chaque centre de données, par exemple, 10.131.82.225

Chacune de ces adresses IP est associée à une interface réseau différente : l'adresse de bouclage est associée à l'interface lo, l'adresse IP publique est associée à l'interface eth0, et l'adresse IP privée à l'interface eth1. Nous utilisons l'interface eth1 pour que tout le trafic reste dans le réseau privé, sans jamais atteindre Internet.

La compréhension des interfaces de réseau n'est pas nécessaire pour cet article, mais si vous souhaitez en savoir plus, Une introduction à la terminologie, aux interfaces et aux protocoles de réseau est un excellent point de départ.

La syntaxe {% %} Jinja2 définit la structure de la boucle for qui itére à travers chaque nœud du groupe etcd pour construire la chaîne du cluster initial dans un format requis par etcd.

Pour former le nouveau cluster de trois membres, vous devez d'abord arrêter le service etcd et effacer le répertoire de données avant de lancer le cluster. Pour ce faire, utilisez un éditeur afin d'ouvrir le fichier playbook.yaml sur votre machine locale :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ensuite, avant la tâche « Create a data directory », ajoutez une tâche pour arrêter le service etcd :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 become: True

 tasks:

 ...

 group: root

 mode: 0644

 &lt;^&gt;- name: "Stop the etcd service"&lt;^&gt;

 &lt;^&gt;command: systemctl stop etcd&lt;^&gt;

 - name: "Create a data directory"

 file:

 ...

				
			

Ensuite, mettez à jour la tâche « Create a data directory » pour d'abord supprimer le répertoire de données et le recréer :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 become: True

 tasks:

 ...

 - name: "Stop the etcd service"

 command: systemctl stop etcd

 - name: "Create a data directory"

 file:

 path: /var/lib/etcd/{{ inventory_hostname }}.etcd

 state: &lt;^&gt;"{{ item }}"&lt;^&gt;

 owner: root

 group: root

 mode: 0755

 &lt;^&gt;with_items:&lt;^&gt;

 &lt;^&gt;- absent&lt;^&gt;

 &lt;^&gt;- directory&lt;^&gt;

 - name: "Create directory for etcd configuration"

 file:

 ...

				
			

La propriété with_items définit une liste de chaînes de caractères sur lesquelles cette tâche va itérer. Cela équivaut à répéter deux fois la même tâche, mais avec des valeurs différentes pour la propriété state. Dans ce cas, nous répétons la liste avec les éléments absents et le répertoire, ce qui garantit que le répertoire de données est d'abord supprimé et ensuite recréé.

Fermez et enregistrez le fichier playbook.yaml en appuyant sur CTRL+X, puis sur Y. Ensuite, lancez à nouveau ansible-playbook. Ansible va maintenant créer un cluster unique de 3 membres etcd :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Vous pouvez vérifier cela en entrant en langage SSH dans n'importe quel nœud membre etcd :

				
					
ssh &lt;^&gt;root&lt;^&gt;@&lt;^&gt;etcd1_public_ip&lt;^&gt;

				
			

Ensuite, lancez l'application etcdctl endpoint health --cluster :

				
					
[environment second]

etcdctl endpoint health --cluster

				
			

Le statut de chaque membre du groupe sera ainsi répertorié :

				
					
[environment second]

[secondary_label Output]

http://&lt;^&gt;etcd2_private_ip&lt;^&gt;:2379 is healthy: successfully committed proposal: took = 2.517267ms

http://&lt;^&gt;etcd1_private_ip&lt;^&gt;:2379 is healthy: successfully committed proposal: took = 2.153612ms

http://&lt;^&gt;etcd3_private_ip&lt;^&gt;:2379 is healthy: successfully committed proposal: took = 2.639277ms

				
			

Nous avons maintenant réussi à créer un cluster de 3 nœuds etcd. Nous pouvons confirmer cela en ajoutant une entrée à etcd sur un nœud membre, et en la récupérant sur un autre nœud membre. Sur l'un des nœuds membres, lancez etcdctl put :

				
					
[environment second]

etcdctl put foo "bar"

				
			

Ensuite, utilisez un nouveau terminal pour SSH dans un autre nœud membre :

				
					
ssh &lt;^&gt;root&lt;^&gt;@&lt;^&gt;etcd2_public_ip&lt;^&gt;

				
			

Ensuite, essayez de retrouver la même entrée en utilisant la clé :

				
					
[environment third]

etcdctl get foo

				
			

Vous pourrez récupérer l'entrée, qui prouve que le cluster fonctionne :

				
					
[environment third]

[secondary_label Output]

foo

bar

				
			

Enfin, sortez de chacun des nœuds gérés et revenez à votre machine locale :

				
					
[environment second]

exit

				
			
				
					
[environment third]

exit

				
			

Dans cette étape, nous avons mis en place un nouveau cluster de 3 nœuds. À l'heure actuelle, la communication entre les membres d'etcd et leurs pairs et clients se fait par HTTP. Cela signifie que la communication n'est pas cryptée et que toute partie qui peut intercepter le trafic peut lire les messages. Ce n'est pas un gros problème si le cluster etcd et les clients sont tous déployés dans un réseau privé ou un _réseau privé virtuel_ (VPN) que vous contrôlez entièrement. Toutefois, si une partie du trafic doit passer par un réseau partagé (privé ou public), vous devez alors vous assurer que ce trafic est crypté. En outre, un mécanisme doit être mis en place pour qu'un client ou un pair puisse vérifier l'authenticité du serveur.

Dans la prochaine étape, nous examinerons comment sécuriser la communication client-serveur et la communication entre pairs en utilisant le TLS.

Étape 9 - Obtenir les adresses IP privées des nœuds gérés

Pour crypter les messages entre les nœuds membres, etcd utilise _Hypertext Transfer Protocol Secure_ , ou _HTTPS_ , qui est une couche au-dessus du protocole _TLS_ , ou _Transport Layer Security_ . TLS utilise un système de clés privées, de certificats et d'entités de confiance appelées _Certificate Authorities_ (Autorités de certification) (CA) pour s'authentifier et s'envoyer des messages cryptés.

Dans ce tutoriel, chaque nœud membre doit générer un certificat pour s'identifier, et faire signer ce certificat par une AC. Nous allons configurer tous les nœuds membres pour qu'ils fassent confiance à cette AC, et donc aussi à tous les certificats qu'elle signe. Cela permet aux nœuds membres de s'authentifier mutuellement.

Le certificat qu'un nœud membre génère doit permettre aux autres nœuds membres de s'identifier. Tous les certificats comportent le _Common Name_ (Nom Commun) (CN) de l'entité à laquelle il est associé. Cela est souvent utilisé comme identité de l'entité. Toutefois, lors de la vérification d'un certificat, les clients peuvent comparer si les informations qu'ils ont recueillies sur l'entité correspondent à celles qui figurent dans le certificat. Par exemple, lorsqu'un client télécharge le certificat TLS avec l'objet CN=foo.bar.com, mais qu'il se connecte en fait au serveur en utilisant une adresse IP (par exemple 167.71.129.110), il y a alors un décalage et le client peut ne pas faire confiance au certificat. En spécifiant un _nom alternatif du sujet_ (SAN) dans le certificat, il informe le vérificateur que les deux noms appartiennent à la même entité.

Comme nos membres etcd s'échangent des informations en utilisant leurs adresses IP privées, lorsque nous définirons nos certificats, nous devrons fournir ces adresses IP privées comme noms alternatifs du sujet.

Pour connaître l'adresse IP privée d'un nœud géré, il faut y entrer en SSH :

				
					
ssh &lt;^&gt;root&lt;^&gt;@&lt;^&gt;etcd1_public_ip&lt;^&gt;

				
			

Exécutez ensuite la commande suivante :

				
					
[environment second]

ip -f inet addr show eth1

				
			

Vous trouverez des résultats similaires aux lignes suivantes :

				
					
[environment second]

[secondary_label Output]

3: eth1: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000

 inet &lt;^&gt;10.131.255.176&lt;^&gt;/16 brd 10.131.255.255 scope global eth1

 valid_lft forever preferred_lft forever

				
			

Dans notre exemple de sortie, <^>10.131.255.176<^> est l'adresse IP privée du nœud géré, et la seule information qui nous intéresse. Pour filtrer tout le reste, à l'exception de la propriété intellectuelle privée, nous pouvons transmettre la sortie de la commande ip à l'utilitaire sed, qui est utilisé pour filtrer et transformer le texte.

				
					
[environment second]

ip -f inet addr show eth1 | sed -En -e 's/.*inet ([0-9.]+).*/\1/p'

				
			

Maintenant, la seule sortie est l'adresse IP privée elle-même :

				
					
[environment second]

[secondary_label Output]

&lt;^&gt;10.131.255.176&lt;^&gt;

				
			

Une fois que vous êtes convaincu que la commande précédente fonctionne, quittez le nœud géré :

				
					
[environment second]

exit

				
			

Pour incorporer les commandes précédentes dans notre playbook, ouvrez d'abord le fichier playbook.yaml :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ensuite, ajoutez une nouvelle pièce avec une seule tâche avant notre play existante :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

...

&lt;^&gt;- hosts: etcd&lt;^&gt;

&lt;^&gt; tasks:&lt;^&gt;

&lt;^&gt; - shell: ip -f inet addr show eth1 | sed -En -e 's/.*inet ([0-9.]+).*/\1/p'&lt;^&gt;

&lt;^&gt; register: privateIP&lt;^&gt;

- hosts: etcd

 tasks:

...

				
			

La tâche utilise le module shell pour exécuter les commandes ip et sed, qui récupère l'adresse IP privée du nœud géré. Elle _enregistre_ ensuite la valeur de retour de la commande shell dans une variable appelée privateIP , que nous utiliserons plus tard.

Dans cette étape, nous avons ajouté une tâche au playbook pour obtenir l'adresse IP privée des nœuds gérés. Dans l'étape suivante, nous allons utiliser ces informations pour générer des certificats pour chaque nœud membre, et faire signer ces certificats par une autorité de certification (CA).

Étape 10 - Générer les clés privées et les RSE des membres d'etcd

Pour qu'un nœud membre puisse recevoir un trafic crypté, l'expéditeur doit utiliser la clé publique du nœud membre pour crypter les données, et le nœud membre doit utiliser sa clé privée pour décrypter le texte chiffré et récupérer les données originales. La clé publique est emballée dans un certificat et signée par une AC pour garantir son authenticité.

Par conséquent, nous devrons générer une clé privée et une demande de signature de certificat (CSR) pour chaque nœud membre etcd. Pour nous faciliter la tâche, nous allons générer toutes les paires de clés et signer tous les certificats localement, sur le nœud de contrôle, puis copier les fichiers pertinents vers les hôtes gérés.

Tout d'abord, créez un répertoire appelé artefacts/, où nous placerons les fichiers (clés et certificats) générés au cours du processus. Ouvrez le fichier playbook.yaml avec un éditeur :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Dans celui-ci, utilisez le module file pour créer le répertoire artefacts/ :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

...

 - shell: ip -f inet addr show eth1 | sed -En -e 's/.*inet ([0-9.]+).*/\1/p'

 register: privateIP

&lt;^&gt;- hosts: localhost&lt;^&gt;

&lt;^&gt; gather_facts: False&lt;^&gt;

&lt;^&gt; become: False&lt;^&gt;

&lt;^&gt; tasks:&lt;^&gt;

&lt;^&gt; - name: "Create ./artifacts directory to house keys and certificates"&lt;^&gt;

&lt;^&gt; file:&lt;^&gt;

&lt;^&gt; path: ./artifacts&lt;^&gt;

&lt;^&gt; state: directory&lt;^&gt;

- hosts: etcd

 tasks:

...

				
			

Ensuite, ajoutez une autre tâche à la fin du play pour générer la clé privée :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

...

- hosts: localhost

 gather_facts: False

 become: False

 tasks:

 ...

&lt;^&gt; - name: "Generate private key for each member"&lt;^&gt;

&lt;^&gt; openssl_privatekey:&lt;^&gt;

&lt;^&gt; path: ./artifacts/{{item}}.key&lt;^&gt;

&lt;^&gt; type: RSA&lt;^&gt;

&lt;^&gt; size: 4096&lt;^&gt;

&lt;^&gt; state: present&lt;^&gt;

&lt;^&gt; force: True&lt;^&gt;

&lt;^&gt; with_items: "{{ groups['etcd'] }}"&lt;^&gt;

- hosts: etcd

 tasks:

...

				
			

La création de clés privées et de CSR peut se faire en utilisant respectivement les modules openssl_privatekey et openssl_csr.

L'attribut force : True garantit que la clé privée est régénérée à chaque fois, même si elle existe déjà.

De même, ajoutez la nouvelle tâche suivante au même play pour générer les RSE pour chaque membre, en utilisant le module openssl_csr :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

...

- hosts: localhost

 gather_facts: False

 become: False

 tasks:

 ...

 - name: "Generate private key for each member"

 openssl_privatekey:

 ...

 with_items: "{{ groups['etcd'] }}"

 &lt;^&gt;- name: "Generate CSR for each member"&lt;^&gt;

 &lt;^&gt;openssl_csr:&lt;^&gt;

 &lt;^&gt;path: ./artifacts/{{item}}.csr&lt;^&gt;

 &lt;^&gt;privatekey_path: ./artifacts/{{item}}.key&lt;^&gt;

 &lt;^&gt;common_name: "{{item}}"&lt;^&gt;

 &lt;^&gt;key_usage:&lt;^&gt;

 &lt;^&gt;- digitalSignature&lt;^&gt;

 &lt;^&gt;extended_key_usage:&lt;^&gt;

 &lt;^&gt;- serverAuth&lt;^&gt;

 &lt;^&gt;subject_alt_name:&lt;^&gt;

 &lt;^&gt;- IP:{{ hostvars[item]['privateIP']['stdout']}}&lt;^&gt;

 &lt;^&gt;- IP:127.0.0.1&lt;^&gt;

 &lt;^&gt;force: True&lt;^&gt;

 &lt;^&gt;with_items: "{{ groups['etcd'] }}"&lt;^&gt;

				
			

Nous précisons que ce certificat peut être impliqué dans un mécanisme de signature numérique à des fins d'authentification du serveur. Ce certificat est associé au nom d'hôte (par exemple, etcd1 ), mais le vérificateur doit également traiter les adresses IP privées et de boucle locale de chaque nœud comme des noms alternatifs.  Notez que nous utilisons la variable privateIP que nous avons enregistrée dans le play précédente.

Fermez et enregistrez le fichier playbook.yaml en appuyant sur CTRL+X suivi de Y. Ensuite, lancez à nouveau ansible-playbook.

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Nous allons maintenant trouver un nouveau répertoire appelé artefacts dans notre répertoire de projets ; utilisez ls pour en énumérer le contenu :

				
					
ls artifacts

				
			

Vous trouverez les clés privées et les RSE de chacun des membres d'etcd :

				
					
[secondary_label Output]

etcd1.csr etcd1.key etcd2.csr etcd2.key etcd3.csr etcd3.key

				
			

Dans cette étape, nous avons utilisé plusieurs modules Ansible pour générer des clés privées et des certificats de clé publique pour chacun des nœuds membres. Dans la prochaine étape, nous examinerons comment signer une demande de signature de certificat (CSR).

Étape 11 - Génération des certificats CA

Au sein d'un cluster etcd, les nœuds membres cryptent les messages en utilisant la clé publique du destinataire. Pour garantir l'authenticité de la clé publique, le destinataire l'emballe dans une demande de signature de certificat (CSR) et la fait signer par une entité de confiance (c'est-à-dire l'AC). Comme nous contrôlons tous les nœuds membres et les AC auxquelles ils font confiance, nous n'avons pas besoin d'utiliser une AC externe et pouvons agir comme notre propre AC. Dans cette étape, nous allons agir comme notre propre AC, ce qui signifie que nous devrons générer une clé privée et un certificat auto-signé pour fonctionner etant qu'AC.

Ouvrez le fichier playbook.yaml avec votre éditeur :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ensuite, comme pour l'étape précédente, ajoutez une tâche au play localhost pour générer une clé privée pour l'AC :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: localhost

 ...

 tasks:

 ...

 - name: "Generate CSR for each member"

 ...

 with_items: "{{ groups['etcd'] }}"

 &lt;^&gt;- name: "Generate private key for CA"&lt;^&gt;

 &lt;^&gt;openssl_privatekey:&lt;^&gt;

 &lt;^&gt;path: ./artifacts/ca.key&lt;^&gt;

 &lt;^&gt;type: RSA&lt;^&gt;

 &lt;^&gt;size: 4096&lt;^&gt;

 &lt;^&gt;state: present&lt;^&gt;

 &lt;^&gt;force: True&lt;^&gt;

- hosts: etcd

 become: True

 tasks:

 - name: "Create directory for etcd binaries"

...

				
			

Ensuite, utilisez le module openssl_csr pour générer un nouveau CSR. Cette étape est similaire à la précédente, mais dans ce CSR, nous ajoutons la contrainte de base et l'extension d'utilisation des clés pour indiquer que ce certificat peut être utilisé comme un certificat CA :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: localhost

 ...

 tasks:

 ...

 - name: "Generate private key for CA"

 openssl_privatekey:

 path: ./artifacts/ca.key

 type: RSA

 size: 4096

 state: present

 force: True

 &lt;^&gt;- name: "Generate CSR for CA"&lt;^&gt;

 &lt;^&gt;openssl_csr:&lt;^&gt;

 &lt;^&gt;path: ./artifacts/ca.csr&lt;^&gt;

 &lt;^&gt;privatekey_path: ./artifacts/ca.key&lt;^&gt;

 &lt;^&gt;common_name: ca&lt;^&gt;

 &lt;^&gt;organization_name: "Etcd CA"&lt;^&gt;

 &lt;^&gt;basic_constraints:&lt;^&gt;

 &lt;^&gt;- CA:TRUE&lt;^&gt;

 &lt;^&gt;- pathlen:1&lt;^&gt;

 &lt;^&gt;basic_constraints_critical: True&lt;^&gt;

 &lt;^&gt;key_usage:&lt;^&gt;

 &lt;^&gt;- keyCertSign&lt;^&gt;

 &lt;^&gt;- digitalSignature&lt;^&gt;

 &lt;^&gt;force: True&lt;^&gt;

- hosts: etcd

 become: True

 tasks:

 - name: "Create directory for etcd binaries"

...

				
			

Enfin, utilisez le module openssl_certificate pour auto-signer le CSR :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: localhost

 ...

 tasks:

 ...

 - name: "Generate CSR for CA"

 openssl_csr:

 path: ./artifacts/ca.csr

 privatekey_path: ./artifacts/ca.key

 common_name: ca

 organization_name: "Etcd CA"

 basic_constraints:

 - CA:TRUE

 - pathlen:1

 basic_constraints_critical: True

 key_usage:

 - keyCertSign

 - digitalSignature

 force: True

 &lt;^&gt;- name: "Generate self-signed CA certificate"&lt;^&gt;

 &lt;^&gt;openssl_certificate:&lt;^&gt;

 &lt;^&gt;path: ./artifacts/ca.crt&lt;^&gt;

 &lt;^&gt;privatekey_path: ./artifacts/ca.key&lt;^&gt;

 &lt;^&gt;csr_path: ./artifacts/ca.csr&lt;^&gt;

 &lt;^&gt;provider: selfsigned&lt;^&gt;

 &lt;^&gt;force: True&lt;^&gt;

- hosts: etcd

 become: True

 tasks:

 - name: "Create directory for etcd binaries"

...

				
			

Fermez et enregistrez le fichier playbook.yaml en appuyant sur CTRL+X suivi de Y. Ensuite, relancez notre playbook pour appliquer les changements :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Vous pouvez également lancer ls pour vérifier le contenu du répertoire artefacts/ :

				
					
ls artifacts/

				
			

Vous trouverez maintenant le certificat CA nouvellement généré ( ca.crt ) :

				
					
[secondary_label Output]

&lt;^&gt;ca.crt ca.csr ca.key&lt;^&gt; etcd1.csr etcd1.key etcd2.csr etcd2.key etcd3.csr etcd3.key

				
			

Dans cette étape, nous avons généré une clé privée et un certificat auto-signé pour l'AC. Dans la prochaine étape, nous utiliserons le certificat de l'AC pour signer la RSE de chaque membre.

Étape 12 - Signature des RSE des membres d'etcd

Dans cette étape, nous allons signer la RSE de chaque nœud membre. Cela sera similaire à la manière dont nous avons utilisé le module openssl_certificate pour auto-signer le certificat CA, mais au lieu d'utiliser le fournisseur auto-signé, nous utiliserons le fournisseur ownca, qui nous permet de signer en utilisant notre propre certificat CA.

Ouvrez votre playbook :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Ajoutez la tâche en surbrillance suivante à la tâche « Generate self-signed CA certificate » (Générer un certificat CA auto-signé) :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: localhost

 ...

 tasks:

 ...

 - name: "Generate self-signed CA certificate"

 openssl_certificate:

 path: ./artifacts/ca.crt

 privatekey_path: ./artifacts/ca.key

 csr_path: ./artifacts/ca.csr

 provider: selfsigned

 force: True

 &lt;^&gt;- name: "Generate an `etcd` member certificate signed with our own CA certificate"&lt;^&gt;

 &lt;^&gt;openssl_certificate:&lt;^&gt;

 &lt;^&gt;path: ./artifacts/{{item}}.crt&lt;^&gt;

 &lt;^&gt;csr_path: ./artifacts/{{item}}.csr&lt;^&gt;

 &lt;^&gt;ownca_path: ./artifacts/ca.crt&lt;^&gt;

 &lt;^&gt;ownca_privatekey_path: ./artifacts/ca.key&lt;^&gt;

 &lt;^&gt;provider: ownca&lt;^&gt;

 &lt;^&gt;force: True&lt;^&gt;

 &lt;^&gt;with_items: "{{ groups['etcd'] }}"&lt;^&gt;

- hosts: etcd

 become: True

 tasks:

 - name: "Create directory for etcd binaries"

...

				
			

Fermez et enregistrez le fichier playbook.yaml en appuyant sur CTRL+X suivi de Y . Ensuite, relancez le playbook pour appliquer les modifications :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Maintenant, énumérez le contenu du répertoire artefacts :

				
					
ls artifacts/

				
			

Vous y trouverez la clé privée, le CSR et le certificat de chaque membre de l'etcd et de l'AC :

				
					
[secondary_label Output]

ca.crt ca.csr ca.key etcd1.crt etcd1.csr etcd1.key etcd2.crt etcd2.csr etcd2.key etcd3.crt etcd3.csr etcd3.key

				
			

Dans cette étape, nous avons signé les RSE de chaque nœud membre en utilisant la clé de l'AC. Dans l'étape suivante, nous allons copier les fichiers pertinents dans chaque nœud géré, de sorte qu'etcd ait accès aux clés et aux certificats pertinents pour établir les connexions TLS.

Étape 13 - Copie de clés privées et de certificats

Chaque nœud doit avoir une copie du certificat auto-signé de l'AC ( ca.crt ). Chaque nœud membre d'etcd doit également avoir sa propre clé privée et son certificat. Dans cette étape, nous allons télécharger ces fichiers et les placer dans un nouveau répertoire /etc/etcd/ssl/.

Pour commencer, ouvrez le fichier playbook.yaml avec votre éditeur :

				
					
nano $HOME/playground/etcd-ansible/playbook.yaml

				
			

Pour effectuer ces changements sur notre playbook Ansible, il faut d'abord mettre à jour la propriété du chemin de la tâche Create directory for etcd configuration pour créer le répertoire /etc/etcd/ssl/ :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 ...

 tasks:

 ...

 with_items:

 - absent

 - directory

 - name: "Create directory for etcd configuration"

 file:

 path: &lt;^&gt;"{{ item }}"&lt;^&gt;

 state: directory

 owner: root

 group: root

 mode: 0755

 &lt;^&gt;with_items:&lt;^&gt;

 &lt;^&gt;- /etc/etcd&lt;^&gt;

 &lt;^&gt;- /etc/etcd/ssl&lt;^&gt;

 - name: "Create configuration file for etcd"

 template:

...

				
			

Ensuite, à la suite de la tâche modifiée, ajoutez trois autres tâches pour copier les fichiers par-dessus :

				
					
[label ~/playground/etcd-ansible/playbook.yaml]

- hosts: etcd

 ...

 tasks:

 ...

 &lt;^&gt;- name: "Copy over the CA certificate"&lt;^&gt;

 &lt;^&gt;copy:&lt;^&gt;

 &lt;^&gt;src: ./artifacts/ca.crt&lt;^&gt;

 &lt;^&gt;remote_src: False&lt;^&gt;

 &lt;^&gt;dest: /etc/etcd/ssl/ca.crt&lt;^&gt;

 &lt;^&gt;owner: root&lt;^&gt;

 &lt;^&gt;group: root&lt;^&gt;

 &lt;^&gt;mode: 0644&lt;^&gt;

 &lt;^&gt;- name: "Copy over the `etcd` member certificate"&lt;^&gt;

 &lt;^&gt;copy:&lt;^&gt;

 &lt;^&gt;src: ./artifacts/{{inventory_hostname}}.crt&lt;^&gt;

 &lt;^&gt;remote_src: False&lt;^&gt;

 &lt;^&gt;dest: /etc/etcd/ssl/server.crt&lt;^&gt;

 &lt;^&gt;owner: root&lt;^&gt;

 &lt;^&gt;group: root&lt;^&gt;

 &lt;^&gt;mode: 0644&lt;^&gt;

 &lt;^&gt;- name: "Copy over the `etcd` member key"&lt;^&gt;

 &lt;^&gt;copy:&lt;^&gt;

 &lt;^&gt;src: ./artifacts/{{inventory_hostname}}.key&lt;^&gt;

 &lt;^&gt;remote_src: False&lt;^&gt;

 &lt;^&gt;dest: /etc/etcd/ssl/server.key&lt;^&gt;

 &lt;^&gt;owner: root&lt;^&gt;

 &lt;^&gt;group: root&lt;^&gt;

 &lt;^&gt;mode: 0600&lt;^&gt;

 - name: "Create configuration file for etcd"

 template:

...

				
			

Fermez et enregistrez le fichier playbook.yaml en appuyant sur CTRL+X, puis sur Y.

Lancez de nouveau ansible-playbook pour apporter ces changements :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Dans cette étape, nous avons réussi à télécharger les clés privées et les certificats vers les nœuds gérés. Après avoir copié les fichiers, nous devons maintenant mettre à jour notre fichier de configuration etcd pour pouvoir les utiliser.

Étape 14 - Activer le TLS sur etcd

Dans la dernière étape de ce tutoriel, nous allons mettre à jour certaines configurations Ansible pour activer TLS dans un cluster etcd.

Tout d'abord, ouvrez le fichier modèle templates/etcd.conf.yaml.j2 à l'aide de votre éditeur :

				
					
nano $HOME/playground/etcd-ansible/templates/etcd.conf.yaml.j2

				
			

Une fois à l'intérieur, modifiez toutes les URL pour utiliser le protocole https au lieu de http.  De plus, ajoutez une section à la fin du modèle pour spécifier l'emplacement du certificat de l'AC, du certificat du serveur et de la clé du serveur :

				
					
[label ~/playground/etcd-ansible/templates/etcd.conf.yaml.j2]

data-dir: /var/lib/etcd/{{ inventory_hostname }}.etcd

name: {{ inventory_hostname }}

initial-advertise-peer-urls: http&lt;^&gt;s&lt;^&gt;://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2380

listen-peer-urls: http&lt;^&gt;s&lt;^&gt;://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2380,http&lt;^&gt;s&lt;^&gt;://127.0.0.1:2380

advertise-client-urls: http&lt;^&gt;s&lt;^&gt;://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2379

listen-client-urls: http&lt;^&gt;s&lt;^&gt;://{{ hostvars[inventory_hostname]['ansible_facts']['eth1']['ipv4']['address'] }}:2379,http&lt;^&gt;s&lt;^&gt;://127.0.0.1:2379

initial-cluster-state: new

initial-cluster: {% for host in groups['etcd'] %}{{ hostvars[host]['ansible_facts']['hostname'] }}=http&lt;^&gt;s&lt;^&gt;://{{ hostvars[host]['ansible_facts']['eth1']['ipv4']['address'] }}:2380{% if not loop.last %},{% endif %}{% endfor %}



&lt;^&gt;client-transport-security:&lt;^&gt;

&lt;^&gt; cert-file: /etc/etcd/ssl/server.crt&lt;^&gt;

&lt;^&gt; key-file: /etc/etcd/ssl/server.key&lt;^&gt;

&lt;^&gt; trusted-ca-file: /etc/etcd/ssl/ca.crt&lt;^&gt;

&lt;^&gt;peer-transport-security:&lt;^&gt;

&lt;^&gt; cert-file: /etc/etcd/ssl/server.crt&lt;^&gt;

&lt;^&gt; key-file: /etc/etcd/ssl/server.key&lt;^&gt;

&lt;^&gt; trusted-ca-file: /etc/etcd/ssl/ca.crt&lt;^&gt;

				
			

Fermez et enregistrez le fichier templates/etcd.conf.yaml.j2

Ensuite, lancez votre playbook Ansible :

				
					
ansible-playbook -i hosts playbook.yaml

				
			

Puis, SSH dans l'un des nœuds gérés :

				
					
ssh &lt;^&gt;root&lt;^&gt;@&lt;^&gt;etcd1_public_ip&lt;^&gt;

				
			

Une fois à l'intérieur, lancez la commande etcdctl endpoint health pour vérifier si les terminaux utilisent le HTTPS, et si tous les membres sont en bon état :

				
					
[environment second]

etcdctl --cacert /etc/etcd/ssl/ca.crt endpoint health --cluster

				
			

Comme notre certificat CA n'est pas, par défaut, un certificat CA root de confiance installé dans le répertoire /etc/ssl/certs/, nous devons le passer à etcdctl en utilisant le drapeau --cacert.

Cela donnera le résultat suivant :

				
					
[environment second]

[secondary_label Output]

https://&lt;^&gt;etcd3_private_ip&lt;^&gt;:2379 is healthy: successfully committed proposal: took = 19.237262ms

https://&lt;^&gt;etcd1_private_ip&lt;^&gt;:2379 is healthy: successfully committed proposal: took = 4.769088ms

https://&lt;^&gt;etcd2_private_ip&lt;^&gt;:2379 is healthy: successfully committed proposal: took = 5.953599ms

				
			

Pour confirmer que le cluster etcd fonctionne réellement, nous pouvons, une fois de plus, créer une entrée sur un nœud membre et la récupérer à partir d'un autre nœud membre :

				
					
[environment second]

etcdctl --cacert /etc/etcd/ssl/ca.crt put foo "bar"

				
			

Ensuite, utilisez un nouveau terminal pour SSH dans un autre nœud membre :

				
					
ssh &lt;^&gt;root&lt;^&gt;@&lt;^&gt;etcd2_public_ip&lt;^&gt;

				
			

Récupérez maintenant la même entrée en utilisant la clé foo :

				
					
[environment third]

etcdctl --cacert /etc/etcd/ssl/ca.crt get foo

				
			

Ceci renverra l'entrée, montrant la sortie ci-dessous :

				
					
[environment third]

[secondary_label Output]

foo

bar

				
			

Vous pouvez faire la même chose sur le troisième nœud pour vous assurer que les trois membres sont opérationnels.

Conclusion

Vous avez maintenant approvisionné avec succès un cluster de 3 nœuds etcd, l'avez sécurisé avec TLS et avez confirmé qu'il fonctionne.

etcd est un outil créé à l'origine par CoreOS .  Pour comprendre l'utilisation d'etcd par rapport à CoreOS, vous pouvez lire Comment utiliser Etcdctl et Etcd, le Distributed Key-Value Store de CoreOS .  L'article vous guide également dans la mise en place d'un modèle de découverte dynamique, ce qui a été discuté mais non démontré dans ce tutoriel.

Comme mentionné au début de ce tutoriel, etcd est une partie importante de l'écosystème de Kubernetes. Pour en savoir plus sur Kubernetes et le rôle d'etcd en son sein, vous pouvez lire Une introduction à Kubernetes. Si vous déployez etcd dans le cadre d'un cluster Kubernetes, sachez que d'autres outils sont disponibles, tels que kubespray et kubeadm . Pour plus de détails sur ce dernier point, vous pouvez lire Comment créer un cluster Kubernetes en utilisant Kubeadm sur Ubuntu 18.04.

Enfin, ce tutoriel a fait appel à de nombreux outils, mais n'a pu se plonger dans chacun d'entre eux de manière trop détaillée. Vous trouverez ci-dessous des liens qui vous permettront d'examiner plus en détail chaque outil :