Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
有关Terraform代码结构的问题是社区中迄今为止最常见的问题。 每个人都在某个时候考虑过项目的最佳代码结构。
这是一个有很多解决方案的问题之一,很难给出通用的建议,所以让我们从理解我们正在处理什么开始。
你的项目有多复杂?
相关resources(资源)数量
Terraform 提供商的数量(参见下面关于“逻辑提供者”的注释)
你的基础架构多久更改一次?
从每月/每周/每天一次
到连续(每次有新提交时)
代码更改发起者? 当一个新的artifact(构件)生成时,是否让 CI 服务器更新存储库?
只有开发人员可以推送到基础架构存储库
每个人都可以通过打开 PR(包括在 CI 服务器上运行的自动化任务)来提出对任何事物的更改
你使用哪种部署平台或部署服务?
AWS CodeDeploy、Kubernetes 或 OpenShift 需要稍微不同的方法
环境如何分组?
按环境、地区、项目
当开始或编写示例代码时,将所有代码放在 main.tf
中是一个好主意。 在所有其他情况下,最好将多个文件按逻辑拆分,如下所示:
main.tf
- 调用modules(模块)、locals(本地)和data sources(数据源)来创建所有资源
variables.tf
- 包含在main.tf
中使用的变量声明
outputs.tf
- 包含在 main.tf
中创建的资源的输出
versions.tf
- 包含 Terraform 和提供商的版本要求
terraform.tfvars
不应在除composition(组合)之外的任何地方使用。
请确保您了解核心概念 - resource module(资源模块),infrastructure module(基础设施模块),和 composition(组合), 因为它们在以下示例中使用。
使用更少的资源可以更轻松、更快速地进行工作
terraform plan
和 terraform apply
都调用 cloud API 来验证资源状态
如果你的整个基础设施都在一个组合中,这可能需要一些时间
资源越少,爆炸半径(A blast radius)就越小
通过将不相关的资源放置在单独的组合中以进行隔离,可以降低如果出现问题时的风险
使用远程状态启动您的项目,因为:
你的笔记本电脑不是基础设施代码真实来源的合适位置
在 git 中管理tfstate
文件是一场噩梦
当基础设施层开始朝多个方向(依赖项或资源数量)增长时,将更容易控制事物
实践一致的结构和 naming convention(命名约定):
与procedural code(过程式代码)一样,Terraform 代码应该首先编写供人们阅读。当六个月后发生变化时,一致性将有所帮助
可以在 Terraform 状态文件中移动资源,但如果结构和命名不一致,则可能更难做到
保持资源模块尽可能简单
不要将可以作为变量传递或使用数据源(data sources)发现的值硬编码
专门使用data sources(数据源)和terraform_remote_state
作为composition(组合)中基础设施模块之间的粘合剂
在本书中,示例项目按复杂性分组 —— 从小型到超大型基础设施。这种分离并不严格,因此还要检查其他结构。
拥有小型基础设施意味着存在少量依赖项和资源。 随着项目的增长,链接 Terraform 配置的执行、连接不同的基础设施模块以及在组合中传递值的需求变得显而易见。
开发人员使用的编排解决方案至少有5个不同的群体:
仅限Terraform。 非常简单,开发人员只需了解 Terraform 即可完成工作。
Terragrunt。 纯编排工具,可用于编排整个基础架构以及处理依赖项。 Terragrunt 原生地操作基础设施模块和组合,因此它减少了代码重复。
In-house scripts(内部脚本)。 通常,这发生在编排的起点和发现 Terragrunt 之前。
Ansible 或类似的通用自动化工具。通常在 Ansible 之后采用 Terraform 时使用,或者在积极使用 Ansible UI 时使用。
Crossplane 和其他受 Kubernetes 启发的解决方案。有时,利用 Kubernetes 生态系统并采用reconciliation loop(协调循环)功能来实现 Terraform 配置的所需状态是有意义的。 观看视频Crossplane vs Terraform了解更多信息。
考虑到这一点,本书回顾了这些项目结构中的前两个,即仅使用Terraform和Terragrunt。
请参阅下一章中 Terraform 或 Terragrunt 的代码结构示例。
来源: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/large-terraform
此示例包含的代码作为为大型基础设施构建 Terraform 配置的示例,该基础设施使用:
2个AWS账户
2个地区
2 个独立的环境(prod
和 stage
什么都不共享)。 每个环境都位于一个单独的 AWS 账户中,并跨越 2 个区域之间的资源
每个环境都使用来自 Terraform Registry 的不同版本的现成基础设施模块 (alb
)
每个环境都使用相同版本的内部模块modules/network
,因为它来自本地目录
在此处描述的大型项目中,使用 Terragrunt 的好处变得非常明显。请参阅Code Structures examples with Terragrunt。
非常适合基础设施在逻辑上分离的项目(单独的 AWS 账户)
适合不需要修改 AWS 账户之间共享的资源(一个环境 = 一个 AWS 账户 = 一个状态文件)
适合不需要编排环境之间的变化
适合基础设施资源因环境而异且无法一概而论时(例如,在一个环境或某些地区缺少某些资源)
随着项目的增长,让这些环境彼此保持最新状态将变得更加困难。 考虑使用基础设施模块(现成的或内部的)来完成可重复的任务。
来源: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/medium-terraform
此示例包含的代码作为为中型基础设施构建 Terraform 配置的示例,该基础设施使用:
2个AWS账户
2 个独立的环境 (prod
和 stage
什么都不共享),每个环境都位于一个单独的 AWS 账户中
每个环境都使用来自 Terraform Registry 的不同版本的现成基础设施模块 (alb
)
每个环境都使用相同版本的内部模块modules/network
,因为它来自本地目录
非常适合基础设施在逻辑上分离的项目(单独的 AWS 账户)
适合不需要修改 AWS 账户之间共享的资源(一个环境 = 一个 AWS 账户 = 一个状态文件)
适合不需要编排环境之间的变化
适合基础设施资源因环境而异且无法一概而论时(例如,在一个环境或某些地区缺少某些资源)
随着项目的增长,让这些环境彼此保持最新状态将变得更加困难。考虑使用基础设施模块(现成的或内部的)来完成可重复的任务。
有很多人创建了很棒的内容并管理了与 Terraform 社区相关的开源项目,但我想不出最好的结构来在不复制像 awesome-terraform 这样的列表的情况下列出这些链接。
https://twitter.com/antonbabenko/lists/terraform-experts - 非常积极地使用 Terraform 并且可以告诉你很多(如果你问他们的话)的人的名单。
https://github.com/shuaibiyy/awesome-terraform - HashiCorp 的 Terraform 上精选的资源列表。
http://bit.ly/terraform-youtube - Anton Babenko 的YouTube 频道“Your Weekly Dose of Terraform”,包含评论、采访、问答、实时编码和一些使用 Terraform 的黑客技术的直播。
https://weekly.tf - Terraform 每周时事通讯。 Terraform 世界中的各种新闻(项目、公告、讨论),由 Anton Babenko 撰写。
来源: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/small-terraform
此示例包含的代码作为为小型基础设施构建 Terraform 配置的示例,其中不使用外部依赖项。
非常适合入门和按需重构
非常适合小型资源模块
适用于小型和线性基础设施模块(例如,terraform-aws-atlantis)
适用于少量资源(少于 20-30)
如果资源数量不断增加,所有资源的单一状态文件会使使用 Terraform 的过程变慢(考虑使用参数 -target
来限制资源数量)
至少应该没有理由不遵循这些约定 :)
请注意,实际的云资源通常对允许的名称有限制。 例如,有些资源不能包含破折号,有些资源必须采用驼峰式大小写。 本书中的约定指的是 Terraform 名称本身。
在任何地方(资源名称、数据源名称、变量名称、输出等)使用 _
(下划线) 而不是 -
(破折号)。
非常适合使用小写字母和数字(即使支持 UTF-8)。
不要在资源名称中重复资源类型(既不要部分,更不要完全):
resource "aws_route_table" "public" {}
resource "aws_route_table" "public_route_table" {}
resource "aws_route_table" "public_aws_route_table" {}
如果没有更多的描述性和通用名称可用,或者如果资源模块创建这种类型的单个资源,资源名称应该被命名为