2. OCI资源模型与IaC映射

在OCI中,所有资源都不是孤立存在的,它们被组织在一个严格的层级结构中。理解这个层级,是编写IaC代码的前提——因为Terraform、Resource Manager或OCI CLI在操作资源时,本质上是在这个层级中定位目标、声明依赖、传递参数。如果层级关系搞错了,代码要么无法通过校验,要么会在错误的位置创建资源,甚至覆盖生产环境的关键配置。

OCI的资源层级从顶层到底层依次为:租户(Tenancy)→ 区间(Region)→ 隔间(Compartment)→ 可用域(Availability Domain, AD)→ 故障域(Fault Domain, FD)。此外还有虚拟云网络(VCN)和子网(Subnet)作为网络层面的划分,它们通常挂载在隔间之下、跨可用域部署。下面逐层剖析,并说明每一层在IaC中如何映射。

租户:资源模型的根节点

租户(Tenancy)是OCI账户的顶层容器,也称为根隔间(Root Compartment)。它拥有全局唯一的OCID,所有其他资源最终都归属于某个租户。在IaC中,租户通常不直接作为资源声明,而是通过Provider配置隐式绑定。例如Terraform的OCI Provider需要指定tenancy_ocid、user_ocid、fingerprint和private_key_path,这些参数决定了代码在哪个租户下执行。一个常见的做法是:将租户级配置放在provider.tf中,而将具体资源放在模块里,通过变量传入隔间OCID,避免硬编码。

区间:物理位置与资源可用性

区间(Region)是OCI的物理数据中心集群,例如ap-singapore-1、us-ashburn-1。区间决定了资源的物理位置、可用服务集以及网络延迟。在IaC中,区间通过Provider的region参数指定,或者通过资源属性中的region字段覆盖。需要注意的是,区间是资源创建时的必填项,但并非所有资源都支持跨区间引用。例如,VCN和子网是区间级资源,而IAM策略、隔间是全局资源(Global),它们不绑定具体区间。在Terraform中,全局资源通常使用oci_identity_*系列,而区间级资源使用oci_core_*、oci_database_*等。

隔间:IaC治理的核心边界

隔间(Compartment)是OCI中最重要的逻辑隔离单元。它类似于文件夹,用于组织资源、隔离权限、划分成本。每个隔间有唯一的OCID,可以嵌套最多6层。在IaC中,隔间是资源声明中最常见的参数——几乎每个资源都需要指定compartment_id。例如:

resource "oci_core_vcn" "prod_vcn" {
  compartment_id = var.prod_compartment_ocid
  cidr_block     = "10.0.0.0/16"
  display_name   = "prod-vcn"
  dns_label      = "prodvcn"
}

这里var.prod_compartment_ocid通常来自terraform.tfvars或远程状态,而不是硬编码。隔间的层级设计直接决定了IaC的模块划分:一个隔间对应一个环境(如dev、test、prod),或者一个业务单元。建议在代码中为每个隔间定义独立的oci_identity_compartment资源,并通过depends_on或输出变量传递OCID,形成清晰的依赖链。

可用域与故障域:高可用的物理边界

可用域(AD)是区间内相互隔离的物理数据中心,通常一个区间有1~3个AD。故障域(FD)是AD内的进一步隔离组,每个AD有3个FD。在IaC中,AD和FD通常不直接作为资源属性出现,而是通过数据源(Data Source)动态获取。例如:

data "oci_identity_availability_domains" "ads" {
  compartment_id = var.tenancy_ocid
}

resource "oci_core_subnet" "app_subnet" {
  compartment_id      = var.prod_compartment_ocid
  vcn_id              = oci_core_vcn.prod_vcn.id
  cidr_block          = "10.0.1.0/24"
  availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
  display_name        = "app-subnet-ad1"
}

这里通过数据源获取第一个AD的名称,再赋给子网。对于需要跨AD高可用的场景,通常会在多个AD中分别创建子网,或者使用区域子网(Regional Subnet)——区域子网不绑定单个AD,而是覆盖整个区间,由OCI自动在AD间分配。在IaC中,区域子网只需省略availability_domain参数即可。故障域则更少直接使用,通常出现在数据库系统或Exadata的配置中,通过fault_domain参数指定,用于控制数据副本的分布。

VCN与子网:网络层的IaC映射

VCN是区间级资源,属于某个隔间,但可以跨AD部署。子网是VCN的子资源,分为区域子网和AD子网。在IaC中,VCN和子网通常成对出现,且子网的vcn_id引用VCN的id属性,形成隐式依赖。一个典型的网络模块会包含:VCN、Internet Gateway、NAT Gateway、Service Gateway、路由表、安全列表,以及多个子网。这些资源全部通过compartment_id绑定到同一个隔间,通过vcn_id绑定到同一个VCN。

租户 Tenancy(根隔间) Provider 绑定:tenancy_ocid · 全局资源归属 区间 Region(如 ap-singapore-1) Provider 参数:region · 决定物理位置与服务可用性 隔间 Compartment(prod / dev / test) 资源参数:compartment_id · 权限隔离与成本划分边界 IaC 映射:oci_identity_compartment 资源 + 变量传递 OCID 虚拟云网络 VCN(区间级资源,跨 AD) IaC 映射:oci_core_vcn · cidr_block · dns_label 可用域 AD-1 数据源动态获取 oci_identity_availability_domains 子网可绑定单个 AD 可用域 AD-2 区域子网跨 AD 自动分配 省略 availability_domain 高可用部署首选 可用域 AD-3 数据库 / Exadata fault_domain 参数控制 副本分布策略 故障域 FD-1 AD 内隔离组 数据库副本分布 故障域 FD-2 AD 内隔离组 Exadata 配置 故障域 FD-3 AD 内隔离组 高可用副本 全局 区间级 逻辑隔离 网络层 物理隔离 副本分布

IaC映射的实践要点

把上述层级映射到代码时,有几个关键决策点。第一,隔间划分策略:是按环境划分(dev/test/prod各一个隔间),还是按业务单元划分(网络隔间、应用隔间、数据库隔间)?前者适合小团队,后者适合多团队协作。第二,变量传递方式:隔间OCID、VCN OCID、子网OCID这些跨模块引用,建议通过output输出,再由根模块通过module引用,而不是在多个.tf文件中重复定义。第三,数据源的使用:AD和FD列表、镜像OCID、可用服务等动态信息,应通过data块获取,而不是写死。例如获取Oracle Linux镜像:

data "oci_core_images" "ol8" {
  compartment_id           = var.tenancy_ocid
  operating_system         = "Oracle Linux"
  operating_system_version = "8"
  shape                    = "VM.Standard.E4.Flex"
  sort_by                  = "TIMECREATED"
  sort_order               = "DESC"
}

这样每次执行terraform plan时,都会拉取最新的镜像OCID,避免因镜像过期导致创建失败。第四,资源依赖的显式声明:虽然Terraform能通过引用自动推断依赖,但在跨隔间、跨区间场景下,建议用depends_on显式声明,确保创建顺序正确。例如,子网依赖VCN,实例依赖子网和安全列表,数据库依赖子网和AD。

实践建议:在编写IaC之前,先用OCI控制台或CLI列出当前租户下的隔间树、每个区间的AD列表,以及目标隔间中已有的VCN和子网。将这些信息整理成一份“资源清单”,作为代码中变量和模块划分的依据。这样能避免代码写完后才发现隔间层级不对、AD名称不匹配等问题。

常见误区与排障思路

初学者最容易犯的错误是混淆全局资源与区间级资源。例如,试图在oci_core_vcn中指定region参数——实际上VCN的区间由Provider决定,不需要也不应该单独指定。另一个常见问题是隔间OCID硬编码,导致代码无法在不同环境复用。正确的做法是把隔间OCID作为变量,在terraform.tfvars中按环境赋值。如果遇到“NotAuthorizedOrNotFound”错误,通常是因为compartment_id指向了错误的隔间,或者当前用户没有该隔间的权限。此时应检查IAM策略中是否授予了manage或use权限,并确认隔间OCID是否拼写正确。

对于跨AD高可用部署,还需要注意区域子网与AD子网的混用。区域子网虽然方便,但某些服务(如特定Shape的裸金属实例)可能要求AD子网。在IaC中,可以通过条件表达式动态选择:

resource "oci_core_subnet" "app" {
  compartment_id      = var.compartment_ocid
  vcn_id              = oci_core_vcn.main.id
  cidr_block          = "10.0.1.0/24"
  availability_domain = var.use_regional_subnet ? null : data.oci_identity_availability_domains.ads.availability_domains[0].name
  display_name        = "app-subnet"
}

这样通过一个布尔变量控制子网类型,既保持了代码的灵活性,又避免了重复定义。总之,OCI资源模型与IaC的映射,核心在于层级清晰、引用准确、变量驱动。把租户、区间、隔间、AD、FD的关系在代码中显式表达出来,才能实现可复用、可审计、可治理的基础设施即代码。