20
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Ansibleのローカル実行

概要

Ansibleによるsshを使用しないローカル実行には、以下の2つの指定が必要。

  • 接続方法: local
  • 宛先: localhost
    • インベントリーが空でなければ必須では無い

それらは、以下などで指定可能。

  • Playbook
  • コマンド引数
  • インベントリー

検証環境

  • macOS 10.15.4
  • ansible 2.9.4
  • phthon 3.8.2 (pyenv環境)

例1a: Playbookでの指定 (全てのtaskがlocal)

インベントリー: 無し

例1a: 接続先をlocalhostのみで指定

接続方法を指定しなくとも、相手がlocalhostの場合には、接続方法はlocalが選択される。

site.yml

---
- hosts: localhost      # 接続先(localhostは、インベントリーになくとも指定可能)
  gather_facts: false
  tasks:

  - shell: hostname
    register: r_hostname
  - debug: { var: r_hostname.stdout }


  - debug: { var: ansible_connection }
  - debug: { var: ansible_playbook_python }
  - debug: { var: ansible_python_interpreter }

コマンドパラメーターと実行結果

パラメーターはplaybook名のみ

$ ansible-playbook site.yml 
[WARNING]: No inventory was parsed, only implicit localhost is available

[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not
match 'all'


PLAY [localhost] *************************************************************************************************

TASK [shell] *****************************************************************************************************
changed: [localhost]

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "r_hostname.stdout": "hogehoge"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_connection": "local"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_playbook_python": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_python_interpreter": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

PLAY RECAP *******************************************************************************************************
localhost                  : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • インベントリーが無いというワーニングが出力される
  • 自動的に "ansible_connection": "local" が設定される
  • 自動的に "ansible_python_interpreter" に、ansible_playbook_python と同じ値が設定される
  • ansible-playbook を、-i localhost, -c local として実行すると、接続方法は正しく local となるが、ansible_python_interpreter が定義されていないので、以下の様なワーニングが出力されることになる。
[WARNING]: Platform darwin on host localhost is using the discovered Python interpreter at /usr/bin/python, but
future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.

例1b: Playbookでの指定 (一部のtaskがlocalhostのみ対象)

例1b-1: 接続方法をtask単位で delegate_to: localhost にて指定

インベントリーは他の接続先が存在する想定

site.yml
---
- hosts: all               # 宛先 インベントリーにおけるデフォルトのallグループ
  gather_facts: false
  tasks:

  - shell: hostname
    register: r_hostname
    delegate_to: localhost  # 接続方法
    #run_once: true         # 各ノード分だけ実行する必要がないならコメントイン

  - debug: { var: r_hostname.stdout }
    delegate_to: localhost  # 接続方法 (debugモジュールなので意味はないが)
    #run_once: true         # 各ノード分だけ実行する必要がないならコメントイン


  - debug: { var: ansible_playbook_python }
    run_once: true
  - debug: { var: hostvars['localhost'].ansible_connection }
    run_once: true
  - debug: { var: hostvars['localhost'].ansible_python_interpreter }
    run_once: true

例1b-2: 接続方法をタスクのブロックに対して指定

site.yml
---
- hosts: all               # 宛先 インベントリーにおけるデフォルトのallグループ
  gather_facts: false
  tasks:

  - delegate_to: localhost  # blockに対して接続方法を指定
    block:                  # blockでまとめて 

    - shell: hostname
      register: r_hostname
      #run_once: true       # 各ノード分だけ実行する必要がないならコメントイン

    - debug: { var: r_hostname.stdout }
      #run_once: true       # 各ノード分だけ実行する必要がないならコメントイン

    # blockはここまで

  - debug: { var: ansible_playbook_python }
    run_once: true
  - debug: { var: hostvars['localhost'].ansible_connection }
    run_once: true
  - debug: { var: hostvars['localhost'].ansible_python_interpreter }
    run_once: true

コマンドパラメーターと実行結果

$ ansible-playbook -i inv site.yml

PLAY [all] *******************************************************************************************************

TASK [shell] *****************************************************************************************************
changed: [host1 -> localhost]             # <= 実行ホストの変更が [host1 -> localhost] の様に表示される
changed: [host2 -> localhost]             # <= run_once: trueが付いていれば1ノードのみで実行

TASK [debug] *****************************************************************************************************
ok: [host2 -> localhost] => {
    "r_hostname.stdout": "hogehoge"
}
ok: [host1 -> localhost] => {
    "r_hostname.stdout": "hogehoge"
}

TASK [debug] *****************************************************************************************************
ok: [host1] => {                          # <= run_once: trueの為、1ノードのみで実行
    "ansible_playbook_python": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

TASK [debug] *****************************************************************************************************
ok: [host1] => {
    "hostvars['localhost'].ansible_connection": "local"  # <= local接続が設定されている
}

TASK [debug] *****************************************************************************************************
ok: [host1] => {
    "hostvars['localhost'].ansible_python_interpreter": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8" # <= 使用されるpythonもコントローラー側の pyton(ansible_playbook_python) と同じものが使用される。
}

PLAY RECAP *******************************************************************************************************
host1                      : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
host2                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

例1c: Playbookでの指定 (localとその他のhostが同時に対象)

インベントリーには、他の接続先とlocalhostが含まれる想定

インベントリー
$ cat inv
localhost
host1 ansible_connection=ssh ansible_user=xxxx ansible_ssh_private_key_file="xxxx/id_rsa" ansible_host=xxxx ansible_port=nnnn ansible_python_interpreter=/usr/bin/python

ここでlocalhost ansible_connection=local ansible_python_interpreter=xxxx などとすることも可能。(例3)

site.yml
- hosts: all
  gather_facts: false
  pre_tasks:                                     # tasksの先頭でも良い。
    - when: inventory_hostname == 'localhost'    # 相手がlocalhostの場合
      set_fact:
        ansible_connection: local                # 接続方法をlocalに
        ansible_python_interpreter: '{{ ansible_playbook_python }}' # 接続先のpythonをコントラーのpythonに設定
  tasks:
    - shell: hostname
      register: r
    - debug: var=r.stdout

    - debug: var=ansible_playbook_python
    - debug: var=ansible_connection
    - debug: var=ansible_python_interpreter
    - debug: var=hostvars[inventory_hostname].ansible_connection
    - debug: var=hostvars[inventory_hostname].ansible_python_interpreter

コマンドパラメーターと実行結果

$ ansible-playbook -i inv site.yml 

PLAY [all] *******************************************************************************************************

TASK [set_fact] **************************************************************************************************
skipping: [host1]
ok: [localhost]               # <= ここでlocalhostのansible_connectionなどを設定

TASK [shell] *****************************************************************************************************
changed: [localhost]
changed: [host1]

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "r.stdout": "hogehoge"
}
ok: [host1] => {
    "r.stdout": "host1"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_playbook_python": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}
ok: [host1] => {
    "ansible_playbook_python": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {      # <= もしansible_connectionを未設定の場合、sshとなる
    "ansible_connection": "local"
}
ok: [host1] => {
    "ansible_connection": "ssh"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {      # <= localhostのpythonは、set_factにてコントーラーのpythonに合わせている
    "ansible_python_interpreter": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}
ok: [host1] => {
    "ansible_python_interpreter": "/usr/bin/python"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {     # <= もしansible_connectionを未設定の場合、VARIABLE IS NOT DEFINED!となる
    "hostvars[inventory_hostname].ansible_connection": "local"
}
ok: [host1] => {
    "hostvars[inventory_hostname].ansible_connection": "ssh"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {     # <= もしansible_python_interpreterを未設定の場合、VARIABLE IS NOT DEFINED!となる
    "hostvars[inventory_hostname].ansible_python_interpreter": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}
ok: [host1] => {
    "hostvars[inventory_hostname].ansible_python_interpreter": "/usr/bin/python"
}

PLAY RECAP *******************************************************************************************************
host1                      : ok=7    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
localhost                  : ok=8    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

例2: パラメーターによる指定

インベントリー: 無し

Playbook

宛先は汎用的に、デフォルトで存在する all group を指定
接続方法指定は行わない。

site.yml

---
- hosts: all              
  gather_facts: false
  tasks:
  - shell: hostname
    register: r
  - debug: var=r.stdout

  - debug: var=ansible_playbook_python
  - debug: var=ansible_connection
  - debug: var=ansible_python_interpreter
  - debug: var=hostvars[inventory_hostname].ansible_connection
  - debug: var=hostvars[inventory_hostname].ansible_python_interpreter

コマンドパラメーターと実行結果

  • --connection=local (もしくは -c local) を使用して接続方法を指定
  • --inventory=localhost, (もしくは -i localhost,) などを使用して接続を指定
    • この例では、直接接続先を指定しているが、ファイル指定でも良い。直接指定の場合、接続先が1つのみであっても、","を付与する必要がある。
    • 接続方法としてlocalを指定する為、実際はインベントリーは空でさえなければ良い
$ ansible-playbook -i localhost, -c local site.yml

PLAY [all] *******************************************************************************************************

TASK [shell] *****************************************************************************************************
[WARNING]: Platform darwin on host localhost is using the discovered Python interpreter at /usr/bin/python, but
future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.

changed: [localhost]

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "r.stdout": "hogehoge"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_playbook_python": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_connection": "local"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_python_interpreter": "VARIABLE IS NOT DEFINED!"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "hostvars[inventory_hostname].ansible_connection": "VARIABLE IS NOT DEFINED!"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "hostvars[inventory_hostname].ansible_python_interpreter": "VARIABLE IS NOT DEFINED!"
}

PLAY RECAP *******************************************************************************************************
localhost                  : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  • Ansible 2.9 から、ansible_python_interpreter 未指定のワーニングが出力される様になっている
  • 対象がlocalhostのみならば、ansible-playbookに、-e ansible_python_interpreter=xxxxとして指定することが可能。localhost以外も対象となるならば、例1の様にplaybook内でset_factを使用するか、例3の様にインベントリーで指定する対応が現実的でしょう。

例3: インベントリーを使用しての指定

例3-1: INI書式

hosts
localhost ansible_connection=local ansible_python_interpreter=/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8

例3-2: YAML書式

hosts
all:
  children:
    ungrouped:
      hosts:
        localhost:
          ansible_connection: local
          ansible_python_interpreter: /usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8

これは、例3-1のファイルを用いて、ansible-inventory -i hosts --list --yaml により生成可能

例3-3: JSON書式

hosts
{
  "all": {
    "children": {
      "ungrouped": {
        "hosts": {
          "localhost": {
            "ansible_connection": "local",
            "ansible_python_interpreter": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
          }
        }
      }
    }
  }
}

これは、例3-1のファイルを用いて、ansible-inventory -i hosts --list --yaml | yq . などにより生成可能 (要 yq などyamlをjson化するコマンド/スクリプト)

ちなみに、ダイナミックインベントリーで返される必要があるJSONのフォーマットとは、ansible-inventory -i hosts --list により生成可能。(ややフォーマットが異なる)

Playbook

宛先は汎用的にall指定
接続方法指定は行わない。

site.yml
---
- hosts: all              
  gather_facts: false
  tasks:
  - shell: hostname
    register: r
  - debug: var=r.stdout

  - debug: var=ansible_playbook_python
  - debug: var=ansible_connection
  - debug: var=ansible_python_interpreter
  - debug: var=hostvars[inventory_hostname].ansible_connection
  - debug: var=hostvars[inventory_hostname].ansible_python_interpreter

コマンドパラメーターと実行結果

--inventory-file=hosts (もしくは -i hosts か --inventory=hosts) にてインベントリーファイルを指定
例3-1のINI書式、3-2のYAML書式、3-3のJSON書式、いずれも使用可能。
また、ダイナミックインベントリ用JSONを返す実行可能スクリプトなどを指定しても良い。

$ ansible-playbook -i hosts site.yml 

PLAY [all] *******************************************************************************************************

TASK [shell] *****************************************************************************************************
changed: [localhost]

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "r.stdout": "hogehoge"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_playbook_python": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_connection": "local"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "ansible_python_interpreter": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "hostvars[inventory_hostname].ansible_connection": "local"
}

TASK [debug] *****************************************************************************************************
ok: [localhost] => {
    "hostvars[inventory_hostname].ansible_python_interpreter": "/usr/local/Cellar/ansible/2.9.4_1/libexec/bin/python3.8"
}

PLAY RECAP *******************************************************************************************************
localhost                  : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

参考:

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
20
Help us understand the problem. What are the problem?