目录
一、管理变量
1.1、变量的基本用法
1.2、使用已注册变量捕获命令输出
二、管理加密
2.1、ansible-vault常用场景
三、管理事实
3.1、事实基本用法
3.2、创建自定义事实
3.3、魔法变量hostvars、group_names、groups、inventory_hostname
一、管理变量
1.1、变量的基本用法
Ansible 支持利用变量来存储值,并在 Ansible 项目的所有文件中重复使用这些值。变量的名称必须以字母开头,并且只能含有字母、数字和下划线
定义变量范围:
- 全局范围:从命令行或 Ansible 配置设置的变量
- Play 范围:在 play 和相关结构中设置的变量
- 主机范围:由清单、事实收集或注册的任务、在主机组和个别主机上设置的变量
变量优先级,如果在多个级别上定义了相同名称的变量,则采用优先级别最高的变量。常用的(需要我们记住的)优先级:命令行中定义的变量 > playbook 定义的变量 > 清单定义的变量
不需要我们记住的(用时候再查文档)优先级,从上到下优先级由高到低
1、ansible-playbook 命令中的变量,ansible-playbook -e var=value |
2、task 变量 |
3、block 变量 |
4、role 中定义的变量 和 include 变量 |
5、set_fact |
6、registered 变量 |
7、vars_files |
8、var_prompt |
9、play 变量 |
10、host facts |
11、playbook 中设置的 host_vars |
12、playbook 中设置的 group_vars |
13、inventory 中设置的 host_vars |
14、inventory 中设置的 group_vars |
15、inventory 变量 |
16、role 中 defaults/main.yml 中定义的变量 |
常用的定义变量方法一:通过 vars 直接定义变量
- hosts: allvars:db_name: foo_dbdb_user: foo_user
常用的定义变量方法二:通过 vars_files 外部文件引入变量
- hosts: allvars_files: vars/dbs.yml# vars/dbs.yml 内容
db_name: foo_db
db_user: foo_user
通过 {{ 变量名 }} 引用变量。当变量用作开始一个值的第一元素时,必须使用引号。
vars:db_name: foo_dbtasks:- name: Create databasemysql_db:name: "{{ db_name }}"state: present
常用的定义变量方法三:主机变量、组变量是应用于特定主机、组的变量。使用目录填充主机和组变量的推荐做法:是在与清单文件或目录相同的工作目录中,创建 group_vars 和 host_vars 两个目录。这两个目录分别包含用于定义组变量和主机变量的文件。比如,
- 为了定义用于 servera.lab.example.com 主机的主机变量,需要创建名为 host_vars/servera.lab.example.com 的YAML文件,然后设置变量
- 为了定义用于 webservers 组的组变量,需要创建名为 group_vars/webservers 的 YAML文件,然后设置变量
1.2、使用已注册变量捕获命令输出
可以使用 register 语句捕获命令输出。输出保存在一个临时变量中,稍 后在 playbook中 可用于调试用途或者达成其他目的。比如,我们把访问网页的输出注册为web_content,把访问mysql数据库的输出注册为db_content。然后在debug的时候输出,注册变量的内容包括多个字段,我们只显示我们需要的内容。
[student@workstation ansible]$ cat web_test.yml ---
- name: Test web pagehosts: webserverstasks:- name: Access url get http200uri:url: http://serverc.lab.example.com/status_code: 200return_content: yesregister: web_content- name: Show web pagedebug:var: web_content.content- name: Test mariadbhosts: devtasks:- name: Show databasesshell: 'mysql -uroot -e "show databases;"'register: db_content- name: Show databases resultdebug:var: db_content.stdout_lines
二、管理加密
Ansible可能需要访问密码或API密钥等敏感数据,以便能配置受管主机。Ansible Vault可以加密和解密任何由Ansible使用的结构化数据文件。可通过一个名为 ansible-vault 的命令行工具创建、编辑、加密、解密和查看文件。Ansible Vault并不实施自有的加密函数,而是使用外部Python工具集。采用对称加密。
2.1、ansible-vault常用场景
使用ansibl-vault命令创建、编辑、查看文件,分别用create、edit、view。修改密码使用rekey。
[student@workstation ansible]$ ansible-vault create users.yml
[student@workstation ansible]$ ansible-vault edit users.yml
[student@workstation ansible]$ ansible-vault view users.yml
[student@workstation ansible]$ ansible-vault rekey users.yml
使用ansible-vault对文件加解密,使用encrypt、decrypt。比如对明文temp.yml进行加密,再解密成明文temp2.yml。
[student@workstation ansible]$ ansible-vault encrypt temp.yml
New Vault password:
Confirm New Vault password:
Encryption successful[student@workstation ansible]$ cat temp.yml
$ANSIBLE_VAULT;1.1;AES256
34623033613639643331383834333939623633343261613865306666623662666266336362646365
3031376464323862386134616136326630613536666166630a666635633834336436636230323461
63633163653232623333333037356234333132386239653835383565343236663561303765323266
3161366338313930620a616364366236303065653632663031376665653832383230323164633835
63396133626334373339313264666531306335343538333264323166633562306662326465353563
6531613731306166303866653330623064373230643164363965[student@workstation ansible]$ ansible-vault decrypt temp.yml --output=temp2.yml
Vault password:
Decryption successful[student@workstation ansible]$ cat temp2.yml
---
- hosts: allvars_files:- users.yml
如果 playbook 使用 的所有 vault 加密文件都使用同一密码,则可以使用 --ask-vault-pass 选项以交互方式提供 vault 密码。也可使用 --vault-password-file 选项指定以纯文本存储加密密码的文件。比如,playbook里面引用了加密的变量文件users.yml,我们把密码放在vpass.txt文件里。
- hosts: all vars_files: - users.yml
[student@workstation ansible]$ ansible-vault view users.yml --vault-password-file=vpass.txt
users:- name:joepassword:redhat- name:janepassword:centos[student@workstation ansible]$ ansible-playbook temp.yml --vault-password-file=vpass.txt
如果playbook使用的 vault 加密文件密码不同,那么可以使用 --vault-id @prompt 选项逐个交互输入密码。比如,playbook引用两个密码不一样的变量文件users.yml、databases.yml。
---
- hosts: allvars_files:- users.yml- databases.yml
[student@workstation ansible]$ ansible-playbook temp.yml --vault-id one@prompt --vault-id two@prompt
Vault password (one):
Vault password (two):
管理变量加密的推荐做法是:可将敏感变量和所有其他变量保存在相互独立的文件中。包含敏感变量的文件用 ansible-vault 命令进行加密。使用 group_vars 管理组变量,host_vars 管理主机变量。
三、管理事实
3.1、事实基本用法
Ansible 事实是 Ansible 在受管主机上自动检测到的变量。事实中含有与主机相关的信息。为受管主机收集的一些事实可能包括
- 主机名称
- 内核版本
- 网络接口
- IP地址
- 操作系统版本
- 各种环境变量
- CPU数量
- 提供的或可用的内存
- 可用磁盘空间
通常,每个 play 在执行第一个任务之前会先自动运行 setup 模块来收集事实。 在 Ansible 中 报告为 Gathering Facts 任务。
查看事实,可以运行一个收集事实的task,并使用 debug 模块显示 ansible_facts 变量。运行这个 playbook 之后,playbook 将以 JSON 格式显示 ansible_facts 变量的内容。
[student@workstation ansible]$ vim print_facts.yml - name: Print factshosts: devtasks:- name: Print all facts of devdebug:var: ansible_facts
ansible_facts 可以见名知意,常用的有:
- ansible_facts.hostname 主机名
- ansible_facts.fqdn FQDN
- ansible_facts.default_ipv4.address IP地址
- ansible_facts.devices /dev目录下的块设备/dev/sda、/dev/sda1、lvm等
- ansible_facts.kernel 内核
收集事实可能耗费时间。在不需要收集事实的 playbook 中可以通过 gather_facts 关闭事实收集。在需要的时候,通过一个 setup 模块的任务即可手动收集。
[student@workstation ansible]$ vim facts.yml ---
- name: Facts hosts: devgather_facts: notasks:- name: Here no factsdebug:msg: "Here no facts"- name: Gather facts mannuallysetup:- name: Here is factsdebug:msg: " {{ ansible_facts.kernel }}"[student@workstation ansible]$ ansible-playbook facts.yml PLAY [Facts] ***********************************************************************************TASK [Here no facts] ***************************************************************************
ok: [servera.lab.example.com] => {"msg": "Here no facts"
}TASK [Gather facts mannually] ******************************************************************
ok: [servera.lab.example.com]TASK [Here is facts] ***************************************************************************
ok: [servera.lab.example.com] => {"msg": " 4.18.0-240.el8.x86_64"
}
3.2、创建自定义事实
自定义事实采用JSON格式编写,一般命名为 xxxx.fact ,使用时将自定义事实文件放在受管主机的 /etc/ansible/facts.d/ 目录。执行 setup 模块时,自定义事实放在 ansible_facts.ansible_local.xxxx 变量中,用法和默认事实一样。
举例,在控制节点上编辑 myfact.fact 自定义事实,受管主机上创建 /etc/ansible/facts.d/ 目录并安装自定义事实 myfact.fact ,使其具有自定义事实ansible_facts.ansible_local.myfact。
[student@workstation ansible]$ vim myfact.json {"users": {"user1": "tom","user2": "jerry",},"packages": {"db_pkg": "mariadb-server","web_pkg": "httpd",},
}
[student@workstation ansible]$ vim myfact.yml---
- name: Custom factshosts: webserversvars:remote_dir: /etc/ansible/facts.d/facts_file: myfact.jsontasks:- name: Create directoryfile:path: "{{ remote_dir }}"state: directoryrecurse: yes- name: Install custom factscopy:src: "{{ facts_file }}"dest: "{{ remote_dir }}"
[student@workstation ansible]$ ansible webservers -m setup | less
......
...skipping..."ansible_local": {"myfact": {"packages": {"db_pkg": "mariadb-server","web_pkg": "httpd"},"users": {"user1": "tom","user2": "jerry"}}},
.......
3.3、魔法变量hostvars、group_names、groups、inventory_hostname
有些变量并不通过 setup 模块来获取,由ansible自动配置,可以获取特定受管主机信息。
hostvars 包含受管主机的变量,可以在一个受管主机上获取另一个受管主机的变量。比如,在test组上获取servera的事实。或者为 webservers 组主机生成 /etc/hosts 文件,里面包含所有受管主机的 IP地址、主机名、FQDN。
[student@workstation ansible]$ ansible test -m debug -a 'var=hostvars["servera.lab.example.com"]'
group_names 当前受管主机所属的所有组。比如,servera属于dev组,serverc属于prod、webservers这两个组。
[student@workstation ansible]$ ansible servera.lab.example.com -m debug -a "var=group_names"
servera.lab.example.com | SUCCESS => {"group_names": ["dev"]
}[student@workstation ansible]$ ansible serverc.lab.example.com -m debug -a "var=group_names"
serverc.lab.example.com | SUCCESS => {"group_names": ["prod","webservers"]
}
groups 列出清单中所有组和主机。比如,使用 groups.all 可以遍历所有主机。
[student@workstation ansible]$ ansible dev -m debug -a "var=groups"
servera.lab.example.com | SUCCESS => {"groups": {"all": ["servera.lab.example.com","serverb.lab.example.com","serverc.lab.example.com","serverd.lab.example.com"],"dev": ["servera.lab.example.com"],"prod": ["serverc.lab.example.com","serverd.lab.example.com"],"test": ["serverb.lab.example.com"],"ungrouped": [],"webservers": ["serverc.lab.example.com","serverd.lab.example.com"]}
}
inventory_hostname 当前受管主机在 inventory 中的主机名。这个名字可能和主机的hostname不一样。
[student@workstation ansible]$ ansible dev -m debug -a "var=inventory_hostname"
servera.lab.example.com | SUCCESS => {"inventory_hostname": "servera.lab.example.com"
}