Sägetstrasse 18, 3123 Belp, Switzerland +41 79 173 36 84 info@ict.technology

    Terraform @ Scale - 第 1a 部分:多租户 - 向组织单位和客户继承信息

    在跨组织边界扩展 Terraform 时,需要在标准化与灵活性之间保持谨慎的平衡。通过清晰的团队结构、完善的治理(Governance)、自动化的 CI/CD 流程以及合适的工具支持,即使是复杂的多租户(Multi-Tenant)基础架构也能得到高效管理。在此基础上,您可以将 Terraform 实践从单个团队扩展到整个组织,同时确保一致性、安全性和效率。

    本系列的第一部分将探讨在大型基础架构中,以 Infrastructure-as-Code 实现多租户能力的设计。

     

    Terraform at Scale - 处理大规模基础架构

    第 1a 部分:多租户 - 向组织单位和客户继承信息

    引言

    在现代云基础架构世界中,“多租户”(Multi-Tenancy)最初听起来像是某种流行语,在会议上被提及时,人们可能正在偷偷查看手机上的邮件。但对于那些在共享基础架构上服务数十甚至数百个不同租户、部门或客户的企业而言,这却是不可忽视的现实:随着租户数量的增加,复杂性呈非线性增长(通常是平方或立方级别),因为依赖关系和接口的数量成倍增加。

    想象一下,您需要管理 20 个独立的 Terraform 项目——每个项目都有自己的变量、State、后端和模块版本。

    再想象一下,您需要在这些项目之间共享基本的网络信息,而不使用复制粘贴的代码块,否则这些代码块在下一次修改时必然会产生偏差。

    如果这听起来还可以应对,那么请再加上组织管理的维度:想象一下,在这些不同的项目中,有不同的员工和 CI/CD 流水线在以 Infrastructure-as-Code 方式实施基础架构。可能它们甚至属于不同的企业部门,由各自的决策者和经理负责。

    欢迎来到 Terraform 的多租户管理世界。

    Resource Dependencies传统的 Terraform 方法在这里很快会遇到瓶颈。经典模式——一个代码库(Repository)、一个 State、一个 Workspace——在小规模环境下运作良好。但一旦您需要在逻辑上分离的基础架构区域之间共享信息,事情就会变得复杂。此时,以下问题将浮现:

    • 如何确保所有团队都能访问相同的基本网络配置?
    • 如何确保对这些基本配置的更改能够自动传播到依赖它们的团队?
    • 如何避免不同团队创建的配置相互重叠,甚至互相冲突,例如使用相同的网络地址?
    • 如何防止某个团队意外覆盖另一个团队的资源?
    • 随着复杂性的增加,如何保持整体架构的可见性和管理性?

    之前的一篇文章中,我们探讨了基础架构灾难如何轻易发生。Knight Capital 事件就是一个警示性的案例——由于仅在八台服务器上实施了不一致的基础架构部署,该公司损失了 4.6 亿美元。如果仅仅是一个小型系统的失误就能造成如此灾难性的后果,那么在复杂的多租户环境下,又该如何应对?

    好消息是,借助正确的模式和技术,可以有效管理这种复杂性。Terraform 提供的 Remote State 机制,能够在不同的基础架构领域之间共享信息,同时不会破坏租户的隔离性。

    在本系列的第一部分“Terraform at Scale”中,我们将重点讨论以下内容:

    • 如何有效利用 Terraform 来管理多租户环境?
    • 如何在组织单位之间有针对性地继承和传播关键信息?

    我们将介绍一些在客户项目中成功实施的实践模式,这些模式将帮助您将自己的 Terraform 基础架构提升到新的水平——而不会犯下 4.6 亿美元的错误。

     

    理解多租户(Multi-Tenancy) - 远不止于环境隔离

    当我们在云计算领域谈论多租户(Multi-Tenancy)或称“租户能力”时,许多人首先会想到完全隔离的环境:客户 A 拥有自己的网络,客户 B 拥有自己的网络,两者互不相交。这种理解并没有错,但在涉及 Infrastructure-as-Code(IaC)时,这种观点过于狭隘。

    在 Terraform 的上下文中,多租户不仅意味着资源的技术性隔离,还涉及代码、State 和工作流的组织结构。关键在于,我们如何通过基础架构模块化,使其能够真实反映组织的实际情况——无论是面向外部客户的服务提供商,还是拥有多个业务部门和项目的大型企业。

    逻辑 vs. 物理租户隔离

    在物理隔离模式下,每个租户都拥有专属的资源——独立的服务器、网络和存储系统。这种方式提供了最高级别的隔离性,但成本高昂,且在很多场景下过于严格。而逻辑隔离则基于共享的物理资源,通过应用层面的数据与访问控制来实现租户的分离。在实际应用中,我们通常会看到混合模式:

    • 网络层:每个租户拥有独立的 VPC 或子网,但共享底层物理基础架构
    • 计算层:每个租户拥有专属的虚拟机实例,但运行在共享的物理硬件上
    • 数据层:每个租户使用独立的数据库或 Schema,但数据库实例可能共享
    • 身份层:租户拥有独立的 IAM 策略和角色,但共享同一个身份管理系统

    借助 Terraform,我们可以灵活地定义这些不同的隔离层级,但必须谨慎设计跨层级的信息流。

    现实中的租户组织管理

    在实际应用中,租户结构往往并非单一维度。一个典型企业的组织架构可能如下:Coworkers

    • 业务部门(财务、人力资源、生产、销售)
    • 功能团队(开发、质量保证、运维)
    • 项目(通常跨业务部门)
    • 环境(开发、测试、生产)
    • 区域结构(受法律或延迟需求影响)

    这些组织维度相互交叉,因此我们的 Terraform 代码结构必须能映射这种复杂性。

    尽管 AWS 提供 Organizations、OCI 提供 Compartments 作为层级结构的解决方案,但我们的 Terraform 代码往往需要更加细粒度的组织方式。不同部门及其团队中的人员技能、责任范围各不相同,甚至在全球性企业中,文化背景、目标和期望也可能存在差异。

    这些因素导致代码组织的复杂性不可避免,甚至会带来意想不到的挑战——既有正面的,也有负面的。

    挑战之一在于,不同的组织维度会产生或需要不同的信息。例如:

    • 网络团队定义基础网络和子网,
    • 安全团队配置防火墙、策略和证书,
    • 存储团队管理文件存储、块存储、对象存储和备份,
    • 数据库团队提供数据库服务,
    • 应用团队需要访问这些信息,而无需重复定义。

    信息继承(Informationsvererbung)的问题

    这正是核心难题所在:如何确保基础架构的关键组件发生变更时,所有依赖的组件都能自动同步更新?

    • 如果网络团队修改了子网 CIDR,所有相关的虚拟机(VM)如何获知变更?
    • 如果新增了云区域,如何确保所有团队都采用相同的默认配置?

    在小规模环境中,我们可以将所有信息存储在一个单一的 Terraform State 中进行管理。然而,这种方式很快会导致一个“State 单体”(State-Monolith),带来以下问题:

    • 包含数百甚至数千个资源,导致管理复杂度上升
    • Terraform 计划(Plan)执行时间变慢
    • 可能出现一个团队无意中影响另一个团队资源的风险

    另一种极端方式——完全独立的 State 且不进行信息共享——又会带来:

    • 数据重复,
    • 配置不一致,
    • 以及我们都希望避免的“复制粘贴式 DevOps”

    幸运的是,Terraform 通过 Remote State(远程 State)提供了一种优雅的解决方案。在下一节中,我们将探讨如何利用 Remote State 来实现灵活、可扩展的信息继承,同时不影响租户隔离。

    Terraform Remote State

    Terraform 通过 State 文件(State File)存储基础架构的相关信息,该文件作为基础架构的单一真实数据源(Single Source of Truth)

    任何曾经意外删除本地 .tfstate 文件的人都深知其重要性。这一看似普通的文件实际上是 Terraform 的记忆库——一旦丢失,Terraform 就无法识别已有资源的状态,并可能尝试重新创建所有资源,往往会带来灾难性的后果。

    什么是 Terraform Remote State 及其用途?

    这带来了几个关键优势:

    • 协作:多个团队成员可以同时管理相同的基础架构,而无需手动交换 State 文件。
    • 安全性:State 文件通常包含敏感信息 - 通过集中存储可以提高安全性。
    • State 锁定(State-Locking):防止多个用户同时进行更改,以避免产生不一致性。
    • 信息共享:Remote State 可以作为其他 Terraform 项目的数据来源。

    大型基础架构中,这一点尤为重要。它使我们能够构建可扩展且模块化的架构

    • 每个团队或项目管理自己的 Terraform State,而无需直接在代码中添加对其他团队的依赖。
    • 共享的基础架构组件(例如网络、身份与访问控制、共享服务)可以通过 Remote State 由相应的责任团队提供。
    • 全局基础架构的变更可以自动传播到所有相关的下游项目。

    Remote State 在多租户架构中的重要性

    Terraform Remote States在典型的多租户环境中,基础架构由多个层级组成,相互依赖:

    1. 全局基础架构:核心网络、IAM 配置、共享服务
    2. 租户专属资源:数据库、应用服务器、存储方案等
    3. 应用层:租户的具体工作负载

    借助 Remote State,我们可以将这些层级清晰分隔,而无需在高层级重复存储低层级的基础信息。

    例如,应用团队可以访问由网络团队管理的网络信息,而无需在自己的 Terraform 配置中重新定义网络资源。

    Remote State 的实际应用

    我们来看一个实际的应用示例:

    • 中央基础架构团队在独立的 Terraform 项目中管理所有团队的核心网络配置和存储系统。
    • 中央安全运营中心(Security NOC)定义防火墙、访问控制策略和安全策略。
    • 数据库团队管理数据库,并为各个租户提供隔离的数据库分区。
    • 应用团队在自己的 Terraform 项目中使用这些网络信息、存储系统、安全策略和数据库,而无需重新定义它们。此外,不同的 Value Stream 之间可以通过 Remote State 共享数据。
    • 如果网络、存储、安全或数据库团队进行更改,这些变更会自动传播到所有相关的下游项目。

    data source "terraform_remote_state" 详解

    这一信息共享的核心是 terraform_remote_state 数据源。它允许一个 Terraform 项目访问另一个项目的 State。以下是一个简单的示例:


    data "terraform_remote_state" "network" {
      backend = "remote"
      config = {
        organization = "my-org"
        workspaces = {
          name = "network-global"
        }
      }
    }
    
    resource "cloud_instance" "app_server" {
      image_id      = "image-12345678"
      instance_type = "standard"
      subnet_id     = data.terraform_remote_state.network.outputs.private_subnet_id
    }

    在此示例中,应用团队访问由网络团队定义的子网 ID。需要注意的是,我们只能访问那些明确作为 output 定义的值——这确保了不同项目之间的清晰接口。

    另一个强大功能是,我们可以跨不同的 Backend 访问 State,从而在不同环境(例如 AWS 和 OCI)之间共享信息。对于采用多云战略的企业而言,这一特性极具价值。

    State 共享的安全性考虑

    虽然 Remote State 功能强大,但在安全方面需要特别关注。State 文件可能包含敏感数据:

    1. 访问控制:并非所有团队都应访问所有 Remote State。应利用后端存储的访问控制(如 S3 IAM 策略)。
    2. 敏感数据:State 文件可能包含密码等机密信息。应使用 Terraform 的 sensitive = true 保护输出,并考虑使用 HashiCorp Vault 存储关键机密。
    3. 加密:确保 State 文件在存储和传输过程中始终加密。
    4. 输出控制:仅通过 Outputs 公开真正需要的信息。每个 Output 都会创建依赖关系,并可能带来潜在的安全风险。不要在 Outputs 中包含敏感数据。一般情况下,应避免在 Outputs 中使用 sensitive = true,因为这些数据无法被继承。

    一种有效的模式是创建“接口 State”或“代理 State”,这些 State 仅用于提供精心筛选的信息,而不包含具体的基础架构资源定义。

    在接下来的章节中,我们将探讨 Multi-Tenancy 的实际架构,并演示如何利用 Remote State 继承信息。