KubeCon + CloudNativeCon 的大量讨论默认 Kubernetes 集群已经存在,但平台团队真正面对的工作往往开始得更早:准备云账号与权限、建立网络、开通托管服务、创建集群,并把这些资源纳入可审计的生命周期管理。2026 年 11 月 9 日的 OpenTofu Day,关注的正是这条位于 Kubernetes 之前、同时也包围着 Kubernetes 的基础设施链路。
集群不是平台的起点
一个能够承载生产工作负载的 Kubernetes 环境,通常依赖多层资源:
- 云账号、项目或订阅,以及对应的身份与权限边界;
- VPC、子网、路由、NAT、负载均衡和 DNS;
- Kubernetes 控制平面与工作节点;
- 数据库、对象存储、消息队列、密钥管理等托管服务;
- 状态存储、审计、策略检查和持续交付流程。
这也是 OpenTofu 这类基础设施即代码工具的价值所在:它不仅负责“创建一个集群”,还可以描述集群与网络、身份和云服务之间的依赖关系。应用团队看到的是一个可用的 Kubernetes API;平台团队需要维护的,则是一张完整的资源图。
这种视角还能减少工具链断层。如果网络由脚本创建、集群由控制台创建、数据库由另一套流水线创建,那么变更审查、环境复制和故障恢复都会变得困难。把这些资源转换为声明式配置,并不意味着必须放进同一个状态文件,而是让它们拥有一致的计划、审查和变更方式。
边界比资源数量更重要
实际采用 OpenTofu 时,不建议把整个组织的基础设施塞进一个巨大的根模块。更稳妥的方式是按生命周期和权限边界拆分,例如:
infrastructure/
├── bootstrap/ # 状态存储、CI 身份等一次性资源
├── accounts/ # 云账号、项目与基础权限
├── network/ # VPC、子网、DNS 与出口
├── clusters/ # Kubernetes 集群和节点池
└── services/ # 数据库、缓存、消息队列等托管服务
这种拆分有三个直接收益:
- 网络调整不必锁住数据库或集群状态;
- 团队可以为不同目录配置不同的审批人与云权限;
- 删除测试集群时,不容易误删共享网络或生产数据。
各层之间可以通过经过审核的输出值、远程状态或配置目录传递信息。不过,远程状态往往包含比调用方实际需要更多的数据,因此生产环境应优先考虑只发布必要参数,并严格控制状态文件访问权限。
还要特别处理“引导问题”:OpenTofu 自己使用的远程状态桶、锁机制和 CI 身份由谁创建?常见做法是保留一个体积很小、变更极少的 bootstrap 栈,先建立这些基础能力,再由正式流水线管理其他栈。
动手示例:用 OpenTofu 创建 VPC 与 EKS 集群
下面是一个可以改造的 AWS 示例。它会创建 VPC、私有子网、NAT 网关、EKS 控制平面和托管节点组,因此会产生云资源费用。示例假设你已经安装 OpenTofu、AWS CLI 和 kubectl,并通过环境变量或 AWS 配置文件取得了沙箱账号凭证。
创建空目录,并保存以下 main.tf:
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
data "aws_availability_zones" "available" {
state = "available"
}
locals {
name = "demo-platform"
azs = slice(data.aws_availability_zones.available.names, 0, 2)
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = local.name
cidr = "10.42.0.0/16"
azs = local.azs
private_subnets = ["10.42.1.0/24", "10.42.2.0/24"]
public_subnets = ["10.42.101.0/24", "10.42.102.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
public_subnet_tags = {
"kubernetes.io/role/elb" = "1"
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = "1"
}
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = local.name
cluster_endpoint_public_access = true
enable_cluster_creator_admin_permissions = true
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
eks_managed_node_groups = {
default = {
instance_types = ["t3.medium"]
min_size = 1
max_size = 3
desired_size = 2
}
}
}
output "cluster_name" {
value = module.eks.cluster_name
}
output "configure_kubectl" {
value = "aws eks update-kubeconfig --region us-west-2 --name ${module.eks.cluster_name}"
}
执行初始化和计划检查:
mkdir opentofu-eks-demo
cd opentofu-eks-demo
# 将上面的配置保存为 main.tf
tofu init
tofu fmt -check
tofu validate
tofu plan -out=tfplan
确认计划中的区域、资源数量和费用影响后再创建:
tofu apply tfplan
aws eks update-kubeconfig --region us-west-2 --name demo-platform
kubectl get nodes
实验结束后及时清理:
tofu destroy
这个配置适合演示依赖关系,但不能直接视为生产基线。生产环境至少需要评估:是否关闭公共 API 端点、如何限制访问 CIDR、是否使用私有集群、节点如何加密、日志保存在哪里,以及模块和 provider 版本如何升级。运行前也应确认示例版本与目标区域当前支持的 EKS 能力兼容。
从一次演示走向团队工作流
OpenTofu 能否在平台团队中发挥作用,取决于变更流程,而不只是 HCL 写得是否漂亮。可以从以下检查清单开始:
tofu plan必须进入代码审查,而不是只保存在 CI 日志中;- 状态文件使用加密、版本控制、锁定和最小权限访问;
- CI 使用短期身份凭证,避免长期云密钥;
- 对删除、公开访问、未加密存储等高风险变更设置策略门禁;
- 将账号、网络、集群和有状态服务拆分为清晰的责任边界;
- 定期运行计划,发现控制台操作造成的配置漂移;
- 在升级 provider、模块或 OpenTofu 本身之前,先在非生产环境验证计划结果。
OpenTofu Day 值得关注的核心,不只是某条命令或某种配置语法,而是如何把“集群出现之前”的工作纳入云原生工程体系。只有账号、网络、托管服务和集群都能被可靠地复现、审查和回滚,Kubernetes 之上的交付速度才有稳定基础。