13分でPostgreSQLの冗長化構成をAnsibleで高速構築してみた!

こんにちは、サイオステクノロジーでLifeKeeperのプリセールスを担当している宇野です。

LifeKeeper for Linux9.5.0より強化された、LifeKeeperのCLI(コマンドラインインターフェイス)とAnsibleを使って、PostgreSQLの冗長構成をVMware上に構築してみました。今回、その手順を共有いたします。

1.  はじめに

HAクラスタソフトであるLifeKeeper for Linux をAnsibleで自動構築したい、という要望を以前よりたくさんいただいておりました。この背景には、50ノード(25クラスター)を数えるような、大規模なHAクラスター案件での導入が増えているためで、ほぼ同じ構成をいくつも構築しなければならず、なんとか効率化したいというものでした。

2020年5月にリリースした、LifeKeeper for Linux v9.5.0にて、従来提供していたCLIを刷新し、Ansibleなどを使って、より簡単に操作できるようにいたしました。今回、VMware環境上に、PostgreSQLを冗長化する構成をAnsibleで構築してみましたので、ぜひご参考ください。

2.  Ansibleで冗長化構成を構築するメリット

構築に入る前に、そもそもAnsibleで冗長化構成を構築すると何が嬉しいのかを、自身の経験も含めて改めて整理してみました。主に以下3つに集約されるかなと思います。

    1. 手作業に比べ、構築時間が大きく削減できる
    2. 構築時の設定ミスや作業漏れを防げ、構築品質を平準化しやすい
    3. 大量のクラスタノード構築時にチェック作業を大幅に簡素化できる

従来の手作業による構築と比べてどう嬉しいのか、もっと具体的に言うとこのようになります。

手動構築と自動構築の比較

手動構築 Ansibleで自動構築
1.構築時間(コスト) 約2時間 約13分
2.構築品質 構築者の技量によってバラつき 誰が行っても一定の品質
3.チェック作業 作業漏れがないよう
毎回チェックシートの運用が必要
1回目の確認で漏れが無ければ、
2回目以降のチェックはほぼ不要

やはり、なんといっても構築時間の短縮です。今回のケースでは、構築時間が約1/9となりました。同様の構成の場合、ノード数が増えれば増えるほどこの効果が高まります。加えてお伝えしたいのが、構築の品質とチェック作業です。私も長年LifeKeeper for Linux の導入作業には携わってきましたが、設定ミスや運用時の作業漏れが無いか、チェック体制やパラメータの管理は大丈夫か、など、大変気を遣う作業が多いです。そのため、構築品質と構築効率の向上は、現場のエンジニアにとっても大変嬉しい話なのではないかと考えます。

なお、Ansibleを使った自動構築のやってみた記事として、仮想環境でのPacemaker, Corosync, DRBDの自動構築もございますので、合わせてご参考ください。

3.  Playbookの構成

前置きが長くなりましたが、以降、仮想マシンテンプレートからデプロイ、LifeKeeper for Linux の導入、リソースの作成などをAnsibleで自動化していきます。

ご紹介する手順は2ノードクラスターを構築するplaybookになっていますが、複数クラスターを自動的に構成することも想定しています。そのため以下のような処理を行うplaybookの作成を試みました。

    1. 1つのVMテンプレートから2ノード分デプロイ
    2. 各ノードを任意のホスト名、IPアドレスへ変更
    3. LifeKeeper for Linuxのインストール準備
    4. LifeKeeper for Linuxのインストール
    5. コミュニケーションパスの作成
    6. ミラーリング用ディスクの準備
    7. PostgreSQLのインストール
    8. IP, DataKeeper, PostgreSQLリソースの作成
    9. PostgreSQL, IPリソースの依存関係作成

4.  環境

今回利用したVMware環境、Ansibleサーバー、テンプレートイメージを以下に紹介します。
*4章以降で紹介するコマンドラインは全てrootユーザーで実行しています。

4-1. VMware ESXi Server

ハイパーバイザー VMware ESXi, 7.0.0, 15843807 2台
VMware vCenter Server Appliance 7.0.0.10100 1VM
共有ストレージ VMFS6 1台
仮想マシン 1台
仮想マシンテンプレート 1台

4-2.   Ansibleサーバー

Ansible管理サーバー
仮想マシン
CPU 1CPU
メモリ 2GB
ハードディスク 16GB X1
ネットワークアダプタ ens192(10.0.0.1/16)
ens224(192.168.0.1/24)
互換性 ESXi7.0以降(VMバージョン17)
OS CentOS8.2
追加アプリケーション python3-pip, pyVmomi

AnsibleでVMwareの管理を行うときはpyVmomiを使用します。pyVmomiはVMware vSphere API の公式の Python SDK であり、VMware環境の管理で必要なPython SDKです。pyVmomiはpipを使用して導入します。そのためAnsibleサーバーには以下のパッケージを追加でインストールします。

dnf install python3-pip

追加したpipを使用してpyVmomiをインストールします。

/usr/bin/pip3.6 install ansible pyvmomi

以下はLifeKeeper for Linux のインストールに利用するインストールイメージやレスポンスファイル、ライセンスファイルです。Ansibleサーバーから各ノードにコピーして使用しますので、事前に/root/siosディレクトリを作成して以下のようにファイルを保管します。

LKCONF:LifeKeeper のインストール用のレスポンスファイル。LifeKeeper for Linuxを自動インストールで利用するテンプレートファイルです。以下のように事前に作成して保管します。

1.以下のダウンロード先から create_response_file スクリプトを入手してください。
自動インストール用設定 作成ツール

2.レスポンスファイルのファイル名を指定して、create_response_file スクリプトを実行します。

./create_response_file /root/lifekeeper/LKCONF

3.create_response_file スクリプトを起動すると、以下のメニュー画面が表示されます。

4. 必要な設定を選択してださい。

      • Install Java Runtime (JRE) の選択
      • Recovery Kit Selection Menu でインストールする Recovery Kit の選択

5. 設定後、< Done > を選択してください。その後、< Yes > を選択し終了します。

6. 生成された LKCONF ファイルを確認し、設定が正しいことを確認してください。以下はPostgreSQL Recovery Kits、DataKeeper for Linux Recovery Kits を選択した場合のレスポンスファイルです。今回は以下の内容のファイルを作成して使用しました。

# LifeKeeper setup response file
# DO NOT EDIT MANUALLY
LKCONF_INSTALL_JRE=”y”
LKCONF_SELONLY=”y”
LKCONF_AUTH=”y”
LKCONF_LKUSER_lkadmin=”root”
LKCONF_steeleye_lkPGSQL=”y”
LKCONF_steeleye_lkDR=”y”

20210120lkl-evalkeys-30day.txt:評価版ライセンスファイル。ライセンスファイルはどのようなファイル名でも問題ありません。適用するライセンスをホスト名毎のディレクトリを作成して保管してください。

sps_951.img:LifeKeeper for Linux 9.5.1インストールイメージです。ISOイメージの中に保管されています。

4-3.テンプレート

クラスターノード用仮想マシンテンプレート CPU 1CPU
メモリ 2GB
ハードディスク 16GB X1
10GB X1 (/dev/sdb)
ネットワークアダプタ ens192(10.0.0.1/16)
ens224(192.168.0.100/24)
互換性 ESXi7.0以降(VMバージョン17)
OS CentOS7.9

追加作業

Ansible管理用OSの公開キーを登録

今回の構成では以下の準備を行ってから、テンプレートに変換します。

  • Ansible管理用サーバーからクラスターノードにsshで接続して設定を行います。その際にパスワードの入力が不要となるようVMテンプレートに対してAnsible管理用サーバーのssh公開キーを登録します。
  • ネットワーク経路は2経路用意してください。それぞれAnsible管理用サーバーの各NICから接続できる同じネットワークセグメントのIPアドレスを設定します。
  • ディスクは2種類用意しましたが、/dev/sdbにあたる10GBのディスクはレプリケーションで使用します。OSのインストール時には使用しないでください。
  • OSのインストールは最小のパッケージ(minimal-environment)で行っています。必要なパッケージはLifeKeeperインストール時に自動的にインストールを行いますので、yumが利用可能な状態にしてください。
  • 仮想マシンテンプレートは2台のESXiホストのどちらからでもアクセスできるよう共有ディスク(VMFS6)に配置してください。

構成図としては以下のようなイメージです。

5.手順

複数クラスターへのデプロイの自動化へと応用できるように、デプロイ元の仮想マシンテンプレートを1つだけとしました。デプロイ後にホスト名、IPアドレスを変更してクラスターノードとして利用します。
以下の手順のplaybookを作成しました。それぞれ紹介します。

  1. VMテンプレートからnode1をデプロイ
  2. node1のホスト名、IPアドレスを変更
  3. VMテンプレートからnode2をデプロイ
  4. node2のホスト名、IPアドレスを変更
  5. LifeKeeper for Linuxのインストール
     ライセンスの適用、LifeKeeper for Linuxの起動
     コミュニケーションパスの作成
  6. ミラーリング用ディスクの準備
     Broadcast pingをオフに変更
     PostgreSQLのインストール、DBの作成
  7. DataKeeperリソースの作成
  8. IPリソースの作成
  9. PostgreSQLリソースの作成
     PostgreSQLリソースとIPリソースの依存関係作成

5-1. Ansible playbookファイルツリー

今回の処理を行うplaybookファイルのツリー構造です。以下のファイルツリー構造で各処理が行われるようにメインのPlaybookファイル”main.yml”が作成されています。

ファイルの役割は以下です。

5-2. inventory

Ansibleサーバーが接続するグループを指定します。playbookで指定したhostsカラムで指定したグループに対してタスクを実行します。

[local]
localhost.localdomain

[nodes]
un087.localdomain
un088.localdomain

[node1]
un087.localdomain

[node2]
un088.localdomain

[template]
192.168.135.81

5-3. main.yml

ansible_playbookコマンドで直接指定するYAMLフォーマットのplaybookファイルです。内部では処理毎にタスク分けされていて必要なファイルを呼び出してそれぞれの処理を行います。以下のファイルを指定することでVMのデプロイからリソースの依存関係作成までの処理が行われる内容になっています。なお各処理のタイトルを表示するのが”– name:” の項目ですが、タイトルが日本語だったり英語だったり統一感はないです。ご了承ください。

– name: Create Virtual Machine(Source node)
  hosts: local
  gather_facts: false
  tasks:
    – include_vars: vars/vmware_info.yml
    – include_vars: vars/template_node1_info.yml
    – include_tasks: vmware/deploy_guestvm.yml

– name: Edit Primary IP and Hostname(Source node).
  hosts: template
  tasks:
    – include_vars: vars/network_info.yml
    – include_vars: vars/template_node1_info.yml
    – include_tasks: vmware/edit_priip_hostname.yml

– name: Edit Secondary IP(Source node).
  hosts: node1
  tasks:
    – include_vars: vars/network_info.yml
    – include_vars: vars/template_node1_info.yml
    – include_tasks: vmware/edit_secip.yml

– name: Create Virtual Machine(Target node)
  hosts: local
  gather_facts: false
  tasks:
    – include_vars: vars/vmware_info.yml
    – include_vars: vars/template_node2_info.yml
    – include_tasks: vmware/deploy_guestvm.yml

– name: Edit Primary IP and Hostname(Target node).
  hosts: template
  tasks:
    – include_vars: vars/network_info.yml
    – include_vars: vars/template_node2_info.yml
    – include_tasks: vmware/edit_priip_hostname.yml

– name: Edit Secondary IP(Target node).
  hosts: node2
  tasks:
    – include_vars: vars/network_info.yml
    – include_vars: vars/template_node2_info.yml
    – include_tasks: vmware/edit_secip.yml

– name: deploy and install lifekeeper on all targets
  hosts: nodes
  tasks:
    – include_vars: vars/works.yml
    – include_vars: vars/template_node1_info.yml
    – include_vars: vars/template_node2_info.yml
    – include_tasks: lk_install/hosts.yml
    – include_tasks: lk_install/firewall.yml}
    – include_tasks: lk_install/selinux.yml
    – include_tasks: lk_install/deploy.yml
    – include_tasks: lk_install/mount.yml
    – include_tasks: lk_install/install.yml
    – include_tasks: lk_install/bash_profile.yml
    – include_tasks: lk_install/license.yml
    – include_tasks: lk_install/lkstart.yml
    – include_tasks: lk_install/clean.yml

– name: create communication path on source
  hosts: node1
  tasks:
    – include_vars: vars/template_node1_info.yml
    – include_tasks: commpath/add_source_compath.yml

– name: create communication path on target
  hosts: node2
  tasks:
    – include_vars: vars/template_node2_info.yml
    – include_tasks: commpath/add_target_compath.yml

– name: create partition
  hosts: nodes
  tasks:
    – include_vars: vars/disk_info.yml
    – include_tasks: datakeeper/disk.yml

– name: Broadcast ping off/Install postgreSQL server and create DB.
  hosts: nodes
  tasks:
  – include_tasks: ip/nobcastping.yml
  – include_tasks: postgresql/inst_pgsql.yml

– name: Create Resources.(DataKeeper, IP, PostgreSQL)
  hosts: node1
  tasks:
   – include_vars: vars/disk_info.yml
   – include_vars: vars/vip_info.yml
   – include_vars: vars/template_node1_info.yml
   – include_vars: vars/template_node2_info.yml
   – include_vars: vars/pgsql_info.yml
   – include_tasks: datakeeper/new_replication.yml
   – include_tasks: ip/ip_resource.yml
   – include_tasks: postgresql/init_db.yml
   – include_tasks: postgresql/pgsql_resource.yml
   – include_tasks: dependency/create_dep_resources.yml

実際に実行する際は以下のようにコマンドを実行します。

ansible-playbook main.yml -i inventory

5-4. varsディレクトリ

playbookの中で呼び出される変数を定義したファイルを保管するディレクトリです。playbook内でinclude_varsカラムを指定して利用されます。

  • vars/disk_info.yml

DataKeeperリソース関連の変数を定義しています。

# レプリケーション用デバイス
disk_device: /dev/sdb
# パーティション番号(ex. sdb1 の1)
disk_num: 1
# パーティションタイプ
disk_label: gpt
# ファイルシステム
disk_fstype: ext4
# レプリケーションリソースタグ
dk_tag: replication-sdb1
# 同期モード
sync_mode: synchronous
# レプリケーションタイプ
rep_type: new
# マウントポイント
mount_dir: /pgdata
# ファイルシステムリソースタグ
fs_tag: /pgdata

  • vars/network_info.yml

各ノードで共通のネットワーク情報を変数として定義しています。

# プライマリIPアドレスNIC
pri_nic: ens192
# セカンダリIPアドレスNIC
sec_nic: ens224
# Default Gateway
pri_gateway: 10.125.0.1
# DNS Server
pri_dns: 10.125.0.1,10.125.0.3

  • vars/pgsql_info.yml

PostgreSQLリソースを作成するために必要な情報を変数として定義しています。

# postgresql server port.
pg_port: 5432               
# postgresql data directory.
initdb_dir: “{{ mount_dir}}/data1”
# postgresql socket file
socket_file: /tmp/.s.PGSQL.5432
# postgresql server 実行ユーザー
pg_user: postgres
# postgresql server LifeKeeper: log.
lk_pg_log: pgsql-lk.log

  • vars/template_node1_info.yml

VMをデプロイする際にnode1(アクティブノード)として変換するために必要な情報を変数として定義しています。

# 作成するVM Name
vm_name: dbv-rh79-1
# 展開する ESXi Server
deploy_esxi_host: 10.125.128.2
# node1 の新しいプライマリIPアドレス
node1_pri_ip: 10.125.135.87
# node1 の新しいプライマリIPアドレス Prefix
node1_pri_prefix: 24
# node1 の新しいセカンダリIPアドレス
node1_sec_ip: 192.168.135.87
# node1 の新しいセカンダリIPアドレス Prefix
node1_sec_prefix: 24
# node1 new ホスト名
node1_hostname: un087.localdomain
# 置き換え(*編集不要)
pri_ip: “{{ node1_pri_ip }}”
pri_prefix: “{{ node1_pri_prefix }}”
sec_ip: “{{ node1_sec_ip }}”
sec_prefix: “{{ node1_sec_prefix }}”
new_hostname: “{{ node1_hostname }}”

  • vars/template_node1_info.yml

VMをデプロイする際にnode2(スタンバイノード)として変換するために必要な情報を変数として定義しています。

# 作成するVM Name
vm_name: dbv-rh79-2
# 展開する ESXi Server
deploy_esxi_host: 10.125.128.3
# node2 の新しいプライマリIPアドレス
node2_pri_ip: 10.125.135.88
# node2 の新しいプライマリIPアドレス Prefix
node2_pri_prefix: 24
# node2 の新しいセカンダリIPアドレス
node2_sec_ip: 192.168.135.88
# node2 の新しいセカンダリIPアドレス Prefix
node2_sec_prefix: 24
# node2 new ホスト名
node2_hostname: un088.localdomain
# 置き換え(*編集不要)
pri_ip: “{{ node2_pri_ip }}”
pri_prefix: “{{ node2_pri_prefix }}”
sec_ip: “{{ node2_sec_ip }}”
sec_prefix: “{{ node2_sec_prefix }}”
new_hostname: “{{ node2_hostname }}”

  • vars/vip_info.yml

IPリソースを登録するために必要な情報を変数として定義しています。

# 仮想IPアドレス
vip: 10.125.135.86
# 仮想IPアドレスのネットマスク
netmask: 255.255.255.0
# uni cast ping 送信先(pinglist) *複数の場合はカンマ(,)で区切る
target_ip: 10.125.135.10

  • vars/vmware_info.yml

IPリソースを登録するために必要な情報を変数として定義しています。

# vCenter ホスト
vcenter_hostname: vcsa.localdomain
# vCenter ログインアカウント
vcenter_username: administrator@vsphere.local
# vCenter ログインアカウントパスワード
vcenter_password: ********************
# データセンター名
vcenter_datacenter: Datacenter
# VMの保管先
deployed_folder: “/Datacenter/vm/個人用/tuno”
# 展開元のテンプレート
vm_template: dbv-temp79

  • vars/works.yml

LifeKeeperをインストールするために必要な準備をするための情報を変数として定義しています。firewallは有効な状態で最低限のポートを有効にします。postgresqlで使用する5432も開けていません。必要な場合はlk_portに追記してください。

# control-node側でインストールに必要なファイルを保存しておくディレクトリ
control_node_dir: /root/sios
# ターゲット側でインストールに一時的に必要なファイルを保存しておくディレクトリ
target_dir: /tmp/lifekeeper
# CentOS7.9 DataKeeper用patchのダウンロードURL
patch_url:https://lkdkuserportal.sios.jp/hc/article_attachments/900004959446/lk-rhel7_9-support
# ターゲット側でインストールイメージのマウントディレクトリ
target_mnt: /sps
# LifeKeeper/DataKeeper が利用して公開するポート
lk_ports: [ 7365/tcp, 10001-49151/tcp ]

5-5. 仮想マシンテンプレートのデプロイ / vmwareディレクトリ

main.ymlファイルは上から順番に読み込まれます。最初はvmwareディレクトリ内にある処理を実行します。ここではVMを2台作成して、それぞれのホスト名、IPアドレスの変更が行われます。なおansibleで接続先のIPアドレスの変更した場合セッションが途切れてしまう問題を引き起こします。

この問題を回避するため、クラスターシステムの特性でもある異なる複数のネットワーク構成を活用しています。1回目の接続ではNIC2から接続を行い、NIC1,hostnameの変更を行います。2回目の接続でNIC2のIPアドレスを変更して、以降の処理は変更したNIC1への接続を使用します。ただこの処理はIPアドレスの重複を避けるためシーケンシャルに実行しますのでPlaybook(main.yml)の内容は以下のように冗長になります。

  1. アクティブノード用のVMの作成
  2. アクティブノード用プライマリIPアドレス、ホスト名の変更(接続はNIC2から).
  3. アクティブノード用セカンダリIPアドレスの変更(接続はNIC1から).
  4. スタンバイノード用のVMの作成
  5. スタンバイノード用プライマリIPアドレス、ホスト名の変更(接続はNIC2から).
  6. スタンバイノード用セカンダリIPアドレスの変更(接続はNIC1から).

main.ymlの処理では以下に該当します。

上記で読み込まれるvmwareディレクトリ内のPlaybookファイルを説明します。

  • deploy_guestvm.ym

仮想マシンテンプレートを使用してデプロイするplaybookです。

– name: vCenterに接続してVMを作成
  vmware_guest:
    name: “{{ vm_name }}”
    hostname: “{{ vcenter_hostname }}”
    username: “{{ vcenter_username }}”
    password: “{{ vcenter_password }}”
    datacenter: “{{ vcenter_datacenter }}”
    folder: “{{ deployed_folder}}”
    validate_certs: false
    template: “{{ vm_template }}”
    state: poweredon             # 起動状態にする
    esxi_hostname: “{{ deploy_esxi_host }}”
    wait_for_ip_address: yes
  delegate_to: localhost

  • edit_priip_hostname.yml

プライマリIPアドレスとホスト名の変更を行うplaybookです。この処理を行う際はセカンダリIPアドレスに接続して行います。

– name: プライマリIPアドレスの変更
  command: nmcli connection modify {{ pri_nic }} ipv4.method manual ipv4.addresses {{ pri_ip }}/{{ pri_prefix }} ipv4.gateway {{ pri_gateway }} ipv4.dns {{ pri_dns }}

– name: プライマリIPアドレスの更新
  shell: sleep 1; ifdown {{ pri_nic }} && ifup {{ pri_nic }}
  async: 5
  poll: 0

– name: ホスト名 “{{ new_hostname }}”への変更.
  become: true
  hostname:
    name: “{{ new_hostname }}”

  • edit_secip.yml

セカンダリIPアドレスの変更を行うplaybookです。この処理を行う際は上記のplaybookで変更したプライマリIPアドレスに接続して行います。

– name: プライマリIPアドレスの変更
  command: nmcli connection modify {{ pri_nic }} ipv4.method manual ipv4.addresses {{ pri_ip }}/{{ pri_prefix }} ipv4.gateway {{ pri_gateway }} ipv4.dns {{ pri_dns }}

– name: プライマリIPアドレスの更新
  shell: sleep 1; ifdown {{ pri_nic }} && ifup {{ pri_nic }}
  async: 5
  poll: 0

– name: ホスト名 “{{ new_hostname }}”への変更.
  become: true
  hostname:
    name: “{{ new_hostname }}”

5-6. LifeKeeperのインストール / lk_installディレクトリ

lk_installディレクトリはLifeKeeper for Linuxのインストールの準備、インストール、LifeKeeperの起動までの手順となります。これらの手順はLifeKeeper for Linuxのテクニカルドキュメント(以下のURL)で公開していますので、テクニカルドキュメントの内容をベースにして手順を作成しています。

https://docs.us.sios.com/spslinux/9.5.1/ja/topic/setting-up-lifekeeper-with-ansible

main.ymlの中では以下の処理が該当します。

lk_installディレクトリには以下のファイルが保管されています。

  • hosts.yml

hosts.ymlはLifeKeeper for Linux のインストールに必要な名前解決の設定を各ノードに対して行います。最低限の登録としてアクティブノードとスタンバイノードのみ追加します。

# /etc/hostsにansibleを実行対象のホストをすべて登録する
– name: update /etc/hosts
  lineinfile:
    dest: /etc/hosts
    state: present
    insertafter: EOF
    regexp: “^{{ item.address }}”
    line: “{{ item.address }}\t{{ item.hostname }}”
  with_items:
    – address: “{{ node1_pri_ip }}”
      hostname: “{{ node1_hostname }}”
    – address: “{{ node2_pri_ip }}”
      hostname: “{{ node2_hostname }}”

  • firewall.yml

firewall.ymlはLifeKeeper for Linux のインストールに必要なポートをオープンにします。lk_portはvars ディレクトリ内でリストとして登録されていますので、追加でオープンしたいポートの追加も容易に可能です。

 

– name: enable lifekeeper port
  firewalld:
    zone: public
    port: “{{ item }}”
    permanent: yes
    state: enabled
  register: firewalld
  with_items:
    – “{{ lk_ports }}”

– name: reload
  command: firewall-cmd –reload
  when: firewalld.changed

なお今回はGUIを使用する想定では無いため、LifeKeeper for Linuxで利用するGUI関連のポートは公開していません。GUIを利用する予定がある場合は以下を参考にGUI関連のポートもオープンしてください。

[Linux]LifeKeeperが使用するポート
https://lkdkuserportal.sios.jp/hc/ja/articles/360037514152

  • selinux.yml

selinux.ymlはselinuxの設定を”disable”に変更します。変更後にシステムの再起動を行います。既に設定済みの場合は変更されませんので再起動も発生しません。

– name: disable SELinux
  become: yes
  selinux: state=disabled
  register: selinux

– name: reboot a node
  become: yes
  reboot:
  when: selinux.reboot_required

  • deploy.yml

deploy.ymlはLifeKeeperに必要なインストールイメージ、ライセンスファイルをノードにコピーします。またCentOS7.9でDataKeeperを使用するために必要なPatchをダウンロードします。

– name: deploy to lifekeeper install files
  copy:
    src: “{{ control_node_dir }}”
    dest: “{{ target_dir }}”

– name: Download DataKeeper patch for CentOS 7.9
  get_url:
    url: “{{ patch_url }}”
    dest: “{{ target_dir }}/sios”
    mode: 0644

ダウンロードするpatchは以下にリンクがあります。詳細は以下を確認してください。
https://lkdkuserportal.sios.jp/hc/ja/articles/900003788726

  • mount.yml

mount.ymlはLifeKeeperに必要なインストールイメージ、ライセンスファイルをノードにコピーします。

– name: mount setup image
  mount:
    path: “{{ target_mnt }}”
    src: “{{ target_dir }}/sios/sps_951.img”
    fstype: iso9660
    state: mounted

  • install.yml

install.ymlはLifeKeeper for Linuxのインストールを行います。

  – name: install lifekeeper
    shell:                                
      # setupを直接実行すると失敗します。
      cmd: script -q -e -c “{{ target_mnt | quote }}/setup -f {{ target_dir | quote }}/sios/LKCONF -q y –addinfo {{ target_dir | quote }}/sios/lk-rhel7_9-support” {{ target_dir | quote }}/sios/lifekeeper_install.log

  • bash_profile.yml

bash_profile.ymlはLifeKeeperのコマンドファイルのPATHやMANページファイルのMANPATHを/root/.bash_profileに追加します。

– name: update lifekeeper PATH in bash_profile
  blockinfile:
    path: /root/.bash_profile
    marker: “# {mark} ANSIBLE MANAGED BLOCK: LifeKeeper”
    block: |
      PATH=$PATH:/opt/LifeKeeper/bin
      MANPATH=$MANPATH:/opt/LifeKeeper/man}
      export PATH MANPATH

  • license.yml

license.ymlはLifeKeeperのライセンスを各ノードにインストールするplaybookです。

– name: install lifekeeper license
  shell:
    cmd: |
      for file in `ls`; do
        /opt/LifeKeeper/bin/lkcli license –file $file
      done
    chdir: “{{ target_dir }}/sios/licenses/{{ inventory_hostname }}”

  • lkstart.yml

lkstart.ymlはLifeKeeperを実行するplaybookです。

– name: start lifekeeper
  command: /opt/LifeKeeper/bin/lkcli start

– name: lifekeeper status
  command: /opt/LifeKeeper/bin/lkcli status
  register: check_comm_path

– name: Show communication path(Source).
  debug:
    msg: “{{ check_comm_path.stdout_lines }}”

  • clean.yml

clean.ymlはLifeKeeperをインストールするにあたり使用した一時ファイルを削除します。

– name: unmount a mounted lifekeeper image
  mount:
    path: “{{ target_mnt }}”
    state: absent

– name: delete lifekeeper files
  file:
    path: “{{ target_dir }}”
    state: absent

5-7. コミュニケーションパスの作成/ commpathディレクトリ

commpathディレクトリには、コミュニケーションパスの作成を作成するためのplaybookが保管されています。main.ymlからは以下で読み込まれてコミュニケーションパスを作成します。コミュニケーションパスの作成は各ノード(ソース、ターゲット)からコミュニケーションパスを作成するコマンドを実行する必要があります。

ディレクトリ内のplaybookファイルを紹介します。

  • add_source_compath.yml

コミュニケーションパスは2経路作成します。ソースノードから実行しただけではコミュニケーションパスの作成は完了しません。

– name: Create primary communication path(Source).
  command: /opt/LifeKeeper/bin/lkcli commpath create –laddr “{{ node1_pri_ip }}” –raddr “{{ node2_pri_ip }}” –dest “{{ node2_hostname }}”

– name: Create secondary communication path(Source).
  command: /opt/LifeKeeper/bin/lkcli commpath create –laddr “{{ node1_sec_ip }}” –raddr “{{ node2_sec_ip }}” –dest “{{ node2_hostname }}”

  • add_target_compath.yml

ターゲットノードからも実行することでコミュニケーションパスがActiveになります。コミュニケーションパスのステータスの確認を行うコマンドを実行して表示します。

– name: Create primary communication path(Target).
  command: /opt/LifeKeeper/bin/lkcli commpath create –laddr “{{ node2_pri_ip }}” –raddr “{{ node1_pri_ip }}” –dest “{{ node1_hostname }}”

– name: Create secondary communication path(Target).
  command: /opt/LifeKeeper/bin/lkcli commpath create –laddr “{{ node2_sec_ip }}” –raddr “{{ node1_sec_ip }}” –dest “{{ node1_hostname }}”

– name: Check communication paths.
  command: /opt/LifeKeeper/bin/lkcli status -q
  register: check_comm_path

– name: Show communication paths.
  debug:
    msg: “{{ check_comm_path.stdout_lines }}”

5-8. パーティションの作成、Broadcast ping の無効化、PostgreSQL Serverのインストール

main.ymlの以下の項目では、リソース作成の準備を行っています。前半の項目ではDataKeeperリソースで利用するGPTパーティションを作成します。後半の項目では、Broadcast pingを無効化する設定を行い、PostgreSQL serverパッケージのインストールを行います。この項目は全て両ノードに対して行う処理となるため、まとめて行っています。

各ファイルは次の項目でまとめて紹介します。

5-9. DataKeeperリソース、IPリソース、PostgreSQLリソースの作成と拡張、依存関係の構築

ここでは各リソースを作成して、依存関係を構築します。この項目で実施するコマンドは全てアクティブノードからのみの実行となります。

各タスクを実行するplaybookファイル紹介します。

DataKeeperリソースを構築するために必要なplaybookファイル

IPリソースを構築するために必要なplaybookファイル

PostgreSQLリソースを構築するために必要なplaybookファイル

依存関係を作成するplaybookファイル

  • disk.yml

/dev/sdbにGPTパーティションを作成します。

– name: “parted {{ disk_device }}”
  parted:
    device: “{{ disk_device }}”
    number: “{{ disk_num }}”
    state: present
    label: “{{ disk_label }}”
   become: yes
   become_user: root

– name: “format {{ disk_device }}{{ disk_num }}”
  filesystem:
    dev: “{{ disk_device }}{{ disk_num }}”
    fstype: “{{ disk_fstype }}”
  become: yes
  become_user: root

  • new_replication.yml

作成したパーティションを使用してDataKeeperリソースを作成します。今回はファイルシステムのフォーマットを行う“Replicate New File System”でのリソース作成です。

– name: Create DataKeeper resource.
  command: /opt/LifeKeeper/bin/lkcli resource create dk –tag “{{ dk_tag }}” –mode “{{ sync_mode }}” –hierarchy “{{ rep_type }}” –device “{{ disk_device }}{{ disk_num }}” –fstype “{{ disk_fstype }}” –mount_point “{{ mount_dir }}” –fstag “{{ fs_tag }}”

– name: Extend DataKeeper resource.
  command: /opt/LifeKeeper/bin/lkcli resource extend dk –tag “{{ dk_tag }}” –mode “{{ sync_mode }}” –dest “{{ node2_hostname }}” –laddr “{{ node1_sec_ip }}” –raddr “{{ node2_sec_ip }}” –fstag “{{ fs_tag }}”

– name: Check resources.
  command: /opt/LifeKeeper/bin/lkcli status -q
  register: check_comm_path

– name: Show Resource tree.
  debug:
    msg: “{{ check_comm_path.stdout_lines }}”

  • nobcastping.yml

今回の環境ではbroadcast ping に応答するホストが無いため、事前にIPリソースの機能であるBroadcast pingの無効化を行うパラメータを設定します。/etc/default/LifeKeeper ファイル内のパラメータ”NOBCASTPING=1”の設定を行います。

– name: ブロードキャストPINGの無効化
  replace:
    dest: /etc/default/LifeKeeper
    regexp: ‘NOBCASTPING=0’
    replace: ‘NOBCASTPING=1’

  • ip_resource.yml

コマンドラインでIPリソースを作成します。Broadcast pingを無効化している為、unicast ping による確認先IPアドレスの設定も行います。

– name: Create IP resource.
  command: /opt/LifeKeeper/bin/lkcli resource create ip –tag ip-“{{ vip }}” –ipaddr “{{ vip }}” –netmask “{{ netmask }}”

– name: Config IP resource.
  command: /opt/LifeKeeper/bin/lkcli resource config ip –tag “ip-{{ vip }}” –pinglist “{{ target_ip }}”

– name: Extend IP resource.
  command: /opt/LifeKeeper/bin/lkcli resource extend ip –tag “ip-{{ vip }}” –dest “{{ node2_hostname }}”

– name: Check resources
  command: /opt/LifeKeeper/bin/lkcli status -q
  register: check_comm_path

– name: Show Resource tree.
  debug:
    msg: “{{ check_comm_path.stdout_lines }}”

  • inst_pgsql.yml

postgresql-server パッケージのインストールを行います。

– name: install postgresql-server.
  yum:
   name: postgresql-server
   state: latest

  • inst_pgsql.yml

DataKeeperリソースで保護したディレクトリ内にデータベース用ディレクトリを作成して、データベースの初期化を行い起動します。

– name: “データベース用ディレクトリの作成“
  file: path={{ initdb_dir }} state=directory owner={{ pg_user }} group={{ pg_user }} mode=755

– name: “データベース有無の確認“
  stat:
    path: “{{ initdb_dir}}/PG_VERSION”
  register: dbcluster

– name: “データベースの初期化“
  shell: /usr/bin/initdb –no-locale -D {{ initdb_dir }} –encoding=UTF-8
  become: yes
  become_user: “{{ pg_user }}”
  when: not dbcluster.stat.exists

– name: “データベースの起動“
  command: /usr/bin/pg_ctl -D {{ initdb_dir }} -l {{ initdb_dir }}/postgresql.log start
  become: yes
  become_user: “{{ pg_user }}”

  • pgsql_resource.yml

PostgreSQLリソースを作成します。作成後にリソース状況を表示します。

– name: Create postgresql resource.
  command: /opt/LifeKeeper/bin/lkcli resource create pgsql –tag “pgsql{{ pg_port }}” –datadir {{ initdb_dir }} –port {{ pg_port }} –socket {{ socket_file }} –dbuser {{ pg_user }} –logfile “{{ initdb_dir }}/{{ lk_pg_log }}”

– name: Extend postgresql resource.
  command: /opt/LifeKeeper/bin/lkcli resource extend pgsql –tag “pgsql{{ pg_port }}” –dest {{ node2_hostname }}

– name: Check resources.
  command: /opt/LifeKeeper/bin/lkcli status -q
  register: check_comm_path

– name: Show Resource tree.
  debug:
    msg: “{{ check_comm_path.stdout_lines }}”

6. Ansible playbookによる自動化を実行

それでは作成したplaybookを使用してVMの作成、LifeKeeperのインストール、リソース構築を行ってみます。

6-1. 実行前の環境

仮想マシン環境には以下のように2台のVMしかない状態です。

テンプレートには今回利用する”dbv-temp79”を配置します。

6-2. ansible-playbookコマンドの実行

ansible-playbookコマンドでplaybookファイルとホストを指定するinventory ファイルを指定して実行します。

ansible-playbook main.yml -i inventory

自動的に処理が行われます。まずはvCenterへの接続をしてアクティブノード(Source node)をデプロイします。その後IPアドレス、ホスト名の変更をします。

続いてスタンバイノード(Target node)を展開します。ホスト名、IPアドレスも変更します。

次はLifeKeeperのインストール処理に入ります。ここでは/etc/hostsファイルの編集とファイアフォールの設定変更を行っています。

LifeKeeperのインストールの続きです。SELinuxをdisableに変更してインストールに必要なファイルの転送、LifeKeeperのインストールを行います。

LifeKeeperのライセンスの適用を行い、LifeKeeperを起動します。

LifeKeeperのインストール処理はアンマウントと不要なファイルを削除して終了します。

LifeKeeperのインストールが完了するとコミュニケーションパスの作成を行います。コミュニケーションパスのステータスがDEADになっていますが、ALIVEまでに時間がかかる影響です。

パーティションの作成、ブロードキャストPINGの無効化、PostgreSQLのインストールなど、リソース作成の前処理が行われます。

リソース作成所に入ってきます。最初はDataKeeperリソースを作成します。時間の経過とともにコミュニケーションパスがALIVEになっていることも確認できます。

IPリソースの作成処理です。

PostgreSQLリソースの作成処理です。リソースの作成は完了です。

最後にPostgreSQLリソースとIPリソースの依存関係を作成します。最終的なステータス表示を見ると、IPリソースがPostgreSQLの下位に入ったことが分かります。

最終的にそれぞれのホストで実行された処理がOKかchangedであれば成功です。既に実施済みの項目についてもskippedとなるため処理は成功となります。unreachable の場合はホストに接続できていない、failedはタスクに失敗したことを示します。それぞれ出力するログを見て原因を探ってplaybookの修正を行ってください。

6-3. Ansibleで構築した環境の確認

仮想マシンは以下のように作成されました。

仮想マシンにログインして構築したLifeKeeper のリソース構成を確認します。

スイッチオーバーやフェイルオーバーを試みてみましたが正常に稼働することを確認しました。

関連記事

AnsibleでLINBIT HAを動かそう