Ansible är ett av de mest välkända och mest använda IT-automationsverktygen, det hjälper oss att automatisera IT-operativa uppgifter som...
- Starta värden (VM eller barmetallmaskin) från början
- Konfigurera värdar och tjänster
- Hantera programvarudistributioner och uppgraderingar
- Ansible har också stöd för orkestrering av molninfrastrukturen som att skapa ett gäng EC2- och RDS-instanser för dina applikationer på offentliga moln (AWS, GCP, Azure). Mer om molnförsörjningen finns här
Eftersom den här bloggen mest handlar om att hantera PostgreSQL med Ansible kommer vi inte att gå in på detaljer om Ansibles användningar, men vi kommer att gå igenom några Ansibles grunder. Jag rekommenderar att du går igenom Ansible-dokumentlänken om du vill veta mer om det.
Ansible Basics
Ansible är ett öppen källkodsprojekt skrivet i python vars källkod är tillgänglig på GitHub. Eftersom det är ett pythonpaket kan vi enkelt installera Ansible med pip.
Ansible behöver bara installeras på en värd från vilken vi kommer att orkestrera våra operativa uppgifter med hjälp av Ansible-kommandon (Ansible, Ansible-playbook). Vi kallar denna orkestreringsvärd för kontrollnoden.
Ansible-kommandon använder OpenSSH-bibliotek för att logga in på målvärdarna för att utföra operativa uppgifter, vi kallar dessa målvärdar Managed Node. Den hanterade nodens värdnamn eller IP nämns i en fil som kallas Inventory, detta inventeringsfilnamn anges sedan som en indata till Ansible-kommandona.
I inventeringsfilen kan vi lista flera värdar under en enda grupp, detta kommer att undvika att upprepa samma uppgifter flera gånger för olika värdar. Mer information om inventeringsfilanvändningen finns här.
Eftersom Ansible-kommandot använder SSH för att logga in, finns det inget behov av att installera Ansible på alla värddatorer, det behöver bara installeras på kontrollnoden. Men alla kontrollnoder och hanterade noder bör ha python och alla nödvändiga pythonbibliotek installerade. Mer om Ansible-installationen finns här.
För demon kommer jag att använda en bärbar dator som kontrollnod och gäst CentOS-7 VM som hanterad nod. CentOS-7 VM förbereddes med Vagrant på leverantören VirtualBox.
Installera Ansible på kontrollnoden
Vi kommer att installera Ansible med pip som hänvisas till på Ansible-dokumentsidan. Följande kommandon kördes som "Ansible" användare.
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py --user
Genom att använda --user-alternativet installeras pip och Ansible-kommandon under HOME-katalogen och vi måste lägga till bin-sökvägen till vår PATH-miljövariabel.
$ echo 'export PATH=$HOME/Library/Python/2.7/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile
Följande pip-kommando har installerat Ansible version 2.8.0 (som är den senaste stabila versionen vid tidpunkten för att skriva denna blogg.)
$ pip install --user ansible
$ which ansible
/Users/Ansible/Library/Python/2.7/bin/Ansible
$ ansible --version
Ansible 2.8.0
...
...
Kontrollnod och förhandskontroll av hanterad nod
Se till att du har en korrekt nätverksanslutning mellan kontrollnoden och den hanterade noden.
Kontrollera din brandvägg för regler som kan blockera inkommande och utgående anslutningar på SSH-porten, öppna i så fall SSH-porten för att ge åtkomst till både kontrollnoderna och de hanterade noderna.
Försök först att ansluta via SSH till den hanterade noden. Du bör kunna logga in på den hanterade noden från kontrollnoden.
Du kan ställa in den lösenordslösa SSH-åtkomsten till de hanterade noderna enligt organisationens säkerhetspolicyer. För denna demo har jag lösenordslöst konfigurerat för SSH till min hanterade nod "pg01" (CentOS-7) för användaren "vagrant". Detta gör att den hanterade noden har sudo-kraften, de flesta av installations- och värdkonfigurationsuppgifterna kommer att utföras som "vagrant" användare med "sudo".
På kontrollnoden har vi konfigurationsfilen ansible.cfg som kommer att användas av Ansible-kommandona. Nedan finns några konfigurationsalternativ som definieras i konfigurationsfilen. För att lära dig mer om de andra tillgängliga konfigurationsalternativen, kolla in exempel på konfigurationsfilen.
- remote_port - Om SSH-servern på den hanterade noden körs på en annan port än standardport 22 kan vi ändra den
- remote_user – Inloggningsanvändarnamnet som kommer att användas av Ansible för att ansluta den hanterade noden, för att köra uppgifterna
- private_key_file - SSH privat nyckel som kommer att användas för Ansible att logga in
Eftersom ovan nämnda konfiguration gäller globalt för alla hanterade noder, om vi vill ha en annan konfiguration för en specifik värd eller värdgrupp kan vi specificera dem i inventeringsfilen. Du kan se ett exempel på detta nedan i inventeringsfilen “development.yaml”.
Utföra en Ansible torrkörning
Skapa en inventeringsfil "development.yaml" som visas nedan.
$ 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"
I inventeringsfilen ovan är värd pg01 en av medlemmarna i värdgruppen postgres_clusters. Variablerna ansible_port, ansible_user och ansible_private_key_file gäller endast för värdarna under gruppen postgres_clusters.
Vi kommer nu att kontrollera om Ansible kan köra uppgifterna på den hanterade noden. I exemplet nedan kör ansible-kommandot modulpingningen på den hanterade noden pg01, om Ansible kunde köra modulpingningen bör du se SUCCESS som svaret.
$ ansible -i development.yaml -m ping pg01
pg01 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
När Ansible körs på den hanterade noden som första uppgift, samlar den in information som värdnamn, IP-adress, minnet för den hanterade noden. För att kontrollera dessa kan vi anropa modulinställningen som skulle returnera en stor JSON. Vi kan använda vilken som helst av dessa i vår Ansible-spelbok.
$ 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"
],
Ansible Roll
Ansible Role är ett sätt att kombinera en viss uppsättning relaterade uppgifter och konfigurationsinställningar till en enda enhet bara genom att tilldela en roll till en viss värd eller värdgrupp. Ansible kommer att tillämpa alla relaterade konfigurationer och uppgifter. Detta undviker att upprepa uppgifterna flera gånger för varje värd eller värdgrupp.
Varje roll representeras som en katalog och inom rollkatalogen kommer det att finnas underkataloger som standardfiler, hanterare, meta, uppgifter, mallar, tester, vars. Syftet med dessa kataloger finns här.
Möjliga kommandon söker som standard i rollkatalogen under sökvägarna som nämns i 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.
Ansible Galaxy
Ansible Galaxy är en portal där communityfolket delar GitHub-förrådet med sina Ansible-roller. Vi kan bläddra igenom galaxportalen efter de nödvändiga Ansible-rollerna. Med kommandot ansible-galaxy kunde vi ladda ner och återanvända rollen. Innan du använder en roll, gå igenom alla Ansible YAML-filer i detalj under katalogerna defaults, vars, tasks, mallar, handlers och var medveten om hur rollen fungerar.
För vår distribution av PostgreSQL kommer vi att använda rollen "postgresql" utvecklad av författaren ANXS och GitHub repo.
Installerar Ansible-rollen "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
Kommandot ovan installerar rollkatalogen "anxs.postgresql" under katalogen "/Users/ansible/.Ansible/roles", detta är en av katalogerna i DEFAULT_ROLES_PATH och ansible-kommandot kommer att söka i den här katalogen efter alla roller.
Ansible Playbook
En Ansible Playbook är en YAML-fil där vi kommer att lista de uppgifter eller roller som måste utföras på en viss värd eller värdgruppen. Du kan läsa mer om att utveckla spelböcker och lära dig definitionen av taggar som värdar, uppgifter, roller, vars här.
Som standard exekveras alla uppgifter som den möjliga användaren som har loggat in. För att utföra vissa uppgifter med en annan användare (eller med "root"-privilegier) kan vi använda oss av bli. Hur du använder det här kommandot finns här.
I spelboken nedan (postgres-play.yaml) har jag listat rollen "anxs.postgresql" under värdgruppen "postgres_clusters", så alla uppgifter i rollen anxs.postgresql kommer att utföras för alla värdar under gruppen “postgres_clusters”.
$ cat postgres-play.yaml
---
- hosts: postgres_clusters
become: yes
roles:
- role: anxs.postgresql
bli:ja i YAML definierar att denna roll kommer att köras med högre behörighet genom att använda 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.
Vi kommer att köra den här spelboken som användarens "vagrant" och användaren var redan försedd med sudo-kraft.
[[email protected] ~]$ sudo cat /etc/sudoers.d/vagrant
%vagrant ALL=(ALL) NOPASSWD: ALL
Severalnines DevOps Guide to Database ManagementLär dig om vad du behöver veta för att automatisera och hantera dina databaser med öppen källkod Ladda ner gratis Distribuera PostgreSQL med Ansible
Vi kommer nu att köra spelboken 'postgres-play.yaml' som kommer att installera alla PostgreSQL-relaterade paket och konfigurera det med standardinställningarna.
I det här exemplet kommer Ansible att installera PostgreSQL 9.6 på port 5432, med postgres max_connections inställd på 100. Alla standardinställningar finns i filen /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
Köra spelboken
$ 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
När Ansible har utfört alla uppgifterna, kommer en sammanfattning av uppgiftsexekveringen att visas under SPELA RECAP.
- ok=21, 21 uppgifter utförda utan ändringar.
- changed=14, 14 uppgifter har gjort ändringar i värden, som att installera postgres, skapa kataloger, filer, starta postgres.
- hoppad=32, 32 uppgifter har hoppats över, kan bero på att någon funktion inte var aktiverad. Eftersom vi installerar på entOS, hoppades Ubuntu-relaterade uppgifter över.
Kontrollera PostgreSQL-tjänstens status och konfiguration.
[[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)
Vi har nu installerat PostgreSQL på den hanterade värden "pg01" med standardkonfigurationen.
Ändra PostgreSQL-konfigurationen
Nu kommer vi att konfigurera om PostgreSQL-instansen med våra anpassade inställningar.
Jag har skapat filen custom.yaml (som visas nedan) som har listan över variabler definierade för att ändra PostgreSQL-inställningar som 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
Vi kommer nu att ändra vår spelbok postgres-play.yaml för att använda denna custom.yaml.
$ cat postgres-play.yaml
---
- hosts: postgres_clusters
become: yes
vars_files:
- ./custom.yaml
roles:
- role: anxs.postgresql
Med vars_files-taggar har jag specificerat den anpassade konfigurationsfilen custom.yaml, som kommer att åsidosätta standardkonfigurationen som anges i rollen anxs.postgresql. Mer information om variabel prioritet finns här.
Vi kunde nu köra om samma ansible-playbook-kommando som vi hade kört tidigare, men detta kommer att utföra alla uppgifter som att installera PostgreSQL, konfigurera, skapa användare och databaser. För detta bör vi begränsa Ansible till att endast utföra de uppgifter som är relaterade till PostgreSQL-konfiguration genom att använda alternativet --tags
För att veta listan över taggar som stöds kan vi köra kommandot med --list-taggar.
$ 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]
Från ovanstående taggar kommer vi endast att ange postgresql-configure-taggen för att ändra postgresql-inställningarna.
$ 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
Som du ser i PLAY RECAP har endast 2 ändringar spridits till den hanterade noden pg01. Den första är att uppdatera konfigurationen och den andra är att ladda om konfigurationerna.
Kontrollera att konfigurationsändringarna har trätt i kraft på den hanterade noden.
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)
Som du kan se ändras vissa konfigurationer som listen_addresses, max_connections, wal_level, hot_standby har ännu inte trätt i kraft. Dessa konfigurationsändringar kräver omstart av PostgreSQL och rollen anxs.postgresql har bara laddat om själva tjänsten.
För att undvika en abrupt omstart av PostgreSQL under produktionstid, kanske den ursprungliga författaren inte har lagt till omstartsuppgiften till rollen. Vi kan manuellt starta om postgresql-tjänsten under den schemalagda driftstoppen.
[[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)
Skapa PostgreSQL-användare och databaser
Vi kommer nu att skapa användarna "app1" och "app2" och databaserna "app1_db" och "app2_db" som ägs av användarna "app1" respektive "app2".
Jag har lagt till två nya variabler, postgresql_users och postgresql_database till custom.yaml, som har listan över användare och databaser som måste skapas. Roll anxs.postgresql använder Ansible-modulen postgresql_users och postgresql_db för att skapa användaren och databasen. Du kan hänvisa till dessa dokument för att lägga till variablerna.
$ 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
Vi kommer nu endast att köra de uppgifter som är associerade med taggarna postgresql-users och 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
Verifiera att användarna och databaserna har skapats på den hanterade värden.
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)
Tillåta externa värdar att ansluta till PostgreSQL-servern
Vi kommer nu att tillåta de externa värdarna att ansluta PostgreSQL-tjänsten genom att lägga till variabeln postgresql_pg_hba_custom till custom.yaml
$ cat custom.yaml
...
...
postgresql_pg_hba_custom:
- {type: "host", database: "all", user: "all", address: "0.0.0.0/0", method: "md5" }
Kör uppgifterna taggade med postgresql-configure, för att tillämpa konfigurationen.
$ ansible-playbook -i development.yaml postgres-play.yaml --tags postgresql-configure
Verifierar om jag kan ansluta till PostgreSQL-servern från min kontrollnod.
$ PGPASSWORD=password psql -h pg01 -U app1 -d app1_db -c 'Select true'
bool
------
(1 row)
Slutsats
Den här bloggen bör ge dig grunderna du behöver veta för att använda Ansible för att distribuera och hantera PostgreSQL. Vi har dock bara täckt ett fåtal PostgreSQL-administrationsuppgifter. Beroende på din organisations infrastruktur kan du behöva åsidosätta flera av standardkonfigurationerna och lägga till ännu fler uppgifter till Ansible-rollen.