使用 App Lifecycle Manager 进行变量和变量映射

本文档介绍了变量、变量映射和依赖项在 App Lifecycle Manager 中的运作方式。

App Lifecycle Manager 可让您将复杂的 SaaS 应用整理成模块化单元,从而部署和管理这些应用。这些单元由蓝图中的 Terraform 配置定义,可以通过依赖项相互连接,从而实现复杂的编排和自动预配。管理这些单元及其交互的一个关键方面是通过变量和变量映射。

您可以通过自动预配、单元间通信和灵活的配置选项,构建复杂、模块化且可伸缩的部署。请仔细考虑变量层次结构、依赖关系和变量映射,以优化 App Lifecycle Manager 中的 SaaS 架构和管理工作流。

单位和变量

App Lifecycle Manager 的核心是单元。单元利用变量来自定义其部署和行为。这些变量本质上是 Terraform 变量,您可以在蓝图的 variables.tf 文件中定义。它们允许您对 Terraform 配置进行参数化,使其可在不同环境和部署中重复使用和调整。

单元预配的必需变量

虽然您可以为单元定义自定义变量,但 App Lifecycle Manager 也会依赖一组强制性变量。即使这些变量未在 Terraform 配置中明确定义,App Lifecycle Manager 也会自动识别和处理这些变量。

强制性变量包括:

  • project_id 和 project_number(或 tenant_project_id 和 tenant_project_number):此变量指定将部署单元资源的 Google Cloud 项目 ID。您可以使用 project_id 和 project_number,也可以使用 tenant_id 和 tenant_project_number。此字段对于在正确的 Google Cloud 项目中创建和管理资源是必需的。

    您可以在 Google Cloud 控制台的信息中心页面上找到项目 ID。在 Cloud 概览部分的项目信息卡片中找到项目 ID 字段。

  • project_number 或 tenant_project_number:与 project_id 类似,此变量表示 Google Cloud 项目编号。您可以交替使用 project_number 或 tenant_project_number。

    您可以在 Google Cloud 控制台信息中心页面的 Cloud 概览部分中的项目信息卡片中找到项目编号和项目 ID。

  • actuation_sa:此变量表示执行服务账号的邮箱。此服务账号是用户管理的服务账号,App Lifecycle Manager 会在预配、更新或取消预配单元时,使用该服务账号(通过 Infrastructure Manager)执行 Terraform 配置。

    我们建议您为每个租户(或单元)使用专用的执行服务账号,以遵循最小权限原则。这可以限制安全事故的潜在影响,并在部署之间提供更好的隔离。

    如需详细了解如何配置执行启动操作的服务账号并向其授予权限,请参阅 App Lifecycle Manager 服务账号。

单元变量层次结构

您可以定义单元变量,并从多个位置获取这些变量。使用 App Lifecycle Manager 时,请务必了解单元操作期间使用的变量值的层次结构。

顺序如下(优先级从最低到最高):

App Lifecycle Manager 会按以下顺序解析变量值:

  1. 单元上的现有输入变量:如果变量已在单元资源本身上定义(例如,来自先前的操作或配置),则此值的优先级最低。如果直接在单元上设置变量值,则当在层次结构中更高级别的来源中找到值时,该值将被覆盖。

  2. 发布默认值:如果单元上尚未设置变量,则会应用发布默认值,但这些值会覆盖现有的单元变量。

  3. 单元操作:执行单元操作(例如 provision 或 upgrade)时,您可以明确提供输入变量作为操作请求的一部分。单元操作中提供的变量将覆盖发布默认值和现有单元变量。

  4. 依赖项的输入变量映射:当某个单元依赖于其他单元时,单元种类中定义的变量映射可以从依赖单元的输出变量中获取变量值。这是优先级最高的来源。通过依赖项映射获取的变量将覆盖单元操作、发布默认值和现有单元变量中的值。

这种分层方法可让您灵活地控制变量管理。您可以直接在单元上建立持久配置(优先级最低),使用版本定义基准默认值,针对特定操作进行自定义,并从单元依赖项中动态获取最重要和覆盖的值(优先级最高)。

单元依赖项

借助 App Lifecycle Manager,您可以定义单元之间的依赖关系。这对于构建不同组件相互依赖的复杂 SaaS 应用非常重要。依赖项可确保以协调的方式预配和管理相关单元。

您可以在单元种类中定义依赖项。当您创建特定单元种类的单元时,App Lifecycle Manager 会自动管理其依赖项。

单元种类中的依赖项定义

在 UnitKind 定义中,您需要指定一个依赖项列表,其中每个依赖项都引用另一个 UnitKind 并为其分配一个别名。此别名用于在变量映射中引用依赖项:

  message UnitKind {
    // ... other fields ...

    // List of other unit kinds that this release will depend on.
    repeated Dependency dependencies = 4
        [(.google.api.field_behavior) = OPTIONAL];
    // ...
  }

  message Dependency {
    // The unit kind of the dependency.
    string unit_kind = 1 [
      (.google.api.field_behavior) = REQUIRED,
      (.google.api.field_behavior) = IMMUTABLE,
      (.google.api.resource_reference) = {
        type: "saasservicemgmt.googleapis.com/UnitKind"
      }
    ];

    // An alias for the dependency. Used for input variable mapping.
    string alias = 2 [(.google.api.field_behavior) = REQUIRED];
  }

自动依赖项预配

当您请求预配在其 UnitKind 中定义了依赖项的单元时,App Lifecycle Manager 会自动检查这些依赖项单元是否存在。

如果未找到依赖单元,App Lifecycle Manager 会在预配依赖单元之前自动预配该依赖单元。

App Lifecycle Manager 可确保在依赖单元之前预配依赖单元,从而保持正确的操作顺序。

变量映射

变量映射是一种在依赖单元及其依赖项之间传递数据(变量值)的机制。这对于根据依赖项的输出配置依赖单元至关重要。

变量映射在依赖单位类型中定义,并使用 FromMapping 和 ToMapping:

  • FromMapping:FromMapping 用于从依赖单元检索输出变量,并将其映射到依赖单元的输入变量。这样,依赖单元就可以从其依赖项获取信息,例如连接端点或资源 ID。

    message VariableMapping {
      // ...
      oneof mapping_type {
        // Output variables which will get their values from dependencies
        FromMapping from = 2 [(.google.api.field_behavior) = OPTIONAL];
        // ...
      }
    }
    
    message FromMapping {
      // Alias of the dependency that the outputVariable will pass its value to
      string dependency = 1 [(.google.api.field_behavior) = REQUIRED];
    
      // Name of the outputVariable on the dependency
      string output_variable = 2 [(.google.api.field_behavior) = REQUIRED];
    }
    

    在提供的 Codelab 示例中,App UnitKind 具有 FromMapping,用于从 Cluster UnitKind 依赖项中检索 cluster_endpoint 输出变量。这样,应用就可以连接到新预配的 Kubernetes 集群。

  • ToMapping:ToMapping 用于将输入变量从依赖单元传递到依赖项单元的输入变量。这样,您就可以根据为依赖单元提供的参数来配置依赖单元。

    message VariableMapping {
      // ...
      oneof mapping_type {
        // ...
        // Input variables whose values will be passed on to dependencies.
        ToMapping to = 3 [(.google.api.field_behavior) = OPTIONAL];
      }
    }
    
    message ToMapping {
      // Alias of the dependency that the inputVariable will pass its value to
      string dependency = 1 [(.google.api.field_behavior) = REQUIRED];
    
      // Name of the inputVariable on the dependency
      string input_variable = 2 [(.google.api.field_behavior) = REQUIRED];
    
      // Tells EasySaaS if this mapping should be used during lookup or not
      bool ignore_for_lookup = 3 [(.google.api.field_behavior) = OPTIONAL];
    }
    

    在此 Codelab 中,App UnitKind 使用 ToMapping 将 tenant_project_id 和 tenant_project_number 输入变量传递给 Cluster UnitKind 依赖项。这可确保在正确的项目中创建 Kubernetes 集群。

  • ToMapping 中的 ignore_for_lookup:ToMapping 中的 ignore_for_lookup 字段用于控制依赖项查找行为。这是一个布尔值:

    • false(或未指定):如果设置为 false,App Lifecycle Manager 会将 ToMapping 中指定的输入变量用作查找键,以查找现有依赖项单元。如果找到具有匹配输入变量的单元,则该单元将作为依赖项重复使用。如果未找到匹配的单元,系统将预配新的依赖项单元。这对于重复使用集群等共享资源非常有用。
    • true:如果设置为 true,则 ToMapping 中的输入变量不会用于依赖项查找。这意味着,即使具有相同输入变量的单元已存在,系统也始终会预配新的依赖项单元。当您需要为每个依赖单元提供专用、非共享的依赖项时,此方法非常有用。

示例:共享 Kubernetes 集群

如果您想在同一项目中为多个应用单元重复使用 Kubernetes 集群,则可以使用 ToMapping,并将 ignore_for_lookup 设置为 false,然后将 tenant_project_id 和 region 等变量映射到集群单元类型。然后,同一项目和区域中的单元将重复使用同一集群。

示例:每个应用一个专用 Kubernetes 集群

如果您需要为每个应用单元提供一个专用 Kubernetes 集群,则可以使用 ToMapping,并将 ignore_for_lookup 设置为 true,或者完全避免使用 ToMapping 查找变量。然后,每个应用单元都会触发一个新的、隔离的 Kubernetes 集群的预配。

管理密文

App Lifecycle Manager 变量不适用于存储密码、API 密钥或证书等敏感信息。直接在变量中存储 Secret 会带来安全风险。变量值可能会被记录下来,并可能通过系统输出暴露,从而增加未经授权访问的几率。

为了在 App Lifecycle Manager 应用中安全地管理 Secret,我们强烈建议您使用 Secret Manager。

后续步骤