YAML注释
注释也可以用于提高可读性。在YAML中,编号或井号字符(#)右侧的所有内容都是注释(推荐使用这一种注释方式)。如果注释的左侧有内容,请在该编号符号的前面加一个空格。
# This is a YAML comment
YAML字符串
内容中有空格或特殊字符(*)建议使用引号。双引号或单引号都行。
编写多行字符串有两种方式。
[root@localhost playbook]# cat test.yml
---
- hosts: "*"
gather_facts: no
tasks:
- name: sync hosts file
lineinfile:
path: /tmp/abc
line: |
hello word
dft
dsdf
create: yes
[root@localhost ansible]# ansible-playbook playbook/test.yml
PLAY [*] ************************************************************************************************
TASK [sync hosts file] **********************************************************************************
changed: [192.168.237.168]
PLAY RECAP **********************************************************************************************
192.168.237.168 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@localhost ~]# cat /tmp/abc
hello word
dft
dsdf
[root@localhost ansible]# cat playbook/test.yml
---
- hosts: "*"
gather_facts: no
tasks:
- name: sync hosts file
lineinfile:
path: /tmp/abc
line: >
hello word
dft
dsdf
state: present
create: yes
[root@localhost ansible]# ansible-playbook playbook/test.yml
PLAY [*] ************************************************************************************************
TASK [sync hosts file] **********************************************************************************
changed: [192.168.237.168]
PLAY RECAP **********************************************************************************************
192.168.237.168 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@localhost ~]# cat /tmp/abc
hello word dft dsdf
YAML字典
下面是一个简单的字典形式:
name: svcrole
svcservice: httpd
svcport: 80
字典也可以使用以大括号括起的内联块格式编写,如下所示:
{name: svcrole, svcservice: httpd, svcport: 80}
当playbook中包含角色列表时,较常使用这种语法,从而更加容易区分play中包含的角色和传递给角色的变量。
YAML列表
最简单的列表如下:
hosts:
- servera
- serverb
- serverc
列表也有以中括号括起的内联格式,如下所示:
hosts: [servera, serverb, serverc]
playbook简写
通过将模块的键值对放在与模块名称相同的行上来定义任务,即“键=值”
简写形式:
tasks:
- name: shorthand form
service: name=httpd enabled=true state=started
普通形式:
tasks:
- name: normal form
service:
name: httpd
enabled: true
state: started
普通形式的行数较多,但更容易操作。
Ansible支持利用变量来存储值,并在Ansible项目的所有文件中重复使用这些值。这可以简化项目的创建和维护,并减少错误的数量。
变量可能包含值:
变量的作用:
变量的名称必须以字母开头,并且只能包含字母、数字和下划线。
示例:
无效的变量名称 | 有效的变量名称 |
---|---|
web server | web_server |
remote.file | remote_file |
1st file | file_1 file1 |
remoteserver$1 | remote_server_1 remote_server1 |
可以在Ansible项目中的多个位置定义变量。不过,这些变量大致可简化为三个范围级别:
优先级:命令行中定义的变量>playbook定义的变量>清单定义的变量
变量在Ansible Playbook中发挥着重要作用,因为它们可以简化playbook中变量数据的管理。
Playbook变量可以通过多种方式定义。一种常见的方式是将变量放在playbook开头的vars块中:
[root@localhost ansible]# cat playbook/test.yml
---
- hosts: "*"
gather_facts: no
vars: //定义变量
name: tom
uid: 2000
tasks:
- name: create user
user:
name: "{
{ name }}" // {
{}}表示引用变量,如果直接跟在键的后面就用引号
uid: "{
{ uid }}"
state: present
[root@localhost ansible]# ansible-playbook playbook/test.yml
[WARNING]: Found variable using reserved name: name
PLAY [*] ************************************************************************************************
TASK [create user] **************************************************************************************
changed: [192.168.237.168]
PLAY RECAP **********************************************************************************************
192.168.237.168 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@localhost ~]# id tom
uid=2000(tom) gid=2000(tom) 组=2000(tom)
也可以在外部文件中定义playbook变量。此时不使用playbook中的vars块,可以改为使用vars_files指令,后面跟上相对于playbook位置的外部变量文件名称列表:
//playbook文件test.yml与变量文件runtime.yml所在目录同级
[root@localhost ansible]# cat playbook/test.yml
---
- hosts: "*"
gather_facts: no
vars_files:
- vars/runtime.yml
tasks:
- name: create user
shell: "echo {
{ content }} > /tmp/abc"
[root@localhost ansible]# cat playbook/vars/runtime.yml
content: hello world
[root@localhost ansible]# ansible-playbook playbook/test.yml
[root@localhost ~]# cat /tmp/abc
hello world
若要引用变量,可以将变量名放在双大括号内。在任务执行时,Ansible会将变量替换为其值。
vars:
user: joe
tasks:
# This line will read: Creates the user joe
- name: Creates the user {
{ user }}
user:
# This line will create the user named joe
name: "{
{ user }}"
直接应用于主机的清单变量分为两类:
主机变量优先于组变量,但playbook中定义的变量的优先级比这两者更高。
定义主机变量和组变量第一种方法是,直接在清单文件中定义主机变量和组变量,这是较旧的做法,不建议采用。
[servers]
172.16.103.129 ansible_user=joe
[servers]
172.16.103.129
172.16.103.130
[servers:vars]
user=joe
[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两个目录。这两个目录分别包含用于定义组变量和主机变量的文件。这是定义此变量的首选。
[root@localhost ansible]# tree
. //host_vars与清单文件inventory同级
├── ansible.cfg
├── hosts
├── host_vars
│ └── 192.168.237.168
├── inventory
├── playbook
│ ├── lamp
│ │ ├── httpd.conf
│ │ ├── httpd-vhosts.conf
│ │ ├── lamp.yml
│ │ └── www.conf
│ └── test.yml
└── roles
[root@localhost ansible]# cat host_vars/192.168.237.168
server: httpd*
state: latest
[root@localhost ansible]# cat playbook/test.yml
---
- hosts: "192.168.237.168"
gather_facts: no
tasks:
- name: install server
yum:
name: "{
{ server }}"
state: "{
{ state }}"
[root@localhost ansible]# ansible-playbook playbook/test.yml
[root@localhost ~]# rpm -qa | grep httpd
httpd-2.4.37-39.module_el8.4.0+778+c970deab.x86_64
httpd-tools-2.4.37-39.module_el8.4.0+778+c970deab.x86_64
httpd-filesystem-2.4.37-39.module_el8.4.0+778+c970deab.noarch
httpd-devel-2.4.37-39.module_el8.4.0+778+c970deab.x86_64
centos-logos-httpd-85.8-1.el8.noarch
httpd-manual-2.4.37-39.module_el8.4.0+778+c970deab.noarch
[root@localhost ansible]# cat group_vars/webserver //group_vars与清单文件同级
ansible_user: root
ansible_passwd: runtime
[root@localhost ansible]# cat inventory
[webserver]
192.168.237.168
清单变量可被playbook中设置的变量覆盖,这两种变量又可通过在命令行中传递参数到ansible或ansible-playbook命令来覆盖。在命令行上设置的变量称为额外变量。
ansible-playbook main.yml -e "package=apache2"
除了将同一元素相关的配置数据(软件包列表、服务列表和用户列表等)分配到多个变量外,也可以使用数组。这种做法的一个好处在于,数组是可以浏览的。
例如,假设下列代码片段:
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
使用以下变量来访问用户数据:
users.bjones.first_name
users.acook.home_dir
由于变量被定义为Python字典,因此可以使用替代语法:
users['bjones']['first-name']
users['acook']['home_dir']
上面两种语法都有效,但为了方便故障排除,建以使用第二种以中括号括起来的。
使用register语句捕获命令输出。输出保存在一个临时变量中,然后在playbook中可用于调试用途或者达成其他目的,例如基于命令输出的特定配置。
[root@localhost ansible]# cat playbook/test.yml
---
- hosts: "*"
gather_facts: no
tasks:
- name: register variables
command: "df -h"
register: result
- debug: var=result
运行该playbook时,debug模块用于将install_result
注册变量的值转储到终端。
[root@localhost ansible]# ansible-playbook playbook/test.yml
PLAY [*] ************************************************************************************************
TASK [register variables] *******************************************************************************
changed: [192.168.237.168]
TASK [debug] ********************************************************************************************
ok: [192.168.237.168] => {
"result": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"cmd": [
"df",
"-h"
],
"delta": "0:00:00.002516",
"end": "2021-07-24 01:12:57.945083",
"failed": false,
"rc": 0,
"start": "2021-07-24 01:12:57.942567",
"stderr": "",
"stderr_lines": [],
"stdout": "文件系统 容量 已用 可用 已用% 挂载点\ndevtmpfs 379M 0 379M 0% /dev\ntmpfs 396M 0 396M 0% /dev/shm\ntmpfs 396M 11M 386M 3% /run\ntmpfs 396M 0 396M 0% /sys/fs/cgroup\n/dev/mapper/rhel-root 17G 1.7G 16G 10% /\n/dev/nvme0n1p1 1014M 179M 836M 18% /boot\ntmpfs 80M 0 80M 0% /run/user/0",
"stdout_lines": [
"文件系统 容量 已用 可用 已用% 挂载点",
"devtmpfs 379M 0 379M 0% /dev",
"tmpfs 396M 0 396M 0% /dev/shm",
"tmpfs 396M 11M 386M 3% /run",
"tmpfs 396M 0 396M 0% /sys/fs/cgroup",
"/dev/mapper/rhel-root 17G 1.7G 16G 10% /",
"/dev/nvme0n1p1 1014M 179M 836M 18% /boot",
"tmpfs 80M 0 80M 0% /run/user/0"
]
}
}
PLAY RECAP **********************************************************************************************
192.168.237.168 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
也可以在debug模块后面指定想要打印至终端的数据
[root@localhost ansible]# cat playbook/test.yml
---
- hosts: "*"
gather_facts: no
tasks:
- name: register variables
command: "df -h"
register: result
- debug: var=result['stdout_lines']
[root@localhost ansible]# ansible-playbook playbook/test.yml
PLAY [*] ************************************************************************************************
TASK [register variables] *******************************************************************************
changed: [192.168.237.168]
TASK [debug] ********************************************************************************************
ok: [192.168.237.168] => {
"result['stdout_lines']": [
"文件系统 容量 已用 可用 已用% 挂载点",
"devtmpfs 379M 0 379M 0% /dev",
"tmpfs 396M 0 396M 0% /dev/shm",
"tmpfs 396M 11M 386M 3% /run",
"tmpfs 396M 0 396M 0% /sys/fs/cgroup",
"/dev/mapper/rhel-root 17G 1.7G 16G 10% /",
"/dev/nvme0n1p1 1014M 179M 836M 18% /boot",
"tmpfs 80M 0 80M 0% /run/user/0"
]
}
PLAY RECAP **********************************************************************************************
192.168.237.168 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0