我在许多应用程序中看到的一个常见模式是多租户。基本上,我在配置一个应用它的一些配置值根据国家不同而不同。我设法完成此配置的方法基本上是在yaml:
中使用"合作伙伴"字典。---
partners:
us:
url: 'http://company.com'
uk:
url: 'http://company.co.uk'
fr:
url: 'https://company.fr'
ch:
url: 'https://company.fr'
因此,当服务被识别为来自'us'的客户时,我们将为url使用一个值,如果应用程序将其识别为来自'fr',则该值将不同。
然后,在配置模板时,我做了类似的事情:
template: xxxx
with_items: partners_list
然后,在模板中我使用partners[item].url
来访问变量。因此,对于一个模板,我根据合作伙伴配置了具有不同值的多个文件。请注意,大多数值都是通用的(大多数配置不在伙伴字典中)。
这个不太令人满意。
我想要的是一个"动态变量"系统来实现类似于"上下文"的东西。例如,将上下文加载到主名称空间的简单且可移植的东西。所以一些东西允许我简单地引用"url",它会自动尝试使用partners[item].url
,如果它不在那里,使用普通的url
。
一个解决方案是使用partners[item].url | default(url)
,但这是非常冗长的,并导致一点混乱。我不想在模板中添加这么多杂乱的东西。
另一种可能是jinja中的"{% set_context 'us' %}" // "{% end_context %}"
,然后将字典中的变量与第一级变量重叠,并带有上下文。我想那样也会令人满意的。问题是,我可以扩展jinja的方式,可以放在我的仓库,而不需要触及每个人的可见/jinja安装?换句话说,我是否可以在ansible中选择另一个模板引擎,这样我就可以编写一个扩展的jinja(它能够查找变量)来供ansible使用?
您可以在Ansible库存中为每个"合作伙伴"创建一个组。并在组的group_vars中设置url变量。
IE groups_vars/uk_partner.yml:
name: uk
url: 'http://company.co.uk'
然后,您需要为每个组创建逻辑主机,并根据该主机列表运行您的游戏。
在inventory.yml:all:
children:
uk_partner:
hosts:
- uk-webserver
- uk-db-server
您还需要为这些逻辑主机在host_vars中硬编码ansible_host变量,或者为它们添加DNS名称。
IE in host_vars/uk-webserver.yml:
ansible_host: 192.0.2.4
然后在host_vars/us-webservers.yml中:
ansible_host: 192.0.2.4
(假设192.0.2.4是这些合作伙伴共享的web服务器地址)
在你的游戏中:
- hosts: "uk-webserver,us-webserver"
tasks:
- name: do webserver things to multiple partners
…
然后在你的模板中,你可以不加限定地引用{{url}},因为它将在每个组中适当地解析。
这些"partner"特定主机只是与这些伙伴关联的真实主机的逻辑迭代,而不管"伙伴"是否存在;与其他"伙伴"共享基础设施。
您可以手动将它们添加到您的库存中,或者如果由于合作伙伴和基础设施的规模而不切实际,则可以使用一个简单的动态库存脚本根据您的合作伙伴列表生成它们。在某些情况下,您还可以使用add_host模块来在play中生成它们。
请记住,当使用add_host时,必须显式地将主机添加到您希望它成为成员的每个组中。根据我的经验,当添加到子组时,它不会继承父组的成员关系。
如果您将您的伙伴字典更改为哈希列表,您可以完成您正在寻找的。这就是我在我支持的应用程序中实现多租户的方法。下面是示例的一种方法:
partners:
- name: us
url: 'http://company.com'
- name: uk
url: 'http://company.co.uk'
- name: fr
url: 'https://company.fr'
- name: ch
url: 'https://company.fr'
渲染模板:
template: xxxx
with_items: partners
现在你可以在你的模板中通过item.url
引用网站的url。