Hang Zhengyang

Terraform 统一流(terraform-k8s 实现剖析)

本文解释 terraform-k8s/ 如何作为本仓库的主交付路径,把应用、入口与观测统一到单条 Terraform 流程。

0. 基础概念速记(高密度)

  • Root Module:可直接执行 terraform 命令的入口目录;本仓库是 envs/dev 与 envs/prod。
  • Child Module:被 root 调用的可复用模块;本仓库是 modules/app|platform|observability。
  • Backend/State 边界:状态文件归属边界;不同环境 root module 形成天然状态隔离。
  • Kubernetes Provider:声明原生 K8s 资源(Deployment/Service/Ingress 等)。
  • Helm Provider:声明 Helm release,把 chart 安装也纳入 Terraform 状态机。
  • depends_on:显式跨模块依赖;避免平台组件未就绪时就下发观测资产。
  • TF_VAR_*:敏感参数注入通道;用于替代把 secret 写入 tfvars。

1. 架构定位

terraform-k8s 不是“又一套脚本”,而是统一控制平面:

  • Root module(envs/dev、envs/prod)负责环境参数与状态边界。
  • modules/app 负责业务运行面(app/postgres/edge-proxy + ingress)。
  • modules/platform 负责平台能力(ingress-nginx、kube-prometheus-stack Helm release)。
  • modules/observability 负责监控资产下发(Grafana dashboard/alert ConfigMap)。

即:环境编排在 env,资源语义在 module,第三方平台通过 Helm provider 接管。

2. 调用图与依赖关系

envs/dev/main.tf(prod 同构):

  1. module "app":传入 namespace/app_image/app_replicas/database_url/ingress_host。
  2. module "platform":传入 grafana_admin_password。
  3. module "observability":depends_on = [module.platform],确保监控栈先存在再投递 dashboard/alert 配置。

这条依赖链避免“资产先下发但接收方未就绪”的竞态问题。

3. module 语义拆解

3.1 modules/app

管理对象(同一 namespace):

  • kubernetes_namespace_v1
  • kubernetes_config_map_v1(Nginx 配置)
  • kubernetes_deployment_v1(app/postgres/edge-proxy)
  • kubernetes_service_v1(app/postgres/edge-proxy)
  • kubernetes_ingress_v1

关键实现点:

  • DATABASE_URL 由变量注入,不硬编码到镜像。
  • app Deployment 包含 requests/limits + readiness/liveness。
  • ingress host 变量化,支持 dev/prod 分离域名。

3.2 modules/platform

通过 Helm release 安装:

  • ingress-nginx
  • kube-prometheus-stack

关键实现点:

  • create_namespace = true,避免外部预建命名空间耦合。
  • Grafana admin 密码通过变量注入。
  • kube-prometheus-stack 显式依赖 ingress release,降低首次安装波动。

3.3 modules/observability

向 monitoring namespace 下发两个 ConfigMap:

  • Dashboard JSON(label: grafana_dashboard=1)
  • Alert rule YAML(label: grafana_alert=1)

这与 platform 模块中的 Grafana sidecar label 配置形成闭环:配置即资产,资产即 Git。

4. Secret 与环境边界

环境目录用 variables.tf 声明必填:

  • database_url
  • grafana_admin_password

推荐注入路径:

  • source ./secrets.example.env(模板)
  • 本地真实值放 secrets.env(应被 .gitignore 忽略)
  • 或直接导出 TF_VAR_*

核心原则:tfvars 保存拓扑参数,敏感值由环境变量注入。

5. 统一流执行语义

以 dev 为例:

  1. 准备镜像:docker build ... + kind load ...
  2. 进入环境根:cd terraform-k8s/envs/dev
  3. 变量注入:source ./secrets.example.env(或 secrets.env)
  4. terraform init/validate/plan/apply

此时 Terraform 同时驱动:

  • Kubernetes provider(原生对象)
  • Helm provider(平台组件)

因此这是一条真正的“单入口多控制器”交付链。

6. 故障面与优先排查顺序

  1. plan/apply 报 provider 初始化问题:
    • 先 terraform init -upgrade 或重新 init。
  2. apply 报 kube API 不可达:
    • 检查 kubectl config current-context 与集群状态。
  3. Pod 未 Ready:
    • 查 namespace 下 deployment/pod/events/logs。
  4. Grafana 无面板:
    • 查 monitoring 下 ConfigMap label 与 sidecar 配置是否一致。

7. 与其他路线的关系

  • 对 serving-lab/docker-compose:统一流复用其镜像产物,但把运行面迁移到集群。
  • 对 k8s/:统一流管理等价对象,但拥有环境隔离、模块复用和审计能力。
  • 对 terraform/:统一流是其复杂版落地,继承同样的 state/plan/apply/destroy 心智模型。

8. 结论(仓库语义)

terraform-k8s 在本仓库中的角色是:唯一工业化主路径。
它把“应用部署 + 平台安装 + 观测资产下发”收敛为单次 Terraform 事务,具备可复用、可审计、可环境隔离的交付属性。