管理变量、机密
Ansible变量
ansbile变量概述
- ansible支持利用变量来存储值,并在ansible项目的所有文件中重复使用这些值,这可以简化项目的创建和维护,并减少错误的数量。
- 通过变量,可以轻松地在Ansible项目中管理给定环境的动态值。
变量命名
变量的名称必须以字母开头,并且只能包含字母、数字和下划线。
变量命名
- Ansible项目中可以在多个位置定义变量
- Ansible变量的三大范围:
全局范围:从命令行或Ansible配置设置的变量
Play范围:在playbook和相关结构中设置的变量
之际范围:由清单、事实收集或注册的任务,在主机组和个别主机上的设置的变量 - 变量优先级:越靠近使用的值,优先级越高
在playbook中定义变量
Playbook变量可以通过多种方式定义。一种常见的方式是将变量放在playbook开头的vars块中
- hosts: all
vars:
user: mike
home: /home/mike
也可以在外部文件中定义playbook变量。此时不使用playbook中的vars块,可以改为使用vars_files指令,后面跟上相对于playbook位置的外部变量文件名称列表:
- hosts: all
vars_files:
- vars/user.yml
而后,可以使用YAML格式在这一/这些文件中定义playbook变量:
user: mike
home: /home/mike
声明了变量后,可以在任务中使用这些变量。若要引用变量,可以将变量名放在双大括号内。在任务执行时,Ansible会将变量替换为其值。
vars:
user: mike
tasks:
- name: create user
user:
name: "{{ user }}"
注意:当变量用作开始一个值的第一元素时,必须使用引号。这可以防止Ansible将变量引用视为YAML字典的开头。
主机变量和主机组变量
应用于主机变量的分类
- 主机变量,应用于特定主机
- 组变量,应用于一个主机组或一组主机组中的所有主机
- 主机变量优先于组变量,但palybook中定义的变量的优先级比这两者更高
定义主机变量
[servers]
192.168.8.128 ansible_user=root
定义主机组变量
[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目录定义清单变量,而不直接在清单文件中定义它们。
[servers1]
node1.example.com
node2.example.com[servers2]
node3.example.com
node4.example.com[servers:children]
servers1
servers2
从命令行覆盖变量
清单变量可被playbook中设置的变量覆盖,这两种变量又可通过在命令行中传递参数到ansible或ansible-playbook命令来覆盖。在命令行上设置的变量称为额外变量。
当需要覆盖一次性运行的playbook的变量的已定义值时,额外变量非常有用。例如:
ansible-playbook test.yml -e “package=apache”
使用已注册变量捕获命令输出
可以使用register语句捕获命令输出。输出保存在一个临时变量中,然后在playbook中可用于调试用途或者达成其他目的,例如基于命令输出的特定配置。
以下playbook演示了如何为调试用途捕获命令输出:
---
- name: httpd
yum:
name: httpd
state: latest
register: install_result
- debug: var=install_result
运行playbook
[root@localhost ~]# ansible-playbook test.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
管理机密
Ansible Vault
- ansible提供的ansible vault可以加密和解密任何由ansible使用的结构化数据文件
- 若要使用ansible vault,可通过一个名为ansible-vault的命令行工具创建、编辑、加密、解密和查看文件
- ansible vault可以加密任何由ansible使用的结构数据文件,包括清单变量、playbook中含有的变量文件
创建加密的文件
要创建新的加密文件,可使用ansible-vault create filename命令。该命令将提示输入新的vault密码,然后利用默认编辑器vi打开文件。
[root@client ansible]# ansible-vault create passwd.yml
New Vault password: 1
Confirm New Vault password: 1
[root@client ansible]# cat passwd.yml
$ANSIBLE_VAULT;1.1;AES256
35356564643139653265313033323137373133666232323531313136343839653264386266663238
3633306662356262333965616636313033633037386666660a366665656637633831646566383935
33633366643466333639383331313264366538333834373432663133306364356530613538333866
3835613936346439360a346338303462656330373861666636373037323037663564383035353935
3436
查看加密的文件
可以使用ansible-vault view filename命令查看Ansible Vault加密的文件,而不必打开它进行编辑。
[root@client vault]# ansible-vault view passwd.yml
Vault password:
123456
编辑现有的加密文件
要编辑现有的加密文件,Ansible Vault提供了ansible-vault edit filename命令。此命令将文件解密为一个临时文件,并允许编辑。保存时,它将复制其内容并删除临时文件。
[root@client vault]# ansible-vault encrypt runtime.yml
New Vault password: 1
Confirm New Vault password: 1
Encryption successful
[root@client vault]# cat runtime.yml
$ANSIBLE_VAULT;1.1;AES256
65376439373233653262396566636437613836323830323034326366366233643738313636326132
3539343433663932613632313965396230336637316534330a643963336138373534383331336638
31666633316639643763303635363832346665343936343166376465623961386433633036363930
3764376536613736370a663939646238336563636563356530663334363736343839623632393237
3531
解密现有的文件
现有的加密文件可以通过ansible-vault decrypt filename命令永久解密。在解密单个文件时,可使用–output选项以其他名称保存解密的文件。
[root@client vault]# ansible-vault decrypt runtime.yml
Vault password:
Decryption successful
[root@client vault]# cat runtime.yml
hell runtime
更改加密文件的密码
使用ansible-vault rekey filename命令更改加密文件的密码。此命令可一次性更新多个数据文件的密钥。它将提示提供原始密码和新密码。
[root@client vault]# ansible-vault rekey passwd.yml
Vault password: 1
New Vault password: 123
Confirm New Vault password: 123
Rekey successful
playbook和ansible vault
要运行可访问通过Ansible Vault加密的文件的playbook,需要向ansible-playbook命令提供加密密码。如果不提供密码,playbook将返回错误:
[root@localhost ~]# ansible-playbook site.yml
ERROR: A Vault password must be specified to decrypt vars/api_key.yml
使用–vault-password-file选项指定以纯文本存储加密密码的文件。密码应当在该文件中存储为一行字符串。由于该文件包含敏感的纯文本密码,因此务必要通过文件权限和其他安全措施对其加以保护。
ansible-playbook --vault-password-file=vault-pw-file test.yml
也可以使用–vault-id选项
ansible-playbook --vault-id @prompt test.yml
变量文件管理
若要简化管理,务必要设置Ansible项目,使敏感变量和其他变量保存在相互独立的文件中。然后,包含敏感变量的文件可通过ansible-vault命令进行保护。
管理组变量和主机变量的首选方式是在playbook级别上创建目录。group_vars目录通常包含名称与它们所应用的主机组匹配的变量文件。host_vars目录通常包含名称与它们所应用的受管主机名称匹配的变量文件。
.
├── ansible.cfg
├── group_vars
│ └── webservers
│ └── vars
├── host_vars
│ └── 172.16.103.129
│ ├── vars
│ └── vault
├── inventory
└── playbook.yml
在这种情况中,其好处在于用于172.16.103.129的大部分变量可以放在vars文件中,敏感变量则可单独放在vault文件中保密。然后使用ansible-vault加密vault文件,而将vars文件保留为纯文本。
在本例中,host_vars/172.16.103.129目录内使用的文件名没有什么特别之处。该目录可以包含更多文件,一些由Ansible Vault加密,另一些则不加密。
Playbook变量(与清单变量相对)也可通过Ansible Vault保护。敏感的playbook变量可以放在单独的文件中,此文件通过Ansible Vault加密,并能vars_files指令包含在该playbook中。这也是推荐做法,因为playbook变量的优先级高于清单变量。
如果需要在playbook中使用多个vault密码,请确保每个加密文件分配一个vaultID,并在运行playbook时输入具有该vaultID的匹配密码。这可确保在解密vault加密文件时先选择正确的密码,这比强制Ansible尝试用户提供的所有vault密码直至找到正确的密码要快。
管理事实
ansible事实
Ansible事实是Ansible在受管主机上自动检测到的变量。事实中包含有与主机相关的信息,可以像play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。
一些事实包括:
主机名称、内核版本、网络接口、IP地址、操作系统版本、各种环境变量、CPU数量、提供的或可用的内存、可用磁盘空间等等
借助事实,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作
- 可以根据含有受管主机当前内核版本的事实运行条件任务,以此来重启服务器
- 可以根据通过事实报告的可用内存来自定义MySQL配置文件
- 可以根据事实的值设置配置文件中使用的IPv4地址
查看为受管主机收集的事实的一种方式是,运行一个收集事实并使用debug模块显示ansible_facts变量值的简短playbook。
[root@client Fact]# cat facts.yml
- name: fact
hosts: 192.168.8.130
tasks:
- name: print facts
debug:
var: ansible_facts
#运行该playbook时,事实将显示在作业输出中:
[root@client Fact]# ansible-playbook facts.yml
PLAY [fact] **********************************************************************************
TASK [Gathering Facts] ***********************************************************************
ok: [192.168.8.130]
TASK [print facts] ***************************************************************************
ok: [192.168.8.130] => {
"ansible_facts": {
"all_ipv4_addresses": [
"192.168.122.1",
"192.168.8.130"
],
"all_ipv6_addresses": [],
"ansible_local": {},
"apparmor": {
"status": "disabled"
},
"architecture": "x86_64",
"bios_date": "07/22/2020",
"bios_version": "6.00",
"cmdline": {
"BOOT_IMAGE": "(hd0,msdos1)/vmlinuz-4.18.0-193.el8.x86_64",
"crashkernel": "auto",
"quiet": true,
"rd.lvm.lv": "rhel/swap",
"resume": "/dev/mapper/rhel-swap",
"rhgb": true,
"ro": true,
"root": "/dev/mapper/rhel-root"
},
······略
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’] |
在playbook中使用事实时,Ansible将事实的变量名动态替换为对应的值:
[root@client Fact]# cat facts.yml
- name: fact
hosts: 192.168.8.130
tasks:
- name: print facts
debug:
msg: >
this host ip is {{ ansible_facts['default_ipv4']['address'] }}
this hostname is {{ ansible_facts['hostname']}}
#执行playbook
[root@client Fact]# ansible-playbook facts.yml
PLAY [fact] **********************************************************************************
TASK [Gathering Facts] ***********************************************************************
ok: [192.168.8.130]
TASK [print facts] ***************************************************************************
ok: [192.168.8.130] => {
"msg": "this host ip is 192.168.8.130 this hostname is node1\n"
}
Ansible事实作为变量注入
在Ansible2.5之前,事实是作为前缀为字符串ansible_的单个变量注入,而不是作为ansible_facts变量的一部分注入。例如,ansible_facts[‘distribution’]事实会被称为ansible_distribution。
许多较旧的playbook仍然使用作为变量注入的事实,而不是在ansible_facts变量下创建命名空间的新语法。我们可以使用临时命令来运行setup模块,以此形式显示所有事实的值。
[root@client Fact]# ansible 192.168.8.130 -m setup
192.168.8.130 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.122.1",
"192.168.8.130"
],
"ansible_all_ipv6_addresses": [],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/22/2020",
"ansible_bios_version": "6.00",
"ansible_cmdline": {
"BOOT_IMAGE": "(hd0,msdos1)/vmlinuz-4.18.0-193.el8.x86_64",
"crashkernel": "auto",
"quiet": true,
"rd.lvm.lv": "rhel/swap",
"resume": "/dev/mapper/rhel-swap",
"rhgb": true,
"ro": true,
"root": "/dev/mapper/rhel-root"
关闭事实收集
有时我们不想为play收集事实。这样做的原因可能有:
- 不准备使用任何事实
- 希望加快play速度
- 希望减小play在受管主机上造成的负载
- 希望主机因为某种原因无法运行setup模块
- 需要安装一些必备软件后再收集事实
以上种种原因导致我们可能想要永久或暂时关闭事实收集的功能,要为play禁用事实收集功能,可将gather_facts关键字设置为no:
[root@client Fact]# cat facts.yml
- name: fact
hosts: 192.168.8.130
gather_fact: no
tasks:
创建自定义事实
除了使用系统捕获的事实外,我们还可以自定义事实,并将其本地存储在每个受管主机上
默认情况下,setup模块从各受管主机的/etc/ansible/facts.d目录下的文件和脚本中加载自定义事实
各个文件或脚本的名称必须以.fact结尾才能被使用;动态自定义事实脚本必须输出JSON格式的事实,而且必须是可执行文件
以下是采用INI格式编写的静态自定义事实文件。INI格式的自定义事实文件包含由一个部分定义的顶层值,后跟用于待定义的事实的键值对:
[packages]
web = apache
db_packages = mysql
[users]
user1 = mike
user2 = jerry
同样的事实可能以JSON格式提供。以下JSON事实等同于以上示例中INI格式指定的事实。JSON数据可以存储在静态文本文件中,或者通过可执行脚本输出到标准输出:
[root@node1 ~]# cat test.fact
{
"packages": {
"web": "apache",
"db_packages": "msyql"
},
"users": {
"user1": "mike",
"user2": "jerry"
}
}
#在控制节点上查看
[root@client Fact]# ansible 192.168.8.130 -m setup| less
······
"ansible_local": {
"test": {
"packages": {
"db_packages": "msyql",
"web": "apache"
},
"users": {
"user1": "mike",
"user2": "jerry"
}
}
},
······
魔法变量
一些变量并非事实或通过setup模块配置,但也由Ansible自动设置。这些魔法变量也可用于获取与特定受管主机相关的信息。
魔法变量 | 说明 |
---|---|
hostvars | 包含受管主机的变量,可以用于获取另一台受管主机的变量的值。 如果还没有为受管主机收集事实,则它不会包含该主机的事实 |
group_names | 列出当前受管主机所属的所有组 |
groups | 列出清单中的所有组和主机 |
inventory_hostname | 包含清单中配置的当前受管主机的主机名称。 因为各种原因有可能与事实报告的主机名称不同 |