Ansible er et af de mest kendte og mest udbredte IT-automatiseringsværktøjer, det hjælper os med at automatisere IT-driftsopgaver såsom...
- Opstart af værten (VM eller bare-metal-maskine) fra bunden
- Konfiguration af værter og tjenester
- Administration af softwareimplementeringer og -opgraderinger
- Ansible har også støtte til at orkestrere cloud-infrastrukturen som at oprette en masse EC2- og RDS-instanser til dine applikationer på offentlige skyer (AWS, GCP, Azure). Mere om cloud-provisionering kan findes her
Da denne blog for det meste handler om at administrere PostgreSQL ved hjælp af Ansible, vil vi ikke gå i detaljer med Ansible-brug, dog vil vi gennemgå nogle Ansible-grundlæggende. Jeg anbefaler at gå gennem Ansible-dokumentlinket, hvis du gerne vil vide mere om det.
Ansible Basics
Ansible er et open source-projekt skrevet i python, hvis kildekode er tilgængelig på GitHub. Da det er en python-pakke, kan vi nemt installere Ansible ved hjælp af pip.
Ansible skal kun installeres på én vært, hvorfra vi vil orkestrere vores operationelle opgaver ved hjælp af Ansible-kommandoer (Ansible, Ansible-playbook). Vi kalder denne orkestreringsvært Control Node.
Ansible-kommandoer bruger OpenSSH-biblioteker til at logge ind på målværterne for at udføre operationelle opgaver, vi kalder disse målværter Managed Node. Den administrerede nodes værtsnavn eller IP er nævnt i en fil, der kaldes Inventory, dette inventory-filnavn angives derefter som input til Ansible-kommandoerne.
I inventarfilen kan vi liste flere værter under en enkelt gruppe, dette vil undgå at gentage de samme opgaver flere gange for forskellige værter. Flere detaljer om brugen af inventarfil kan findes her.
Da Ansible-kommandoen bruger SSH til at logge på, er der ingen grund til at installere Ansible på hele værten, den skal kun installeres på kontrolnoden. Imidlertid bør alle kontrolknuder og administrerede knudepunkter have python og eventuelle nødvendige pythonbiblioteker installeret. Mere om Ansible-installationen kan findes her.
Til demoen vil jeg bruge en bærbar computer som kontrolknudepunkt og gæst CentOS-7 VM som den administrerede node. CentOS-7 VM blev klargjort ved hjælp af Vagrant på udbyderen VirtualBox.
Installation af Ansible på kontrolnoden
Vi installerer Ansible ved hjælp af pip som refereret til på Ansible-dokumentsiden. Følgende kommandoer blev udført som "Ansible" bruger.
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py --user
Ved at bruge --user option installeres pip- og Ansible-kommandoer under HOME-mappen, og vi skal tilføje bin-stien til vores PATH-miljøvariabel.
$ echo 'export PATH=$HOME/Library/Python/2.7/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile
Følgende pip-kommando har installeret Ansible version 2.8.0 (som er den seneste stabile version på tidspunktet for skrivning af denne blog.)
$ pip install --user ansible
$ which ansible
/Users/Ansible/Library/Python/2.7/bin/Ansible
$ ansible --version
Ansible 2.8.0
...
...
Kontrol node og Managed Node Prechecks
Sørg for, at du har en ordentlig netværksforbindelse mellem kontrolnoden og den administrerede node.
Tjek din firewall for regler, der kan blokere indgående og udgående forbindelser på SSH-porten, hvis det er tilfældet, åbn SSH-porten for at give adgang til både kontrol- og administrerede noder.
Prøv først at oprette forbindelse via SSH til den administrerede node. Du bør være i stand til at logge ind på den administrerede node fra kontrolnoden.
Du kan konfigurere den adgangskodeløse SSH-adgang til de administrerede noder i henhold til din organisations sikkerhedspolitikker. Til denne demo har jeg konfigureret uden adgangskode til SSH til min administrerede node "pg01" (CentOS-7) for brugeren "vagrant". Dette gør, at den administrerede node har sudo-kraften, de fleste af installations- og værtskonfigurationsopgaverne vil blive udført som "vagrant"-bruger med "sudo".
På kontrolnoden har vi konfigurationsfilen ansible.cfg, som vil blive brugt af Ansible kommandoerne. Nedenfor er nogle konfigurationsmuligheder, som er defineret i konfigurationsfilen. For at lære mere om de andre tilgængelige konfigurationsmuligheder, tjek eksempelkonfigurationsfilen.
- remote_port - Hvis SSH-serveren på den administrerede node kører på en anden port end standardport 22, kan vi ændre den
- remote_user - Login-brugernavnet, der vil blive brugt af Ansible til at forbinde den administrerede node til at køre opgaverne
- private_key_file - SSH privat nøgle, som vil blive brugt til Ansible at logge ind
Da ovennævnte konfiguration gælder globalt for alle de administrerede noder, hvis vi ønsker at have en anden konfiguration for en specifik vært eller værtsgruppe, kan vi angive dem i inventarfilen. Du kan se et eksempel på dette nedenfor i "development.yaml" inventarfilen.
Udførelse af et Ansible tørløb
Opret en inventarfil "development.yaml" som vist nedenfor.
$ 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 inventarfilen ovenfor er vært pg01 et af medlemmerne af værtsgruppen postgres_clusters. Variablerne ansible_port, ansible_user og ansible_private_key_file gælder kun for værterne under gruppen postgres_clusters.
Vi vil nu kontrollere, om Ansible kan køre opgaverne på den administrerede node. I eksemplet nedenfor udfører ansible-kommandoen modul-ping på den administrerede node pg01, hvis Ansible var i stand til at køre modul-ping, skulle 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ører på den administrerede node som den første opgave, indsamler den information som værtsnavn, IP-adresse, hukommelsen på den administrerede node. For at kontrollere disse kan vi kalde modulopsætningen, som ville returnere en stor JSON. Vi kan gøre brug af enhver af disse i vores Ansible-spillebog.
$ 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 Rolle
Ansible Role er en måde at samle et bestemt sæt af relaterede opgaver og konfigurationsindstillinger i én enkelt enhed blot ved at tildele en rolle til en bestemt vært eller værtsgruppe. Ansible vil anvende alle de relaterede konfigurationer og opgaver. Dette undgår at gentage opgaverne flere gange for hver forskellig vært eller værtsgruppe.
Hver rolle er repræsenteret som en mappe, og i rollemappen vil der være undermapper som standardfiler, handlere, meta, opgaver, skabeloner, tests, vars. Formålet med disse mapper kan findes her.
Ansible kommandoer, som standard, søg i rollebiblioteket under stierne nævnt 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 er en portal, hvor fællesskabets folk deler GitHub-lageret med deres Ansible-roller. Vi kan gennemse galakseportalen efter de nødvendige Ansible-roller. Ved at bruge kommandoen ansible-galaxy kunne vi downloade og genbruge rollen. Før du bruger en rolle, skal du gennemgå alle Ansible YAML-filer i detaljer under mapperne defaults, vars, tasks, templates, handlers og være opmærksom på, hvordan rollen fungerer.
Til vores udrulning af PostgreSQL vil vi bruge rollen "postgresql" udviklet af forfatteren ANXS og GitHub repo.
Installerer 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
Ovenstående kommando installerer rollemappen "anxs.postgresql" under mappen "/Users/ansible/.Ansible/roles", dette er en af mapperne i DEFAULT_ROLES_PATH, og ansible-kommandoen vil søge i denne mappe for alle roller.
Ansible Playbook
En Ansible Playbook er en YAML-fil, hvori vi vil liste de opgaver eller roller, som skal udføres på en bestemt vært eller værtsgruppen. Du kan læse mere om udvikling af playbooks samt lære definitionen af tags som værter, opgaver, roller, vars her.
Som standard udføres alle opgaver som den mulige bruger, der har logget ind. For at udføre bestemte opgaver med en anden bruger (eller med 'root'-privilegium), kan vi gøre brug af blive. Hvordan man bruger denne kommando kan findes her.
I playbook nedenfor (postgres-play.yaml) har jeg angivet rollen "anxs.postgresql" under værtsgruppen "postgres_clusters", så alle opgaverne i rollen anxs.postgresql vil blive udført for alle værterne under gruppen "postgres_clusters".
$ cat postgres-play.yaml
---
- hosts: postgres_clusters
become: yes
roles:
- role: anxs.postgresql
bliver:ja i YAML definerer, at denne rolle vil blive udført med højere privilegier ved at bruge 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 kører denne afspilningsbog som brugerens "vagrant", og brugeren var allerede klaret med sudo-kraft.
[[email protected] ~]$ sudo cat /etc/sudoers.d/vagrant
%vagrant ALL=(ALL) NOPASSWD: ALL
Severalnines DevOps Guide til Database Management Lær om, hvad du skal vide for at automatisere og administrere dine open source-databaser. Download gratis Implementering af PostgreSQL ved hjælp af Ansible
Vi vil nu køre playbook 'postgres-play.yaml', som vil installere alle PostgreSQL-relaterede pakker og konfigurere den ved hjælp af standardindstillingerne.
For dette eksempel vil Ansible installere PostgreSQL 9.6 på port 5432, med postgres max_connections sat til 100. Alle standardindstillingerne kan findes 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øre afspilningsbogen
$ 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 udført alle opgaverne, vil en oversigt over opgaveudførelserne blive vist under PLAY RECAP.
- ok=21, 21 opgaver udført uden ændringer.
- ændret=14, 14 opgaver har foretaget ændringer på værten, som at installere postgres, oprette mapper, filer, starte postgres.
- sprunget over=32, 32 opgaver er blevet sprunget over, kan skyldes, at en funktion ikke var aktiveret. Da vi installerer på entOS, blev Ubuntu-relaterede opgaver sprunget over.
Tjek PostgreSQL-tjenestestatus og -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 installeret PostgreSQL på den administrerede vært "pg01" ved hjælp af standardkonfigurationen.
Ændring af PostgreSQL-konfigurationen
Nu vil vi omkonfigurere PostgreSQL-instansen ved hjælp af vores brugerdefinerede indstillinger.
Jeg har oprettet en custom.yaml-fil (som vist nedenfor), som har listen over variabler defineret til at ændre PostgreSQL-indstillinger 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 vil nu ændre vores playbook postgres-play.yaml til at bruge denne custom.yaml.
$ cat postgres-play.yaml
---
- hosts: postgres_clusters
become: yes
vars_files:
- ./custom.yaml
roles:
- role: anxs.postgresql
Ved at bruge vars_files-tags har jeg specificeret den brugerdefinerede konfigurationsfil custom.yaml, som vil tilsidesætte standardkonfigurationen angivet i rollen anxs.postgresql. Flere detaljer om variabel prioritet kan findes her.
Vi kunne nu køre den samme ansible-playbook-kommando igen, som vi havde udført tidligere, men dette vil udføre alle opgaver som at installere PostgreSQL, konfigurere, oprette brugere og databaser. Til dette bør vi begrænse Ansible til kun at udføre opgaver relateret til PostgreSQL-konfiguration ved at bruge --tags
For at kende listen over understøttede tags, kunne vi køre kommandoen med --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]
Fra ovenstående tags vil vi kun specificere postgresql-configure tag for at ændre postgresql indstillingerne.
$ 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 kan se i PLAY RECAP, har kun 2 ændringer forplantet sig til den administrerede node pg01. Den første er at opdatere konfigurationen og den anden er at genindlæse konfigurationerne.
Bekræft, at konfigurationsændringerne er trådt i kraft på den administrerede node.
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, ændres nogle konfigurationer som listen_addresses, max_connections, wal_level, hot_standby endnu ikke trådt i kraft. Disse konfigurationsændringer kræver en PostgreSQL-genstart, og rollen anxs.postgresql har kun genindlæst selve tjenesten.
For at undgå en brat genstart af PostgreSQL i produktionstiden, har den oprindelige forfatter muligvis ikke tilføjet genstartsopgaven til rollen. Vi kan manuelt genstarte postgresql-tjenesten under den planlagte nedetid.
[[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)
Oprettelse af PostgreSQL-brugere og -databaser
Vi vil nu oprette brugerne "app1" og "app2" og databaserne "app1_db" og "app2_db", der ejes af henholdsvis brugerne "app1" og "app2".
Jeg har tilføjet to nye variabler, postgresql_users og postgresql_database til custom.yaml, som har listen over brugere og databaser, som skal oprettes. Rolle anxs.postgresql bruger Ansible-modulet postgresql_users og postgresql_db til at oprette brugeren og databasen. Du kan henvise til disse dokumenter for at tilføje variablerne.
$ 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 vil nu kun køre de opgaver, der er forbundet med tags postgresql-users og 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
Bekræft, at brugerne og databaserne er oprettet på den administrerede vært.
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)
Tillade eksterne værter at oprette forbindelse til PostgreSQL-serveren
Vi vil nu tillade de eksterne værter at forbinde PostgreSQL-tjenesten ved at tilføje variablen postgresql_pg_hba_custom til custom.yaml
$ cat custom.yaml
...
...
postgresql_pg_hba_custom:
- {type: "host", database: "all", user: "all", address: "0.0.0.0/0", method: "md5" }
Kørsel af opgaverne tagget med postgresql-configure for at anvende konfigurationen.
$ ansible-playbook -i development.yaml postgres-play.yaml --tags postgresql-configure
Bekræfter, om jeg er i stand til at oprette forbindelse til PostgreSQL-serveren fra min kontrolnode.
$ PGPASSWORD=password psql -h pg01 -U app1 -d app1_db -c 'Select true'
bool
------
(1 row)
Konklusion
Denne blog bør give dig det grundlæggende, du skal vide for at bruge Ansible til at implementere og administrere PostgreSQL. Vi har dog kun dækket nogle få PostgreSQL-administrationsopgaver. Afhængigt af din organisations infrastruktur skal du muligvis tilsidesætte flere af standardkonfigurationerne og tilføje endnu flere opgaver til Ansible-rollen.