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

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

    LifeKeeper for Linux9.5.0より強化された、LifeKeeperCLI(コマンドラインインターフェイス)と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, 158438072台
    VMware vCenter Server Appliance7.0.0.101001VM
    共有ストレージVMFS61台
    仮想マシン1台
    仮想マシンテンプレート1台

    4-2.   Ansibleサーバー

    Ansible管理サーバー
    仮想マシン
    CPU1CPU
    メモリ2GB
    ハードディスク16GB X1
    ネットワークアダプタens192(10.0.0.1/16)
    ens224(192.168.0.1/24)
    互換性ESXi7.0以降(VMバージョン17)
    OSCentOS8.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.テンプレート

    クラスターノード用仮想マシンテンプレートCPU1CPU
    メモリ2GB
    ハードディスク16GB X1
    10GB X1 (/dev/sdb)
    ネットワークアダプタens192(10.0.0.1/16)
    ens224(192.168.0.100/24)
    互換性ESXi7.0以降(VMバージョン17)
    OSCentOS7.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ディレクトリ内にある処理を実行します。ここではVM2台作成して、それぞれのホスト名、IPアドレスの変更が行われます。なおansibleで接続先のIPアドレスの変更した場合セッションが途切れてしまう問題を引き起こします。

    この問題を回避するため、クラスターシステムの特性でもある異なる複数のネットワーク構成を活用しています。1回目の接続ではNIC2から接続を行い、NIC1hostnameの変更を行います。2回目の接続でNIC2IPアドレスを変更して、以降の処理は変更した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_portvars ディレクトリ内でリストとして登録されていますので、追加でオープンしたいポートの追加も容易に可能です。

     

    – 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.9DataKeeperを使用するために必要な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のコマンドファイルのPATHMANページファイルの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のインストールの続きです。SELinuxdisableに変更してインストールに必要なファイルの転送、LifeKeeperのインストールを行います。

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

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

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

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

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

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

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

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

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

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

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

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

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

    関連記事

    AnsibleでLINBIT HAを動かそう

    SNSでもご購読できます。