管理变量、机密和事实

tech2025-05-17  10

文章目录

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" ] } }
最新回复(0)