到目前为止,我们看到的大多数例子本质上都是静态的。对于最简单的剧本示例来说,这很不错,但在许多情况下,最好能够存储值或在中心位置轻松地定义它们,而不必在剧本(和角色树)中查找特定的硬编码值。与其他语言一样,Ansible也需要以某种方式采集值,以便以后重用。
Ansible中有许多不同类型的变量,你必须知道它们有严格的优先顺序。尽管在本书中我们不会遇到这么多变量,但注意这一点很重要,否则你可能会从变量中收到意外的结果。
有关变量优先级的更多详细信息,请参阅https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.xhtml#variable-precedence-where-should-i-put-a-variable。
简言之,变量可以在多个位置定义,给定场景的正确位置将由剧本的目标驱动。例如,如果一个变量对于整个服务器组是公共的,那么在清单中将其定义为组变量是合乎逻辑的。如果它适用于特定剧本所针对的每个主机,那么你几乎可以肯定地在playbook中定义它。在此通过修改本章前面的剧本中的simple.yml,定义一个名为message的play变量,以便在运行剧本时显示debug语句,如下:
请注意,我们在tasks前面定义了一个vars节,可以通过成对的花括号访问变量。运行这个剧本的结果如图2-9所示。
图 2-9
如果参考变量优先顺序列表,你会注意到在命令行上传递给ansible-playbook二进制文件的变量位于列表的顶部,并覆盖所有其他变量。因此,如果想重写message变量的内容而不编辑剧本,我们可以按如下操作:
注意处理变量内容中的空格所需的特殊引号和转义,这对剧本操作的影响如图2-10所示。
变量也可以传递给角色,这是创建通用角色的一种简单而强大的方法,可以在多种场景中使用,而不需要使用相同的配置数据。例如,在上一节中,我们探讨了如何安装MariaDB服务器。虽然这是一个很好的角色候选者,但你肯定不希望在每台服务器上都配置相同的根数据库口令。因此,为口令定义一个变量并将其从调用剧本(或其他适当的源,如主机或组变量)传递给角色是有意义的。
除了用户定义的变量外,Ansible还有许多内置变量,称为特殊变量。这些变量可以从剧本中的任何地方访问,这对获取与剧本状态相关的某些细节非常有用。
例如,如果你需要知道当前对特定任务执行操作的主机名,可以通过inventory_hostname变量获取。这些变量的完整列表可在https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html找到。
图 2-10
到目前为止,许多读者都会注意到,我们所有示例剧本的输出都包含一行文字,显示Gathering Facts。虽然可以关闭它,但实际上它非常有用,并且用有用的关键系统数据填充了大量变量。要了解在此阶段收集的数据类型,请从命令行运行以下代码:
此命令指示Ansible直接在localhost上运行setup模块,而不是运行剧本——setup模块是在收集事实阶段在幕后运行的模块。输出如图2-11所示,接下来的页面只剩下前几行。
我们可以立即看到那里有一些非常有用的信息,例如主机的IP地址、根卷等。还记得我们在第1章中关于通用性的讨论,以及在检测运行的操作系统时遇到的困难吗?好吧,Ansible使这变得很容易,因为数据在收集的事实中都是现成的。我们可以修改debug语句来显示我们运行的Linux发行版,只需指定适当的事实,可以从上一个命令的输出访问,如下所示:
现在,当运行剧本时,我们可以很容易地判断运行的是Ubuntu,如图2-12所示。
图 2-11
图 2-12
Ansible使你能够有条件地运行单个任务、角色,甚至整个任务块,因此,通过访问事实,可以直接编写健壮的剧本,可以在多个平台上运行,并在每个平台上执行正确的操作。
值得注意的是,变量不一定要存储在未加密的文本中。有时,可能需要在变量中存储口令(如前面讨论的,可能是MariaDB服务器安装的root口令)。以纯文本格式存储这些信息会带来很大的安全风险,但幸运的是,Ansible包含一种称为 Vault(保险库) 的技术,该技术能够存储使用AES256加密的变量数据。任何剧本都可以引用这些加密的保险库,只要在剧本运行时将Vault口令传递给剧本。Vault超出了本章的范围,但如果你想了解更多有关它们的信息,请参阅https://docs.ansible.com/ansible/latest/user_guide/playbooks_vault.html。在本书中,为了保持示例代码简洁,我们不会广泛地使用它们。但是,强烈建议在生产环境中,在需要存储剧本的敏感数据的地方使用Vault。
既然已经介绍了Ansible中变量的概念以及可用的各种类型,那么让我们来看看在Ansible中管理配置文件的一种重要方法——使用模板。