Fleet Terraform 模块:用 BYO 分层架构把 Fleet 部署到 AWS
【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet
本文围绕 Fleet 官方的 Terraform 部署模块展开:解释为什么 Fleet 把 AWS 部署方式从"照搬 Dogfood 环境代码"改为"发布带语义化版本号的 Terraform 模块",完整介绍模块的 BYO-Nothing → BYO-VPC → BYO-Database → BYO-ECS 分层设计、fleet_config对象型变量的全部字段与默认值,并结合当前仓库中的 Dogfood 基础设施代码(infrastructure/dogfood/terraform/aws-tf-module/main.tf)与 BYO-VPC 实例(infrastructure/dogfood/terraform/aws-tf-module/free.tf),给出可直接参考的部署与演进路径。
为什么放弃"直接复用 Dogfood 代码"
在 Terraform 模块出现之前,Fleet 团队自己(Dogfood 环境)的 Terraform 代码是 AWS 部署的主要参考样本。仓库中这份代码至今仍然存在,即 infrastructure/dogfood/terraform/aws-tf-module/main.tf,它完整地描述了 Fleet 生产级部署所需的 ACM 证书、RDS 参数、ECS 集群、日志投递等一整套资源。但官方明确给出三点原因,说明这段代码并不适合被外部团队直接拿来用于生产部署:
- Dogfood 代码本意不是生产模板。为了在不破坏他人部署的前提下测试新特性,Dogfood 代码中夹带了额外资源,这些维护成本本可以投入到其他改进上。
- 没有可观测的用户面。因为不预期别人使用 Dogfood 代码,团队没有任何手段知道谁拿它做了生产部署,也就无从在破坏性变更前通知用户。
- 需要一个既能快速迭代、又方便部署到各种独特环境的方案——这正是 Terraform 模块(module)的经典解决场景:模块提供精简的接口,团队可以用极少的代码把 Fleet 尽快部署到 AWS,并随着 Fleet 的演进而持续更新环境。
模块设计:最小安装 + 逐层放权
官方模块的设计目标有两条:
- 基本安装必须足够简单。如果要用一个模块,却必须传入每个参数才能工作,那这个模块就失去了意义。根模块(root module)以默认值覆盖绝大多数场景,只把真正必须外部提供的资源(如 ACM 证书)作为入参。
- 必须足够灵活,能支撑所有需求。实现方式是"模块中嵌套模块":最外层模块负责把 Fleet 尽快跑起来,内层模块则提供对 Fleet 安装方式的逐层控制。
这让小型团队可以零定制地部署 Fleet,而大型组织可以传入变量来为特定部门构建 RDS 数据库、复用既有 VPC 等。无论哪种用法,升级基础设施都很简单——拉取模块的新版本并 apply 即可。同时,语义化版本(semantic versioning)让 Fleet 团队能够清晰地标注每一次变更,改变了此前"不知道谁在用 Dogfood 代码、无法通知"的困境。
BYO 分层:从 BYO-Nothing 到 BYO-ECS
模块按"逐层 Bring Your Own(自带资源)"的程度排布,从 BYO-Nothing(根模块,全部资源由模块创建)一路到 BYO-ECS(最底层,连 ECS 集群都由调用方提供):
- BYO-Nothing - BYO-VPC - BYO-Database - BYO-ECS你可以按部署环境自由选择 BYO 层级。这一分层在当前仓库的 Dogfood 代码中有直接的源码级印证——从源码结构看,Dogfood 根模块通过嵌套输出路径逐层访问内层资源(见 main.tf):
alias { name = module.main.byo-vpc.byo-db.alb.lb_dns_name zone_id = module.main.byo-vpc.byo-db.alb.lb_zone_id }以及 ECS 侧的输出(见 main.tf):
ecs_cluster = module.main.byo-vpc.byo-db.byo-ecs.service.cluster task_definition = module.main.byo-vpc.byo-db.byo-ecs.task_definition.family min_capacity = module.main.byo-vpc.byo-db.byo-ecs.appautoscaling_target.min_capacity max_capacity = module.main.byo-vpc.byo-db.byo-ecs.appautoscaling_target.max_capacitybyo-vpc.byo-db.byo-ecs这条输出链恰好对应 BYO-VPC → BYO-Database → BYO-ECS 的模块嵌套结构:外层模块把 ALB、RDS 集群、ECS 服务这些内层资源"逐层透传"出来,调用方无需了解内部细节,也能按需在任意层级替换为自己提供的资源。
模块生命周期:用对象型变量实现"后期自定义"
另一个必须考虑的问题是模块生命周期:你可能先以 BYO-Nothing 级别安装,之后又决定定制模块内部。为了让"从全托管走向自定义"成为平滑演进而不是推倒重来,模块把变量设计成对象(object)类型——这些对象一路暴露到根层级,无论部署时处于哪个 BYO 层级,都可以完全自定义内部资源。相比一长串扁平变量,对象变量也更组织化、更可读。
原文档给出的fleet_config变量完整定义如下(这是模块 2023 年发布时的接口形态):
variable "fleet_config" { type = object({ mem = optional(number, 512) cpu = optional(number, 256) image = optional(string, "fleetdm/fleet:v4.22.1") extra_environment_variables = optional(map(string), {}) extra_secrets = optional(map(string), {}) security_groups = optional(list(string), null) iam_role_arn = optional(string, null) database = object({ password_secret_arn = string user = string database = string address = string rr_address = optional(string, null) }) redis = object({ address = string use_tls = optional(bool, true) }) awslogs = optional(object({ name = optional(string, null) region = optional(string, null) prefix = optional(string, "fleet") retention = optional(number, 5) }), { name = null region = null prefix = "fleet" retention = 5 }) loadbalancer = object({ arn = string }) networking = object({ subnets = list(string) security_groups = optional(list(string), null) }) autoscaling = optional(object({ max_capacity = optional(number, 5) min_capacity = optional(number, 1) memory_tracking_target_value = optional(number, 80) cpu_tracking_target_value = optional(number, 80) }), { max_capacity = 5 min_capacity = 1 memory_tracking_target_value = 80 cpu_tracking_target_value = 80 }) }) default = { mem = 512 cpu = 256 image = "fleetdm/fleet:v4.22.1" extra_environment_variables = {} extra_secrets = {} security_groups = null iam_role_arn = null database = { password_secret_arn = null user = null database = null address = null rr_address = null } redis = { address = null use_tls = true } awslogs = { name = null region = null prefix = "fleet" retention = 5 } loadbalancer = { arn = null } networking = { subnets = null security_groups = null } autoscaling = { max_capacity = 5 min_capacity = 1 memory_tracking_target_value = 80 cpu_tracking_target_value = 80 } } description = "The configuration object for Fleet itself. Fields that default to null will have their respective resources created if not specified." nullable = false }各字段的关键默认值一览:
| 字段 | 默认值 | 说明 |
|---|---|---|
mem/cpu | 512/256 | Fleet 容器的内存(MiB)与 CPU 配额(AWS 单位),即最简部署仅需 0.25 vCPU / 0.5 GiB |
image | fleetdm/fleet:v4.22.1 | 发布时默认的 Fleet 容器镜像版本 |
extra_environment_variables/extra_secrets | {} | 附加环境变量与 Secrets Manager ARN 透传,用于接入监控、授权等集成 |
database/redis/loadbalancer/networking | 默认null | 声明为必填子字段但默认值为null;按变量描述,默认值为 null 的字段会在未指定时由模块创建对应资源——这就是"BYO 层级可选"的实现机制 |
database.rr_address | null | 可选的读副本地址,Fleet 支持把只读查询分流到 RDS 读副本 |
awslogs | 前缀fleet、保留 5 天 | CloudWatch 日志组配置 |
autoscaling | 最小 1、最大 5,CPU/内存目标 80% | ECS 应用自动伸缩(Application Auto Scaling)参数 |
从当前仓库 Dogfood 的实际用法可以推断该对象接口在后续版本中的演进方向:Dogfood 的fleet_config在保留image、cpu、mem、autoscaling、awslogs的同时,还加入了family(任务定义族名)、task_cpu/task_mem(任务级预留资源)、pid_mode、iam(角色与执行角色命名)以及extra_iam_policies/extra_execution_iam_policies等字段(见 main.tf),说明对象型接口让模块可以在不破坏根层级调用方式的前提下持续扩展能力——这正是变量采用对象形态的收益。
最小部署示例
以下是模块发布时给出的最小可用示例:一个 ACM 证书、根模块、一条 Route 53 别名记录,即可让 Fleet 在 AWS 上运行:
module "main" { source = "git::https://github.com/fleetdm/fleet.git//terraform/" certificate_arn = module.acm.acm_certificate_arn } module "acm" { source = "terraform-aws-modules/acm/aws" version = "4.3.1" domain_name = "fleet.loadtest.fleetdm.com" zone_id = data.aws_route53_zone.main.id wait_for_validation = true } resource "aws_route53_record" "main" { zone_id = data.aws_route53_zone.main.id name = "fleet.loadtest.fleetdm.com" type = "A" alias { name = module.main.byo-vpc.byo-db.alb.lb_dns_name zone_id = module.main.byo-vpc.byo-db.alb.lb_zone_id evaluate_target_health = true } } data "aws_route53_zone" "main" { name = "loadtest.fleetdm.com." private_zone = false }从这份代码可以读出模块接口的几个要点:
- 唯一必填入参是
certificate_arn。VPC、RDS、ElastiCache、ECS、ALB 全部由模块内部按 BYO 层级自动创建,这对应"基本安装必须足够简单"的设计目标。 - DNS 接入靠 ALB 输出。模块把 ALB 的
lb_dns_name与lb_zone_id从byo-vpc.byo-db层级透出,调用方据此创建 Route 53 别名记录(evaluate_target_health = true开启目标健康检查)。Dogfood 环境正是这样接入的(main.tf)。
可以从这个最小代码出发按需扩展:在旁边添加额外资源,或者为规模化部署细化安装参数。完整变量清单可参考仓库中的 terraform/README.md。
仓库内的进阶用法:BYO-VPC 与多环境共存
"大型组织为不同部门定制"并非纸面描述。Dogfood 环境在同一份 Terraform 中部署了两套 Fleet 实例来验证不同层级:
- 根模块(BYO-Nothing):
module "main"创建 VPC、Aurora MySQL(8.0.mysql_aurora.3.10.3,require_secure_transport = "ON"强制 TLS)、ElastiCache Redis 7.1、ECS 集群与 ALB(main.tf); - BYO-VPC 实例:
module "free"直接引用byo-vpc子模块(free.tf),通过vpc_config.networking.subnets = module.main.vpc.private_subnets复用根模块创建的 VPC 子网,自建独立的 RDS 快照恢复集群与 Redis 集群——这正是"同一 VPC 内为特定环境/部门独立建库"的典型场景; - ECS 主机挂载:部署好的 ECS 服务再被复用为免费套餐测试主机的载体,通过
module.free.byo-db.byo-ecs.service的 cluster、subnets、security_groups 输出创建配套任务(free-ecs-hosts.tf)。
另外可以注意到模块引用的语义化版本 ref:根模块使用tf-mod-root-v1.30.0、BYO-VPC 子模块使用tf-mod-byo-vpc-v1.31.0(free.tf),印证了"用语义化版本清晰标注变更"的说法——不同 BYO 层级模块可以独立发版,调用方按需锁定。
当前状态:模块已迁移至独立仓库
需要说明一个时效性前提:原文档发表于 2023 年 1 月,彼时模块位于主仓库terraform/目录。当前仓库中该目录已变成迁移说明文件,terraform/README.md 明确写道:Fleet Terraform 模块已迁移至独立的fleetdm/fleet-terraform仓库,所有旧版本模块的 tag 仍可按名称版本查到,可以用如下命令在仓库中检索:
git tag | grep tf-mod因此按本文实操时:
- 新部署请从
fleetdm/fleet-terraform仓库获取模块(Dogfood 代码中的tf-mod-root-*、tf-mod-byo-vpc-*版本 ref 可作为可用的命名参照,见 main.tf 与 free.tf); - 仍在使用旧版 ref 的部署可继续锁定
tf-mod-*历史版本,避免破坏性变更; - 无论哪种方式,升级路径一致:拉取模块新版本、锁定新的
tf-mod-ref、terraform apply,模块的语义化版本号会明确告诉你跨了什么级别的变更。
小结
Fleet 的 Terraform 模块把"照抄内部 Dogfood 代码"升级为"面向生产的版本化基础设施组件":根模块以最少入参(一个证书 ARN)完成 BYO-Nothing 部署;BYO-VPC / BYO-Database / BYO-ECS 三级内嵌模块支持按环境自选托管边界;对象型fleet_config变量把内部资源配置一路暴露到根层级,使部署方式可以从全托管平滑演进到深度自定义。仓库中的 Dogfood 基础设施(infrastructure/dogfood/terraform/aws-tf-module/)既是这一分层结构的活体示例,也是理解各 BYO 层级输出与集成方式的现成参考。
【免费下载链接】fleetOpen device management项目地址: https://gitcode.com/GitHub_Trending/fl/fleet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考