3. 组织与项目结构设计
在 Google Cloud 上做平台工程,最先要解决的不是“用什么服务”,而是“资源放在哪里、权限在哪里继承、成本由谁承担”。Google Cloud 的资源层次结构(Resource Hierarchy)正是这一切的骨架:组织(Organization)→ 文件夹(Folder)→ 项目(Project)→ 资源(Resource)。IAM 策略、组织策略(Org Policy)、配额、结算与审计日志都沿着这条链自上而下继承。理解继承方向,是设计“多团队项目工厂”的前提。
继承规则可以概括为一句话:父节点的允许策略向下继承,子节点只能在此基础上收紧,不能放宽被父级拒绝的边界。例如在组织层授予某用户 roles/viewer,该用户在所有文件夹和项目中都拥有查看权限;而在组织层用 Org Policy 设置 constraints/compute.vmExternalIpAccess 为拒绝,则任何子项目都无法创建带外部 IP 的虚拟机,除非在更高层被显式放开(通常不允许)。因此,越靠上的节点越应承载“不可协商的边界”,越靠下的节点越应承载“团队自治的灵活性”。
上图展示了典型的“多团队项目工厂”骨架:组织下按环境划分文件夹,文件夹下按服务划分项目,项目内承载具体资源;标签则横向切分,用于成本与筛选。下面把这条链上的关键设计决策逐一展开。
文件夹:环境隔离与策略分层的载体
文件夹不是“目录”,而是策略继承的中间层。推荐按“环境”或“业务域”建立第一层文件夹,例如 fld-prod、fld-dev、fld-shared。生产文件夹上可以绑定更严格的 Org Policy,例如禁止外部 IP、强制使用 CMEK、限制可用区域;开发文件夹则允许更宽松的试验。这样,新项目只要挂到对应文件夹下,就自动获得正确的边界,无需逐项目重复配置。
文件夹的另一个价值是权限委派。可以把“生产环境管理员”角色授予某个团队,但只绑定在 fld-prod 上,而不是组织层。这样该团队只能管理生产文件夹内的项目,无法触碰开发或其他业务域。对于平台团队而言,这意味着可以安全地把“项目创建”能力下放给各团队,而平台团队只保留组织层和文件夹层的策略控制。
项目:自助服务的原子单元
项目是资源、结算、配额和 API 启用的基本单位。在项目工厂中,每个项目应遵循统一命名:prj-<服务名>-<环境>,例如 prj-order-prod、prj-pay-dev。项目 ID 全局唯一且不可更改,因此命名规范必须在创建前确定。建议同时维护一份“项目元数据表”,记录项目 ID、所属文件夹、负责人、成本中心、创建时间与用途,作为后续审计和成本分摊的依据。
项目创建不应手工完成,而应通过基础设施即代码(IaC)或内部开发者平台(IDP)触发。一个可复用的项目工厂流程通常包含:创建项目 → 挂载到指定文件夹 → 启用所需 API → 绑定默认服务账号 → 应用标签 → 配置结算账户 → 设置预算告警。这些步骤可以用 Terraform 模块封装,团队只需提交一份参数文件即可获得合规项目。
# 项目工厂 Terraform 模块调用示例(示意)
module "project_factory" {
source = "./modules/project-factory"
project_id = "prj-order-prod"
folder_id = "folders/1234567890" # fld-prod
billing_account = "012345-6789AB-CDEF01"
labels = {
env = "prod"
team = "order"
cost-center = "CC-1024"
}
apis = ["compute.googleapis.com", "container.googleapis.com", "sqladmin.googleapis.com"]
}
这段配置的输入是项目 ID、文件夹、结算账户、标签和需要启用的 API;输出是一个已挂载、已启用 API、已打标签的项目。团队不需要知道底层如何创建,只需要填写参数。这就是“自助服务”的核心:把合规性封装进模板,把选择权留给团队。
标签:横向切分与成本可见性
资源层次结构是纵向的,而标签是横向的。一个项目只能属于一个文件夹,但可以同时拥有多个标签。标签的典型用途包括:成本分摊(cost-center)、环境识别(env)、团队归属(team)、合规等级(data-class)。标签应尽量在项目层统一设置,并向下继承到资源;对于无法继承的资源(如部分网络资源),需要在创建时显式打标。
标签策略需要治理:定义一套受控的键值集合,避免出现 env=prod 与 environment=production 混用。可以借助 Org Policy 的 constraints/gcp.resourceLocations 或标签策略(Tag Policy)来限制允许的标签值。成本分析时,按 cost-center 聚合即可得到各团队的实际支出,而不必依赖项目命名的人工解析。
IAM 边界:谁能在哪里做什么
IAM 的核心是“成员 + 角色 + 资源”三元组。在项目工厂中,建议遵循最小权限与职责分离:
- 组织层:只授予平台团队的组织管理员、安全团队的审计员,以及少数需要全局可见性的角色。
- 文件夹层:授予环境管理员(如
roles/resourcemanager.folderAdmin)和网络管理员,使其能管理该环境下的项目,但无法跨环境。 - 项目层:授予团队自己的开发者角色(如
roles/editor或更细粒度的自定义角色),以及服务账号的roles/iam.serviceAccountUser。 - 资源层:对敏感资源(如密钥、数据库)使用条件绑定(IAM Conditions),限制访问来源或时间。
一个常见的误区是把 roles/owner 授予整个团队。Owner 包含结算和 IAM 管理权限,风险极高。更安全的做法是:团队拥有 roles/editor 用于日常开发,平台团队保留 roles/owner 用于结算和 IAM 变更。对于需要自助创建项目的团队,可以授予文件夹级的 roles/resourcemanager.projectCreator,并结合 Org Policy 限制可创建的项目位置和标签。
可扩展项目工厂的落地要点
把上述结构组合成一个可扩展的工厂,需要关注三点。第一,模板化:项目创建、文件夹挂载、API 启用、标签设置全部通过 IaC 模块完成,避免手工操作带来的漂移。第二,策略前置:把安全与合规要求写在组织层和文件夹层的 Org Policy 中,而不是依赖项目创建后的检查。第三,可观测:为每个项目自动启用审计日志,并将日志汇聚到组织级的日志桶,便于统一检索和告警。
当团队数量从几个增长到几十个时,这套结构的优势会显现:新增团队只需在对应文件夹下创建项目并绑定标签,权限和策略自动继承;平台团队无需逐项目审批,只需维护文件夹层和模板。资源层次结构、文件夹、项目、标签与 IAM 边界共同构成了自助服务的“骨架”,而项目工厂则是让这套骨架可复制、可治理的“生产线”。