我正在使用Ansible进行一小组计算机的简单用户管理任务。目前,我将我的Playbooks设置为hosts: all
,而我的主机文件只是一个列出所有机器的组:
# file: hosts
[office]
imac-1.local
imac-2.local
imac-3.local
我发现自己经常不得不针对一台机器。 ansible-playbook
命令可以限制这样的播放:
ansible-playbook --limit imac-2.local user.yml
但这似乎有点脆弱,特别是对于潜在的破坏性剧本。省略limit
标志意味着剧本将在任何地方运行。由于这些工具只是偶尔使用,似乎值得采取措施来简化播放,因此我们不会在几个月之后意外地进行核心操作。
是否有将playbook运行限制为单台机器的最佳做法?理想情况下,如果省略一些重要的细节,剧本应该是无害的。
答案 0 :(得分:182)
事实证明可以直接在剧本中输入主持人名称,因此使用hosts: imac-2.local
运行剧本可以正常工作。但它有点笨重。
更好的解决方案可能是使用变量定义playbook的主机,然后通过--extra-vars
传递特定的主机地址:
# file: user.yml (playbook)
---
- hosts: '{{ target }}'
user: ...
运行剧本:
ansible-playbook user.yml --extra-vars "target=imac-2.local"
如果未定义{{ target }}
,则剧本不执行任何操作。如果需要,也可以传递来自hosts文件的组。总的来说,这似乎是构建潜在破坏性剧本的一种更安全的方式。
定位单个主机的Playbook:
$ 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
Playbook与一组主持人:
$ 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
答案 1 :(得分:154)
还有一个可爱的小技巧,可以让你在命令行上指定一个主机(或者我想是多个主机),没有中间库存:
ansible-playbook -i "imac1-local," user.yml
注意最后的逗号(,);这表明它是一个列表,而不是文件。
现在,如果您不小心传递了真实的库存文件,这将无法保护您,因此它可能不是解决此特定问题的好方法。但这是一个方便的技巧!
答案 2 :(得分:73)
如果通过检查play_hosts变量提供了多个主机,则此方法将退出。如果不满足单个主机条件,则fail module用于退出。以下示例使用带有两个主机alice和bob的主机文件。
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
在单一主机上运行playbook
$ 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!"
}
答案 3 :(得分:24)
恕我直言,这是一种更方便的方式。您确实可以通过vars_prompt
以交互方式提示用户输入他想要应用剧本的机器:
---
- hosts: "{{ hosts }}"
vars_prompt:
- name: "hosts"
prompt: "Which hosts would you like to setup?"
private: no
tasks:
[…]
答案 4 :(得分:16)
要扩展joemailer的答案,如果你想让模式匹配能力匹配远程机器的任何子集(就像ansible
命令那样),但仍然希望能够做到这一点很难不小心在所有机器上运行剧本,这就是我提出的:
与其他答案相同的剧本:
# 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
答案 5 :(得分:9)
使用EC2外部清单脚本的AWS用户只需按实例ID进行过滤:
ansible-playbook sample-playbook.yml --limit i-c98d5a71 --list-hosts
这是因为库存脚本creates default groups。
答案 6 :(得分:5)
由于版本1.7 ansible具有run_once选项。该部分还包含对各种其他技术的一些讨论。
答案 7 :(得分:2)
我真的不明白所有答案都是如此复杂,这样做的方法很简单:
ansible-playbook user.yml -i hosts/hosts --limit imac-2.local --check
检查模式允许您在干运行模式下运行,无需进行任何更改。
答案 8 :(得分:2)
我们有一些可供大量团队使用的通用手册。我们还有特定于环境的库存文件,其中包含多个组声明。
要强制某人调用playbook来指定要反对的组,我们会在游戏手册的顶部播种一个虚拟条目:
[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),则调用者未指定组,并且游戏手册执行将失败。
答案 9 :(得分:1)
这显示了如何在目标服务器本身上运行剧本。
如果要使用本地连接,这会有些棘手。但是,如果将变量用于主机设置,并且在主机文件中为本地主机创建一个特殊条目,则应该可以。
在(所有)剧本中,主机:行设置为:
- hosts: "{{ target | default('no_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
并且如上所述,您可以使用以下方式定位一台计算机(只要它位于主机文件中):
$ ansible-playbook --extra-vars "target=server.domain" test.yml
或具有类似内容的组:
$ ansible-playbook --extra-vars "target=web-servers" test.yml
答案 10 :(得分:0)
我有一个名为provision的包装脚本强制您选择目标,所以我不必在其他地方处理它。
对于那些好奇的人,我使用ENV vars作为我的vagrantfile使用的选项(为云系统添加相应的ansible arg)并让其余的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)/
'
答案 11 :(得分:0)
稍微不同的解决方案是使用特殊变量ansible_limit
,该变量是--limit
CLI选项的内容,用于当前执行Ansible。
- hosts: "{{ ansible_limit | default(omit) }}"
无需在此处定义额外的变量,只需运行带有--limit
标志的剧本即可。
ansible-playbook --limit imac-2.local user.yml
答案 12 :(得分:-1)
我建议使用--limit <hostname or ip>