文章目录
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_hostname |
ansible_facts[‘fqdn’] | ansible_fqdn |
ansible_facts[‘default_ipv4’][‘address’] | ansible_default_ipv4[‘address’] |
ansible_facts[‘interfaces’] | ansible_interfaces |
ansible_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"
]
}
}