Ansible:assertモジュールについて
assertモジュール
assertは与えられた条件を評価してメッセージを出力するモジュールです。テストやデバッグで、設定が正しく行われているか確認したい場合に役立ちます。
| パラメータ | 説明 |
|---|---|
| that | 条件式。このパラメータの指定は必須。 |
| success_msg | 条件が成立した時に表示するメッセージ |
| fail_msg | 条件が不成立の時に表示するメッセージ |
| quiet | ログ表示を詳細に表示するかどうかを表す。 noで表示する、yesで表示しない。デフォルト値はnoとなっている。 |
実行例1
ホスト名が想定した値かどうかを判定するassert文の例です。必須パラメータであるthatのみ指定しています。
thatで指定した条件が成立しない場合、taskはfatalとなりプレイブックの実行はそこで終了します。引き続き次のタスクを実行させたければ「ignore_errors: yes」をつけておかないといけません。
--- - hosts: all tasks: - debug: msg: "{{ ansible_facts.hostname }}" - name: assert [ failed pattern ] assert: that: ansible_facts.hostname == "dummy_hostname" ignore_errors: yes - name: assert [ success pattern] assert: that: ansible_facts.hostname == "CentOS7_6" ignore_errors: yes
# ansible-playbook -i hosts assert_test1.yml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [CentOS7_6]
TASK [debug] *******************************************************************
ok: [CentOS7_6] => {
"msg": "CentOS7_6"
}
TASK [assert [ failed pattern ]] ***********************************************
fatal: [CentOS7_6]: FAILED! => {
"assertion": "ansible_facts.hostname == \"dummy_hostname\"",
"changed": false,
"evaluated_to": false,
"msg": "Assertion failed"
}
...ignoring
TASK [assert [ success pattern]] ***********************************************
ok: [CentOS7_6] => {
"changed": false,
"msg": "All assertions passed"
}
PLAY RECAP *********************************************************************
CentOS7_6 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1実行例2
実行例1と同じくホスト名が想定した値かどうかを判定するassert文の例です。パラメータを付けたしました。
success_msg、fail_msgに指定した文字列が、条件の成立時、不成立時にそれぞれ出力されています。
--- - hosts: all tasks: - debug: msg: "{{ ansible_facts.hostname }}" - name: assert [ failed pattern ] assert: that: ansible_facts.hostname == "dummy_hostname" success_msg: "ホスト名はdummy_hostnameです" fail_msg: "ホスト名はdummy_hostnameではありません" ignore_errors: yes - name: assert [ success pattern] assert: that: ansible_facts.hostname == "CentOS7_6" success_msg: "ホスト名はCentOS7_6です" fail_msg: "ホスト名はCentOS7_6ではありません" ignore_errors: yes
# ansible-playbook -i hosts assert_test2.yml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
Enter passphrase for key '/home/tkd/.ssh/id_rsa':
ok: [CentOS7_6]
TASK [debug] *******************************************************************
ok: [CentOS7_6] => {
"msg": "CentOS7_6"
}
TASK [assert [ failed pattern ]] ***********************************************
fatal: [CentOS7_6]: FAILED! => {
"assertion": "ansible_facts.hostname == \"dummy_hostname\"",
"changed": false,
"evaluated_to": false,
"msg": "ホスト名はdummy_hostnameではありません"
}
...ignoring
TASK [assert [ success pattern]] ***********************************************
ok: [CentOS7_6] => {
"changed": false,
"msg": "ホスト名はCentOS7_6です"
}
PLAY RECAP *********************************************************************
CentOS7_6 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1実行例3
thatに複数の条件を指定するパターンです。thatには、配列で複数の条件を記載できます。その場合、各条件式はandでつながります。
test_assert3.ymlでは、/var/log/cronが存在し、かつ、/var/log/cronのサイズが0でない場合に、条件がtrueとなります。
--- - hosts: all tasks: - stat: path: /var/log/cron register: cron_log - debug: msg: "{{ cron_log }}" - name: assert message assert: that: - cron_log.stat.exists is true - cron_log.stat.size != 0
ansible-playbook -i hosts assert_test3.yml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [CentOS7_6]
TASK [stat] ********************************************************************
ok: [CentOS7_6]
TASK [debug] *******************************************************************
ok: [CentOS7_6] => {
"msg": {
"changed": false,
"failed": false,
"stat": {
"atime": 1612464614.0189674,
"attr_flags": "",
"attributes": [],
"block_size": 4096,
"blocks": 8,
"charset": "unknown",
"ctime": 1612464601.4457855,
"dev": 64770,
"device_type": 0,
"executable": false,
"exists": true,
"gid": 0,
"gr_name": "root",
"inode": 1123797,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mimetype": "unknown",
"mode": "0600",
"mtime": 1612464601.4457855,
"nlink": 1,
"path": "/var/log/cron",
"pw_name": "root",
"readable": false,
"rgrp": false,
"roth": false,
"rusr": true,
"size": 492,
"uid": 0,
"version": null,
"wgrp": false,
"woth": false,
"writeable": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
}
}
TASK [assert message] **********************************************************
ok: [CentOS7_6] => {
"changed": false,
"msg": "All assertions passed"
}
PLAY RECAP *********************************************************************
CentOS7_6 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0ちなみに、thatはwhen文で評価可能な式であれば同じく評価することができます。なので、複数の条件式を記載する場合、andやorで条件式をつらねることもできます。test_assert3.ymlのthatで指定した条件式を以下のように書くこともできます。
- name: assert message assert: that: > cron_log.stat.exists is true and cron_log.stat.size != 0
Ansible:インベントリ変数について
インベントリ変数は以下の2つの方法で定義することができます。
- インベントリファイルに直接記述する
- host_vars、group_varsを作成し、その下のファイルに記述する
インベントリファイルに変数を記述する場合
ホスト変数
ホスト変数は、インベントリファイル内のホスト名、またはIPアドレスの後に「変数名=値」の書式でスペース区切りで記載します。1つのホストに対して複数のホスト変数を設定すると1行が長くなりますが、途中で改行することはできません…
以下の例では、serverA_01にはfooというホスト変数が定義され、serverA_02にはfooとbarの2つのホスト変数が定義されています。
※ちなみに、ansible_hostはansibleがリモートマシンへの接続のために用いる特殊な変数です。
[serverA] serverA_01 ansible_host=192.168.1.1 foo="ホスト変数foo" serverA_02 ansible_host=192.168.1.2 foo="ホスト変数foo" bar="ホスト変数bar"
グループ変数
グループ変数を定義する場合、新たに「グループ名:vars」の名前でセクションを作り、その下に記載します。
以下の例では、serverAというグループにfooとbarの2つの変数を定義しています。
[serverA] serverA_01 ansible_host=192.168.1.1 serverA_02 ansible_host=192.168.1.2 [serverA:vars] foo="グループ変数foo" bar="グループ変数bar"
親子関係のグループの場合
グループが親子関係でも同じように「グループ名:vars」で変数を定義できます。親で定義した変数は子にも受け継がれます。親、子で変数が重複した場合、子の変数が適用されます。
[parent] [parent:vars] foo="parentグループ変数foo" bar="parentグループ変数bar" [parent:children] serverA [serverA] serverA_01 ansible_host=192.168.1.1 [serverA:vars] foo="serverAグループ変数foo"
--- - hosts: all tasks: - debug: msg: "{{ foo }}" - debug: msg: "{{ bar }}"
$ ansible-playbook -i inventory -l serverA_01 play_serverA.yml
PLAY [all] **************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [serverA_01]
TASK [debug] ************************************************************************************************************************************************
ok: [serverA_01] => {
"msg": "serverAグループ変数foo"
}
TASK [debug] ************************************************************************************************************************************************
ok: [serverA_01] => {
"msg": "parentグループ変数bar"
}
PLAY RECAP **************************************************************************************************************************************************
serverA_01 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0ホスト変数とグループ変数で変数が重複する場合
ホスト変数とグループ変数に重複して変数を定義した場合、ホスト変数の値が適用されます。
[serverA] serverA_01 ansible_host=192.168.1.1 foo="ホスト変数foo" bar="ホスト変数bar" [serverA:vars] foo="グループ変数foo" bar="グループ変数bar"
--- - hosts: all tasks: - debug: msg: "{{ foo }}" - debug: msg: "{{ bar }}"
$ ansible-playbook -i inventory -l serverA_01 play_serverA.yml
PLAY [all] **************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [serverA_01]
TASK [debug] ************************************************************************************************************************************************
ok: [serverA_01] => {
"msg": "ホスト変数foo"
}
TASK [debug] ************************************************************************************************************************************************
ok: [serverA_01] => {
"msg": "ホスト変数bar"
}
PLAY RECAP **************************************************************************************************************************************************
serverA_01 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0全ホストに共通する変数を定義する
インベントリファイルに定義した全てのホストは「all」というグループに所属します。「all:vars」に変数を定義することで全ホストに共通した値を定義することができます。
なお、「グループ名:vars」と「all:vars」で重複して変数を定義した場合、「グループ名:vars」で定義した値が適用されます。
[serverA] serverA_01 ansible_host=192.168.1.1 [serverA:vars] foo="serverAグループ変数foo" [all:vars] foo="allグループ変数foo" bar="allグループ変数bar"
--- - hosts: all tasks: - debug: msg: "{{ foo }}" - debug: msg: "{{ bar }}"
$ ansible-playbook -i inventory -l serverA_01 play_serverA.yml
PLAY [all] **************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [serverA_01]
TASK [debug] ************************************************************************************************************************************************
ok: [serverA_01] => {
"msg": "serverAグループ変数foo"
}
TASK [debug] ************************************************************************************************************************************************
ok: [serverA_01] => {
"msg": "allグループ変数bar"
}
PLAY RECAP **************************************************************************************************************************************************
serverA_01 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0host_vars、group_vars下のファイルに変数を記述する場合
インベントリ変数はインベントリファイルに記載する以外にも、host_varsやgroup_varsのようなディレクトリを用意し、その下のファイルに記載することもできます。
イメージとしては以下のようなディレクトリ構成です。host_vars、group_varsはインベントリファイルと同じ階層に作成しなければなりません。
|-- group_vars | |-- all.yml | `-- serverA.yml |-- host_vars | |-- serverA_01.yml | `-- serverA_02.yml |-- inventory `-- play_serverA.yml
ホスト変数
host_varsの下にホスト名と同じ名前でyamlファイルを作成し、その中にホスト変数を定義します。
|-- inventory
`-- host_vars
|-- serverA_01.yml
`-- serverA_02.ymlfoo: "serverA_01のホスト変数foo" bar: "serverA_01のホスト変数bar"
foo: "serverA_02のホスト変数foo" bar: "serverA_02のホスト変数bar"
ホスト変数をさらにファイルに分割する
host_varsの下にホスト名と同じ名前のディレクトリを作成し、その下にホスト変数を記述したyamlファイルを配置することもできます。yamlファイルのファイル名はどんなものでもかまいません。この場合、サーバの機能や特徴ごとにファイルを分けるのがよさそうです。
|-- inventory
`-- host_vars
`-- serverA_01
|-- feature1
`-- feature2foo: "serverA_01のホスト変数foo"
bar: "serverA_01のホスト変数bar"
グループ変数
group_varsの下にグループ名と同じ名前でyamlファイルを作成し、その中にグループ変数を定義します。
|-- inventory
`-- group_vars
|-- all
|-- serverA.yml
`-- serverB.ymlfoo: "serverAのグループ変数foo" bar: "serverAのグループ変数bar"
foo: "serverBのグループ変数foo" bar: "serverBのグループ変数bar"
グループ変数をさらにファイルに分割する
ホスト変数と同様に、group_varsの下にグループ名と同じ名前のディレクトリを作成し、その下にグループ変数を記述したyamlファイルを配置できます。yamlファイルのファイル名はどんなものでもかまいません。
|-- inventory
`-- group_vars
`-- serverA
|-- feature1.yml
`-- feature2.ymlfoo: "serverAのグループ変数foo"
bar: "serverAのグループ変数bar"
親子関係のグループの場合
親グループも子グループもgroup_varsの下に作成します。
|-- inventory
`-- group_vars
|-- parent.yml
`-- serverA.yml[parent] [parent:children] serverA [serverA] serverA_01 ansible_host=192.168.1.1
foobar: "parentのグループ変数:foobar"
foo: "serverAのグループ変数:foo" bar: "serverAのグループ変数:bar"
Ansible:プレイブック中の長い1行を複数行に分割する
*ansible 2.10.4で動作を確認しています
Ansibleのdebugやshellモジュールを使う際に1行が長くなりすぎたため改行したい、という場合があります。
ブロックスタイルを使えば、yamlの中で文字列を複数行にわたり記載できます。
yamlの記法では「フロースタイル」と「ブロックスタイル」が存在するそうです。(以下のサイトを参考させていただきました)
フロースタイルの文字列はクォーテーションで囲まれた文字列です。ブロックスタイルは文字列を改行して記載します。以下のymlのdebugメッセージをブロックスタイルで記載しました。
--- - hosts: all tasks: - name: Pattern 1 [ | ] debug: # ブロックスタイル1 # 各行の改行を保存 msg: | aaaaa bbbbb ccccc - name: Pattern 2 [ |+ ] debug: # ブロックスタイル2 # 各行の改行を保存、最終行の次の行の改行も保存 msg: |+ aaaaa bbbbb ccccc - name: Pattern 3 [ |- ] debug: # ブロックスタイル3 # 各行の改行を保存、最終行の改行は取り除く msg: |- aaaaa bbbbb ccccc - name: Pattern 4 [ > ] debug: # ブロックスタイル4 # 最終行以外の改行を半角スペースに置換 msg: > aaaaa bbbbb ccccc - name: Pattern 5 [ >+ ] debug: # ブロックスタイル5 # 最終行以外の改行を半角スペースに置換、最終行の次の行の改行も保存 msg: >+ aaaaa bbbbb ccccc - name: Pattern 6 [ >- ] debug: # ブロックスタイル6 # 各行の改行を半角スペースに置換、最終行の改行は取り除く msg: >- aaaaa bbbbb ccccc
実行結果は以下になります。
# ansible-playbook -i hosts block_literal.yml
PLAY [all] **************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [CentOS7.6]
TASK [Pattern 1 [ | ]] **************************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "aaaaa\nbbbbb\nccccc\n"
}
TASK [Pattern 2 [ |+ ]] *************************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "aaaaa\nbbbbb\nccccc\n\n"
}
TASK [Pattern 3 [ |- ]] *************************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "aaaaa\nbbbbb\nccccc"
}
TASK [Pattern 4 [ > ]] **************************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "aaaaa bbbbb ccccc\n"
}
TASK [Pattern 5 [ >+ ]] *************************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "aaaaa bbbbb ccccc\n\n"
}
TASK [Pattern 6 [ >- ]] *************************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "aaaaa bbbbb ccccc"
}
PLAY RECAP **************************************************************************************************************************************************
CentOS7.6 : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0shellモジュールに渡すコマンドもブロックスタイルを使えば改行できます。他にも、jinja2の構文を使う際などに利用するとよさそうです。
--- - hosts: all tasks: - name: check root user shell: >- cat /etc/passwd | grep ^root | wc -l register: response - debug: msg: >- {% if response.stdout != "0" %} exist {% else %} not exist {% endif %}
# ansible-playbook -i hosts check_root_user.yml
PLAY [all] **************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [CentOS7.6]
TASK [check root user] *******************************************************************************************************************************************
changed: [CentOS7.6]
TASK [debug] ************************************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "exist "
}
PLAY RECAP **************************************************************************************************************************************************
CentOS7.6 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Ansible:CentOSのctrl-alt-del.targetを無効にする
CentOSやRHELでは、キーボードからCtrl-Alt-Delを入力するとOSの再起動が始まります。何かしらのサービスを提供しているサーバで誤ってCtrl-Alt-Delを打つと、サービスが一時的に停止してしまいます(恐ろしいですね…)。また、Ctrl-Alt-DelはWindowsサーバだとサインイン時に使うので、なおさら入力ミスしてしまう可能性があります。
というわけで、Ctrl-Alt-Delによる再起動を無効化しておく方がよいです。
ターミナルでctrl-alt-del.targetを無効化
ctrl-alt-delを無効にするには、systemctlコマンドでctrl-alt-del.targetをマスクします、
# echo "実行前ステータス確認" > /dev/null
# systemctl status ctrl-alt-del.target
● reboot.target - Reboot
Loaded: loaded (/usr/lib/systemd/system/reboot.target; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:systemd.special(7)
#
# echo "ctrl-alt-delをマスク" > /dev/null
# systemctl mask ctrl-alt-del.target
#
# echo "実行後ステータス確認" > /dev/null
# systemctl status ctrl-alt-del.target
● ctrl-alt-del.target
Loaded: masked (/dev/null; bad)
Active: inactive (dead)ただ、これだけではctrl-alt-delが2秒以内に7回以上押された場合、再起動が実行されてしまうそうです。ctrl-alt-delが2秒以内に7回以上押されても再起動されないように「/etc/systemd/system.conf」を編集し、CtrlAltDelBurstActionというパラメータにnoneを設定します。
~ 省略 ~ #CtrlAltDelBurstAction=reboot-force ~ 省略 ~
~ 省略 ~ #CtrlAltDelBurstAction=reboot-force CtrlAltDelBurstAction=none ~ 省略 ~
Ansibleでctrl-alt-del.targetを無効化
先ほどの内容をAnsibleで記述すると以下のようになります。
systemdモジュールでctrl-alt-del.targetをマスクし、copyモジュールで/etc/systemd/system.confを書き換えています。
--- - hosts: all become: yes become_method: su tasks: - name: disable ctrl-alt-del.target systemd: name: ctrl-alt-del.target masked: yes - name: copy system.conf copy: src: system.conf dest: /etc/systemd/system.conf mode: 0644 owner: root group: root backup: yes
[Manager] CtrlAltDelBurstAction=none
OS自作入門:QEMUをインストールしてフロッピーディスクをエミュレート
OSの自作には興味があったので川合秀実さん著の「30日でできる!OS自作入門」を買ってみました。付属のCDが充実していて、ソースコードやOSの実行に必要な各種ツールなどがそろっており、本に記載されている通りの方法で実行できます(素晴らしい!!)。
https://book.mynavi.jp/supportsite/detail/4839919844.html
とはいえ、せっかくなので実行環境の準備は自分でやってみたいな、と思い自身のPC(Windows 10)にQEMUをインストールしました。
QEMUのインストール
まずはQEMUのダウンロードサイトにアクセスします。
https://www.qemu.org/download/#windows
64bitのWindowsにインストールするので64bitをクリックします。

最新のインストーラをダウンロードします。

ダウンロードしたインストーラを実行します。実行するとセットアップウィザードが立ち上がります。
インストール時の言語選択です。「English」のまま「OK」を押します。

「Next」を押します。

ライセンス条項に同意するか聞かれます。同意する場合は「I Agree」を押します。

インストールするコンポーネントを選択します。デフォルトのまま全てにチェックが入った状態で「Next」を押します。

インストール先のパスを選択します。特にこだわりはないのでデフォルトのまま「C:\Program Files」の下にします。

インストールがはじまります。

インストールが終わると完了画面が表示されます。

QEMUでOSを起動する
OSが起動できるかやってみます。
「30日でできる!OS自作入門」ではフロッピーディスクのディスクイメージからOSをブートします。helloos.imgがディスクイメージです。「hello world」と文字を表示する簡素なものです。
フロッピーディスクをマウントするのでqemuの-deviceでfloppyを指定しています。
PS C:\Users\muknow\Documents\OS自作入門\my_work\helloos0> ls
ディレクトリ: C:\Users\muknow\Documents\OS自作入門\my_work\helloos0
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2004/04/01 1:07 7 !cons_9x.bat
-a---- 2004/04/01 1:09 7 !cons_nt.bat
-a---- 2005/05/29 13:36 1474560 helloos.img
-a---- 2005/05/29 13:36 1474560 helloos.nas
-a---- 2005/03/04 22:13 38 install.bat
-a---- 2005/03/03 13:24 85 run.bat
PS C:\Users\muknow\Documents\OS自作入門\my_work\helloos0> qemu-system-x86_64 -blockdev driver=file,node-name=f0,filename=helloos.img -device floppy,drive=f0
無事、起動ができました。

Ansible:roles_pathでロール検索パスを設定する
*ansible 2.10.4で動作を確認しています
Ansibleでroleを利用する際、よく見かけるのは以下のようなディレクトリ構成かと思います。プレイブック(playbook.yml)と同じ階層にrolesというディレクトリが存在し、その下にロールが存在するという構成です。
|-- inventory
|-- playbook.yml
`-- roles
`-- foo
`-- tasks
`-- main.yml
Ansibleは標準でロールを検索する際、プレイブックからの相対パスでrolesというディレクトリを検索するそうで、そのため、playbook.ymlからroles/fooを実行できるわけです。
rolesを他の場所に配置したい
以下のように、プレイブック(playbook.yml)とは別の階層にrolesを配置したとします。
|-- host1
| `-- playbook.yml
|-- inventory
`-- roles
`-- foo
`-- tasks
`-- main.yml
この時、playbook.ymlを実行すると検索パスにrolesが存在しないためエラーが出てしまいます。
--- - hosts: all roles: - foo
--- - name: output message debug: msg: "foo"
$ pwd /home/muknow/workspace/ansible/test_role_path $ ls host1 inventory roles $ ansible-playbook -i inventory host1/playbook.yml ERROR! the role 'foo' was not found in /home/muknow/workspace/ansible/test_role_path/host1/roles:/home/muknow/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:/home/muknow/workspace/ansible/test_role_path/host1 The error appears to be in '/home/muknow/workspace/ansible/test_role_path/host1/playbook.yml': line 5, column 7, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: roles: - foo ^ here
roles_pathを設定する
ansible.cfgでroles_pathを設定することで検索パスを追加することができます。検索パスを追加すれば、このプレイブックもうまく実行できるはずです。
今回はansible.cfgをrolesと同じ階層に配置し、ここからansible-playbookコマンドを実行することにします。roles_pathには相対パスでrolesを指定しました。
[defaults] roles_path = ./roles
最終的な構成は以下のようになります。
|-- ansible.cfg
|-- host1
| `-- playbook.yml
|-- inventory
`-- roles
`-- foo
`-- tasks
`-- main.yml
fooが実行されました。成功です。
$ pwd /home/muknow/workspace/ansible/test_role_path $ ls ansible.cfg host1 inventory roles $ ansible-playbook -i inventory host1/playbook.yml PLAY [all] ************************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************** ok: [CentOS7.6] TASK [foo : output message] ********************************************************************************************************************************* ok: [CentOS7.6] => { "msg": "foo" } PLAY RECAP ************************************************************************************************************************************************** CentOS7.6 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host1の下にもrolesを作ったらどうなるのか?
気になったのでためしてみました。
先ほどの構成から追加で、host1の下にrolesを作り、barとfooというロールを作成しました。fooに関しては、同じ名前のロールがrolesの下、host1/rolesの下の2か所に存在する場合、どちらが優先されるかを見てみたいと思います。
|-- ansible.cfg
|-- host1
| |-- playbook.yml
| `-- roles
| |-- bar
| | `-- tasks
| | `-- main.yml
| `-- foo
| `-- tasks
| `-- main.yml
|-- inventory
`-- roles
`-- foo
`-- tasks
`-- main.yml
--- - hosts: all roles: - bar - foo
--- - name: output message debug: msg: "bar [host1/roles/bar]"
--- - name: output message debug: msg: "foo [host1/roles/foo]"
--- - name: output message debug: msg: "foo [roles/foo]"
実行結果は以下となりました。
fooはroles/fooとhost1/roles/fooの2か所に作成しましたが、host1/roles/fooが実行されています。どうやら、roles_pathの設定したパスよりも、プレイブックと同階層のrolesの方が優先されるようです。
$ pwd
/home/muknow/workspace/ansible/test_role_path
$ ls
ansible.cfg host1 inventory roles
$ ansible-playbook -i inventory host1/playbook.yml
PLAY [all] **************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [CentOS7.6]
TASK [bar : output message] *********************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "bar [host1/roles/bar]"
}
TASK [foo : output message] *********************************************************************************************************************************
ok: [CentOS7.6] => {
"msg": "foo [host1/roles/foo]"
}
PLAY RECAP **************************************************************************************************************************************************
CentOS7.6 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Ansible:docker_containerモジュールを使ってみた
AnsibleでDockerコンテナを実行したいと思って調べていたらdocker_containerモジュールなるものを見つけました。
ドキュメントを見るとオプションの多さに面食らいます…
ひとまず、細かいオプションは置いておいてコンテナを起動してみました。
準備
docker_containerモジュールを使うための大前提として、ターゲットホスト上にdockerがインストールされていなければなりません。(dockerのインストール方法については割愛)
また、pythonからdockerを操作するためのDocker SDKをインストールする必要があります。Docker SDKはpipでインストールできます。
$ pip install docker
※公式ドキュメントにも記載されていますが、Python2.6を使う場合は「pip install docker」ではなく「pip install docker-py」する必要があります。
コントロールノード側では、community.generalというコレクションのインストールが必要です。
$ ansible-galaxy collection install community.general Process install dependency map Starting collection install process Installing 'ansible.netcommon:1.4.1' to '/home/muknow/.ansible/collections/ansible_collections/ansible/netcommon' Installing 'google.cloud:1.0.1' to '/home/muknow/.ansible/collections/ansible_collections/google/cloud' Installing 'community.general:1.3.1' to '/home/muknow/.ansible/collections/ansible_collections/community/general' Installing 'community.kubernetes:1.1.1' to '/home/muknow/.ansible/collections/ansible_collections/community/kubernetes'
nginxコンテナを起動する
nginxを立ち上げる簡単なプレイブックを書きました。コンテナ側の80番ポートをホスト側の8080番ポートにフォワーディングしています。
ちなみに、ansible_python_interpreterを使ってpythonバージョンを指定しています。今回の環境では、リモートホストはpyenvを使いpythonの環境を分けています。Docker SDKがインストールされたpython環境で、Ansibleがコマンド実行できるようにするため、ansible_python_interpreterで環境を指定しています。
--- - hosts: all become: yes become_method: su tasks: - name: Create nginx community.general.docker_container: name: nginx image: nginx:latest state: started container_default_behavior: compatibility network_mode: bridge published_ports: 0.0.0.0:8080:80 vars: ansible_python_interpreter: /root/.pyenv/versions/3.8.1/bin/python
以下がプレイブックの実行結果です。
ansible-playbook -i hosts run_nginx.yml PLAY [all] ************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************** ok: [CentOS7.6] TASK [Create nginx] ***************************************************************************************************************************** changed: [CentOS7.6] PLAY RECAP ************************************************************************************************************************************** CentOS7.6 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
リモートホスト側で「docker ps」した結果が以下です。起動成功してそうです。
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d9f0b5bc6c23 nginx:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp nginx