Ansible Tips

忘れがちな小技を整理する。Ansible2.0以降を前提にしてる。

pingを飛ばす

1
$ ansible target.host -m ping

factで取れる情報を確認する

1
$ ansible target.host -m setup

rebootして再接続できるまで待つ

こんな感じ。

1
2
3
4
5
6
7
8
- hosts: all
  tasks:
    - name: reboot!
      command: shutdown -r now
    - name: wait for SSH port down
      local_action: wait_for host={{ inventory_hostname }} port=22 state=stopped
    - name: wait for SSH port up
      local_action: wait_for host={{ inventory_hostname }} port=22 state=started delay=30

set_factで情報を書き換える

set_factモジュールを使えば接続情報を変更できる。

1
2
- set_fact:
    ansible_port: 12222

前述の再起動と合わせれば sshd のポート変更とかも対応できてやってる人がいた

フラグからvarsファイルを使う

プレイブックに明示せず実行時に変数を与えたい場合は --extra-vars オプションを使う。 変数をスペース区切りの形式やJSONで与えられる。 @filename でファイルを渡すこともできる。

1
2
3
$ ansible-playbook -i site.yml --extra-vars='user=masumi stage=dev'
$ ansible-playbook -i site.yml --extra-vars='{"user": "masumi", "stage": "dev"}'
$ ansible-playbook -i site.yml --extra-vars='@vars.yml'

lookup pluginで外部から取得する

lookupプラグインを使ってデータソースから値を取得する。

環境変数, fileglob, HashiCorp Vault, Consul, k8s, redis, digとデータ取得元は色々ある。 環境変数から取得する場合は下のようにできる。インベントリファイルでも利用できる。

1
- debug: msg="{{ lookup('env','HOME') }} is an environment variable"

タスクをinclude

タスクを別のファイルに分けて when とかの条件で読み込むのはよくなる。 with_items を使って3回 include させられる。

1
2
3
4
5
6
7
# ...
- task:
  - include: application.yml foo={{ item }} bar=$item
    with_items:
      - "item 1"
      - "item 2"
      - "item 3"

include される側で下のように確認したが、どの形式も問題なく表示される。

1
2
3
4
---
- debug: var=item
- debug: var=foo
- debug: var=bar

blockディレクティブで共通化

blockディレクティブで複数の処理を束ねられる。下みたいな感じ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
- block:
    - copy:
      dest: '...'
      src: '...'
    - template:
      dest: '...'
      src: '...'
  when: result.rc == 0
  become: true
  become_user: root

blockディレクティブで例外処理

resque,always でエラーハンドリングもできる。

meta: flush_handlersを使うと block 内部で notify ハンドラーの実行を止められる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
tasks:
  - block:
      - task:
      - task:
      - notify: handler a
    resque:
      - error_handle_task:
      - meta: flush_handlers
    always:
      - always_task:
handlers:
  - name: handler a
    debug: var=foo

metaでAnsibleのバージョン依存を指定する

下みたいにAnsibleのバージョンを指定できる。

1
min_ansible_version: 2.2

デプロイの適用戦略を調整する

linear がデフォルトの strategy になっていて、タスクの進捗は、ホスト横並びで進められる。 serial を使えば同時実行台数や割合を指定できる。

そして、以下のようにすれば strategyfree に切り替えられる。

1
2
3
4
- hosts: all
  strategy: free
  tasks:
  # ...

registerで結果を取り出す

下のように register を使うことでコマンドの結果を利用することができる。

1
2
3
4
5
6
7
8
---
# tasks file for java8
- shell: java -version 2>&1 | awk '/version/{print $3}' | grep -E '^1\.8\..*'
  register: result
  failed_when: no
  changed_when : no
- import_tasks: install.yml
  when: result.rc != 0

taskによる変更記録を強制する

changed_whenを使うことでタスクの実行によって変更があったかを明記することができる。特に shell などで重要になる。

1
2
- shell: ....
  changed_when: no

taskの失敗を無視する

failed_when を指定することで失敗などを制御できる。例えば失敗するかしないかを利用するようなタスクを作った場合、タスク失敗として停止されては困るために使ったりする。

1
2
- shell: ....
  failed_when: no

checkモードに対応する

check モードを使って事前に検証するけど、 shell とかは実行されない。後続タスクの情報取得などに利用する場合はcheckモードでも動いてほしい。そんな時にはcheck_mode: noと指定する。 これによっていつでも動く。古いAnsibleの場合には always_run ディレクティブを用いる。

1
2
3
4
- shell: ...
  check_mode: no
- shell: ...
  always_run: yes

inventoryをyamlで記述する(配列が使える)

2.4以降ではインベントリファイルにyamlが使える。古い形式はプラグインによって互換性が確保されている。yamlで書く方に統一するのが良さそう。

callback pluginでslackに通知を出す

callbackプラグリンはたくさんあるslack(doc)に従って ansible.cfg で設定する。

したみたいに書く。

1
2
3
4
5
6
7
[defaults]
stdout_callback = slack

[callback_slack]
channel = '#deploy-reports'
nme = ansible
webhook_url = https://hooks.slack.com/services/XXXXXXXXX/YYYYYYY/ZZZZZZZZZZZZZZ

下みたいに報告される。詳細が出ないのが気になる。

slack message

comments powered by Disqus