文章目录
管理变量、机密和事实
1.管理变量
1.1Ansible变量简介
Ansible支持利用变量来存储值,并在Ansible项目的所有文件中重复使用这些值。这可以简化项目的创建和维护,并减少错误的数量。
通过变量,可以轻松地在Ansible项目中管理给定环境的动态值。例如,变量可能包含下面这些值:
- 要创建的用户
- 要安装的软件包
- 要重新启动的服务
- 要删除的文件
- 要从互联网检索的存档
1.1.1 命令变量
变量的名称必须以字母开头,并且只能包含字母、数字和下划线。
无效和有效的Ansible变量名称示例
无效的变量名称 | 有效的变量名称 |
---|---|
web server | web_server |
remote.file | remote_file |
1st file | file_1 file1 |
remoteserver$1 | remote_server_1 remote_server1 |
1.12 定义变量
可以在Ansible项目中的多个位置定义变量。不过,这些变量大致可简化为三个范围级别:
- 全局范围:从命令行或Ansible配置设置的变量
- Play范围:在play和相关结构中设置的变量
- 主机范围:由清单、事实收集或注册的任务,在主机组和个别主机上设置的变量
如果在多个级别定义了相同名称的变量,则采用优先级别最高的变量。窄范围优先于更广泛的范围:由清单定义的变量将被playbook定义的变量覆盖,后者将被命令行中定义的变量覆盖。
1.2 playbook中的变量
变量在Ansible Playbook中发挥着重要作用,因为它们可以简化playbook中变量数据的管理。
1.2.1在Playbook中定义变量
编写playbook时,可以定义自己的变量,然后在任务中调用这些值。例如,名为web_package的变量可以使用值httpd来定义。然后,任务可以使用yum模块调用该变量来安装httpd软件包。
Playbook变量可以通过多种方式定义。一种常见的方式是将变量放在playbook开头的vars块中:
- hosts: all
vars:
user: joe
home: /home/joe
/ / 查看node1的/etc/hosts信息
[root@node1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
/ / 进入ansible清单文件目录
[root@master ~]# cd /opt/project/
[root@master project]# ls
[root@master project]# cd playbook/
ansible.cfg hehe inventories playbook
[root@master playbook]# ls
files httpd.yml vsftpd.yml
firewalld.yml test.yml
httpd-install.yml user.yml
/ / 通过vars块使用变量编辑playbook
[root@master playbook]# vim test.yml
[root@master playbook]# cat test.yml
---
- hosts: '192.168.91.129'
gather_facts: no
vars:
IP: 192.168.91.130 / / 定义变量IP和NAME
NAME: node2
tasks:
- name: test
lineinfile:
path: /etc/hosts
line: "{
{ IP }} {
{ NAME }}"
state: present
[root@master playbook]# cd ..
[root@master project]# ls
ansible.cfg inventories playbook
/ / 先查看主机是否ping的通
[root@master project]# ansible all -m ping
192.168.91.129 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
/ / 使用playbook执行
[root@master project]# ansible-playbook playbook/test.yml
PLAY [192.168.91.129] **********************************************************
TASK [test] ********************************************************************
changed: [192.168.91.129]
PLAY RECAP *********************************************************************
192.168.91.129 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
/ / /etc/hosts文件发生改变,执行成功
[root@node1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.91.130 node2
也可以在外部文件中定义playbook变量。此时不使用playbook中的vars块,可以改为使用vars_files指令,后面跟上相对于playbook位置的外部变量文件名称列表:
- hosts: all
vars_files:
- vars/users.yml
而后,可以使用YAML格式在这一/这些文件中定义playbook变量:
user: joe
home: /home/joe
[root@master project]# cd playbook/
/ / 创建一个vars目录
[root@master playbook]# mkdir vars
[root@master playbook]# ls
files httpd-install.yml user.yml vsftpd.yml
firewalld.yml test.yml vars
/ / 在vars目录里面编辑一个runtime.yml和run.yml文件
[root@master playbook]# vim vars/runtime.yml
[root@master playbook]# cat vars/runtime.yml
IP: 192.168.91.131
NAME: node3
[root@master playbook]# vim vars/run.yml
[root@master playbook]# cat vars/run.yml
IP: 192.168.91.132
NAME: node4
/ / vars目录需要和test.yml文件在同一个级别才可以使用这个方法
[root@master ~]# tree /opt/project/playbook/
/opt/project/playbook/
├── files
│ └── vsftpd.conf
├── firewalld.yml
├── httpd-install.yml
├── test.yml
├── user.yml
├── vars
│ ├── run
│ ├── runtime.yml
│ └── run.yml
└── vsftpd.yml
2 directories, 9 files
/ / 把runtime.yml文件带入到test.yml
[root@master playbook]# vim test.yml
[root@master playbook]# cat test.yml
---
- hosts: '192.168.91.129'
gather_facts: no
vars_files:
- vars/runtime.yml
- vars/run.yml
tasks:
- name: test
lineinfile:
path: /etc/hosts
line: "{
{ IP }} {
{ NAME }}"
state: present
[root@master playbook]# cd ..
/ / 使用ansible执行playbook
[root@master project]# ansible-playbook playbook/test.yml
PLAY [192.168.91.129] **********************************************************
TASK [test] ********************************************************************
changed: [192.168.91.129]
PLAY RECAP *********************************************************************
192.168.91.129 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
/ / 查看其结果,执行成功
[root@node1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.91.130 node2
192.168.91.131 node3
192.168.91.132 node4
1.2.2 在playbook使用变量
声明了变量后,可以在任务中使用这些变量。若要引用变量,可以将变量名放在双大括号内。在任务执行时,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 }}"
注意:当变量用作开始一个值的第一元素时,必须使用引号。这可以防止Ansible将变量引用视为YAML字典的开头。
1.3 主机变量和组变量
直接应用于主机的清单变量分为两在类:
- 主机变量,应用于特定主机
- 组管理,应用于一个主机组或一组主机组中的所有主机
主机变量优先于组变量,但playbook中定义的变量的优先级比这两者更高。
若要定义主机变量和组变量,一种方法是直接在清单文件中定义。这是较旧的做法,不建议采用,但你可能会在未来的工作当中遇到。
定义192.168.91.129的ansible_user主机变量:
[webservers]
192.168.91.129 ansible_user=joe / / 这种用起来不方便
定义webservers主机组的user组变量:
[root@master project]# vim inventories
[root@master project]# cat inventories
[webservers]
192.168.91.129
[webservers:vars]
user=joe
[root@master project]# vim inventories
[root@master project]# vim inventories
[root@master project]# cat inventories
[webservers]
192.168.91.129 / / 只要有主机用户密码相同,就可以往里面添加
[webservers:vars]
ansible_user=root
ansible_password=123456
[root@master project]# ansible all -m ping
192.168.91.129 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
定义webservers组的user组变量,该组由两个主机组成,每个主机组有两个服务器:
[webserver1]
node1.example.com
node2.example.com
[webserver2]
node3.example.com
node4.example.com
[webservers:children]
webservers1
webservers2
[webservers:vars]
user=joe
此做法存在一些缺点,它使得清单文件更难以处理,在同一文件中混合提供了主机和变量信息,而且采用的也是过时的语法。
1.3.1 使用目录填充主机和组变量
定义主机和主机组的变量的首选做法是在与清单文件或目录相同的工作目录中,创建group_vars和host_vars两个目录。这两个目录分别包含用于定义组变量和主机变量的文件。
建议的做法是使用host_vars和group_vars目录定义清单变量,而不直接在清单文件中定义它们。
为了定义用于servers组的组变量,需要创建名为group_vars/servers的YAML文件,然后该文件的内容将使用与playbook相同的语法将变量设置为值:
user: joe
类似的,为了定义用于特定主机的主机变量,需要在host_vars目录中创建名称与主机匹配的文件来存放主机变量。
下面的示例更加详细的说明了这一做法。例如在一个场景中,需要管理两个数据中心,并在~/project/inventory清单文件中定义数据中心主机:
[root@node1 ~]# mkdir ~/project
[root@node1 ~]# vim ~/project/inventory
[datacenter1]
node1.example.com
node2.example.com
[datacenter2]
node3.example.com
node4.example.com
[datacenters:children]
datacenter1
datacenter2
如果需要为两个数据中心的所有服务器定义一个通用值,可以为datacenters主机组设置一个组变量:
[root@node1 ~]# mkdir ~/project/groupo_vars
[root@node1 ~]# vim ~/project/groupo_vars/datacenters
package: httpd
如果要为每个数据中心定义不同的值,可以为每个数据中心主机组设置组变量
[root@node1 ~]# vim ~/project/groupo_vars/datacenter1
package: httpd
[root@node1 ~]# vim ~/project/groupo_vars/datacenter2
package: apache2
如果要为每一数据中心的各个主机定义不同的值,则在单独的主机变量文件中定义变量:
[root@node1 ~]# mkdir ~/project/host_vars
[root@node1 ~]# vim ~/project/host_vars/node1.example.com
package: httpd
[root@node1 ~]# vim ~/project/host_vars/node2.example.com
package: apache2
[root@node1 ~]# vim ~/project/host_vars/node3.example.com
package: mariadb-server
[root@node1 ~]# vim ~/project/host_vars/node4.example.com
package: mysql-server
以上示例项目project的目录结构如果包含上面所有示例文件,将如下所示:
[root@node1 ~]# tree ~/project
/root/project
├── ansible.cfg
├── group_vars
│ ├── datacenters
│ ├── datacenters1
│ └── datecenters2
├── host_vars
│ ├── node1.example.com
│ ├── node2.example.com
│ ├── node3.example.com
│ └── node4.example.com
├── inventory
└── playbook.yml
2 directories, 10 files
例子:
/ / 创建group_vars和host_vars目录组
[root@master project]# mkdir group_vars
[root