Ansible est l'un des outils d'automatisation informatique les plus connus et les plus utilisés, il nous aide à automatiser les tâches opérationnelles informatiques telles que...
- Démarrer l'hôte (VM ou machine sans système d'exploitation) à partir de zéro
- Configuration des hôtes et des services
- Gestion des déploiements et des mises à niveau de logiciels
- Ansible prend également en charge l'orchestration de l'infrastructure cloud, comme la création d'un ensemble d'instances EC2 et RDS pour vos applications sur des clouds publics (AWS, GCP, Azure). Pour en savoir plus sur le provisionnement cloud, cliquez ici
Étant donné que ce blog concerne principalement la gestion de PostgreSQL à l'aide d'Ansible, nous n'entrerons pas dans les détails des utilisations d'Ansible, cependant, nous passerons en revue quelques bases d'Ansible. Je vous recommande de passer par le lien du document Ansible si vous souhaitez en savoir plus à ce sujet.
Les bases d'Ansible
Ansible est un projet open-source écrit en python dont le code source est disponible sur GitHub. Puisqu'il s'agit d'un package python, nous pouvons facilement installer Ansible en utilisant pip.
Ansible doit être installé sur un seul hôte à partir duquel nous orchestrerons nos tâches opérationnelles à l'aide des commandes Ansible (Ansible, Ansible-playbook). Nous appelons cet hôte d'orchestration le nœud de contrôle.
Les commandes Ansible utilisent les bibliothèques OpenSSH pour se connecter aux hôtes cibles pour exécuter des tâches opérationnelles, nous appelons ces hôtes cibles Managed Node. Le nom d'hôte ou l'adresse IP du nœud géré sont mentionnés dans un fichier appelé Inventory, ce nom de fichier d'inventaire est ensuite spécifié en entrée des commandes Ansible.
Dans le fichier d'inventaire, nous pouvons répertorier plusieurs hôtes sous un seul groupe, cela évitera de répéter plusieurs fois les mêmes tâches pour différents hôtes. Plus de détails sur l'utilisation du fichier d'inventaire peuvent être trouvés ici.
Étant donné que la commande Ansible utilise SSH pour se connecter, il n'est pas nécessaire d'installer Ansible sur tous les hôtes, il suffit de l'installer sur le nœud de contrôle. Cependant, tous les nœuds de contrôle et nœuds gérés doivent avoir python et toutes les bibliothèques python nécessaires installées. Vous trouverez plus d'informations sur l'installation d'Ansible ici.
Pour la démonstration, j'utiliserai un ordinateur portable comme nœud de contrôle et une machine virtuelle CentOS-7 invitée comme nœud géré. La machine virtuelle CentOS-7 a été provisionnée à l'aide de Vagrant sur le fournisseur VirtualBox.
Installer Ansible sur le nœud de contrôle
Nous allons installer Ansible en utilisant pip comme indiqué dans la page du document Ansible. Les commandes suivantes ont été exécutées en tant qu'utilisateur "Ansible".
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py --user
En utilisant l'option --user, les commandes pip et Ansible doivent être installées sous le répertoire HOME et nous devons ajouter le chemin bin à notre variable d'environnement PATH.
$ echo 'export PATH=$HOME/Library/Python/2.7/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile
La commande pip suivante a installé Ansible version 2.8.0 (qui est la dernière version stable au moment de la rédaction de ce blog.)
$ pip install --user ansible
$ which ansible
/Users/Ansible/Library/Python/2.7/bin/Ansible
$ ansible --version
Ansible 2.8.0
...
...
Prévérifications des nœuds de contrôle et des nœuds gérés
Assurez-vous d'avoir une connexion réseau appropriée entre le nœud de contrôle et le nœud géré.
Vérifiez votre pare-feu pour toute règle susceptible de bloquer les connexions entrantes et sortantes sur le port SSH. Si c'est le cas, ouvrez le port SSH pour fournir un accès à la fois aux nœuds de contrôle et aux nœuds gérés.
Tout d'abord, essayez de vous connecter via SSH au nœud géré. Vous devriez pouvoir vous connecter au nœud géré à partir du nœud de contrôle.
Vous pouvez configurer l'accès SSH sans mot de passe aux nœuds gérés en fonction des politiques de sécurité de votre organisation. Pour cette démo, j'ai configuré SSH sans mot de passe sur mon nœud géré "pg01" (CentOS-7) pour l'utilisateur "vagrant". Cela donne au nœud géré le pouvoir sudo, la plupart des tâches d'installation et de configuration de l'hôte seront exécutées en tant qu'utilisateur « vagabond » avec « sudo ».
Sur le nœud de contrôle, nous avons le fichier de configuration ansible.cfg qui sera utilisé par les commandes Ansible. Vous trouverez ci-dessous quelques options de configuration définies dans le fichier de configuration. Pour en savoir plus sur les autres options de configuration disponibles, consultez l'exemple de fichier de configuration.
- remote_port - Si le serveur SSH sur le nœud géré s'exécute sur un autre port que le port par défaut 22, nous pouvons le modifier
- remote_user - Le nom d'utilisateur de connexion qui sera utilisé par Ansible pour connecter le nœud géré, pour exécuter les tâches
- private_key_file - Clé privée SSH qui sera utilisée pour qu'Ansible se connecte
Étant donné que la configuration ci-dessus s'applique globalement à tous les nœuds gérés, si nous voulons avoir une configuration différente pour un hôte ou un groupe d'hôtes spécifique, nous pouvons les spécifier dans le fichier d'inventaire. Vous pouvez en voir un exemple ci-dessous dans le fichier d'inventaire "development.yaml".
Effectuer une simulation Ansible
Créez un fichier d'inventaire "development.yaml" comme indiqué ci-dessous.
$ pwd
/Users/Ansible/postgres-setup
$ cat development.yaml
all:
hosts:
children:
postgres_clusters:
hosts:
pg01:
vars:
ansible_port: 22
ansible_user: "vagrant"
ansible_private_key_file: "/Users/Ansible/postgres-setup/private_key"
Dans le fichier d'inventaire ci-dessus, l'hôte pg01 est l'un des membres du groupe d'hôtes postgres_clusters. Les variables ansible_port, ansible_user et ansible_private_key_file s'appliquent uniquement aux hôtes du groupe postgres_clusters.
Nous allons maintenant vérifier si Ansible peut exécuter les tâches sur le nœud géré. Dans l'exemple ci-dessous, la commande ansible exécute le module ping sur le nœud géré pg01, si Ansible a pu exécuter le module ping, vous devriez voir SUCCESS comme réponse.
$ ansible -i development.yaml -m ping pg01
pg01 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Lors de l'exécution d'Ansible sur le nœud géré en tant que première tâche, il collecte les informations telles que le nom d'hôte, l'adresse IP, la mémoire du nœud géré. Pour les vérifier, nous pouvons appeler la configuration du module qui renverrait un grand JSON. Nous pouvons utiliser n'importe lequel d'entre eux dans notre playbook Ansible.
$ ansible -i development.yaml -m setup pg01
pg01 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.100.4",
"10.0.2.15"
],
"ansible_all_ipv6_addresses": [
"fe80::a00:27ff:fe29:ac89",
"fe80::5054:ff:fe26:1060"
],
Rôle Ansible
Ansible Role est un moyen de regrouper un certain ensemble de tâches et de paramètres de configuration connexes dans une seule unité en attribuant simplement un rôle à un hôte ou à un groupe d'hôtes particulier. Ansible appliquera toute la configuration et les tâches associées. Cela évite de répéter les tâches plusieurs fois pour chaque hôte ou groupe d'hôtes différent.
Chaque rôle est représenté sous la forme d'un répertoire et dans le répertoire du rôle, il y aura des sous-répertoires comme les fichiers par défaut, les gestionnaires, les méta, les tâches, les modèles, les tests, les vars. Le but de ces répertoires peut être trouvé ici.
Les commandes Ansible, par défaut, recherchent le répertoire des rôles sous les chemins mentionnés dans DEFAULT_ROLES_PATH.
$ ansible-config list | grep -A2 '^DEFAULT_ROLES_PATH'
DEFAULT_ROLES_PATH:
default: ~/.Ansible/roles:/usr/share/Ansible/roles:/etc/Ansible/roles
description: Colon separated paths in which Ansible will search for Roles.
Galaxie Ansible
Ansible Galaxy est un portail où les membres de la communauté partagent le référentiel GitHub de leurs rôles Ansible. Nous pouvons parcourir le portail Galaxy pour les rôles Ansible requis. En utilisant la commande ansible-galaxy, nous pourrions télécharger et réutiliser le rôle. Avant d'utiliser un rôle, parcourez en détail tous les fichiers Ansible YAML sous les répertoires defaults, vars, tasks, templates, handlers et soyez conscient du fonctionnement du rôle.
Pour notre déploiement de PostgreSQL, nous utiliserons le rôle "postgresql" développé par l'auteur ANXS et le repo GitHub.
Installation du rôle Ansible "anxs.postgresql"
$ ansible-galaxy install anxs.postgresql
- downloading role 'postgresql', owned by anxs
- downloading role from https://github.com/ANXS/postgresql/archive/v1.10.1.tar.gz
- extracting anxs.postgresql to /Users/ansible/.Ansible/roles/anxs.postgresql
- anxs.postgresql (v1.10.1) was installed successfully
La commande ci-dessus installe le répertoire de rôle "anxs.postgresql" sous le répertoire "/Users/ansible/.Ansible/roles", c'est l'un des répertoires de DEFAULT_ROLES_PATH et la commande ansible recherchera dans ce répertoire tous les rôles.
Livret Ansible
Un Playbook Ansible est un fichier YAML dans lequel nous allons lister les tâches ou rôles qui doivent être exécutés sur un hôte particulier ou le groupe d'hôtes. Vous pouvez en savoir plus sur le développement de playbooks et apprendre la définition des balises comme les hôtes, les tâches, les rôles, les variables ici.
Par défaut, toutes les tâches sont exécutées en tant qu'utilisateur ansible qui s'est connecté. Afin d'exécuter des tâches particulières avec un utilisateur différent (ou avec le privilège "root"), nous pouvons utiliser devenir. Vous trouverez ici comment utiliser cette commande.
Dans le playbook ci-dessous (postgres-play.yaml), j'ai répertorié le rôle "anxs.postgresql" sous le groupe d'hôtes "postgres_clusters", donc toutes les tâches du rôle anxs.postgresql seront exécutées pour tous les hôtes du groupe "postgres_clusters".
$ cat postgres-play.yaml
---
- hosts: postgres_clusters
become: yes
roles:
- role: anxs.postgresql
devenu :oui dans le YAML définit que ce rôle sera exécuté avec des privilèges plus élevés en utilisant le DEFAULT_BECOME_METHOD "sudo"
$ ansible-config list | grep -A2 '^DEFAULT_BECOME_METHOD'
DEFAULT_BECOME_METHOD:
default: sudo
description: Privilege escalation method to use when `become` is enabled.
Nous exécuterons ce playbook en tant qu'utilisateur "vagabond" et l'utilisateur a déjà été provisionné avec sudo power.
[[email protected] ~]$ sudo cat /etc/sudoers.d/vagrant
%vagrant ALL=(ALL) NOPASSWD: ALL
Guide DevOps de la gestion des bases de données de ManyninesDécouvrez ce que vous devez savoir pour automatiser et gérer vos bases de données open sourceTélécharger gratuitement Déployer PostgreSQL avec Ansible
Nous allons maintenant exécuter le playbook 'postgres-play.yaml' qui installera tous les packages liés à PostgreSQL et le configurera en utilisant les paramètres par défaut.
Pour cet exemple, Ansible installera PostgreSQL 9.6 sur le port 5432, avec postgres max_connections défini sur 100. Tous les paramètres par défaut se trouvent dans le fichier /Users/ansible/.Ansible/roles/anxs.postgresql/defaults/main.yml .
$ grep -E '^postgresql_(version|port|max_connections):' ~/.Ansible/roles/anxs.postgresql/defaults/main.yml
postgresql_version: 9.6
postgresql_port: 5432
postgresql_max_connections: 100
Exécuter le playbook
$ ansible-playbook -i development.yaml postgres-play.yaml
PLAY [postgres_clusters] ***************************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [pg01]
...
...
PLAY RECAP *****************************************************************************************************************************************************************************************************
pg01 : ok=21 changed=14 unreachable=0 failed=0 skipped=32 rescued=0 ignored=0
Une fois qu'Ansible a exécuté toutes les tâches, un résumé des exécutions de tâches sera affiché sous PLAY RECAP.
- ok=21, 21 tâches exécutées sans modification.
- changed=14, 14 tâches ont apporté des modifications à l'hôte, comme l'installation de postgres, la création de répertoires, de fichiers, le démarrage de postgres.
- skipped=32, 32 tâches ont été ignorées, peut-être parce que certaines fonctionnalités n'ont pas été activées. Puisque nous installons sur entOS, les tâches liées à Ubuntu ont été ignorées.
Vérifiez l'état et la configuration du service PostgreSQL.
[[email protected] ~]$ systemctl status postgresql-9.6
● postgresql-9.6.service - PostgreSQL 9.6 database server
Loaded: loaded (/usr/lib/systemd/system/postgresql-9.6.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/postgresql-9.6.service.d
└─custom.conf
Active: active (running) since Wed 2019-05-29 07:15:25 UTC; 24min ago
Docs: https://www.postgresql.org/docs/9.6/static/
Process: 7559 ExecStartPre=/usr/pgsql-9.6/bin/postgresql96-check-db-dir /var/lib/pgsql/9.6/data (code=exited, status=0/SUCCESS)
Main PID: 7564 (postmaster)
CGroup: /system.slice/postgresql-9.6.service
├─7564 /usr/pgsql-9.6/bin/postmaster -D /etc/postgresql/9.6/data
├─7567 postgres: checkpointer process
├─7568 postgres: writer process
├─7569 postgres: wal writer process
├─7570 postgres: autovacuum launcher process
└─7571 postgres: stats collector process
[[email protected] ~]$ psql -U postgres
psql (9.6.13)
Type "help" for help.
postgres=# show max_connections ;
max_connections
-----------------
100
(1 row)
postgres=# show statement_timeout ;
statement_timeout
-------------------
(1 row)
postgres=# show log_min_duration_statement ;
log_min_duration_statement
----------------------------
-1
(1 row)
Nous avons maintenant installé PostgreSQL sur l'hôte géré "pg01" en utilisant la configuration par défaut.
Modification de la configuration PostgreSQL
Nous allons maintenant reconfigurer l'instance PostgreSQL en utilisant nos paramètres personnalisés.
J'ai créé le fichier custom.yaml (comme indiqué ci-dessous) qui contient la liste des variables définies pour modifier les paramètres PostgreSQL tels que listen_addresses, max_connections, wal_level, hot_standby, statement_timeout, log_checkpoint, log_lock_waits, log_destination, log_min_duration_statement.
$ pwd
/Users/ansible/postgres-setup
$ cat custom.yaml
postgresql_listen_addresses: "*"
postgresql_max_connections: 300
postgresql_wal_level: "hot_standby"
postgresql_hot_standby: "on"
postgresql_statement_timeout: 60000
postgresql_log_lock_waits: "on"
postgresql_log_destination: "csvlog"
postgresql_log_min_duration_statement: 0
Nous allons maintenant changer notre playbook postgres-play.yaml pour utiliser ce custom.yaml.
$ cat postgres-play.yaml
---
- hosts: postgres_clusters
become: yes
vars_files:
- ./custom.yaml
roles:
- role: anxs.postgresql
À l'aide des balises vars_files, j'ai spécifié le fichier de configuration personnalisé custom.yaml, qui remplacera la configuration par défaut spécifiée dans le rôle anxs.postgresql. Vous trouverez plus de détails sur la priorité des variables ici.
Nous pouvons maintenant réexécuter la même commande ansible-playbook que nous avions exécutée précédemment, mais cela exécutera toutes les tâches telles que l'installation de PostgreSQL, la configuration, la création d'utilisateurs et de bases de données. Pour cela, nous devons restreindre Ansible pour qu'il n'exécute que les tâches liées à la configuration de PostgreSQL en utilisant l'option --tags
Afin de connaître la liste des balises prises en charge, nous pourrions exécuter la commande avec --list-tags.
$ ansible-playbook -i development.yaml postgres-play.yaml --list-tags
playbook: postgres-play.yaml
play #1 (postgres_clusters): postgres_clusters TAGS: []
TASK TAGS: [always, postgresql, postgresql-configure, postgresql-databases, postgresql-extensions, postgresql-install, postgresql-monit, postgresql-users]
Parmi les balises ci-dessus, nous spécifierons uniquement la balise postgresql-configure pour modifier les paramètres postgresql.
$ ansible-playbook -i development.yaml postgres-play.yaml --tags postgresql-configure
PLAY [postgres_clusters] ***************************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [pg01]
...
...
TASK [anxs.postgresql : PostgreSQL | Update configuration - pt. 2 (postgresql.conf)] ***************************************************************************************************************************
changed: [pg01]
...
...
TASK [anxs.postgresql : PostgreSQL | Reload all conf files] ****************************************************************************************************************************************************
changed: [pg01]
PLAY RECAP *****************************************************************************************************************************************************************************************************
pg01 : ok=13 changed=2 unreachable=0 failed=0 skipped=6 rescued=0 ignored=0
Comme vous le voyez dans le PLAY RECAP, seuls 2 changements se sont propagés au nœud géré pg01. Le premier met à jour la configuration et le second recharge les configurations.
Vérifiez que les modifications de configuration ont pris effet sur le nœud géré.
postgres=# show listen_addresses ;
listen_addresses
------------------
localhost
(1 row)
postgres=# show max_connections ;
max_connections
-----------------
100
(1 row)
postgres=# show wal_level ;
wal_level
-----------
minimal
(1 row)
postgres=# show hot_standby ;
hot_standby
-------------
off
(1 row)
postgres=# show statement_timeout;
statement_timeout
-------------------
1min
(1 row)
postgres=# show log_lock_waits ;
log_lock_waits
----------------
on
(1 row)
postgres=# show log_destination ;
log_destination
-----------------
csvlog
(1 row)
postgres=# show log_min_duration_statement;
log_min_duration_statement
----------------------------
(1 row)
Comme vous pouvez le voir, certaines configurations changent comme listen_addresses, max_connections, wal_level, hot_standby n'ont pas encore pris effet. Ces modifications de configuration nécessitent un redémarrage de PostgreSQL et le rôle anxs.postgresql n'a fait que recharger le service lui-même.
Afin d'éviter un redémarrage brutal de PostgreSQL pendant les heures de production, l'auteur d'origine peut ne pas avoir ajouté la tâche de redémarrage au rôle. Nous pouvons redémarrer manuellement le service postgresql, pendant le temps d'arrêt planifié.
[[email protected] ~]$ sudo systemctl restart postgresql-9.6
[[email protected] ~]$ psql -U postgres
psql (9.6.13)
postgres=# show listen_addresses ;
listen_addresses
------------------
(1 row)
postgres=# show max_connections ;
max_connections
-----------------
300
(1 row)
postgres=# show wal_level;
wal_level
-----------
replica
(1 row)
postgres=# show hot_standby;
hot_standby
-------------
on
(1 row)
Création d'utilisateurs et de bases de données PostgreSQL
Nous allons maintenant créer les utilisateurs "app1" et "app2" et les bases de données "app1_db" et "app2_db" appartenant respectivement aux utilisateurs "app1" et "app2".
J'ai ajouté deux nouvelles variables, postgresql_users et postgresql_database à custom.yaml, qui contient la liste des utilisateurs et des bases de données à créer. Rôle anxs.postgresql utilise les modules Ansible postgresql_users et postgresql_db pour créer l'utilisateur et la base de données. Vous pouvez vous référer à ces documents pour ajouter les variables.
$ cat custom.yaml
...
...
postgresql_users:
- name: app1
pass: md5bb0592c05941d14c231da96950c71b60
encrypted: yes
- name: app2
pass: md5bbb1e4d09b64ca54a237727af46cba7c
encrypted: yes
postgresql_databases:
- name: app1_db
owner: app1
- name: app2_db
owner: app2
Nous allons maintenant exécuter uniquement les tâches associées aux balises postgresql-users et postgresql-databases.
$ ansible-playbook -i development.yaml postgres-play.yaml --tags postgresql-users,postgresql-databases
PLAY [postgres_clusters] ***************************************************************************************************************************************************************************************
...
...
TASK [anxs.postgresql : PostgreSQL | Make sure the PostgreSQL users are present] *******************************************************************************************************************************
changed: [pg01] => (item=None)
changed: [pg01] => (item=None)
changed: [pg01]
...
...
TASK [anxs.postgresql : PostgreSQL | Make sure the PostgreSQL databases are present] ***************************************************************************************************************************
changed: [pg01] => (item={u'owner': u'app1', u'name': u'app1_db'})
changed: [pg01] => (item={u'owner': u'app2', u'name': u'app2_db'})
...
...
PLAY RECAP *****************************************************************************************************************************************************************************************************
pg01 : ok=6 changed=2 unreachable=0 failed=0 skipped=9 rescued=0 ignored=0
Vérifiez que les utilisateurs et les bases de données sont créés sur l'hôte géré.
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
app1 | | {}
app2 | | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
app1_db | app1 | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
app2_db | app2 | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
Autoriser les hôtes externes à se connecter au serveur PostgreSQL
Nous allons maintenant autoriser les hôtes externes à se connecter au service PostgreSQL en ajoutant la variable postgresql_pg_hba_custom à custom.yaml
$ cat custom.yaml
...
...
postgresql_pg_hba_custom:
- {type: "host", database: "all", user: "all", address: "0.0.0.0/0", method: "md5" }
Exécution des tâches balisées avec postgresql-configure, pour appliquer la configuration.
$ ansible-playbook -i development.yaml postgres-play.yaml --tags postgresql-configure
Vérifier si je peux me connecter au serveur PostgreSQL depuis mon nœud de contrôle.
$ PGPASSWORD=password psql -h pg01 -U app1 -d app1_db -c 'Select true'
bool
------
(1 row)
Conclusion
Ce blog devrait vous donner les bases que vous devez connaître pour utiliser Ansible pour déployer et gérer PostgreSQL. Cependant, nous n'avons couvert que quelques tâches d'administration de PostgreSQL. En fonction de l'infrastructure de votre organisation, vous devrez peut-être remplacer plusieurs des configurations par défaut et ajouter encore plus de tâches au rôle Ansible.