web-dev-qa-db-ja.com

Ansibleプレイバックを1台のコンピュータに安全に制限しますか?

私は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台のコンピューターに制限するためのベストプラクティスはありますか?いくつかの重要な詳細が省かれていても、理想的にはプレイブックは無害であるべきです。

192
joemaller

プレイブックに直接ホスト名を入力することが可能であることがわかったので、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
183
joemaller

中間のインベントリを使わずに、コマンドラインで単一のホスト(または複数のホスト)を指定できるようにするための、ちょっとしたコツがあります。

ansible-playbook -i "iMac1-local," user.yml

末尾のカンマ()に注意してください。これは、ファイルではなくリストであることを示しています。

さて、誤って実際のインベントリファイルを渡したとしても、これはあなたを保護しません。そのため、この特定の問題に対する良い解決策ではないかもしれません。しかし、知っておくと便利です。

154
Tybstar

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!"
}
74

私見はもっと便利な方法です。 vars_Promptのおかげで、プレイブックを適用したいマシンをユーザーに対話的にプロンプ​​トで指示できます。

---

- hosts: "{{ hosts }}"
  vars_Prompt:
    - name: "hosts"
      Prompt: "Which hosts would you like to setup?"
      private: no
  tasks:
    […]
24
Buzut

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
16
deadbeef404

EC2外部インベントリスクリプトを使用するAWSユーザーは、インスタンスIDで簡単にフィルタリングできます。

ansible-playbook sample-playbook.yml --limit i-c98d5a71 --list-hosts

これは、インベントリスクリプト がデフォルトグループ を作成するために機能します。

9
Frank

バージョン1.7以降、ansibleには run_once オプションがあります。セクションはまた他のさまざまなテクニックのいくつかの議論を含んでいます。

4
Berend de Boer

すべての答えがとても複雑であることを私は本当に理解していません、それをする方法は単純です:

ansible-playbook user.yml -i hosts/hosts --limit iMac-2.local --check

チェックモードでは、何も変更せずにドライランモードで実行できます。

3
knocte

これは、ターゲットサーバー自体でプレイブックを実行する方法を示しています。

ローカル接続を使用したい場合、これは少し面倒です。しかし、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
2
bailey86

私たちには、多数のチームが使える一般的なプレイブックがいくつかあります。複数のグループ宣言を含む環境固有のインベントリファイルもあります。

プレイブックを呼び出している人に対抗するグループを指定させるには、プレイブックの先頭にダミーのエントリを追加します。

[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)に対して実行されるようにスケジュールされているホストのリストにダミーサーバーが表示された場合、呼び出し元はグループを指定せず、プレイブックの実行は失敗します。

2
mcdowellstl

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)/
'
0
iheggie