导航指南:模块化基础架构配置
注意:这是《导航指南》内容的早期版本,由 DigitalOcean 解决方案工程师提供。 本书的目标是帮助企业客户规划他们的基础设施需求,提供沿途的工作示例,并包括技术细微差别和使某些决策比其他决策更好的“原因”。
这本书和随附的代码将在 GitHub 存储库中公开提供。 因为这是一个早期版本,所以这本书还没有完成,存储库还没有公开,但请继续关注!
上一节使用 Terraform 和 Ansible 来配置资源(Droplet、负载均衡器和浮动 IP)并部署您的 WordPress 应用程序。
Terraform 使用 main.tf
文件创建了这些资源。 目前,该文件中的所有资源都单独列出。 你的环境越复杂,你需要的资源就越多,这个文件就会变得越长越复杂。 从长远来看,这将使您的配置更难管理。
在本补充部分中,我们将讨论一些使用 Terraform 模块和单独的基础设施环境来简化此配置的方法。 本节无需执行任何代码,也无需进行任何更改,但这些概念在构建实际设置时很重要。
了解 Terraform 模块
要使用 Terraform 自己的模块描述:
Terraform 中的模块是作为一个组进行管理的 Terraform 配置的独立包。 模块用于在 Terraform 中创建可重用组件以及基本代码组织。
模块创建可重用基础设施块,可以接受输入并提供输出,就像高级编程语言中的函数一样。 我们可以为类似的基础设施创建接受可选输入参数的模块,并为这些输入参数设置默认值。 这有助于组织和简化您的配置。 您可以在 Terraform 的模块文档 中了解有关模块的更多信息。
有关完整的示例,请查看 main.tf
文件。 最后一部分实际上已经在使用 Terraform 模块:
module "sippin_db" { source = "github.com/cmndrsp0ck/galera-tf-mod.git?ref=v1.0.6" ... }
您可以将此部分与文件顶部的 wp_node
的资源块进行比较,它有更多的代码行并且更难理解。 您会注意到该模块是使用远程 git 存储库调用的。 您可以使用本地文件路径,这可以用于一些快速的开发和测试,但使用远程 git 存储库会使您的环境隔离更进一步。 这在运行多个基础架构环境(如登台和生产)时特别有用。 当在多个基础设施环境中使用本地文件路径时,您最终可能会进行旨在仅影响暂存的更改,但如果您要在 prod 上运行应用程序并且正在共享模块文件路径,那么您最终可能会破坏某些东西。 如果您对每个环境都有专门的目录,那么您最终不得不维护两个或多个脚本副本,并且恢复到以前的状态不会那么容易。
使用远程 git 存储库并为模块指定版本号可以避免这个问题。 如前所述,如果出现问题,它还可以更轻松地恢复到已知的工作版本,从而提高您管理事件和中断的能力(我们将在第 9 章中详细介绍)。
这个模块不仅仅是创建一个 Droplet。 它创建 Droplet 标签、Galera 集群节点、负载均衡器和浮动 IP。 您可以将 terraform 模块视为打包/或整个服务的组件的好方法。 这也意味着您可以向模块添加更多资源,或者您可以创建模块输出,这些输出又可以用作您可能正在开发的另一个模块的输入。 当创建新模块有意义时,例如添加新服务或您想要解耦的某些支持功能,您绝对可以在模块中创建输出,它们将作为您的状态的一部分存储。 如果您使用远程状态,当您想要在基础架构的不同组件之间共享只读信息或提供外部服务以检索它可能需要的信息时,模块输出可能非常有用。
简而言之,如果您将 Terraform 计划中的资源部分视为乐高积木,那么您的模块将是预组装的部分。 这比必须到处追踪乐高积木并可能踩到一块要好得多。 除了帮助防止这种痛苦之外,这些模块还可用于在您增加基础架构计划的复杂性时通知其他模块的配置。
设置基础设施环境
在大多数专业项目中,您将使用三种不同的环境:开发、登台和生产。
您的开发环境通常是本地的,并为您提供了在工作时独立修补和测试的空间。 另一方面,您的登台和生产环境将位于共享或公共空间中,并将使用 Terraform 等自动化流程进行配置。
从一个深思熟虑和有计划的部署工作流程开始将大大有助于防止头痛,其中一部分包括将环境彼此隔离。 Terraform 的工作空间功能使 terraform.tfstate
文件在每个环境中都是分开的,但对描述资源的 terraform 文件所做的更改则不会。 因此,虽然此功能作为一种快速进行小更改、测试和部署的方法可能非常有效,但当您有可能需要将服务彼此以及团队隔离的较大部署时,不应该依赖它管理他们。
这是一个示例目录树,描述了如何使用目录设置环境隔离:
. ├── ansible.cfg ├── bin/ ├── environments/ │ ├── config/ │ │ └── cloud-config.yaml │ │ │ ├── dev/ │ ├── prod/ │ │ ├── config -> ../config │ │ ├── group_vars │ │ ├── host_vars │ │ ├── main.tf │ │ ├── terraform.tfvars │ │ ├── terraform-inventory -> ../terraform-inventory │ │ └── variables.tf │ │ │ ├── staging/ │ │ ├── config -> ../config │ │ ├── group_vars │ │ ├── host_vars │ │ ├── main.tf │ │ ├── terraform.tfvars │ │ ├── terraform-inventory -> ../terraform-inventory │ │ └── variables.tf │ │ │ └── terraform-inventory │ ├── site.yml ├── wordpress.yml │ └── roles/
这种布局背后的关键逻辑是将与类似组件相关的文件保持在不同的环境中,彼此分开。
例如,在 environments
目录中,我们为我们想要的三个环境中的每一个都有一个子目录:dev
、staging
和 prod
。 这种隔离有助于防止意外在错误的位置运行 Ansible 或 Terraform 脚本。 您可以更进一步,使用另一层子目录来保存每个环境基础架构不同部分的文件。
有许多关于这个话题的精彩文章网上,其中一本居然变成了书 Terraform:启动并运行由叶夫根尼布里克曼。
对环境使用模块版本控制
Terraform 模块还可以帮助您在不影响其他环境的情况下进行更改。 例如,看看这两个模块。
一个用于暂存环境(例如,staging/main.tf
):
module "sippin_db" { source = "github.com/cmndrsp0ck/galera-tf-mod.git?ref=v1.0.8" project = "${var.project}" region = "${var.region}" keys = "${var.keys}" private_key_path = "${var.private_key_path}" ssh_fingerprint = "${var.ssh_fingerprint}" public_key = "${var.public_key}" ansible_user = "${var.ansible_user}" }
一个用于生产环境(例如,prod/main.tf
):
module "sippin_db" { source = "github.com/cmndrsp0ck/galera-tf-mod.git?ref=v1.0.6" project = "${var.project}" region = "${var.region}" keys = "${var.keys}" private_key_path = "${var.private_key_path}" ssh_fingerprint = "${var.ssh_fingerprint}" public_key = "${var.public_key}" ansible_user = "${var.ansible_user}" }
它们之间的唯一区别是 source
行末尾的 ref
键的值,它指定要部署的版本。 暂存时为 v1.0.8
,生产时为 v1.0.6
。 使用版本控制,您可以在部署到生产之前在暂存中进行和测试更改,并且像这样的设置简化了支持它的配置。
现在,上一节中的动手设置不使用远程状态。 在第 6 章中,我们介绍了如何使用远程状态后端(如 Consul),这在团队工作时很关键。 如果没有远程状态后端,您和其他团队成员都可能同时对基础架构执行更改,从而导致冲突、中断或损坏您的状态文件。
下一步是什么?
一旦您了解了如何通过模块化来简化基础架构代码以及如何隔离环境以实现更安全的开发和部署,我们就可以了解如何通过创建模板来提高部署速度。 下一章将介绍如何使用持续开发工具自动化部署工作流程,这将帮助您安全快速地部署新代码。