公式ドキュメント を読んで重要な点をメモしておく。
version 1.9 を前提にメモ。
用語の整理
-
facts
: 更新先となるリモートサーバの各種情報。冒頭で取ってくる。 -
inventory
:hosts
ファイルで定義されるもののこと。 -
handler
: サーバでの変更に応じて他サーバで何かをするためのイベントの仕組み。 -
playbook
:ansible-playbook
コマンドに渡すメインの yml のこと。設計する上では、構築手順を書くのでなく、何者なのかを書くこと。 -
冪等性(べきとうせい/idempotent)
: 何度動かしても大丈夫なこと。
hosts
- host をグループ化できる。グループごとにキーバリューを設定できる:
グループごとの値設定
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
- グループはネストできる:
グループのネスト
[southeast:children]
group1
group2
tasks
- 書かれている順に実行される。
- 1つ
task
を対象サーバすべてに適用してから、次のtask
に移る。
handlers
playbook
tasks:
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
と書いておくと、変更があった場合のみ、handler
の実行できる。
注:
-
notify
の中は書かれている順に実行される。 -
handlers
の中の名前は global スコープ。(同名があれば片方のみ実行される。) -
include
の中にあるhandler
はnotify
できない。 -
pre_tasks
,tasks
,post_tasks
の中でnotify
されたhandler
は、各セクションの終了時にフラッシュ(≒実際に実行)され、roles
の中でnotify
されたhandler
は、tasks
セクションの全のhandler
の後にフラッシュされる。 -
meta: flush_handlers
でただちにフラッシュすることも可能:
playbook
tasks:
- shell: some tasks go here
- meta: flush_handlers
- shell: some other tasks
include
- トップ階層に
tasks
ディレクトリを作成し、その中に再利用可能な task の yml を保存しておくことで、playbook 中で再利用できる。 - パラメータを渡すことも可能:
パラメータを渡す例
- include: wordpress.yml wp_user=timmy
もしくは
- include: wordpress.yml
vars:
wp_user: timmy
- 別の playbook を include することも可能。その場合、パラメータは渡せない?
role
次のように振る舞う:
- roles/x/tasks/main.yml (あれば)
- roles/x/handlers/main.yml (あれば)
- roles/x/vars/main.yml (あれば)
- roles/x/meta/main.yml (あれば) 内の role dependencies が roles に加わる。
- role 内の
copy
,script
,template
,include
タスクはroles/x/{files,templates,tasks}/
(ディレクトリはタスクによる) の下を見る。
パラメータを渡す role:
roles:
- common
- { role: foo_app_instance, dir: '/opt/a', app_port: 5000 }
- { role: foo_app_instance, dir: '/opt/b', app_port: 5001 }
条件付きの role:
roles:
- { role: some_role, when: "ansible_os_family == 'RedHat'" }
タグ付きの role (role内の全タグを上書くので注意):
roles:
- { role: foo, tags: ["bar", "baz"] }
role の前後に task を走らせないなら:
pre_tasks:
- shell: echo 'hello'
roles:
- { role: some_role }
tasks:
- shell: echo 'still busy'
post_tasks:
- shell: echo 'goodbye'
別の role に依存するなら (roles/x/meta/main.yml の中で) :
dependencies:
- { role: common, some_parameter: 3 }
- { role: apache, appache_port: 80 }
- { role: postgres, dbname: blarg, other_parameter: 12 }
- 同じ role は(パラメータが異なっていたとしても)デフォルトでは複数回適用されない。複数適用したいなら呼ばれる側で
allow_duplicates: yes
(複数回の適用を許す) が必要:
roles/car/meta/main.yml (呼び出す側)
dependencies:
- { role: wheel, n: 1 }
- { role: wheel, n: 2 }
roles/wheel/meta/main.yml (呼ばれる側)
allow_duplicates: yes
dependencies:
- { role: tire }
変数
命名ルール
-
foo_port
のようなフォーマットであること。 - 値は yaml で map を書くこともできる。
値の定義場所
inventory:
hosts
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
playbook:
playbook
- hosts: webservers
vars:
http_port: 80
include に渡す:
playbook
tasks:
- include: foo.yml
vars:
aa: timmy
bb:
key1: keys/one.txt
key2: keys/two.txt
値を外出し:
playbook
- hosts: all
remote_user: root
vars:
favcolor: blue
vars_files:
- /vars/external_vars.yml
/vars/external_vars.yml
somevar: somevalue
password: magic
コマンドライン:
ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
もしくは
ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
もしくは
ansible-playbook release.yml --extra-vars "@some_file.json"
もしくは
ansible-playbook release.yml --extra-vars "@some_file.yml"
優先順位(下にいくほど強い)
- role defaults
- inventory の定義
- facts
- その他(コマンドラインのスイッチ、playのvars、includeされたvars、roleのvarsなど)
- コネクション変数(
ansible_user
など) - extra vars(コマンドラインの
-e
)
※2.x で変わるらしい。
値を使う
-
{{ aa }}
や{{ bb.key1 }}
のように使う。 -
foo: {{ bar }}/22
は NG。foo: "{{ bar }}/22"
とすべき。これは yaml の文法上、{
がディクショナリの開始と混同されるため。
フィルタ
-
{{ val|default('aaa') }}
-val
が未定義の場合にaaa
を採用。 -
{{ val|default('aaa', true) }}
-val
がfalse
として評価される値の場合(''
等)にaaa
を採用。 -
{{ val|escape }}
-<>&"'
を HTML 用にエスケープ。 -
{{ "%s - %s"|format("Hello?", "Foo!") }}
- フォーマット。 -
{{ val|trim }}
- トリム。 - shell: echo {{ string_value | quote }}
-
{{ (name == "John") | ternary('Mr','Ms') }}
- true なら左。 {{ list | join(" ") }}
-
{{ path | basename }}
- ファイル名 -
{{ path | dirname }}
- ディレクトリ名 {{ path | realpath }}
{{ path | relpath('/etc') }}
-
when: some_string_value | bool
- bool にキャスト -
when: url | match("http://example.com/users/.*/resources/.*")
- 正規表現でえ完全一致 -
when: url | search("/users/.*/resources/.*")
- 正規表現で中間一致 -
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}
- 正規表現で置き換え
register
tasks:
- shell: /usr/bin/foo
register: foo_result
ignore_errors: True
- shell: /usr/bin/bar
when: foo_result.rc == 5
結果をフィルタして条件に使う
- shell: /usr/bin/foo
register: result
ignore_errors: True
- debug: msg="it failed"
when: result|failed
# in most cases you'll want a handler, but if you want to do something right now, this is nice
- debug: msg="it changed"
when: result|changed
- debug: msg="it succeeded in Ansible >= 2.1"
when: result|succeeded
- debug: msg="it succeeded"
when: result|success
- debug: msg="it was skipped"
when: result|skipped
- 結果が失敗でも skip されても
foo_result
は失敗/skipの結果が登録される。登録を避けたいならタグを使えばいい。
予約語
-
hostvars
- 別host用の値が入っている。この時点で全くやりとりの無いサーバでも変数値は取れるが、その場合 facts は取れない。使用例:{{ hostvars['test.example.com']['ansible_distribution'] }}
-
group_names
- 現在のhost
が属するグループのリスト(配列)。 -
groups
- inventory に存在するすべてのグループとhost。
スコープ
- global - コンフィグ、環境変数、コマンドラインによるもの。
- play - 各playと、含まれる構造体, varsのentries, include_vars, role defaults , vars
- host - hostに直接関連する値(inventory、facts、taskの出力をregisterしたものなど)