
用Ansible角色配置验证功能
AEM OpenCloud是一个开源的平台,用于在AWS云上托管Adobe Experience Manager(AEM)。它的配置过程主要由Ansibleplaybooks驱动,YAML配置文件包含100多个参数。它是高度可配置的,但这种可配置性意味着有很多参数需要正确处理,也有很多机会出现打错和使用不支持的值。这些都会导致堆栈创建失败,以及冗长的周转时间,等待失败后的资源清理。我们可以通过采取快速失败的方法来节省时间,在承诺提供资源之前验证参数。
为了尽早发现有问题的变量,我开发了一个Ansible角色,用Cerberus来验证基于模式的配置。Cerberus是 "一个轻量级和可扩展的Python数据验证库"。这个Ansible角色可以在游戏手册的开头执行,以确保只使用经过验证的值。
在这篇文章中,我将介绍一个自定义的Ansible角色,名为**vars_schema_validator**,用于根据特定规则和限制来验证参数值。vars_schema_validator的用户必须在playbook任务中提供一个正确的YAML模式文件路径;我们已经为AEM OpenCloud创建了一个合适的模式,但这个角色不限于此。下图是利用Ansible与变量验证器角色的AWS部署的系统架构。
图1.系统结构
1 背景
在深入了解细节之前,让我们先从两个关键概念开始。
1.1 什么是Ansible角色?
角色是Ansible的一个强大的功能,有利于配置的重复使用和模块化。一个角色通常包含一组变量、任务、文件和处理程序,具有标准化的文件结构。它是一个类似于Puppet Modules的概念。像Python包一样,在使用它们之前,你需要运行安装。Ansible Roles可以由Ansible Galaxy管理。使用ansible-galaxy install <the name of role> 命令,从Galaxy服务器下载角色。
安装完所有需要的角色后,你就可以把它们包含在任何playbook项目中。默认情况下,Ansible会在相对于playbook文件的roles/ 目录中和/etc/ansible/roles 中搜索角色。在Ansible 1.4及以后的版本中,你可以配置一个额外的role_path 来搜索角色。更多细节请参考角色搜索路径。
一个示例性的游戏手册如下所示。角色在依次运行的任务之前被执行。
---
- name: Playbook example
hosts: localhost
roles:
- role: '/path/to/your/role'
tasks:
- debug: msg=hello
1.2 什么是验证模式?
验证模式是一个YAML文件,定义了所有参数的名称和它们的值必须遵循的规则。YAML 模式必须满足 Cerberus 中定义的验证规则。例如,如果一个系统只支持Redhat 7和Centos 7操作系统,那么os_type 参数的模式可以是。
os_type:
type: string
allowed:
- rhel7
- centos7
2 使用Validator验证配置
本节通过一个例子展示了设置环境和在playbook中使用验证器的步骤。以下是vars_schema_validator支持的一些关键功能。
- 支持Ansible 2、3和4
- 支持通过自定义关键字进行验证模式引用
!include
2.1 安装
- 通过运行安装所需的python包。
$ pip install cerberus==1.3.2
$ pip install ansible==4.0.0
- 通过运行来安装vars_schema_validator角色。
$ ansible-galaxy install shinesolutions_opensource.vars_schema_validator
2.2 使用方法
将该角色添加到playbook中,并指定验证器将在哪里找到它要使用的模式。
roles:
- role: 'shinesolutions_opensource.vars_schema_validator'
vars:
schema: 'path/to/your/schema.yaml'
2.3 示例
让我们看看如何使用vars_schema_validator来验证一个简单的YAML配置文件,我们将其称为vars.yaml 。
---
global:
name: Little Joe
age: 15
group1:
os_type: windows
url: s3://xxx.xxx.xxx.xxx/xxxxxxx
jvm_mem_opts: -Xms4096m
user: admin
为了验证这个配置,我们需要一个模式。好的做法是以模块化的方式创建我们的模式,这样我们就可以重复使用它们。在这个例子中,我们将通过把group1 的模式分割成第二个文件来证明这一点。首先,我们在schema.yaml 中创建我们的顶层。
---
global:
type: dict
required: true
allow_unknown: false
empty: false
schema:
name:
type: string
age:
type: integer
min: 10
max: 20
group1:
required: true
schema: !include sub_schema.yaml
然后我们需要定义sub_schema.yaml 来描述group1 。
---
os_type:
type: string
allowed:
- rhel7
- amazon-linux2
- centos7
url:
type: string
regex: (s3://|http://|https://|file://)(.+)
jvm_mem_opts:
type: string
allowed:
- -Xss4m
- -Xms4096m
- -Xmx8192m
user:
type: string
forbidden:
- root
- admin
为了运行我们的例子验证,我们需要一个playbook,所以我们将创建playbook.yml ,加载vars.yaml 文件,并使用我们上面创建的schema.yaml 的角色。
---
- name: Test vars-schema-validator
hosts: localhost
vars_files:
- ./vars.yaml
roles:
- role: 'vars_schema_validator'
vars:
schema: './schema.yaml'
现在我们可以通过运行playbook.yml看到我们简单例子的结果。
$ ansible-playbook playbook.yml
验证器没有通过这个配置,并告诉我们问题出在哪里。
TASK [vars_schema_validator : Validate Ansible variables using the provided YAML schema] ***
fatal: [localhost]: FAILED! => changed=false
msg:
global:
- group1:
- os_type:
- unallowed value windows
user:
- unallowed value admin
有两个变量违反了规则。一个使用了一个不在允许列表中的值。另一个使用了一个被禁止的值。
3 结论
vars-schema-validator对于确保你的playbook在运行时配置满足指定的模式是非常有用的。你可以通过艰苦的方式发现这些错误,运行游戏手册,配置失败,并在资源清理完成后再次尝试,但这更快。模式还可以帮助诊断,显示可接受的值、不可接受的值、甚至可接受值的模式的列表。模式对开发者来说是自带文档的,这有助于在模式处于源控制中时跟踪系统的变化。
