注释也可以用于提高可读性。在YAML中,编号或井号字符(#)右侧的所有内容都是注释。如果注释的左侧有内容,请在该编号符号的前面加一个空格。
#This is a YAML comment
[defaults] # This is also a YAML comment
# some basic default values...
YAML中的字符串通常不需要放在引号里,即使字符串中包含空格。字符串可以用双引号或单引号括起。
This is a string
'This is another string'
"This is yet another a string"
编写多行字符串有两种方式。可以使用管道符表示要保留字符串中的换行字符。
line: |
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
要编写多行字符串,还可以使用大于号字符来表示换行字符转换成空格并且行内的引导空白将被删除。这种方法通常用于将很长的字符串在空格字符处断行,使它们跨占多行来提高可读性。
line: >
LoadModule proxy_module modules/mod_proxy.so,
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
查看:
LoadModule proxy_module modules/mod_proxy.so,LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
简单的字典形式:
name:role
service:httpd
port:80
字典也可以使用以大括号括起的内联块格式编写:
{name: role, service: httpd, port: 80}
大多数情况下应避免内联块格式,因为其可读性较低。不过,至少有一种情形中会较常使用它。当playbook中包含角色列表时,较常使用这种语法,从而更加容易区分play中包含的角色和传递给角色的变量。
最简单的列表如下:
hosts:
hosts: [servera, serverb, serverc]
我们应该避免使用此语法,因为它通常更难阅读。
variables —变量
Ansible支持利用变量来存储值,并在Ansible项目的所有文件中重复使用这些值。这可以简化项目的创建和维护,并减少错误的数量。
变量的作用:
存储数据
引用数据
通过变量,可以轻松地在Ansible项目中管理给定环境的动态值。
变量的名称必须以字母开头,并且只能包含字母、数字和下划线。
无效的变量名称 | 有效的变量名称 |
---|---|
web server | web_server |
remote.file | remote_file |
1stfile | file_1 file1 |
remoteserver$1 | remote_server_1 remote_server1 |
可以在Ansible项目中的多个位置定义变量。不过,这些变量大致可简化为三个范围级别:
如果在多个xeklh定义了相同名称的变量,则采用优先级别最高的变量。窄范围优先于更广泛的范围:由清单定义的变量将被playbook定义的变量覆盖,后者将被命令行中定义的变量覆盖。
编写playbook时,可以定义自己的变量,然后在任务中调用这些值。例如,名为web_package的变量可以使用值httpd来定义。然后,任务可以使用yum模块调用该变量来安装httpd软件包。
Playbook变量可以通过多种方式定义。一种常见的方式是将变量放在playbook开头的vars块中:
[root@ansible playbook]# cat user.yml
---
- hosts: apache
vars:
name: yy
uid: 2000
tasks:
- name: create user
user:
name: "{{ name }}"
uid: "{{ uid }}"
state: present
[root@apache ~]# id yy
uid=2000(yy) gid=1002(yy) 组=1002(yy)
也可以在外部文件中定义playbook变量。此时不使用playbook中的vars块,可以改为使用vars_files指令,后面跟上相对于playbook位置的外部变量文件名称列表,而后,可以使用YAML格式在这一/这些文件中定义playbook变量:
[root@ansible playbook]# mkdir vars
[root@ansible playbook]# cat vars/yy.yml
content: hello,my name is meinv!
[root@ansible playbook]# cat user.yml
---
- hosts: apache
vars_files:
- vars/yy.yml
tasks:
- name:
shell: "echo {{ content }} > /tmp/abc"
[root@apache tmp]# cat /tmp/abc
hello,my name is meinv!
直接应用于主机的清单变量分为两在类:
若要定义主机变量和组变量,一种方法是直接在清单文件中定义。这是较旧的做法,不建议采用,但你可能会在未来的工作当中遇到。
定义192.168.235.141的ansible_user主机变量:
[servers]
192.168.235.141 ansible_user=root ansible_password=1
定义servers主机组的user组变量:
192.168.235.141
192.168.235.142
[servers:vars]
user=root
定义servers组的user组变量,该组由两个主机组成,每个主机组有两个服务器:
[servers1]
node1.example.com
node2.example.com
[servers2]
node3.example.com
node4.example.com
[servers:children]
servers1
servers2
[servers:vars]
user=joe
使用目录填充主机和组变量 :
定义主机和主机组的变量的首选做法是在与清单文件或目录相同的工作目录中,创建group_vars和host_vars两个目录。这两个目录分别包含用于定义组变量和主机变量的文件。
建议的做法是使用host_vars和group_vars目录定义清单变量,而不直接在清单文件中定义它们。
清单变量可被playbook中设置的变量覆盖,这两种变量又可通过在命令行中传递参数到ansible或ansible-playbook命令来覆盖。在命令行上设置的变量称为额外变量。
当需要覆盖一次性运行的playbook的变量的已定义值时,额外变量非常有用。例如:
[root@ansible playbook]# cat user.yml
---
- name: task1
hosts: apache
tasks:
- name: 创建用户
user:
name: "{{user}}"
state: present
[root@ansible playbook]# ansible-playbook -e "user=lhh" user.yml
PLAY [task1] *********************************************************************************
TASK [Gathering Facts] ***********************************************************************
ok: [192.168.235.141]
TASK [创建用户] **********************************************************************************
changed: [192.168.235.141]
PLAY RECAP ***********************************************************************************
192.168.235.141 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@apache ~]# id lhh
uid=2001(lhh) gid=2001(lhh) 组=2001(lhh)
[root@apache ~]#
除了将同一元素相关的配置数据(软件包列表、服务列表和用户列表等)分配到多个变量外,也可以使用数组。这种做法的一个好处在于,数组是可以浏览的。
user1_first_name: Bob
user1_last_name: Jones
user1_home_dir: /users/bjones
user2_first_name: Anne
user2_last_name: Cook
user2_home_dir: /users/acook
这将可以改写成名为users的数组:
users:
bjones:
first_name: Bob
last_name: jones
home_dir: /users/bjones
acook:
first_name: Anne
last_name: Cook
home_dir: /users/acook
然后可以使用以下变量来访问用户数据:
# Returns 'Bob'
users.bjones.first_name
# Returns '/users/acook'
users.acook.home_dir
由于变量被定义为Python字典,因此可以使用替代语法:
# Returns 'Bob'
users['bjones']['first-name']
# Returns '/users/acook'
users['acook']['home_dir']
如果键名与python方法或属性的名称(如discard、copy和add)相同,点表示法可能会造成问题。使用中括号表示法有助于避免冲突和错误。
但要声明的是,上面介绍的两种语法都有效,但为了方便故障排除,建议在任何给定Ansible项目的所有文件中一致地采用一种语法,不要混用。
可以使用register语句捕获命令输出。输出保存在一个临时变量中,然后在playbook中可用于调试用途或者达成其他目的,例如基于命令输出的特定配置。
以下playbook演示了如何为调试用途捕获命令输出:
---
name: Installs a package and prints the result
hosts: all
tasks:
- name: Install the package
yum:
name: httpd
state: installed
register: install_result
- debug: var=install_result
运行该playbook时,debug模块用于将install_result注册变量的值转储到终端。
[root@localhost ~]# ansible-playbook playbook.yml
PLAY [Installs a package and prints the result] *************************************
TASK [Gathering Facts] **************************************************************
ok: [172.16.103.129]
TASK [Install the package] **********************************************************
ok: [172.16.103.129]
TASK [debug] ************************************************************************
ok: [172.16.103.129] => {
"install_result": {
"changed": false,
"failed": false,
"msg": "",
"rc": 0,
"results": [
"httpd-2.4.6-93.el7.centos.x86_64 providing httpd is already installed"
]
}
}
PLAY RECAP **************************************************************************
t129 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ig