news 2026/10/10 5:08:58

Cloudflare Terraform 实战模式:用 autoskills 的 cloudflare-deploy 技能搭建多环境基础设施即代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cloudflare Terraform 实战模式:用 autoskills 的 cloudflare-deploy 技能搭建多环境基础设施即代码

【免费下载链接】autoskills

One command. Your entire AI skill stack. Installed.

项目地址:https://gitcode.com/gh_mirrors/au/autoskills
点击查看免费下载

导读

本文以 autoskills 仓库中cloudflare-deploy技能的 Terraform 实战参考文档 patterns.md 为核心,系统讲解使用 Cloudflare Terraform Provider 落地基础设施即代码(IaC)的架构模式与真实用例:从推荐的目录结构、多环境编排、R2 远程状态后端,到携带全部绑定(KV/R2/D1/Secret)的 Worker 定义、与 Wrangler 的职责边界划分及 CI/CD 集成,再到静态站点 + API Worker、多区域负载均衡、Zero Trust Access 安全管理员、可复用模块四大实战场景。读完本文,你将掌握一套可直接复制运行的 Cloudflare 基础设施代码骨架,并理解 Provider v5 时代的关键约束与避坑点。


一、为什么需要 Terraform 模式文档

在 Cloudflare 平台上,部署手段众多:Wrangler CLI、Pages Git 集成、REST API、Pulumi、Terraform。当基础设施规模超出单个 Worker、涉及多个环境(staging/production)、需要 DNS + 安全规则 + 负载均衡 + Access 协同管理时,Terraform 是官方推荐的声明式 IaC 方案。

在 autoskills 的cloudflare-deploy技能中,Terraform 被归类为基础设施即代码(IaC)三选一(terraform/、pulumi/、api/)之一,见 SKILL.md。而 patterns.md 正是这一分类下的架构落地指南,与同目录的 README.md(Provider 配置)、configuration.md(资源清单)、api.md(数据源)、gotchas.md(排障)共同构成完整参考体系。

核心原则(来自 README.md):

  • Provider 优先:所有基础设施一律用 Terraform Provider 管理,绝不与 wrangler.jsonc 对同一资源重复声明;
  • 远程状态:团队环境必须使用远程状态(S3、Terraform Cloud 等);
  • 模块化架构:为常见模式(zone、worker、pages)创建可复用模块;
  • 版本锁定:用~>锁定 Provider 版本以保证可预测升级;
  • 密钥管理:敏感数据用变量 + 环境变量,绝不硬编码 API Token。

二、推荐的目录结构:环境目录 + 共享状态

patterns.md 给出的推荐目录结构如下:

terraform/ ├── environments/ │ ├── production/ │ │ ├── main.tf │ │ └── terraform.tfvars │ └── staging/ │ ├── main.tf │ └── terraform.tfvars ├── modules/ │ ├── zone/ │ ├── worker/ │ └── dns/ └── shared/ # Shared resources across envs └── main.tf

设计要点:

  • environments/下每个环境一个目录,各自持有main.tf与terraform.tfvars(环境专属变量,如account_id、environment名称、域名);
  • modules/沉淀跨环境复用的抽象(zone、worker、dns);
  • shared/存放跨环境共享的资源(例如 R2 公共桶、全局规则集)。

特别提示:patterns.md 明确强调 —— Cloudflare 官方建议避免为 Provider 资源过度封装模块,原因是 Provider v5 由 OpenAPI 自动生成后,模块接口的自动生成复杂度上升。更推荐的做法是:环境目录 + 共享状态(shared state),即每个环境拥有独立状态文件、直接引用共享状态中的资源 ID,而非层层套模块。


三、多环境设置:模块调用 + 环境变量

在environments/{production,staging}/main.tf中,通过模块复用 zone 与 worker 定义,以environment变量区分环境:

# Directory: environments/{production,staging}/main.tf + modules/{zone,worker,pages} module "zone" { source = "../../modules/zone"; account_id = var.account_id; zone_name = "example.com"; environment = "production" } module "api_worker" { source = "../../modules/worker"; account_id = var.account_id; zone_id = module.zone.zone_id name = "api-worker-prod"; script = file("../../workers/api.js"); environment = "production" }

关键点:

  • source = "../../modules/zone"以相对路径引用modules/下的本地模块,无需额外 registry 发布;
  • module.zone.zone_id将模块输出传递给下游模块,形成依赖链;
  • 环境差异集中在terraform.tfvars(如api-worker-prod与api-worker-staging的命名后缀),代码本身保持单一。

配套验证:Terraform 支持terraform validate校验语法、terraform plan对比环境差异、terraform fmt -recursive统一格式(命令清单见 README.md)。在每个环境目录内执行terraform init && terraform plan,即可确认 staging 与 production 的差异是否如预期。


四、R2 远程状态后端:跨环境共享状态的关键

Terraform 团队协作必须使用远程状态。patterns.md 给出了一套完全基于 Cloudflare 自身产品(R2 + S3 兼容端点)的状态后端方案,无需引入 AWS 即可实现团队共享:

terraform { backend "s3" { bucket = "terraform-state" key = "cloudflare.tfstate" region = "auto" endpoints = { s3 = "https://<account_id>.r2.cloudflarestorage.com" } skip_credentials_validation = true skip_region_validation = true skip_requesting_account_id = true skip_metadata_api_check = true skip_s3_checksum = true } }

参数说明:

参数作用
bucketR2 中承载状态文件的桶名(需先在 R2 中创建)
key状态对象在桶内的路径,可用环境区分(如staging.tfstate/production.tfstate)
region = "auto"R2 无区域概念,必须固定为auto
endpoints.s3指向你的 R2 账户端点https://<account_id>.r2.cloudflarestorage.com
skip_*系列跳过 AWS 特有校验,适配 S3 兼容存储

注意:region、endpoints等属于后端配置的静态参数,HCL 中不能引用变量,请直接字面量填写。

远程状态与“环境目录 + 共享状态”模式配合:shared/环境产出的输出(如共享 zone_id、KV namespace_id)可被各环境通过terraform_remote_state数据源读取,实现跨环境引用而不产生资源重复管理。


五、全绑定 Worker:KV / R2 / D1 / Secret 一网打尽

patterns.md 提供了一个“full-stack-worker”示例,把 Cloudflare 最常见的四类 Worker 绑定全部接入同一脚本:

locals { worker_name = "full-stack-worker" } resource "cloudflare_workers_kv_namespace" "app" { account_id = var.account_id; title = "${local.worker_name}-kv" } resource "cloudflare_r2_bucket" "app" { account_id = var.account_id; name = "${local.worker_name}-bucket" } resource "cloudflare_d1_database" "app" { account_id = var.account_id; name = "${local.worker_name}-db" } resource "cloudflare_worker_script" "app" { account_id = var.account_id; name = local.worker_name; content = file("worker.js"); module = true compatibility_date = "2025-01-01" kv_namespace_binding { name = "KV"; namespace_id = cloudflare_workers_kv_namespace.app.id } r2_bucket_binding { name = "BUCKET"; bucket_name = cloudflare_r2_bucket.app.name } d1_database_binding { name = "DB"; database_id = cloudflare_d1_database.app.id } secret_text_binding { name = "API_KEY"; text = var.api_key } }

要点解读:

  • module = true声明使用 ES Module 格式的 Worker 脚本;
  • compatibility_date = "2025-01-01"固定运行时兼容性日期,避免行为漂移;
  • 绑定块(kv_namespace_binding、r2_bucket_binding、d1_database_binding、secret_text_binding)直接引用同文件内创建的资源 ID,Terraform 会自动建立依赖顺序:先建 KV/R2/D1,再部署 Worker;
  • Worker 内通过绑定名称KV、BUCKET、DB、API_KEY访问这些资源。

Provider v5 支持的全部绑定类型见 configuration.md 的表格:除 KV/R2/D1/Secret 外,还包括 Service、Queue、Vectorize、Hyperdrive、AI、Browser、Analytics Engine、mTLS 证书绑定。

生产环境进阶:configuration.md 还推荐了“渐进式发布(Gradual Rollouts)”模式 —— 用cloudflare_worker定义 Worker 本体,cloudflare_worker_version上传带content_sha256的版本,再由cloudflare_workers_deployment控制各版本流量百分比(如percentage = 100),实现灰度上线,详见 configuration.md。


六、Wrangler 集成:职责边界与 CI/CD 模式

职责划分(CRITICAL)

patterns.md 明确指出:Wrangler 与 Terraform 绝不能同时管理同一批资源,否则会出现 409 Conflict、状态漂移等冲突(详见 gotchas.md 的 “409 Conflict on worker deployment”)。

推荐分工:

工具负责范围
TerraformZones、DNS、安全规则、Access、负载均衡、Worker 部署(CI/CD 管道)、KV/R2/D1 等资源创建
Wrangler本地开发(wrangler dev)、手动部署、D1 迁移、KV 批量操作、日志流式查看(wrangler tail)

Wrangler 侧能力全景可参考 wrangler/README.md:wrangler dev/wrangler deploy/wrangler rollback、KV 的kv key put/get、D1 的d1 migrations apply、R2 的r2 object put/get、监控用的wrangler tail等。

CI/CD 模式:terraform apply → envsubst → wrangler deploy

典型的流水线分三步:Terraform 建基础设施并输出资源 ID,用envsubst将 ID 注入wrangler.jsonc模板,最后用 Wrangler 部署代码:

# Terraform creates infrastructure resource "cloudflare_workers_kv_namespace" "app" { account_id = var.account_id; title = "app-kv" } resource "cloudflare_d1_database" "app" { account_id = var.account_id; name = "app-db" } output "kv_namespace_id" { value = cloudflare_workers_kv_namespace.app.id } output "d1_database_id" { value = cloudflare_d1_database.app.id }
# GitHub Actions: terraform apply → envsubst wrangler.jsonc.template → wrangler deploy - run: terraform apply -auto-approve - run: | export KV_NAMESPACE_ID=$(terraform output -raw kv_namespace_id) envsubst < wrangler.jsonc.template > wrangler.jsonc - run: wrangler deploy

流程说明:

  1. terraform apply -auto-approve保证 KV namespace 与 D1 数据库已存在,并通过output暴露 ID;
  2. terraform output -raw kv_namespace_id读取输出值,envsubst把模板中的$KV_NAMESPACE_ID占位符替换为真实 ID;
  3. wrangler deploy仅部署 Worker 代码,不再创建资源 —— 资源的创建与代码的部署由两个工具各司其职。

CI/CD 认证:流水线环境不适用交互式wrangler login,应设置CLOUDFLARE_API_TOKEN环境变量(见 SKILL.md 与 README.md)。


七、实战用例一:静态站点 + API Worker

这是最常见的组合:Pages 托管前端静态站,Workers 承载 API,DNS 与路由统一由 Terraform 管理:

resource "cloudflare_pages_project" "frontend" { account_id = var.account_id; name = "frontend"; production_branch = "main" build_config { build_command = "npm run build"; destination_dir = "dist" } } resource "cloudflare_worker_script" "api" { account_id = var.account_id; name = "api"; content = file("api-worker.js") d1_database_binding { name = "DB"; database_id = cloudflare_d1_database.api_db.id } } resource "cloudflare_dns_record" "frontend" { zone_id = cloudflare_zone.main.id; name = "app"; content = cloudflare_pages_project.frontend.subdomain; type = "CNAME"; proxied = true } resource "cloudflare_worker_route" "api" { zone_id = cloudflare_zone.main.id; pattern = "api.example.com/*"; script_name = cloudflare_worker_script.api.name }

要点:

  • cloudflare_pages_project声明构建命令npm run build与产物目录dist,可配合 GitHub 源(source { type = "github"; config { ... } },见 configuration.md);
  • 前端域名通过cloudflare_dns_record(CNAME 指向 Pages 的.pages.dev子域,proxied = true走代理)暴露;
  • API 通过cloudflare_worker_route挂到api.example.com/*模式;
  • 若项目还有自定义域名,可用cloudflare_pages_domain绑定site.example.com。

八、实战用例二:多区域负载均衡(geo steering)

面向全球用户时,用 Load Balancer 按地理位置把流量分发给不同区域源站:

resource "cloudflare_load_balancer_pool" "us" { account_id = var.account_id; name = "us-pool"; monitor = cloudflare_load_balancer_monitor.http.id origins { name = "us-east"; address = var.us_east_ip } } resource "cloudflare_load_balancer_pool" "eu" { account_id = var.account_id; name = "eu-pool"; monitor = cloudflare_load_balancer_monitor.http.id origins { name = "eu-west"; address = var.eu_west_ip } } resource "cloudflare_load_balancer" "global" { zone_id = cloudflare_zone.main.id; name = "api.example.com"; steering_policy = "geo" default_pool_ids = [cloudflare_load_balancer_pool.us.id] region_pools { region = "WNAM"; pool_ids = [cloudflare_load_balancer_pool.us.id] } region_pools { region = "WEU"; pool_ids = [cloudflare_load_balancer_pool.eu.id] } }

解读:

  • 两个 pool 共用同一个健康检查 monitor(cloudflare_load_balancer_monitor.http,type = http、path = /health,见 configuration.md);
  • steering_policy = "geo"启用地理路由;default_pool_ids作为兜底池;
  • region_pools把 WNAM(北美西部)、WEU(西欧)等 Cloudflare 区域代码映射到对应 pool。

提示:load_balancer 资源存在已知状态漂移(adaptive_routing、random_steering属性),建议在 lifecycle 中添加ignore_changes,见 gotchas.md。


九、实战用例三:用 Zero Trust Access 保护管理员后台

把管理后台变成仅限指定邮箱访问的受保护应用:

resource "cloudflare_pages_project" "admin" { account_id = var.account_id; name = "admin"; production_branch = "main" } resource "cloudflare_access_application" "admin" { account_id = var.account_id; name = "Admin"; domain = "admin.example.com"; type = "self_hosted"; session_duration = "24h" allowed_idps = [cloudflare_access_identity_provider.google.id] } resource "cloudflare_access_policy" "allow" { account_id = var.account_id; application_id = cloudflare_access_application.admin.id name = "Allow admins"; decision = "allow"; precedence = 1; include { email = var.admin_emails } }

要点:

  • cloudflare_access_application定义受保护应用(self_hosted 类型),session_duration = "24h"控制会话时长;
  • allowed_idps引用身份提供方(本例为 Google,也可用 GitHub 等,其创建方式见 configuration.md);
  • cloudflare_access_policy的include { email = var.admin_emails }限定允许访问的管理员邮箱列表,decision = "allow"、precedence = 1定义策略优先级。

版本提示:Provider v5 中 Access 系列资源已更名为cloudflare_zero_trust_*(cloudflare_access_application→cloudflare_zero_trust_application等),迁移细节见 gotchas.md。


十、实战用例四:可复用模块封装 zone

若确实需要模块化,patterns.md 给出了一个最小 zone 模块示例 —— 封装 Zone 创建、SSL 设置与 zone_id 输出:

# modules/cloudflare-zone/main.tf variable "account_id" { type = string }; variable "domain" { type = string }; variable "ssl_mode" { default = "strict" } resource "cloudflare_zone" "main" { account = { id = var.account_id }; name = var.domain } resource "cloudflare_zone_settings_override" "main" { zone_id = cloudflare_zone.main.id; settings { ssl = var.ssl_mode; always_use_https = "on" } } output "zone_id" { value = cloudflare_zone.main.id } # Usage: module "prod" { source = "./modules/cloudflare-zone"; account_id = var.account_id; domain = "example.com" }

模块设计要点:

  • variable声明入参(ssl_mode带默认值strict),调用方只需传account_id与domain;
  • cloudflare_zone_settings_override统一开启always_use_https,并可通过ssl_mode调整 TLS 模式;
  • output "zone_id"向调用方暴露 zone ID,供 DNS、路由等下游资源引用。

结合 api.md,模块内也可以用数据源按域名反查已有 zone(data "cloudflare_zone")而非新建,实现“引用现有资源”的混合模式。


十一、落地前的关键检查清单

把 patterns.md 的架构落地到生产前,请对照以下清单(细节均可在 gotchas.md 找到依据):

  1. Provider 版本:使用~> 5.15.0及以上并锁定(required_providers),注意 v4→v5 的资源重命名:cloudflare_record→cloudflare_dns_record、cloudflare_worker_*→cloudflare_workers_*;升级后需terraform state mv迁移状态;
  2. 认证方式:优先 API Token(CLOUDFLARE_API_TOKEN),按账户/Zone 最小权限授权;Global API Key 属于 legacy,不推荐;
  3. 状态漂移防护:对cloudflare_pages_project加ignore_changes = [deployment_configs]、对cloudflare_workers_script加ignore_changes = [secret_text_binding](secret 在 API 中返回为 REDACTED);
  4. R2 位置大小写:location必须大写(WNAM、ENAM、WEUR、EEUR、APAC),否则后续 apply 会失败;
  5. D1 只建库不建表:Terraform 只创建 D1 数据库,schema 需在 apply 后用wrangler d1 migrations apply <db-name>完成;
  6. Worker 体积:脚本 + 依赖合计上限 10 MB,超限需代码分割或压缩;
  7. 资源导入:已有资源(如已存在的 DNS 记录)应使用terraform import(格式见 api.md),或先用cf-terraforming生成 HCL,避免 “DNS record already exists” 报错;
  8. 并发锁:多成员同时 apply 时如遇 “State locking errors”,用terraform force-unlock <lock-id>清理过期锁(慎用)。

容量参考(来自 gotchas.md):D1 每账户 50,000 个(免费档 10 个);Pages 项目每账户 500 个(免费账户 100 个);免费计划下每个 Zone DNS 记录 3,500 条;R2 存储与 KV 键数无上限、按量计费。


十二、延伸阅读

patterns.md 的 “See Also” 指向同目录其余四份文档,构成了完整的 Terraform 参考闭环:

  • README.md — Provider 安装、认证方式(API Token / Global Key / User Service Key)、常用命令与 cf-terraforming 导入工具;
  • configuration.md — Zone/DNS、Workers、KV/R2/D1、Pages、Rulesets(WAF/重定向/缓存)、Load Balancer、Access 的全量资源写法;
  • api.md — 数据源查询(zone、accounts、worker、KV、list、IP ranges)与 Import ID 格式;
  • gotchas.md — 状态漂移表、v5 破坏性变更对照、资源级陷阱与常见错误处理。

此外,cloudflare-deploy技能还提供 Pulumi(references/pulumi/)与 REST API(references/api/)两种 IaC 替代方案,以及 wrangler CLI 的完整参考,供不同团队按既有工具链选择。

【免费下载链接】autoskills

One command. Your entire AI skill stack. Installed.

项目地址:https://gitcode.com/gh_mirrors/au/autoskills
点击查看免费下载
上一篇:espefuse burn-key 命令完全指南:向 ESP32 系列 eFuse 烧写安全密钥的实战解析
下一篇:【免费下载】 OCR自动评分系统:OCRAutoScore,开启智能教育新篇章

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 5:05:12

PCA9422+MKV42F64嵌入式电源管理闭环设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/10 5:04:54

智能计算系统课程设计:从PyTorch训练到算子优化与部署全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/10 5:04:35

PCA9422与STM32F767BI电源管理实战:从供电树到低功耗调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华