我对 ansible 还很陌生,所以这也许很容易做到。
我们有大量的设备在不同的环境中具有一致的命名约定。
app0[01:25].dev.domain.com
app[01:25].qa.domain.com
app[01:25].uat.domain.com
app[01:25].prod.domain.com
这些应用服务器中的各种设备具有特定角色,如 Web 服务器、应用服务器、API 服务器等,并且跨环境都相同。因此,app05 是 dev、qa、uat、uat、prod 中的 Web 服务器。
现在我正在使用 group_vars 并为组名分配特定的服务器角色。但我不想为每个环境设置组名(webdev、webqa、webuat 等)
有没有简单的解决方案?我认为角色会让事情变得有点复杂,但也许这就是解决方案?
答案1
问:“为每个环境设置组名(webdev、webqa、webuat 等)“
答:动态创建变量,例如
- hosts: all
gather_facts: false
vars:
env:
app05: web
tasks:
- set_fact:
env_local: "{{ env[_host]|d('none') }}{{ _group }}"
vars:
_arr: "{{ inventory_hostname.split('.') }}"
_host: "{{ _arr.0 }}"
_group: "{{ _arr.1 }}"
- debug:
var: env_local
给出
ok: [app01.dev.domain.com] =>
env_local: nonedev
ok: [app02.dev.domain.com] =>
env_local: nonedev
ok: [app03.dev.domain.com] =>
env_local: nonedev
ok: [app04.dev.domain.com] =>
env_local: nonedev
ok: [app05.dev.domain.com] =>
env_local: webdev
使用模块添加主机并动态创建组。例如,创建文件
shell> cat add_host_to_groups.yml
- add_host:
name: "{{ i }}"
groups: "{{ item }}{{ (i.split('.')).1 }}"
loop: "{{ _hosts }}"
loop_control:
loop_var: i
并将其包含在分配规则的循环中
- hosts: all
gather_facts: false
vars:
env:
web: app05
tasks:
- include_tasks: add_host_to_groups.yml
loop: "{{ env.keys()|list }}"
vars:
_hosts: "{{ ansible_play_hosts_all|select('match', env[item] ~ '.*') }}"
run_once: true
- debug:
var: groups
run_once: true
给出
groups:
all:
- app01.dev.domain.com
- app02.dev.domain.com
- app03.dev.domain.com
...
- app25.prod.domain.com
webdev:
- app05.dev.domain.com
webprod:
- app05.prod.domain.com
webqa:
- app05.qa.domain.com
webuat:
- app05.uat.domain.com
在连续的游戏中使用这些组,例如
- hosts: webqa
gather_facts: false
tasks:
- debug:
var: ansible_play_hosts_all
给出
ansible_play_hosts_all:
- app05.qa.domain.com
适合字典环境满足您的需求。
答案2
建立真实来源的清单方案是从某个系统查询这些组。比 DNS 名称中的字符串更复杂的东西。
例如,netbox 库存数据库系统有一个可以适应的设备角色。不是要挑剔 netbox,而是它有一个 Ansible 库存插件和一个开放的数据库模型,所以很容易谈论。
但是,也许还没有一个好的外部数据库。可以生成这样的常规命名方案。使用 Ansible 库存插件中最递归的生成器:
# inventory.yml
plugin: generator
hosts:
name: "{{ application }}{{ number }}.{{ environment }}.example.com"
parents:
- name: "{{ application }}_{{ environment }}"
parents:
- name: "{{ application }}"
vars:
application: "{{ application }}"
- name: "{{ environment }}"
vars:
environment: "{{ environment }}"
layers:
application:
- app
- api
environment:
- dev
- qa
- uat
- prod
number:
- "01"
- "02"
- "05"
层名称是任意的。给定“主机”根和“父级”符号,更深的缩进名称是包含外部名称的组。
ansible-inventory -i inventory.yml --list
将在 Ansible 的清单 JSON 文档中打印主机。部分输出:
{
"_meta": {
"hostvars": {
"app05.qa.example.com": {
"application": "app",
"environment": "qa"
}
}
},
"app_qa": {
"hosts": [
"app01.qa.example.com",
"app02.qa.example.com",
"app05.qa.example.com"
]
},
"app": {
"children": [
"app_dev",
"app_prod",
"app_qa",
"app_uat"
]
},
"qa": {
"children": [
"api_qa",
"app_qa"
]
},
}
并继续进行其他组合。
注意它做了:
- “应用程序”组
- “环境” 组
- “应用环境”组合组
- 符合 DNS 名称模式的主机名
- 包含每个主机的“应用程序”和“环境”的变量
该插件的局限性包括:
始终对图层组合进行笛卡尔积运算。某个组不能多或少,也不能以不同的值开始编号方案。
没有紧凑的主机范围。[01:25] 语法和 range() 函数都不起作用。请考虑通过提交问题来请求。作为一种解决方法,配置文件中的数十个数字是有用的。