私はAnsibleを少数のコンピュータグループでの簡単なユーザー管理作業に使っています。現在のところ、私は自分のプレイブックをhosts: all
に設定しています。そして私のhostsファイルは、すべてのマシンがリストされた単一のグループです。
# file: hosts
[office]
iMac-1.local
iMac-2.local
iMac-3.local
私は自分が頻繁に単一のマシンをターゲットにしなければならないことに気づきました。 ansible-playbook
コマンドは、このように再生を制限することができます。
ansible-playbook --limit iMac-2.local user.yml
しかしそれは、特に破壊的な可能性のあるプレイブックにとっては、ちょっと壊れやすいようです。 limit
フラグを省略すると、プレイブックはどこでも実行されることになります。これらのツールは時折使用されるだけなので、絶対確実な再生をするための手段を講じる価値があるように思われます。
プレイブックの実行を1台のコンピューターに制限するためのベストプラクティスはありますか?いくつかの重要な詳細が省かれていても、理想的にはプレイブックは無害であるべきです。
プレイブックに直接ホスト名を入力することが可能であることがわかったので、hosts: iMac-2.local
でプレイブックを走らせることはうまくいくでしょう。しかし、それはちょっと不格好です。
より良い解決策は、変数を使ってプレイブックのホストを定義し、それから--extra-vars
を通して特定のホストアドレスを渡すことです:
# file: user.yml (playbook)
---
- hosts: '{{ target }}'
user: ...
プレイブックを実行する:
ansible-playbook user.yml --extra-vars "target=iMac-2.local"
{{ target }}
が定義されていない場合、プレイブックは何もしません。必要に応じて、hostsファイルからのグループも通過させることができます。全体として、これは破壊的な可能性のあるプレイブックを作成するためのはるかに安全な方法のように思えます。
単一のホストをターゲットとしたプレイブック:
$ ansible-playbook user.yml --extra-vars "target=iMac-2.local" --list-hosts
playbook: user.yml
play #1 (iMac-2.local): Host count=1
iMac-2.local
ホストのグループとプレイブック:
$ ansible-playbook user.yml --extra-vars "target=office" --list-hosts
playbook: user.yml
play #1 (office): Host count=3
iMac-1.local
iMac-2.local
iMac-3.local
ホストを定義するのを忘れても安全です。
$ ansible-playbook user.yml --list-hosts
playbook: user.yml
play #1 ({{target}}): Host count=0
中間のインベントリを使わずに、コマンドラインで単一のホスト(または複数のホスト)を指定できるようにするための、ちょっとしたコツがあります。
ansible-playbook -i "iMac1-local," user.yml
末尾のカンマ(、)に注意してください。これは、ファイルではなくリストであることを示しています。
さて、誤って実際のインベントリファイルを渡したとしても、これはあなたを保護しません。そのため、この特定の問題に対する良い解決策ではないかもしれません。しかし、知っておくと便利です。
play_hosts 変数をチェックすることによって複数のホストが提供されている場合、このアプローチは終了します。単一のホスト条件が満たされない場合、 失敗モジュール を使用して終了します。以下の例では、2つのホストaliceとbobを持つhostsファイルを使用しています。
user.yml(playbook)
---
- hosts: all
tasks:
- name: Check for single Host
fail: msg="Single Host check failed."
when: "{{ play_hosts|length }} != 1"
- debug: msg='I got executed!'
ホストフィルタなしでplaybookを実行します
$ ansible-playbook user.yml
PLAY [all] ****************************************************************
TASK: [Check for single Host] *********************************************
failed: [alice] => {"failed": true}
msg: Single Host check failed.
failed: [bob] => {"failed": true}
msg: Single Host check failed.
FATAL: all hosts have already failed -- aborting
単一のホストでプレイブックを実行する
$ ansible-playbook user.yml --limit=alice
PLAY [all] ****************************************************************
TASK: [Check for single Host] *********************************************
skipping: [alice]
TASK: [debug msg='I got executed!'] ***************************************
ok: [alice] => {
"msg": "I got executed!"
}
私見はもっと便利な方法です。 vars_Prompt
のおかげで、プレイブックを適用したいマシンをユーザーに対話的にプロンプトで指示できます。
---
- hosts: "{{ hosts }}"
vars_Prompt:
- name: "hosts"
Prompt: "Which hosts would you like to setup?"
private: no
tasks:
[…]
Joemailerの答えを広げるために、(ansible
コマンドがするように)リモートマシンの任意のサブセットにパターンマッチング機能を使いたいが、それでもすべてのマシンで誤ってplaybookを実行することを非常に困難にしたいなら、私が思いついたものです:
他の答えと同じプレイブック:
# file: user.yml (playbook)
---
- hosts: '{{ target }}'
user: ...
以下のホストを用意しましょう。
iMac-10.local
iMac-11.local
iMac-22.local
さて、すべてのデバイスでコマンドを実行するには、ターゲット変数を "all"に明示的に設定する必要があります。
ansible-playbook user.yml --extra-vars "target=all"
そしてそれを特定のパターンに限定するために、あなたはtarget=pattern_here
をセットすることができます。
あるいは、target=all
を残して--limit
引数を追加することもできます。
--limit iMac-1*
すなわち。 ansible-playbook user.yml --extra-vars "target=all" --limit iMac-1* --list-hosts
その結果、
playbook: user.yml
play #1 (office): Host count=2
iMac-10.local
iMac-11.local
EC2外部インベントリスクリプトを使用するAWSユーザーは、インスタンスIDで簡単にフィルタリングできます。
ansible-playbook sample-playbook.yml --limit i-c98d5a71 --list-hosts
これは、インベントリスクリプト がデフォルトグループ を作成するために機能します。
バージョン1.7以降、ansibleには run_once オプションがあります。セクションはまた他のさまざまなテクニックのいくつかの議論を含んでいます。
すべての答えがとても複雑であることを私は本当に理解していません、それをする方法は単純です:
ansible-playbook user.yml -i hosts/hosts --limit iMac-2.local --check
チェックモードでは、何も変更せずにドライランモードで実行できます。
これは、ターゲットサーバー自体でプレイブックを実行する方法を示しています。
ローカル接続を使用したい場合、これは少し面倒です。しかし、hosts設定に変数を使用し、hostsファイルにlocalhost用の特別なエントリを作成すれば、これは問題ありません。
(すべての)プレイブックでは、hosts:行が次のように設定されています。
- hosts: "{{ target | default('no_hosts')}}"
Inventory hostsファイルに、接続をローカルに設定するlocalhostのエントリを追加します。
[localhost]
127.0.0.1 ansible_connection=local
次に、コマンドラインで明示的にターゲットを設定してコマンドを実行します。次に例を示します。
$ ansible-playbook --extra-vars "target=localhost" test.yml
これはansible-pullを使うときにもうまくいきます。
$ ansible-pull -U <git-repo-here> -d ~/ansible --extra-vars "target=localhost" test.yml
コマンドラインで変数を設定するのを忘れた場合、コマンドは( 'no_hosts'という名前のホストグループを作成していない限り)安全にエラーを起こし、
skipping: no hosts matched
そして、上で述べたように、(hostsファイルにある限り)単一のマシンをターゲットにすることができます。
$ ansible-playbook --extra-vars "target=server.domain" test.yml
あるいは次のようなグループ
$ ansible-playbook --extra-vars "target=web-servers" test.yml
私たちには、多数のチームが使える一般的なプレイブックがいくつかあります。複数のグループ宣言を含む環境固有のインベントリファイルもあります。
プレイブックを呼び出している人に対抗するグループを指定させるには、プレイブックの先頭にダミーのエントリを追加します。
[ansible-dummy-group]
dummy-server
次に、共有プレイブックの最初のステップとして次のチェックを含めます。
- hosts: all
gather_facts: False
run_once: true
tasks:
- fail:
msg: "Please specify a group to run this playbook against"
when: '"dummy-server" in ansible_play_batch'
このプレイブックが(ansible_play_batch)に対して実行されるようにスケジュールされているホストのリストにダミーサーバーが表示された場合、呼び出し元はグループを指定せず、プレイブックの実行は失敗します。
Provisionというラッパースクリプトを使ってターゲットを選択するようにしているので、他の場所で処理する必要はありません。
興味がある人のために、私は私のvagrantfileが使うオプション(クラウドシステムのための対応するansible argを加える)のためにENV varsを使い、残りのansible argsを通過させます。一度に10台以上のサーバーを作成してプロビジョニングする場合、失敗したサーバーの自動再試行を含めます(進行中であれば - 一度に100台程度のサーバーを作成すると最初に失敗することがよくあります) ).
echo 'Usage: [VAR=value] bin/provision [options] dev|all|TARGET|vagrant'
echo ' bootstrap - Bootstrap servers ssh port and initial security provisioning'
echo ' dev - Provision localhost for development and control'
echo ' TARGET - specify specific Host or group of hosts'
echo ' all - provision all servers'
echo ' vagrant - Provision local vagrant machine (environment vars only)'
echo
echo 'Environment VARS'
echo ' BOOTSTRAP - use cloud providers default user settings if set'
echo ' TAGS - if TAGS env variable is set, then only tasks with these tags are run'
echo ' SKIP_TAGS - only run plays and tasks whose tags do not match these values'
echo ' START_AT_TASK - start the playbook at the task matching this name'
echo
ansible-playbook --help | sed -e '1d
s#=/etc/ansible/hosts# set by bin/provision argument#
/-k/s/$/ (use for fresh systems)/
/--tags/s/$/ (use TAGS var instead)/
/--skip-tags/s/$/ (use SKIP_TAGS var instead)/
/--start-at-task/s/$/ (use START_AT_TASK var instead)/
'