2. Oracle Cloud基础设施即代码基础
在OCI上做平台工程,绕不开一个核心问题:如何让网络、计算、存储、身份策略这些资源可重复、可审计、可回滚地创建出来。控制台点击虽然直观,但无法版本化,也无法在多个环境之间保持一致。Terraform与OCI资源管理器(Resource Manager)正是解决这个问题的两条路径:前者是业界通用的IaC工具,后者是OCI原生的托管式Terraform服务。理解它们的关系,是掌握OCI自动化交付的起点。
一、Terraform在OCI中的工作模型
Terraform的核心是“声明式配置 + 状态文件 + 执行计划”三件套。你写的是期望状态,Terraform负责计算从当前状态到期望状态的差异,并生成执行计划。在OCI场景中,这个模型具体化为:
- Provider:
provider "oci",通过tenancy_ocid、user_ocid、fingerprint、private_key_path、region等参数建立与OCI的认证连接。 - Resource:如
oci_core_vcn、oci_core_subnet、oci_core_instance,每个资源对应OCI中的一个真实对象。 - State:记录资源ID与属性的映射,是Terraform判断“资源是否已存在”的唯一依据。
- Plan/Apply:先plan看差异,再apply执行变更。
一个最小的VCN定义如下,注意CIDR块和DNS标签是后续子网划分的基础:
resource "oci_core_vcn" "prod_vcn" {
compartment_id = var.compartment_ocid
cidr_block = "10.20.0.0/16"
display_name = "prod-vcn"
dns_label = "prodvcn"
}
resource "oci_core_subnet" "app_subnet" {
compartment_id = var.compartment_ocid
vcn_id = oci_core_vcn.prod_vcn.id
cidr_block = "10.20.10.0/24"
display_name = "app-subnet"
dns_label = "app"
security_list_ids = [oci_core_vcn.prod_vcn.default_security_list_id]
}
这里有一个关键细节:oci_core_subnet引用了oci_core_vcn.prod_vcn.id,Terraform会自动推导出依赖关系,先建VCN再建子网。这种隐式依赖是Terraform相比脚本化API调用的最大优势之一。
二、状态管理:本地、远程与锁定
状态文件是Terraform的“记忆”。默认情况下,terraform apply会在当前目录生成terraform.tfstate。这在单人实验中可行,但在团队协作中会立刻出问题:两个人同时apply,状态文件互相覆盖,资源就会失控。
OCI场景下推荐的做法是把状态放到OCI Object Storage中,并启用锁定。配置方式是在backend块中指定bucket和namespace:
terraform {
backend "oci" {
bucket = "tf-state-prod"
namespace = "mytenancy"
key = "network/terraform.tfstate"
region = "ap-singapore-1"
}
}
状态文件里包含资源ID、敏感属性(如数据库密码的初始值),因此bucket必须设置为私有,并配合IAM策略限制访问。另一个常见做法是使用OCI资源管理器,它天然把状态托管在服务端,不需要自己维护backend配置。
terraform import或terraform state rm等命令修正,而不是直接改文件。三、模块化组织:从单文件到可复用单元
当资源数量超过几十个,把所有内容写在一个main.tf里会变得难以维护。模块化的思路是把一组相关资源封装成一个可调用的单元,通过输入变量暴露差异点,通过输出值暴露下游需要引用的ID。
以“标准三层网络”为例,可以定义一个modules/network模块,输入是compartment_id、vcn_cidr、子网列表,输出是vcn_id和各子网id。根目录的main.tf只需要调用:
module "prod_network" {
source = "./modules/network"
compartment_id = var.compartment_ocid
vcn_cidr = "10.20.0.0/16"
subnets = {
app = "10.20.10.0/24"
db = "10.20.20.0/24"
}
}
模块化的收益在环境复制时最明显:dev、staging、prod三个环境可以复用同一个模块,只替换变量文件。但要注意,模块不是越细越好。如果一个模块只封装一个资源,反而增加了调用复杂度。合理的粒度是“一组生命周期一致、被一起创建和销毁的资源”。
四、OCI资源管理器:托管式Terraform
OCI资源管理器把Terraform的执行环境托管在OCI内部。你上传配置或指向Git仓库,资源管理器负责运行plan和apply,状态由服务管理。它适合以下场景:
- 团队中没有专人维护Terraform执行环境;
- 需要通过OCI控制台或API触发部署,而不是本地CLI;
- 希望把状态、日志、权限统一收敛到OCI IAM体系内。
资源管理器的Stack概念对应一个Terraform工作目录,Job对应一次plan或apply。它支持从GitHub、GitLab、OCI DevOps拉取配置,也支持直接上传zip。对于平台工程团队,一个常见模式是:用资源管理器管理基础网络和共享服务,用本地Terraform或CI流水线管理应用层资源。
五、从入门到可用的关键判断
学完这一节,可以用三个问题检验自己是否真正入门:第一,能否说清楚terraform plan输出的“+、-、~”分别代表什么,以及为什么plan结果和apply结果有时不完全一致;第二,能否在OCI Object Storage中配置好backend并验证状态锁定生效;第三,能否把一段单文件配置拆成模块,并在另一个compartment中复用。
实际项目中,最常见的错误不是语法写错,而是状态管理失控:有人手动在控制台改了安全列表,Terraform下次plan就会试图改回去;有人把state文件提交到了Git,导致敏感信息泄露。这些问题的根源都在于没有把“状态”当作一等公民来对待。Terraform的声明式模型要求你接受一个前提:所有变更都通过代码走,控制台只用于查看和排障。这个纪律建立起来之后,OCI上的资源交付才真正具备可重复性和可审计性。