场景预设
- role 的默认变量文件里,有不同类型的变量,K/V、Dict、List 都有。
- 目标 host 同时归属于几个分组(groups)
期望结果
可以在 group_vars 里给某些组自定义一些变量,可以与 role 默认变量合并,优先使用自定义变量。
举例
role 默认变量 defaults/main.yml
# mysql 配置,只包含基本设置,优化参数请自行决定。
pxc_custom_cnf:
mysqld:
ssl_ca: "/cert/ca.pem"
ssl_cert: "/cert/server-cert.pem"
ssl_key: "/cert/server-key.pem"
bind_address: "{
{ global_bond_ip }}"
wsrep_node_address: "{
{ global_bond_ip }}"
wsrep_node_name: "{
{ ansible_hostname }}"
server_id: "{
{ global_bond_ip | ipaddr('int') }}"
wsrep_cluster_address: "gcomm://{
{ gcomm_nodes }}"
wsrep_node_incoming_address: "{
{ global_bond_ip }}:{
{ combined_vars.pxc_port | default(pxc_port) }}"
port: "{
{ combined_vars.pxc_port | default(pxc_port) }}"
skip_name_resolve: "on"
client:
ssl_ca: "/cert/ca.pem"
ssl_cert: "/cert/client-cert.pem"
ssl_key: "/cert/client-key.pem"
sst:
encrypt: "4"
ssl_ca: "/cert/ca.pem"
ssl_cert: "/cert/server-cert.pem"
ssl_key: "/cert/server-key.pem"
xtrabackup:
host: "{
{ global_bond_ip }}"
user: "{
{ mysql_backup_username }}"
password: "{
{ mysql_backup_password }}"
port: "{
{ combined_vars.pxc_port | default(pxc_port) }}"
target_dir: "/backup"
自定义变量 group_vars/pxc.yml
# mysql 配置
pxc_custom_cnf:
mysqld:
# 自定义配置,替代 role 对应的默认值,并合并其余默认值。
character_set_server: "utf8mb4"
collation_server: "utf8mb4_unicode_ci"
max_connections: "1000"
open_files_limit: "200000"
pxc_strict_mode: "PERMISSIVE"
skip_name_resolve: "on"
expire_logs_days: "7"
max_prepared_stmt_count: "65528"
innodb_buffer_pool_instances: "16"
innodb_buffer_pool_chunk_size: "256M"
合并后的变量内容
"pxc_custom_cnf": {
"client": {
"ssl_ca": "/cert/ca.pem",
"ssl_cert": "/cert/client-cert.pem",
"ssl_key": "/cert/client-key.pem"
},
"mysqld": {
"bind_address": "192.168.56.16",
"character_set_server": "utf8mb4",
"collation_server": "utf8mb4_unicode_ci",
"expire_logs_days": "7",
"innodb_buffer_pool_chunk_size": "256M",
"innodb_buffer_pool_instances": "16",
"max_connections": "1000",
"max_prepared_stmt_count": "65528",
"open_files_limit": "200000",
"port": "13306",
"pxc_strict_mode": "PERMISSIVE",
"server_id": "3232249872",
"skip_name_resolve": "on",
"ssl_ca": "/cert/ca.pem",
"ssl_cert": "/cert/server-cert.pem",
"ssl_key": "/cert/server-key.pem",
"wsrep_cluster_address": "gcomm://192.168.56.17,192.168.56.18",
"wsrep_node_address": "192.168.56.16",
"wsrep_node_incoming_address": "192.168.56.16:13306",
"wsrep_node_name": "192-168-56-16"
},
"sst": {
"encrypt": "4",
"ssl_ca": "/cert/ca.pem",
"ssl_cert": "/cert/server-cert.pem",
"ssl_key": "/cert/server-key.pem"
},
"xtrabackup": {
"host": "192.168.56.16",
"password": "jNeYsi0ATJkyDTh1vXs4",
"port": "13306",
"target_dir": "/backup",
"user": "bkuser"
}
}
playbook 代码
首先,在需要合并变量的 role 里,调用合并变量的 tasks
- name: Pre tasks
block:
- name: Combine role vars and group vars
import_role:
name: pre-tasks
tasks_from: vars_combine
tags: always
roles/pre-tasks/vars_combine.yml 内容
- name: Combine default vars and custom vars
block:
- name: "Include role's defaults vars"
ansible.builtin.include_vars:
dir: "{
{ item }}/defaults"
name: "temp_role_vars"
loop: "{
{ ansible_parent_role_paths }}"
- name: Assembling group vars files
assemble:
src: "{
{ inventory_dir }}/group_vars"
dest: "{
{ inventory_dir }}/assembled_vars/{
{ group_names | hash('md5') }}.yml"
regexp: "({
{ group_names | join('|') }})"
delegate_to: localhost
become: false
- name: "Include group custom vars"
ansible.builtin.include_vars:
file: "{
{ inventory_dir }}/assembled_vars/{
{ group_names | hash('md5') }}.yml"
name: "temp_group_vars"
- name: Combine vars from role and groups
set_fact:
combined_vars: "{
{ role_vars | combine(group_vars, recursive=true) }}"
vars:
role_vars: "{
{ lookup('vars', 'temp_role_vars') }}"
group_vars: "{
{ lookup('vars', 'temp_group_vars') }}"
rescue:
- name: "Create {
{ inventory_dir }}/assembled_vars"
file:
path: "{
{ inventory_dir }}/assembled_vars"
state: directory
delegate_to: localhost
become: false
- include_tasks: vars_combine.yml
完整代码:https://gitee.com/bottlelee/haibinlee-ansible-roles/blob/develop/pre-tasks/tasks/vars_combine.yml
变量调用
合并的变量,以 combined_vars 开头,那么变量的使用就从原来的 var_a
变成 combined_vars.var_a
即可。
这种方法,方便了使用者用最少的代码量,自定义所需的变量。尤其是你遇到 failed to combine variables, expected dicts but got a 'NoneType' and a 'dict'
这样的报错。