文章目录
1. 管理变量1.1 Ansible变量简介1.1.1 命名变量1.1.2 定义变量
1.2 在Playbook中定义变量1.3 主机变量和组变量1.4 使用已注册变量捕获命令输出
2. 管理机密2.1 创建加密文件2.2 查看加密文件2.3 编辑现有的加密文件2.4 加密已存在的文件2.5 解密已存在的文件2.6 更改加密文件密码2.7 playbook和ansible vault2.8 变量文件管理的推荐做法
3. 管理事实3.1 使用debug模块查看事实3.2 Ansible事实作为变量注入3.3 关闭事实收集3.4 创建自定义事实3.5 使用魔法变量
1. 管理变量
1.1 Ansible变量简介
Ansible支持利用变量来存储值,并在Ansible项目的所有文件中重复使用这些值。这可以简化项目的创建和维护,并减少错误的数量。
通过变量,可以轻松地在Ansible项目中管理给定环境的动态值。例如,变量可能包含下面这些值:
要创建的用户要安装的软件包要重新启动的服务要删除的文件要从互联网检索的存档
1.1.1 命名变量
变量的名称必须以字母开头,并且只能包含字母、数字和下划线。
1.1.2 定义变量
可以在Ansible项目中的多个位置定义变量。不过,这些变量大致可简化为三个范围级别:
全局范围:从命令行或Ansible配置设置的变量Play范围:在play和相关结构中设置的变量主机范围:由清单、事实收集或注册的任务,在主机组和个别主机上设置的变量
1.2 在Playbook中定义变量
示例:现在用变量给受控机安装阿帕奇
1.查看受控机没有阿帕奇
[root@localhost ~]# rpm -qa|grep httpd
[root@localhost ~]# rpm -qa|grep httpd
在主控机playbook中编写
[root@localhost playbook]# vim myplay.yml
---
- hosts: 192.168.50.136
vars:
package_name: httpd
tasks:
- name: jjyy
yum:
name: '{{ package_name }}'
state: present
运行playbook
[root@localhost playbook]# ansible-playbook myplay.yml
PLAY [192.168.50.136] **********************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [jjyy] ********************************************************************
ok: [192.168.50.136]
PLAY RECAP *********************************************************************
192.168.50.136 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
查看受控机是否安装了阿帕奇(完成安装)
[root@localhost ~]# rpm -qa|grep httpd
httpd-filesystem-2.4.37-21.module_el8.2.0+382+15b0afa8.noarch
httpd-2.4.37-21.module_el8.2.0+382+15b0afa8.x86_64
httpd-tools-2.4.37-21.module_el8.2.0+382+15b0afa8.x86_64
centos-logos-httpd-80.5-2.el8.noarch
示例:把变量写到vars文件里去卸载受控机的阿帕奇 1 . 在playbook下面创建一个vars目录,该目录必须和myplay.yml是同级目录
[root@localhost playbook]# mkdir vars
[root@localhost playbook]# ls
myplay.yml vars
2 . 进入vars编写一个(叫测试的文件)test.yml的文件
[root@localhost playbook]# cd vars
[root@localhost vars]# vim test.yml
packages_name: httpd
~
3 . 使用tree查看test.yml在哪个文件下面
[root@localhost playbook]# tree vars
vars
└── test.yml
0 directories, 1 file
4 . 进入myplay.yml,把vars改成vars_files并跟上文件,把下面的package加个s
[root@localhost playbook]# vim myplay.yml
---
- hosts: 192.168.50.136
vars_files:
- vars/test.yml
tasks:
- name: jjyy
yum:
name: '{{ packages_name }}'
state: absent absent : 卸载(因为我要卸载阿帕奇所以用absent)
5 . 执行playbook
[root@localhost playbook]# ansible-playbook myplay.yml
PLAY [192.168.50.136] **********************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [jjyy] ********************************************************************
ok: [192.168.50.136]
PLAY RECAP *********************************************************************
192.168.50.136 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
6 . 查看受控机是否已经卸载阿帕奇(已卸载)
[root@localhost ~]# rpm -qa|grep httpd
httpd-filesystem-2.4.37-21.module_el8.2.0+382+15b0afa8.noarch
httpd-tools-2.4.37-21.module_el8.2.0+382+15b0afa8.x86_64
centos-logos-httpd-80.5-2.el8.noarch
1.3 主机变量和组变量
创建group_vars和host_vars两个目录。这两个目录分别包含用于定义组变量和主机变量的文件。
[root@localhost ~]# tree /opt/qq
/opt/qq
├── files 放文件
├── group_vars 主机组对应的变量
├── hosts_vars 主机对应的变量
├── inventory 项目里面有哪些主机就在此写哪些主机
└── playbook.yml 编写playbook
3 directories, 2 files
比如:进入qq下面的inventory进行编写也可以ping通受控机
[root@localhost qq]# vim inventory
192.168.50.136 ansible_password=redhat
[root@localhost qq]# ansible 192.168.50.136 -i inventory -m ping
192.168.50.136 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
1.4 使用已注册变量捕获命令输出
[root@localhost qq]# vim playbook.yml
---
- hosts: all
tasks:
- name: install httpd and print result
yum:
name: httpd
state: present
register: result register捕获命令输出
- debug: var=result debug模块可以打印一个变量(这里就打印result变量)
~
[root@localhost qq]# ansible-playbook playbook.yml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [install httpd and print result] ******************************************
changed: [192.168.50.136]
TASK [debug] *******************************************************************
ok: [192.168.50.136] => {
"result": {
"changed": true,
"failed": false,
"msg": "",
"rc": 0,
"results": [
"Installed: httpd-2.4.37-21.module_el8.2.0+382+15b0afa8.x86_64",
"Installed: mod_http2-1.11.3-3.module_el8.2.0+307+4d18d695.x86_64"
]
}
}
PLAY RECAP *********************************************************************
192.168.50.136 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2. 管理机密
2.1 创建加密文件
创建时需要输入密码
[root@localhost group_vars]# ansible-vault create webservers ansible-vault create +文件名 来创建加密文件
New Vault password: 输入密码123456
Confirm New Vault password:
[root@localhost group_vars]# ls
webservers
创建时不需要输入密码
先在vault密码文件里写入密码12345 , 该文件不要让别人知道
[root@localhost group_vars]# vim vault_pass
123456
用以下命令来创建一个加密文件
[root@localhost group_vars]# ansible-vault create --vault-password-file=vault_pass webservers
[root@localhost group_vars]# ls
vault_pass webservers
2.2 查看加密文件
[root@localhost group_vars]# ansible-vault view webservers 使用view来查看加密文件,需要输入密码
Vault password:
ansible_password: redhat
2.3 编辑现有的加密文件
[root@localhost group_vars]# ansible-vault edit webservers 使用edit来编辑加密文件
Vault password: 输入密码后编写name: tom
[root@localhost group_vars]# ansible-vault view webservers
Vault password:
ansible_password: redhat view查看该文件就有刚编写的name: tom
name: tom
2.4 加密已存在的文件
[root@localhost group_vars]# vim webservers 先写一个有内容的文件
[root@localhost group_vars]# cat webservers 未加密可以查看其内容
ansible_password: redhat
[root@localhost group_vars]# ansible-vault encrypt webservers 用encrypt对该文件加密
New Vault password:
Confirm New Vault password:
Encryption successful 加密成功
[root@localhost group_vars]# cat webservers 用cat命令查看不了加密文件
$ANSIBLE_VAULT;1.1;AES256
32306438396564386139376336653134663137666565623332646135663834326363343132383737
3039343663366130323932353730383136393839616232360a326332373336303836663762653063
32376632636232393239666137393863386238323164373230386466613466313863613466663664
3364643236323336660a636361663835386166386364633662623631343937643435613462333166
35376564333736363866386565306334396662313962383435623566323664636134
[root@localhost group_vars]# ansible-vault view webservers 用view来查看加密文件
Vault password:
ansible_password: redhat
2.5 解密已存在的文件
[root@localhost group_vars]# ansible-vault decrypt webservers 用decrpt来解密文件
Vault password:
Decryption successful 解密成功
[root@localhost group_vars]# cat webservers cat命令可以查看该文件
ansible_password: redhat
[root@localhost group_vars]#
2.6 更改加密文件密码
[root@localhost group_vars]# ansible-vault rekey webservers 使用rekey来修改密码
Vault password: 输入旧密码123456
New Vault password: 输入新密码 maqiang
Confirm New Vault password:
Rekey successful 修改成功
[root@localhost group_vars]# ansible-vault view webservers 使用新密码查看加密文件
Vault password:
ansible_password: redhat
2.7 playbook和ansible vault
ping通主机需要给加密文件密码
[root@localhost qq]# ansible all -i inventory --vault-id @prompt -m ping
Vault password (default): 输入加密文件密码maqiang
192.168.50.136 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@localhost qq]# ansible all -i inventory --vault-id 136@prompt -m ping 加个136(主机名)可以ping哪台主机
Vault password (136):
192.168.50.136 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
运行playbook需要给加密文件密码才能运行
[root@localhost qq]# ansible-playbook -i inventory --vault-id @prompt playbook.yml
Vault password (default):
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [install httpd and print result] ******************************************
ok: [192.168.50.136]
TASK [debug] *******************************************************************
ok: [192.168.50.136] => {
"result": {
"changed": false,
"failed": false,
"msg": "Nothing to do",
"rc": 0,
"results": []
}
}
PLAY RECAP *********************************************************************
192.168.50.136 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@localhost qq]#
2.8 变量文件管理的推荐做法
[root@localhost qq]# ls
files hosts_vars playbook.yml
group_vars inventory
[root@localhost qq]# cd group_vars/
[root@localhost group_vars]# mkdir webservers 创建一个webservers的目录
[root@localhost group_vars]# cd webservers/ 进入该目录
[root@localhost webservers]# ls
[root@localhost webservers]# vim var 不用加密的东西放入var中
[root@localhost webservers]# ansible-vault create vault 需要加密的东西放入vault中
New Vault password:
Confirm New Vault password:
[root@localhost webservers]# cd ../..
[root@localhost qq]# ls
files hosts_vars playbook.yml
group_vars inventory
[root@localhost qq]# tree .
.
├── files
├── group_vars
│ └── webservers 一个目录
│ ├── var 放不用加密的文件
│ └── vault 放需要加密的文件
├── hosts_vars
├── inventory
└── playbook.yml
4 directories, 4 files
[root@localhost qq]# ansible all -i inventory --vault-id @prompt -m ping
Vault password (default):
192.168.50.136 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
3. 管理事实
3.1 使用debug模块查看事实
[root@localhost qq]# vim playbook.yml
---
- hosts: all
tasks:
- name: 取出所有事实
debug:
var: ansible_facts
[root@localhost qq]# ansible-playbook --syntax-check playbook.yml 查看语法是否错误
playbook: playbook.yml
[root@localhost qq]# ansible-playbook --vault-id @prompt playbook.yml
Vault password (default):
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [取出所有事实] ****************************************************************** 取出所有事实
ok: [192.168.50.136] => {
"ansible_facts": {
"all_ipv4_addresses": [
"192.168.50.136"
],
"all_ipv6_addresses": [
......
"system_capabilities_enforced": "True",
"system_vendor": "VMware, Inc.",
"uptime_seconds": 20458,
"user_dir": "/root",
"user_gecos": "root",
"user_gid": 0,
"user_id": "root",
"user_shell": "/bin/bash",
"user_uid": 0,
"userspace_architecture": "x86_64",
"userspace_bits": "64",
"virtualization_role": "guest",
"virtualization_type": "VMware"
}
}
PLAY RECAP *********************************************************************
192.168.50.136 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Ansible事实的示例
短主机名 : ansible_facts[‘hostname’] 完全限定域名 : ansible_facts[‘fqdn’] IPv4地址 :ansible_facts[‘default_ipv4’][‘address’] 所有网络接口的名称列表 :ansible_facts[‘interfaces’] /dev/vda1磁盘分区的大小 :ansible_facts[‘devices’][‘vda’][‘partitions’][‘vda1’][‘size’] DNS服务器列表 : ansible_facts[‘dns’][‘nameservers’] 当前运行的内核版本 : ansible_facts[‘kernel’]
比如查看IPV4地址
[root@localhost qq]# vim playbook.yml
---
- hosts: all
tasks:
- name: 取出所有事实
debug:
var: ansible_facts['default_ipv4']['address']
[root@localhost qq]# ansible-playbook --vault-id @prompt playbook.yml
Vault password (default):
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [取出所有事实] ******************************************************************
ok: [192.168.50.136] => {
"ansible_facts['default_ipv4']['address']": "192.168.50.136"
} 取出IP
PLAY RECAP *********************************************************************
192.168.50.136 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
比如查看主机地址
[root@localhost qq]# vim playbook.yml
---
- hosts: all
tasks:
- name: 取出所有事实
shell: echo 本机的IP地址是:{{ ansible_facts['default_ipv4']['address'] }} 也可以用点的方式取出事实 {{ ansible_facts.default_ipv4.address }}
register: result 打印结果
- debug: var=result
[root@localhost qq]# ansible-playbook --vault-id @prompt playbook.yml
Vault password (default):
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [取出所有事实] ******************************************************************
changed: [192.168.50.136]
TASK [debug] *******************************************************************
ok: [192.168.50.136] => {
"result": {
"changed": true,
"cmd": "echo 本机的IP地址是:192.168.50.136",
"delta": "0:00:00.003446",
"end": "2020-09-06 15:14:19.278589",
"failed": false,
"rc": 0,
"start": "2020-09-06 15:14:19.275143",
"stderr": "",
"stderr_lines": [],
"stdout": "本机的IP地址是:192.168.50.136",
"stdout_lines": [
"本机的IP地址是:192.168.50.136"
]
}
}
PLAY RECAP *********************************************************************
192.168.50.136 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3.2 Ansible事实作为变量注入
选定的Ansible事实名称比较
ansible_facts形式旧事实变量形式
ansible_facts[‘hostname’]ansible_hostnameansible_facts[‘fqdn’]ansible_fqdnansible_facts[‘default_ipv4’][‘address’]ansible_default_ipv4[‘address’]ansible_facts[‘interfaces’]ansible_interfacesansible_facts[‘devices’][‘vda’][‘partitions’][‘vda1’][‘size’]ansible_devices[‘vda’][‘partitions’][‘vda1’][‘size’]ansible_facts[‘dns’][‘nameservers’]ansible_dns[‘nameservers’]ansible_facts[‘kernel’]ansible_kernel
示例:
用新的写法
[root@localhost playbook]# vim myplay.yml
---
- hosts: all
tasks:
- name: jfldajlfd
debug:
msg: >
{{ ansible_facts['hostname'] }}
[root@localhost playbook]# ansible-playbook -C myplay.yml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [jfldajlfd] ***************************************************************
ok: [192.168.50.136] => {
"msg": "localhost \n"
}
PLAY RECAP *********************************************************************
192.168.50.136 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
用旧的写法
[root@localhost playbook]# vim myplay.yml
---
- hosts: all
tasks:
- name: jfldajlfd
debug:
msg: >
{{ ansible_hostname }}
[root@localhost playbook]# ansible-playbook -C myplay.yml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.50.136]
TASK [jfldajlfd] ***************************************************************
ok: [192.168.50.136] => {
"msg": "localhost \n"
}
PLAY RECAP *********************************************************************
192.168.50.136 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
将Ansible配置文件的[default]部分中inject_facts_as_vars参数设置为False,可关闭旧命名系统。默认设置目前为True。
# inject_facts_as_vars = True 将注释取消,把Ture改为False后将不能使用旧的写法
3.3 关闭事实收集
禁用play事实收集功能,可将gather_facts关键字设置为no:
[root@localhost playbook]# vim myplay.yml
---
- hosts: all
gather_facts: no 添加此行将无法进行收集事实
tasks:
- name: jfldajlfd
debug:
msg: >
{{ ansible_facts['hostname'] }}
[root@localhost playbook]# ansible-playbook -C myplay.yml
PLAY [all] *********************************************************************
TASK [jfldajlfd] ***************************************************************
fatal: [192.168.50.136]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'hostname'\n\nThe error appears to be in '/root/playbook/myplay.yml': line 5, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: jfldajlfd\n ^ here\n"} 报错,无法收集事实
PLAY RECAP *********************************************************************
192.168.50.136 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
使用setup模块临时开启事实收集
[root@localhost playbook]# vim myplay.yml
---
- hosts: all
gather_facts: no
tasks:
- name: jjyy
setup: 添加setup模块
- name: jfldajlfd
debug:
msg: >
{{ ansible_facts['hostname'] }}
[root@localhost playbook]# ansible-playbook -C myplay.yml
PLAY [all] *********************************************************************
TASK [jjyy] ********************************************************************
ok: [192.168.50.136]
TASK [jfldajlfd] ***************************************************************
ok: [192.168.50.136] => {
"msg": "localhost \n"
}
PLAY RECAP *********************************************************************
192.168.50.136 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3.4 创建自定义事实
在受控机上采用INI格式编写的静态自定义事实文件
[root@localhost facts.d]# vi jjyy.fact
[packages]
web_package = httpd
db_package = mariadb-server
[users]
user1 = joe
user2 = jane
在主控机上搜索jjyy
[root@localhost ansible]# ansible all -m setup|less
......
"jjyy": {
"packages": {
"db_package": "mariadb-server",
"web_package": "httpd"
......
3.5 使用魔法变量
最常用的有四个:
魔法变量说明
hostvars包含受管主机的变量,可以用于获取另一台受管主机的变量的值。如果还没有为受管主机收集事实,则它不会包含该主机的事实。group_names列出当前受管主机所属的所有组groups列出清单中的所有组和主机inventory_hostname包含清单中配置的当前受管主机的主机名称。因为各种原因有可能与事实报告的主机名称不同
示例:
[root@localhost ansible]# ansible all -m debug -a 'var=hostvars' 用debug模块查看受管主机的变量
192.168.50.136 | SUCCESS => {
"hostvars": {
"192.168.50.136": {
"ansible_check_mode": false,
"ansible_diff_mode": false,
"ansible_facts": {},
"ansible_forks": 5,
"ansible_inventory_sources": [
"/etc/ansible/inventory"
],
"ansible_password": "redhat",
"ansible_playbook_python": "/usr/bin/python3.6",
"ansible_verbosity": 0,
"ansible_version": {
"full": "2.9.11",
"major": 2,
"minor": 9,
"revision": 11,
"string": "2.9.11"
},
"group_names": [
"ungrouped"
],
"groups": {
"all": [
"192.168.50.136"
],
"ungrouped": [
"192.168.50.136"
]
},
"inventory_dir": "/etc/ansible",
"inventory_file": "/etc/ansible/inventory",
"inventory_hostname": "192.168.50.136",
"inventory_hostname_short": "192",
"omit": "__omit_place_holder__c4523dfb5de86623c8328d7a9e4d91434f7fb22b",
"playbook_dir": "/etc/ansible"
}
}
}
[root@localhost ansible]# ansible all -m debug -a "var=hostvars['192.168.50.136']['ansible_password']" 查看上面的redhat
192.168.50.136 | SUCCESS => {
"hostvars['192.168.50.136']['ansible_password']": "redhat"
}
[root@localhost ansible]# ansible all -m debug -a 'var=groups'
192.168.50.136 | SUCCESS => {
"groups": {
"all": [
"192.168.50.136"
],
"ungrouped": [
"192.168.50.136"
]
}
}