模式:目标主机与组
当你通过 ad hoc 命令或运行 playbook 执行 Ansible 时,必须选择想要执行的受管节点或组。模式(Patterns)允许你针对清单(inventory)中的特定主机和/或组运行命令和 playbook。Ansible 模式可以指代单个主机、一个 IP 地址、一个清单组、一组组,或者清单中的所有主机。模式非常灵活 —— 你可以排除或要求主机子集,使用通配符或正则表达式等。Ansible 将在模式中包含的所有清单主机上执行。
使用模式
几乎在每次执行 ad hoc 命令或 playbook 时,你都会使用模式。模式是 ad hoc 命令 中唯一没有标志(flag)的元素。它通常是第二个元素
ansible <pattern> -m <module_name> -a "<module options>"
例如
ansible webservers -m service -a "name=httpd state=restarted"
在 playbook 中,模式是每个 play 的 hosts: 行的内容
- name: <play_name>
hosts: <pattern>
例如
- name: restart webservers
hosts: webservers
由于你经常希望一次性地在多个主机上运行命令或 playbook,因此模式通常指向清单组。上述 ad hoc 命令和 playbook 都将在 webservers 组中的所有机器上执行。
常用模式
本表列出了用于指定清单主机和组的常用模式。
描述 |
模式 (Pattern(s)) |
目标 |
|---|---|---|
所有主机 |
all (或 *) |
|
单个主机 |
host1 |
|
多个主机 |
host1:host2 (或 host1,host2) |
|
单个组 |
webservers |
|
多个组 |
webservers:dbservers |
webservers 组中的所有主机加上 dbservers 组中的所有主机 |
排除组 |
webservers:!atlanta |
webservers 组中的所有主机,但不包括 atlanta 组中的主机 |
组的交集 |
webservers:&staging |
同时在 webservers 和 staging 组中的任何主机 |
注意
你可以使用逗号 (,) 或冒号 (:) 来分隔主机列表。在处理范围和 IPv6 地址时,首选逗号。
掌握基础模式后,你可以将它们组合起来。这个例子
webservers:dbservers:&staging:!phoenix
目标是‘webservers’和‘dbservers’组中且同时在‘staging’组中的所有机器,但排除‘phoenix’组中的任何机器。
只要你的主机在清单中是以 FQDN 或 IP 地址命名的,你就可以对 FQDN 或 IP 地址使用通配符模式
192.0.*
*.example.com
*.com
你可以同时混合使用通配符模式和组
one*.com:dbservers
模式的局限性
模式依赖于清单。如果主机或组未列在你的清单中,你无法使用模式来指定它。如果你的模式包含一个未出现在清单中的 IP 地址或主机名,你会看到类似这样的错误
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: Could not match supplied host pattern, ignoring: *.not_in_inventory.com
你的模式必须符合你的清单语法。如果你将主机定义为 别名 (alias)
atlanta:
hosts:
host1:
http_port: 80
maxRequestsPerChild: 808
ansible_host: 127.0.0.2
你必须在模式中使用该别名。在上面的示例中,你必须在模式中使用 host1。如果你使用 IP 地址,将再次收到错误
[WARNING]: Could not match supplied host pattern, ignoring: 127.0.0.2
模式处理顺序
处理过程比较特殊,并按以下顺序进行
:和,&!
这种定位仅适用于每个操作内部的处理顺序:a:b:&c:!d:!e == &c:a:!d:b:!e == !d:a:!e:&c:b
这些结果都如下所示
主机在/是 (a 或 b) 且 主机在/是 所有(c) 且 主机不在/不是 所有(d, e)。
现在 a:b:!e:!d:&c 有细微变化,因为 !e 在 !d 之前被处理,但这并没有太大区别
主机在/是 (a 或 b) 且 主机在/是 所有(c) 且 主机不在/不是 所有(e, d)。
高级模式选项
上述常用模式将满足你的大部分需求,但 Ansible 还提供了其他几种定义目标主机和组的方法。
在模式中使用变量
你可以使用变量来允许通过 ansible-playbook 的 -e 参数传递组指定符
webservers:!{{ excluded }}:&{{ required }}
在模式中使用组位置
你可以通过主机在组中的位置来定义主机或主机子集。例如,给定以下组
[webservers]
cobweb
webbing
weber
你可以使用下标来选择 webservers 组中的单个主机或范围。
对特定项目进行切片
操作:
s[i]结果:
s的第i个项目,索引原点为0
如果 i 是负数,则索引相对于序列 s 的末尾:用 len(s) + i 代替。但 -0 即为 0。
webservers[0] # == cobweb
webservers[-1] # == weber
使用起点和终点进行切片
操作:
s[i:j]结果:
s从i到j的切片
s 从 i 到 j 的切片定义为索引 k 满足 i <= k <= j 的项目序列。如果省略 i,则使用 0。如果省略 j,则使用 len(s)。同时省略 i 和 j 的切片将导致无效的主机模式。如果 i 大于 j,则切片为空。如果 i 等于 j,则用 s[i] 代替。
webservers[0:2] # == webservers[0],webservers[1],webservers[2]
# == cobweb,webbing,weber
webservers[1:2] # == webservers[1],webservers[2]
# == webbing,weber
webservers[1:] # == webbing,weber
webservers[:3] # == cobweb,webbing,weber
在模式中使用正则表达式
你可以通过在模式开头使用 ~ 将模式指定为正则表达式
~(web|db).*\.example\.com
模式与 ad-hoc 命令
你可以使用命令行选项来改变 ad-hoc 命令中定义的模式行为。你还可以使用 --limit 标志在特定运行中限制目标主机。
限制为单个主机
$ ansible all -m <module> -a "<module options>" --limit "host1"
限制为多个主机
$ ansible all -m <module> -a "<module options>" --limit "host1,host2"
取反限制。请注意,必须使用单引号以防止 bash 插值。
$ ansible all -m <module> -a "<module options>" --limit 'all:!host1'
限制为主机组
$ ansible all -m <module> -a "<module options>" --limit 'group1'
模式与 ansible-playbook 标志
你可以使用命令行选项来改变 playbook 中定义的模式行为。例如,你可以通过指定 -i 127.0.0.2,(注意末尾的逗号)在单个主机上运行定义了 hosts: all 的 playbook。即使目标主机未在清单中定义,此方法依然有效,但该方法将不会从清单中读取与此主机绑定的变量,playbook 所需的任何变量都需要在命令行上手动指定。你也可以使用 --limit 标志在特定运行中限制目标主机,该标志将引用你的清单
ansible-playbook site.yml --limit datacenter2
最后,你可以使用 --limit 通过在文件名前加上 @ 来从文件中读取主机列表
ansible-playbook site.yml --limit @retry_hosts.txt
如果 RETRY_FILES_ENABLED 设置为 True,则在 ansible-playbook 运行后将创建一个 .retry 文件,其中包含所有 play 中失败的主机列表。每次 ansible-playbook 运行结束时,此文件都会被覆盖。
ansible-playbook site.yml --limit @site.retry
要将你对模式的知识应用于 Ansible 命令和 playbook,请阅读 ad hoc 命令简介 和 Ansible playbooks。
另请参阅
- 即席命令(ad hoc commands)介绍
基本命令示例
- 使用 Playbook
学习 Ansible 配置管理语言
- 交流方式
有疑问?需要帮助?想分享你的想法?请访问 Ansible 通信指南