创建新的Ansible角色时,模板会创建一个vars
和defaults
目录,其中包含一个空的main.yml
文件。在定义我的角色时,我可以将变量定义放在其中任何一个中,并且它们将在我的任务中可用。
将定义放入defaults
和vars
之间的区别是什么?什么应该进入defaults
,什么应该进入vars
?将两者用于相同的数据是否有意义?
我知道两者之间的优先级/优先级存在差异,但我想了解应该去哪里。
让我们说我的角色会在目标系统上创建一个目录列表。我想提供一个要创建的默认目录列表,但是希望允许用户在使用该角色时覆盖它们。
以下是这样的:
---
- directories:
- foo
- bar
- baz
我可以将其放入defaults/main.yml
或vars/main.yml
,从执行的角度来看,它不会有任何区别 - 但它应该去哪里?
答案 0 :(得分:86)
variable precedence上的Ansible文档总结了这个不错的文章:
如果在不同的地方定义了多个同名变量,他们会以某种顺序获胜,即:
- 额外的变量(命令行中的-e)总是胜利
- 然后是库存中定义的连接变量(ansible_ssh_user等)
- 然后“大多数其他”(命令行开关,游戏中的变种,包括变量,角色变量等)
- 然后是库存中定义的其余变量
- 然后发现了关于系统的事实
- 然后是“角色默认值”,这是最“默认”并且优先于所有内容。
假设你有一个“tomcat”角色用于在一堆webhost上安装Tomcat,但是你需要在几台主机上使用不同版本的tomcat,需要在其他情况下以不同的用户身份运行,等等。 defaults/main.yml
文件可能如下所示:
tomcat_version: 7.0.56
tomcat_user: tomcat
由于这些只是默认值,这意味着如果这些变量没有在相关主机的任何其他位置定义,则会使用它们。您可以通过额外变量,库存文件中的事实等覆盖这些变量,以指定这些变量的不同值。
编辑:请注意,以上列表适用于Ansible 1.x.在Ansible 2.x中,列表已经扩展。与往常一样,Ansible Documentation提供了2.x的变量优先级的详细描述。
答案 1 :(得分:25)
var
中定义的角色变量具有非常高的优先级 - 只能通过在命令行,特定任务或块中传递它们来覆盖它们。因此,几乎所有变量都应在defaults
中定义。
在文章“Variable Precedence - Where To Put Your Role Vars”中,作者给出了vars
中放置内容的一个示例:系统特定的常量不会发生太大变化。因此,vars/debian.yml
和vars/centos.yml
可以使用相同的变量名但不同的值,并有条件地包含它们。
答案 2 :(得分:3)
基本上,任何涉及“角色默认值”(角色内的默认值文件夹)的东西都是最易延展的,并且很容易被覆盖。角色的vars目录中的所有内容都会覆盖名称空间中该变量的先前版本。这里要遵循的想法是,范围越明确,使用命令行的优先级就越高-e总是赢得额外的var。主机变量和/或清单变量可以取代角色默认值,但不能像vars目录或include_vars任务那样显式包含。 doc
答案 3 :(得分:1)
恕我直言,将Ansible在角色的 vars 中放在如此高的优先级上是不切实际且不明智的。 vars/main.yml
和defaults/main.yml
中的配置应该较低,并且优先级应该相同。
在现实生活中是否存在我们想要这种行为的案例?
有些例子是我们不想要的。
此处要说明的是defaults/main.yml
中的配置不能是动态的。 vars/main.yml
中的配置可以。因此,例如,您可以动态包含针对特定操作系统和版本的配置,如geerlingguy.postgresql
但是,由于优先级在Ansible中是如此奇怪且不切实际,geerlingguy需要引入伪变量,如variables.yml
所示- name: Define postgresql_packages.
set_fact:
postgresql_packages: "{{ __postgresql_packages | list }}"
when: postgresql_packages is not defined
这是一个具体的现实生活示例,展示了优先级是不切实际的。
这里要做的另一点是我们希望角色是可配置的。角色可以是外部角色,也可以由其他人管理。通常,您不希望角色中的配置具有高优先级。
答案 4 :(得分:-4)
变量和默认值齐头并进。这是一个例子
-name: install package
yum: name=xyz{{package_version}} state=present
在您的默认文件中,您将拥有以下内容:
package_version: 123
ansible将会做什么,它将取package_version
的值并将其放在包名旁边,以便它在某处读取:
-name: install package
yum: name=xyz123 state=present
这样它将安装xyz123
而不是xyz123.4
或xyz的大型存储库中的任何内容。
最后它会yum install -y xyz123
所以基本上默认值是存在的值,如果没有为变量设置特定值,则导致该空间不能保持为空。