安全地将Ansible游戏手册限制在一台机器上?

我正在使用Ansible进行一些简单的用户pipe理任务,只有一小组计算机。 目前,我有我的剧本设置为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标志放在外面意味着剧本可以在任何地方运行。 由于这些工具只是偶尔使用,所以似乎值得采取措施来保证回放的安全,所以我们不会在几个月后不小心触及到这些东西。

是否有限制剧本运行到一台机器的最佳做法? 理想情况下,如果忽略了一些重要的细节,剧本应该是无害的。

原来可以直接input一个主机名到剧本中,所以用hosts: imac-2.local运行剧本将会正常工作。 但它有点笨重。

更好的解决scheme可能是使用variables定义剧本的主机,然后通过--extra-vars传递特定的主机地址:

 # file: user.yml (playbook) --- - hosts: '{{ target }}' user: ... 

运行剧本:

 ansible-playbook user.yml --extra-vars "target=imac-2.local" 

如果{{ target }}没有被定义,那么剧本就什么也不做。 如果需要,来自主机文件的组也可以通过。 总的来说,这似乎是构build一个潜在破坏性剧本的更安全的方法。

针对单个主机的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 

还有一个可爱的小窍门,可以让你在命令行(或者多个主机)上指定一个主机,而不需要中间清单:

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

注意最后的逗号( ); 这表示它是一个列表,而不是一个文件。

现在,如果你不小心传入了真实的库存文件,这不会保护你,所以这可能不是一个很好的解决scheme。 但这是一个方便的技巧知道!

如果通过检查play_hostsvariables提供多个主机,则此方法将退出。 如果单个主机条件不满足,则使用故障模块退出。 下面的例子使用两个主机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!' 

运行没有主机filter的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!" } 

有恕我直言更方便的方式。 您可以确实交互式地提示用户input他想要应用该手册的机器,这要归功于vars_prompt

 --- - hosts: "{{ hosts }}" vars_prompt: - name: "hosts" prompt: "Which hosts would you like to setup?" private: no tasks: […] 

为了扩大joemailer的答案,如果你想要使模式匹配能力匹配远程机器的任何子集(就像命令那样),但是仍然想要在所有机器上意外运行这个剧本,是我所想到的:

和其他答案一样的剧本:

 # file: user.yml (playbook) --- - hosts: '{{ target }}' user: ... 

让我们有以下主机:

 imac-10.local imac-11.local imac-22.local 

现在,要在所有设备上运行该命令,必须明确将目标variables设置为“全部”

 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 

这是因为库存脚本创build了默认组 。

自1.7版以来, 有了run_once选项。 部分还包含一些其他各种技术的讨论。

我有一个叫做Provision的包装脚本强制你select目标,所以我不必在其他地方处理它。

对于那些好奇的人,我使用ENV vars来select我的vagrantfile所使用的选项(为云系统添加相应的安全参数),并让其余的ansible args通过。 在一次创build和configuration超过10台服务器的地方,我会在失败的服务器上包含一个自动重试(只要正在取得进展 – 我发现每次创build100台左右的服务器时,往往有几台服务器会在第一次失败)。

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

我们有一些通用的剧本可供大量的团队使用。 我们也有环境特定的库存文件,包含多个组声明。

为了强制某人调用剧本来指定一个组来运行,我们在剧本的顶部播放一个虚拟条目:

 [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)主机列表中,则调用者没有指定一个组,剧本执行将失败。

我真的不明白所有的答案是如此复杂,如何做到这一点很简单:

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

检查模式允许您以干运行模式运行,而不作任何改变。