ansibleを使うと、1つのマシンから複数のマシンの構成を行うことができます。
構成するためのコマンドの引数が各マシンで異なる場合は、それを変数化して処理します。この記事では、IBM の Db2 の導入・構成を例に、そのやり方を説明します。
ポイント
- マシンによらず固定値またはシェル・スクリプトで生成するような値は、ansible playbook(yamlファイル)に変数を定義することができます。
- この記事の例では、
- 導入時のログのファイル名にホスト名と日付を付与
- DB接続に必要なDB名、ユーザーID、パスワードを変数化
- この記事の例では、
- マシンごとに異なる値を定義したい場合は、ホスト名のリストとともに変数を定義することができます(この記事の例では、
inventories/hosts.ini
ファイルに定義)。- この記事の例では、
- Db2サーバーとDb2クライアントで異なる導入定義ファイルを指定
- Db2クライアントのマシンごとに、異なるDB接続先ホスト名、ポート番号を指定
- この記事の例では、
シナリオ
この記事の例では、Db2サーバーは2つのマシンで構成され、それぞれ2つのノードで動作し、各マシンの1つ目のノードは50000ポート、2つ目のノードは50001ポートでDb2クライアントからのリクエストを受け付けます。
Db2クライアントとして4つのマシンからDb2サーバーにアクセスします。各クライアントからのアクセスは負荷分散するために、以下のDb2サーバーにアクセスするようにします。
Db2クライアント | Db2サーバー接続先 |
---|---|
host3 | host1の50000ポート |
host4 | host1の50001ポート |
host5 | host2の50000ポート |
host6 | host2の50001ポート |
この記事では、上記を実現するための構成の一部である「1. Db2の導入」と「2. Db2クライアントの接続構成」、およびDb2接続確認を行う「3. Db2クライアントからDb2接続」を説明します。
その前に、ansibleのセットアップと、ansibleのシンプルな実行例を述べます。
ansibleのセットアップ
ansibleの実行は、上記のうち1つのサーバーから実行するか、別のマシンから実行することができます。
実行するマシンにはansibleを導入し、構成するすべてのサーバーに対して、rootでパスワードレスでアクセスできるようにします。
ansibleの導入例 (Red Hat 9.2の場合)
# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y
# yum install ansible -y
ansibleのシンプルな実行例
シンプルな例として、Db2が導入されているか確認するために、すべてのマシンに対してls /opt/ibm/db2
を実行します。
まずは、inventories/hosts.ini
ファイルにマシンのリストを記述します。
(この例では、以下の3つのマシンに対して実行します)
[db2hosts]
host1
host2
host3
実行する内容はansible playbookと呼ばれるyamlファイルに記載します。この例では、ファイル名をdb2_check.yml
とし、以下を記載します。
- name: db2 check
hosts: all
tasks:
- name: ls /opt/ibm/db2
shell:
cmd: ls /opt/ibm/db2
register: result
- name: result
debug:
msg: "{{ result.stdout }}"
上記のansible playbookを実行するために、以下のコマンドを実行します。
# ansible-playbook -i inventories/hosts.ini db2_check.yml
結果として、以下のように出力されます。
PLAY [db2 check] ***********************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************
ok: [host2]
ok: [host3]
ok: [host1]
TASK [ls /opt/ibm/db2] *****************************************************************************************************************************************
fatal: [host3]: FAILED! => {"changed": true, "cmd": "ls /opt/ibm/db2", "delta": "0:00:00.011545", "end": "2024-09-08 19:23:04.972991", "msg":
"non-zero return code", "rc": 2, "start": "2024-09-08 19:23:04.961446", "stderr": "ls: '/opt/ibm/db2' にアクセスできません: そのようなファイルやディレクトリは
ありません", "stderr_lines": ["ls: '/opt/ibm/db2' にアクセスできません: そのようなファイルやディレクトリはありません"], "stdout": "", "stdout_lines": []}
changed: [host1]
changed: [host2]
TASK [result] **************************************************************************************************************************************************
ok: [host1] => {
"msg": "V11.5"
}
ok: [host2] => {
"msg": "V11.5"
}
PLAY RECAP *****************************************************************************************************************************************************
host1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host3 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
上記出力から、host3には/opt/ibm/db2
にDb2が導入されておらず、host1とhost2には少なくとも/opt/ibm/db2/V11.5
ディレクトリまたはファイルが作成されていることがわかります。
シナリオの実行
以下の3つのansible playbookを作成・実行します。
1. Db2の導入
設計
すべてのマシンにDb2を導入します。
Db2サーバーの導入にはDb2サーバー用にパラメータ設定された db2server.rsp
ファイルを指定して導入し、Db2クライアントの導入にはDb2クライアント用にパラメータ設定された db2client.rsp
ファイルを指定して導入します。
Db2導入コマンドdb2setupファイルは、事前に、すべてのマシンにNFSマウントされた /download/db2
ディレクトリ下に置きます。
db2server.rsp
とdb2client.rsp
ファイルは、ansibleを実行するディレクトリに置き、ansible playbookで各マシンの/db2install
ディレクトリにコピーします。
Db2の導入ログを /log/db2_install_[ホスト名]_[YYYYMMDD].log
ファイルに取得し、ansible playbook実行マシンの /log
ディレクトリ下にコピーします。
Db2の導入コマンドは以下のようになります。
- Db2サーバー
- 実行ディレクトリ: /download/db2
- 実行コマンド: ./db2setup -r /db2install/db2server.rsp -l "/log/db2_install_`hostname`_`date +%Y%m%d`.log"
- Db2クライアント
- 実行ディレクトリ: /download/db2
- 実行コマンド: ./db2setup -r /db2install/db2client.rsp -l "/log/db2_install_`hostname`_`date +%Y%m%d`.log"
ansibleの構築
実行コマンドで、マシンごとに異なるパラメータは以下となります。
- Db2サーバーは
db2server.rsp
、Db2クライアントはdb2client.rsp
を指定する。 - すべてのマシンで、"/log/db2_install_`hostname`_`date +%Y%m%d`.log" を指定する。
1は導入するマシンで決まります。その場合、inventories/hosts.ini
ファイルにその変数を記載することができます。
この例では、Db2サーバーとDb2クライアントで値が異なるので、以下のように、すべてのホストをその2つに分類します。
[db2server]
host1
host2
[db2client]
host3
host4
host5
host6
さらに、以下のように、上記に続けて変数を記載します。
[db2server:vars]
rsp_file=db2server.rsp
[db2client:vars]
rsp_file=db2client.rsp
この例では、rsp_file
が変数名になります。
2は、マシンによらずコマンドの実行結果を変数の値としてセットするものです。その場合、ansible playbook(yamlファイル)に以下のように記載します。
tasks:
- name: log name
shell:
cmd: echo "/log/db2_install_`hostname`_`date +%Y%m%d`.log"
register: log_name
上記のlog_name
が変数名で、log_name.stdout
に標準出力の値がセットされます。
Db2の導入は、以下のように記載します。
- name: db2 install
shell:
cmd: ./db2setup -r "/db2install/{{ rsp_file }}" -l "{{ log_name.stdout }}"
chdir: /download/db2
Db2導入実行後のログファイルの取得は、以下のように記載します。
- name: fetch log file
fetch:
src: "{{ log_name.stdout }}"
dest: "/log/"
flat: yes
flat:
の値をyes
にすると、dest:
の値が/で終わっている場合、そのディレクトリ下にsrc:
のファイルがコピーされます。
上記をまとめると、inventories/hosts.ini
は、以下のようになります。
[db2server]
host1
host2
[db2client]
host3
host4
host5
host6
[db2server:vars]
rsp_file=db2server.rsp
[db2client:vars]
rsp_file=db2client.rsp
ansible playbookは以下のようになります(この例では、ファイル名をdb2_install.yml
とします)。
- name: db2 install
hosts: all
tasks:
- name: log name
shell:
cmd: echo "/log/db2_install_`hostname`_`date +%Y%m%d`.log"
register: log_name
- name: copy rsp file
copy:
src: "{{ rsp_file }}"
dest: /db2install/
owner: root
group: root
mode: 0644
- name: db2 install
shell:
cmd: ./db2setup -r "/db2install/{{ rsp_file }}" -l "{{ log_name.stdout }}"
chdir: /download/db2
- name: fetch log file
fetch:
src: "{{ log_name.stdout }}"
dest: "/log/"
flat: yes
このansible playbookを実行するために、以下のコマンドを実行します。
# ansible-playbook -i inventories/hosts.ini db2_install.yml
2. Db2クライアントの接続構成
設計
Db2クライアントの接続構成は、Db2インスタンス・ユーザー(この記事ではdb2inst1
ユーザーとします)で行います。
ansibleでリモート接続した後、ユーザーを切り替えるには以下のようにbecome
とbecome_user
を指定します。
- name: db2client config
hosts: db2client
become: yes
become_user: db2inst1
しかしながら、この方法でユーザーを切り替えると、ユーザーのプロファイルが実行されません (su - db2inst1
ではなく、su db2inst1
で切り替えられる)。結果として、Db2のコマンドの実行でエラーとなります。
そこで、上記の代わりに、各コマンドの実行で、su - db2inst1 -c コマンド
で対応することとします。
ここで使用するコマンドは各マシンでパラメータが異なり、以下のようになります。
ホスト名 | コマンド |
---|---|
host3 | db2 catalog tcpip node db2svr remote host1 server 50000 |
host4 | db2 catalog tcpip node db2svr remote host1 server 50001 |
host5 | db2 catalog tcpip node db2svr remote host2 server 50000 |
host6 | db2 catalog tcpip node db2svr remote host2 server 50001 |
上記でマシンごとの違いは、接続先のホスト名とポート番号になります。
Db2クライアント | 接続先ホスト | 接続先ポート |
---|---|---|
host3 | host1 | 50000 |
host4 | host1 | 50001 |
host5 | host2 | 50000 |
host6 | host2 | 50001 |
ansibleの構築
「1. Db2の導入」では、inventories/hosts.ini
でdb2serverとdb2clientに分類しましたが、ここでは、以下のようにdb2clientをさらに分類し、個々のマシンに対して上記の変数を定義します。
[db2server]
host1
host2
[db2client:children]
client1
client2
client3
client4
[db2server:vars]
rsp_file=db2server.rsp
[db2client:vars]
rsp_file=db2client.rsp
[client1]
host3
[client2]
host4
[client3]
host5
[client4]
host6
[client1:vars]
db2host=host1
db2port=50000
[client2:vars]
db2host=host1
db2port=50001
[client3:vars]
db2host=host2
db2port=50000
[client4:vars]
db2host=host2
db2port=50001
ansible playbookは以下のようになります(この例では、ファイル名をdb2client_config.yml
とします)。
- name: db2client config
hosts: db2client
tasks:
- name: catalog node
shell:
cmd: su - db2inst1 -c 'db2 catalog tcpip node db2svr remote "{{ db2host }}" server "{{ db2port }}"'
実行するマシンはDb2クライアントのみですので、hosts: には db2client をセットします。
このansible playbookを実行するために、以下のコマンドを実行します。
# ansible-playbook -i inventories/hosts.ini db2client_config.yml
3. Db2クライアントからDb2接続
Db2クライアントからDb2サーバーに接続するためには、Db2のインスタンス・ユーザーから、以下のコマンドを実行します。
$ db2 connect to [DB名] user [ユーザー名] using [パスワード]
DB名、ユーザー名、パスワードを変数化する場合、ansible playbookは以下のようになり(ファイル名をdb2client_connect.yml
とします)、変数値はvars:
に指定します。
- name: db2 connect
hosts: db2client
vars:
dbname: "db1"
user: "db2inst1"
pwd: "password"
tasks:
- name: db2 connect
shell:
cmd: su - db2inst1 -c 'db2 connect to "{{ dbname }}" user "{{ user }}" using "{{ pwd }}"'
register: result
- name: result
debug:
msg: "{{ result.stdout }}"
このansible playbookを実行するために、以下のコマンドを実行します。
# ansible-playbook -i inventories/hosts.ini db2client_connect.yml
インベントリーの親子関係と変数定義の確認
以下のように、ansible-inventory
コマンドでインベントリーの親子関係と変数定義を確認することができます。
# ansible-inventory --graph --vars -i inventories/hosts.ini
@all:
|--@ungrouped:
|--@db2server:
| |--teljpdb41.fyre.ibm.com
| | |--{rsp_file = db2server.rsp}
| |--teljpdb42.fyre.ibm.com
| | |--{rsp_file = db2server.rsp}
| |--{rsp_file = db2server.rsp}
|--@db2client:
| |--@client1:
| | |--teljpdb43.fyre.ibm.com
| | | |--{db2host = host1}
| | | |--{db2port = 50000}
| | | |--{rsp_file = db2client.rsp}
| | |--{db2host = host1}
| | |--{db2port = 50000}
| |--@client2:
| | |--teljpdb31.fyre.ibm.com
| | | |--{db2host = host2}
| | | |--{db2port = 50001}
| | | |--{rsp_file = db2client.rsp}
| | |--{db2host = host2}
| | |--{db2port = 50001}
| |--{rsp_file = db2client.rsp}