CentOS8へのPostgresql11のインストール by ansible

# hostsの準備
ansibleのhostsは以下の通り準備しておきます。
<pre>
[ansible@mng053 playbooks]$ cat /etc/ansible/hosts
all:
  children:
    centos8:
      hosts:
        192.168.0.54:
    postgre11:
      hosts:
        192.168.0.54:
</pre>

# Playbookの準備
Playbookは以下の通り

<pre>
[ansible@mng053 playbooks]$ cat /etc/ansible/playbooks/postgresql.yml
⁻⁻⁻
- hosts: postgre11
  vars:
    pg_owner: postgres
    pg_group: postgres
    directory_pgdata: /var/lib/pgsql
  remote_user: root
  tasks:
    - name: test connection
      ping:
    - name: Group Add
      group:
        name: "{{ pg_group}}"
    - name: User Add
      user:
        name: "{{ pg_owner }}"
        group: "{{ pg_group }}"
    - name: Make Directory for DB Cluster
      file:
        path: "{{ directory_pgdata }}"
        state: directory
        owner: "{{ pg_owner }}"
        group: "{{ pg_group }}"
        mode: '0755'
    - name: install Postgresql repository
      dnf:
        name: https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
    - name: install postgresql
      dnf:
        name: postgresql-server,libicu,postgresql-contrib
        enablerepo: pgdg11
        state: latest
    - name: Check DB Cluster
      stat:
        path: "{{ directory_pgdata }}/data/postgresql.conf"
      register: conf_pgdata
    - name: Create DB Cluster
      become: yes
      become_user: "{{ pg_owner }}"
      become_method: su
      shell: /usr/bin/initdb -D "{{ directory_pgdata }}/data"
      when: conf_pgdata.stat.exists == false
    - name: Auto Start
      systemd:
        name: postgresql
        enabled: yes
</pre>

# Playbook(task以下)の解説
##ping
<pre>
    - name: test connection
      ping:
</pre>
疎通確認、ここで失敗すると後続処理が行われないので、まずは疎通確認しておくのがよさそう
##group
<pre>
    - name: Group Add
      group:
        name: "{{ pg_group}}"
</pre>
postgresql用のグループ作成
##user
<pre>
    - name: User Add
      user:
        name: "{{ pg_owner }}"
        group: "{{ pg_group }}"
</pre>
postgresql用のユーザ作成
##file
<pre>
    - name: Make Directory for DB Cluster
      file:
        path: "{{ directory_pgdata }}"
        state: directory
        owner: "{{ pg_owner }}"
        group: "{{ pg_group }}"
        mode: '0755'
</pre>
DBクラスタ用のディレクトリの作成
ディレクトリの作成も「file」モジュールになります。stateで「directory」とすることで、ディレクトリが作成できます。
今回の指定はデフォルト値なのであえて作らなくてもインストール時に作られますが、一応。
##dnf
<pre>
    - name: install Postgresql repository
      dnf:
        name: https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
    - name: install postgresql
      dnf:
        name: postgresql-server,libicu,postgresql-contrib
        enablerepo: pgdg11
        state: latest
</pre>
CentOS8からはyumではなく、dnfのコマンドになります。
1つ目のdnfモジュール処理でPostgreSQLのリポジトリを追加
2つ目のdnfモジュール処理でパッケージ「postgresql-server,libicu,postgresql-contrib」のインストール
PostgreSQLのリポジトリは以下のように複数バージョンあるので、
enablerepoで今回導入したいPostgreSQL11のリポジトリを指定しています。
<pre>
[root@dbpg054 ~]# dnf repolist | grep PostgreSQL
Last metadata expiration check: 0:00:11 ago on Mon 13 Apr 2020 11:35:31 PM JST.
pgdg-common         PostgreSQL common for RHEL/CentOS 8 - x86_64            302
pgdg10              PostgreSQL 10 for RHEL/CentOS 8 - x86_64                274
pgdg11              PostgreSQL 11 for RHEL/CentOS 8 - x86_64                295
pgdg12              PostgreSQL 12 for RHEL/CentOS 8 - x86_64                223
pgdg94              PostgreSQL 9.4 for RHEL/CentOS 8 - x86_64               341
pgdg95              PostgreSQL 9.5 for RHEL/CentOS 8 - x86_64               158
pgdg96              PostgreSQL 9.6 for RHEL/CentOS 8 - x86_64               258
</pre>

##stat
<pre>
    - name: Check DB Cluster
      stat:
        path: "{{ directory_pgdata }}/data/postgresql.conf"
      register: conf_pgdata
</pre>
後続で利用するPostgreSQLのコンフィグファイルのフルパスを「conf_pgdata」としています。

##shell
<pre>
    - name: Create DB Cluster
      become: yes
      become_user: "{{ pg_owner }}"
      become_method: su
      shell: /usr/bin/initdb -D "{{ directory_pgdata }}/data"
      when: conf_pgdata.stat.exists == false
</pre>
shellはコマンド実行をします。initdbコマンドでDBクラスターの作成をします。
さすがにこのモジュールはなかったので致し方なくshellでコマンド実行。

このplaybookでは先頭でremote_user: rootとrootユーザでの接続をしていますが、
ユーザの変更が必要な場合にbecome～の文言でユーザ変更をしています。

whenは実行する条件を指定します。
前述のstatで定義したconf_pgdataのファイルがないことを条件に実行します。

Ansibleは何度同じPlaybookを実行しても同じ結果が得られる（冪等性）ことが前提です。
これをきちんと守るからすっごい楽、とちょっと触って実感しています。

複数回実行してはまずいものはしっかりスキップするような手当が必要です。

## systemd
    - name: Auto Start
      systemd:
        name: postgresql
        enabled: yes
CentOS7から導入されたsystemdでPostgreSQLのOS起動時の自動起動設定を有効化
サービスのファイルはPostgreSQLのインストール時に導入されるものを今回はそのまま利用しているので有効化のみ

# Playbookの実行
実行結果は以下の通り。
<pre>
[ansible@mng053 playbooks]$ ansible-playbook /etc/ansible/playbooks/postgresql.ymml

PLAY [postgre11] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.0.54]

TASK [test connection] *********************************************************
ok: [192.168.0.54]

TASK [Group Add] ***************************************************************
changed: [192.168.0.54]

TASK [User Add] ****************************************************************
changed: [192.168.0.54]

TASK [Make Directory for DB Cluster] *******************************************
changed: [192.168.0.54]

TASK [install Postgresql repository] *******************************************
changed: [192.168.0.54]

TASK [install postgresql] ******************************************************
changed: [192.168.0.54]

TASK [Check DB Cluster] ********************************************************
ok: [192.168.0.54]

TASK [Create DB Cluster] *******************************************************
[WARNING]: Module remote_tmp /home/postgres/.ansible/tmp did not exist and was
created with a mode of 0700, this may cause issues when running as another
user. To avoid this, create the remote_tmp dir with the correct permissions
manually
changed: [192.168.0.54]

TASK [Auto Start] **************************************************************
changed: [192.168.0.54]

PLAY RECAP *********************************************************************
192.168.0.54               : ok=10   changed=7    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

</pre>
postgresにsuした際にWARNINGが出ています。ansible用のディレクトリがないとのことなので、
初回のみ出力される警告ですね。

結果は10タスクOK（うち7つ変更）との結果でした。問題なくてよかった。
2回目実行すると以下の通り。

<pre>
[ansible@mng053 playbooks]$ ansible-playbook /etc/ansible/playbooks/postgresql.yml

PLAY [postgre11] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.0.54]

TASK [test connection] *********************************************************
ok: [192.168.0.54]

TASK [Group Add] ***************************************************************
ok: [192.168.0.54]

TASK [User Add] ****************************************************************
ok: [192.168.0.54]

TASK [Make Directory for DB Cluster] *******************************************
ok: [192.168.0.54]

TASK [install Postgresql repository] *******************************************
ok: [192.168.0.54]

TASK [install postgresql] ******************************************************
ok: [192.168.0.54]

TASK [Check DB Cluster] ********************************************************
ok: [192.168.0.54]

TASK [Create DB Cluster] *******************************************************
skipping: [192.168.0.54]

TASK [Auto Start] **************************************************************
ok: [192.168.0.54]

PLAY RECAP *********************************************************************
192.168.0.54               : ok=9    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
</pre>
DBクラスターの作成がスキップされているので、okは9件、skip1件という結果になりました。

# DBサーバでの結果確認

##サービスの自動起動
自動起動設定がされていることを確認しました。
<pre>
[root@dbpg054 ~]# systemctl list-unit-files | grep postgresql.service
postgresql.service                         enabled
</pre>

## PostgreSQLの起動
停止状態であることを確認して、起動します。
<pre>
[root@dbpg054 ~]# systemctl status postgresql
● postgresql.service - PostgreSQL database server
   Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; vendor >
   Active: inactive (dead)
[root@dbpg054 ~]# systemctl start postgresql
[root@dbpg054 ~]# systemctl status postgresql
● postgresql.service - PostgreSQL database server
   Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; vendor >
   Active: active (running) since Mon 2020-04-13 23:09:50 JST; 27s ago
  Process: 25524 ExecStartPre=/usr/libexec/postgresql-check-db-dir postgresql (>
 Main PID: 25526 (postmaster)
    Tasks: 8 (limit: 11080)
   Memory: 16.1M
   CGroup: /system.slice/postgresql.service
           tq25526 /usr/bin/postmaster -D /var/lib/pgsql/data
           tq25528 postgres: logger process
           tq25530 postgres: checkpointer process
           tq25531 postgres: writer process
           tq25532 postgres: wal writer process
           tq25533 postgres: autovacuum launcher process
           tq25534 postgres: stats collector process
           mq25535 postgres: bgworker: logical replication launcher

Apr 13 23:09:49 dbpg054.localdomain systemd[1]: Starting PostgreSQL database se>
Apr 13 23:09:49 dbpg054.localdomain postmaster[25526]: 2020-04-13 23:09:49.596 >
Apr 13 23:09:49 dbpg054.localdomain postmaster[25526]: 2020-04-13 23:09:49.596 >
Apr 13 23:09:49 dbpg054.localdomain postmaster[25526]: 2020-04-13 23:09:49.672 >
Apr 13 23:09:49 dbpg054.localdomain postmaster[25526]: 2020-04-13 23:09:49.821 >
Apr 13 23:09:49 dbpg054.localdomain postmaster[25526]: 2020-04-13 23:09:49.903
</pre>

正しく起動できました。
本日は、ここまで！

#触ってみた感想
冪等性の意識は超重要。これがAnsibleを手軽に実行できる一つの要素だと思う。
PostgreSQLもAnsibleも初めてだったので、双方のマニュアルを確認しながら、少しずつPlaybookを作りました。
冪等性をしっかり守っていると、Playbookを少し改良しても、同じPlaybookを何度も実行できることが手軽でした。

shellモジュールは最終手段にしたい。なるべく、用意されたモジュールを利用するのがよいと思いました。
通常のモジュールは冪等性をモジュールが担保してくれていますが、shellの場合は自分で作り込みが必要。
自分でどんどん作り込んでしまったら、Ansibleでなくても単純にスクリプトをsshなどで自動実行してしまえば済んでしまうので、Ansible導入の価値が半減するな・・・と思いました。