Module 是一个Terraform 模板,是对多个子节点,子资源,子架构模板的组合和抽象。利用Module 在降低模板编写和维护复杂度的同时,使得模板结构更加简洁清楚。为什么要使用 Module,详见文章 Module 让 Terraform 使用更简单
。
本文将根据自己对 Module 的理解,向大家讲解如何编写一个通用,标准的 Module。
建立 Module 的 Github 仓库
在 Terraform 官方注册 module,目前只支持 Github 的仓库,因此,在编写模板之前,必须先建立一个
标准的 Github 仓库:
- 仓库必须是 Public 的;
- 仓库名称必须符合格式:
,如terraform-<PROVIDER>-<NAME>
,terraform-alicloud-ecs-instance
等terraform-alicloud-vpc
- 仓库建好后必须给仓库添加一个描述
为了更好的管理所有阿里云的terraform module,现在所有的仓库都建在组织
terraform-alicloud-modules
下。当有新建仓库需求时,可联系负责人。
编写Module
Module 仓库建立完毕后,首先要 fork 仓库并将其clone到本地。接下来,开始 Mudole 的编写工作。官方已经给出了一个标准的 Module 应该遵循的原则和规范,详见
standard-module-structure. 本文将在此基础上进行补充。
- 基本原则
- 每个Module不宜包含过多的资源,要尽可能只包含同一产品的相关资源,这样带来的好处是Module的复杂度不高,便于维护和阅读;
- 对于统一产品的不同资源,应该分别放在不同的子module中,然后在最外层的main.tf中组织所有的子资源,比如 module slb 中定义了两个资源
和slb instance
,这两个子资源分别定义在了slb attachment
modules/slb
中,然后在最外层的modules/slb_attachment
中将这两个module组合为一个新的modulemain.tf
- 每个module要尽可能单元化,以便可以在实际使用过程中自由添加和删除而不影响其他resource。即一个module尽可能叙述1-2件事情,如创建一个slb实例,并将一组ecs的挂载到这个slb下(slb的作用就是实现对ecs的负载均衡),至于slb的listener配置,应该放置在一个独立的mudule中,一方面listeners比较复杂,涉及四种协议,另一方面,对于同一协议的listener,除了监听端口外,大部分的配置都是相同的,而这些相同的配置可以通过一个单独的module被复用在不同其他资源模板中;
- 模板编写过程中,需要使用到大量的TF语法,详见 configuration syntax interpolation syntax
- main.tf
- 每个 Module 都必须包含一个 main.tf 用于存放 resource 和 datasource。resource和datasource的参数禁止使用硬编码,必须通过变量进行引用;
- 为了标准起见,每个 resource 和 data source 的命名均以一些关键字或者关键字前缀为主,如
this
,尽量避免使用default
foo
test
- 为了更好的了解Module被他人引用的次数,阿里云Provider支持对每个Module进行打标,即在main.tf的provider中声明字段configuration_source,格式如下:
provider "alicloud" { ... configuration_source = "terraform-alicloud-modules/demo" // This should be replaced by the specified owner and module name }
- variables.tf
- 每个变量都要添加该参数对应的描述信息,这个信息最终是要呈现在terraform registry官网上的;
- 对于一些非关系型的参数,可设置一个默认值,如name,description等
- 对于复杂类型的变量,要显示声明其类型,如list,map
- 子资源的变量要在Readme中以列表的形式予以呈现
- outputs.tf
- module中output的作用是被其他模板和module引用,因此,每个module要讲一些重要的信息输出出来,如资源ID,资源name 等;
- 重复资源的变量要以列表的形式予以输出,如module ecs-instance中,创建多个instance资源,这些资源的ID应该输出到一个list变量
中instance_ids
- 和variables一样,子资源的output变量也要在Readme中以列表的形式予以呈现
- README
- 描述下当前Module是用来干什么的,涉及哪些resource和data source
- 增加
,指明该如何使用这个 Module。Module 的source 格式为Usage
,如:source = "<Repo Organization>/<NAME>/alicloud"
source = "terraform-alicloud-modules/slb-listener/alicloud"
- 添加module暴露的入参和出参,帮助开发者更好的使用Module
- 具体细节可参考其他module
为了更好地编写Module,阿里云提供了一个
Module Demo,大家可以参考。
测试并发布
在完成模板的编写后,可以通过
terratest来实现对当前Module的验证性测试。测试无误后,提交代码到github。
如果想要把Module提交到阿里云官方组织
terraform-alicloud-modules,可直接在下方留言或者发邮件到 [email protected] 进行申请。申请通过后,我将为大家新建一个属于自己的Repo。每个贡献Module的开发者都将有机会成为terraform-alicloud-modules members中的一员。
由于Terraform Module 是以 Repo releases 来实现版本控制的,因此在确定代码无误后,包括Readme,发布一个新的Release。之后在terraform module 注册和完成module的发布,具体操作详见
registry modules.