1.6.13.1. ModTM Provider:Terraform 模块遥测 Provider

在大型组织或社区中,往往会维护一系列可重复使用的 Terraform 模块。然而,随着模块数量和使用规模的扩大,模块治理面临诸多挑战。团队负责人和模块维护者通常难以回答以下问题:哪些模块被广泛使用?哪些版本仍在生产中?是否有模块已经无人使用、可以弃用?如果没有有效的数据支持,这些决策只能依赖于猜测或手工统计,既不准确也不及时。缺乏对模块使用情况的可见性,会导致模块重复建设、未及时升级甚至安全合规隐患。

Azure 在推动 Azure Verified Modules (AVM) 等最佳实践过程中,深刻认识到 “遥测” 对于模块治理的重要性。通过对模块使用数据的收集和分析,维护者才能基于事实做决策。这催生了 Terraform 模块遥测 Provider ModTM 的出现。ModTM 由 Azure 提供的一个 Terraform 插件,用于解决大规模模块治理中的 使用跟踪 问题。

1.6.13.1.1. ModTM 简介:它是什么?

ModTM(Terraform Module TeleMetry) 是一个专门用于收集 Terraform 模块使用数据的 Terraform Provider 插件。它引入了一个自定义资源类型 modtm_telemetry,当你在模块中包含该资源时,ModTM 会在模块的生命周期操作(创建、更新、删除等)发生时,将预先定义在模块内的 标签数据 通过 HTTP POST 请求发送到指定的遥测接收端。简单来说,ModTM 为 Terraform 模块添加了遥测能力,让模块 “自己报告” 它的使用情况和生命周期事件。

ModTM 的目标是 提升对模块生命周期的可见性,帮助了解模块的使用模式:哪些模块被频繁部署,哪些版本最受欢迎,哪些模块可能已经不再被使用,用户分别在哪些区域使用模块。这些数据对于模块治理非常有价值,可以用于识别出 广受欢迎的模块(重点维护)以及 长期未使用的模块(考虑下架或重构)。同时,ModTM 强调 数据隐私和控制,它只收集用户自行定义的标签以及一个模块实例的 UUID,用于标识实例,没有收集任何其他环境或资源敏感信息。通过让使用者明确要上报哪些数据,ModTM 将遥测的主动权交给了用户。

需要注意的是,ModTM 是一个 轻量级、非侵入式 的解决方案。它不会对基础设施本身产生影响,也不依赖云端资源部署,仅通过 Terraform Provider 的机制在计划执行过程中发送 HTTP 请求。其实现确保对 Terraform 部署流程 无阻碍,即使在没有网络或受限网络环境下,遥测发送失败也不会导致 Terraform 执行报错或中断(最多延迟几秒并记录日志)。正因如此,使用 ModTM 不会影响现有基础设施的正常部署和运行,兼顾了数据收集与系统稳定。

1.6.13.1.2. 核心原理:如何收集与传输遥测数据

ModTM 的工作原理 可以分为模块端和服务端两部分:

  • 客户端(Terraform Provider):当你在模块中配置了 modtm_telemetry 资源,Terraform 在执行 apply 时,ModTM Provider 会拦截模块的生命周期事件。在模块 创建(Create)更新(Update)销毁(Delete) 时,ModTM Provider 将预先定义的一组标签作为 Json 负载,通过 HTTP POST 发送到指定的遥测服务端 URL。这些标签通常包括:模块的名称或来源、版本号、部署所处环境信息等,由用户在模块中自行指定。

  • 服务端(遥测收集服务):Azure 提供了对应的遥测接收服务实现。例如,在 Azure Verified Modules 方案中,ModTM 默认将数据发送到一个由 Azure 托管的 Web 服务,该服务再将遥测数据转发存储到 Azure Application Insights(Azure 的云端应用监控服务)。Application Insights 用于集中记录和分析这些遥测日志,维护者可以在其中查询模块的使用情况。例如,可以根据模块名 / 版本统计使用次数,按订阅 ID 汇总模块部署数量,或跟踪模块实例的生命周期(创建于何时,销毁于何时)。

为什么不直接将数据发送到 Application Insights 呢?因为 ModTM 希望成为一个平台无关的中立解决方案,不希望将自己绑定在 Azure 平台上,所以使用了 HTTP 发送数据。任何希望部署私有遥测数据收集服务的用户都可以自行实现一个 HTTP 服务端,然后将收集到的数据以需要的方式保存起来。

Azure 官方将 ModTM 描述为 “轻量级的遥测提供程序,通过 HTTP POST 前端服务将遥测数据发送到 Azure Application Insights”。这一架构保证了模块代码中 不直接嵌入 任何敏感的 Telemetry 密钥。模块只是把数据发送到公开的接收端 URL,真正的 Azure 监控凭据仅保存在服务端。对于企业用户而言,如果不希望遥测数据发送到微软托管的服务,ModTM 也支持自定义 发送端点(endpoint) 和筛选规则。例如,你可以在 Provider 配置中指定自己的接收服务 URL,以及限定仅收集特定来源的模块数据。默认情况下,Azure 提供的 ModTM 已内置了官方遥测服务的 URL 和允许列表,确保使用 Azure Verified Modules 的用户开箱即用。

数据内容与隐私控制 方面,ModTM 采用完全由用户定义的 标签(tags) 机制。你可以选择收集哪些数据作为标签键值对,比如模块标识、版本、所在 Azure 订阅或租户、部署区域等。官方示例中,一般会收集 Azure 环境的订阅 ID、租户 ID,以及模块的来源和版本,再加上一个随机 UUID 来标识每个模块实例。例如,某模块可能定义如下标签:

tags = {
  subscription_id = one(data.azurerm_client_config.telemetry).subscription_id
  tenant_id       = one(data.azurerm_client_config.telemetry).tenant_id
  module_source   = one(data.modtm_module_source.telemetry).module_source
  module_version  = one(data.modtm_module_source.telemetry).module_version
  random_id       = one(random_uuid.telemetry).result
  location        = var.location
}

上述标签中,subscription_idtenant_id 表明了部署该模块的 Azure 环境,module_sourcemodule_version 则由 ModTM 自动提取当前模块的源地址和版本号(通过 modtm_module_source 数据源或 Provider 内置函数),random_id 是生成的模块实例 UUID,每次部署保持不变,而 location 则是模块使用者提供的地域参数。你也可以根据需要添加更多业务相关标签(例如环境类型、使用者团队等),以丰富遥测信息。ModTM 不主动收集任何未经声明的数据,只有这些用户提供的标签和 UUID 会被打包发送。如果用户出于隐私考虑不想上报某些信息,可以选择不将其作为标签,或 完全关闭遥测

1.6.13.1.3. 使用 ModTM:在模块中集成遥测

ModTM 的设计使其易于集成到 Terraform 模块中。以下是使用 ModTM 的基本步骤和示例:

  1. 在模块中声明 ModTM Provider 确保在模块的 terraform 配置中要求了 ModTM 提供程序。例如,在模块的 terraform.tf 文件里添加:

    terraform {
      required_providers {
        modtm = {
          source  = "Azure/modtm"
          version = "~> 0.3"
        }
      }
    }
    

    这样 Terraform 会下载 Azure 提供的 modtm 插件(版本 0.3.x)。Azure 官方的模块规范强制要求包含此配置,甚至在模块代码审核(linter)时检查 ModTM 是否被正确声明。

  2. 添加遥测配置开关 一般建议模块提供一个布尔变量(如 enable_telemetry)让用户可以控制是否启用遥测。Azure 模块中该变量默认值为 true(开启),并在文档中明确说明设置为 false 时将不收集任何遥测。这既尊重用户选择,也方便在某些环境(如离线环境)关闭不必要的网络通信。

  3. 在模块中定义 ModTM 资源 创建 main.telemetry.tf 或等价的 Terraform 配置文件,在其中使用 ModTM 的数据源和资源。例如:

    data "azurerm_client_config" "telemetry" {
      count = var.enable_telemetry ? 1 : 0
    }
    
    data "modtm_module_source" "telemetry" {
      count       = var.enable_telemetry ? 1 : 0
      module_path = path.module
    }
    
    resource "random_uuid" "telemetry" {
      count = var.enable_telemetry ? 1 : 0
    }
    
    resource "modtm_telemetry" "telemetry" {
      count = var.enable_telemetry ? 1 : 0
      tags = {
        subscription_id = one(data.azurerm_client_config.telemetry).subscription_id
        tenant_id       = one(data.azurerm_client_config.telemetry).tenant_id
        module_source   = one(data.modtm_module_source.telemetry).module_source
        module_version  = one(data.modtm_module_source.telemetry).module_version
        random_id       = one(random_uuid.telemetry).result
        location        = var.location
      }
    }
    

    上述代码采用了 条件计数(count) 技巧:当 enable_telemetry 为 false 时,这些数据源和资源的 count0,相当于完全不创建,从而实现一键关闭遥测的效果。反之,当开启时,ModTM 会在 Terraform 部署该模块时:调用 azurerm_client_config 获取订阅和租户 ID;利用 data.modtm_module_source 自动读取模块的 sourceversion 属性;创建 random_uuid 以生成 模块实例唯一标识;最后执行 modtm_telemetry 资源。每当该模块实例被创建、更新或销毁时modtm_telemetry.telemetry 都会向预设的端点发送包含上述标签的 HTTP 请求,从而记录下一条遥测日志。

    特别说明的是,data.modtm_module_source.telemetry 通过在运行时读取 path.module 获得当前模块在部署时所处的路径,从此路径向上层逐层寻找在 .terraform/modules/modules.json 文件,根据路径从中匹配到自身的 sourceversion 信息返回给调用者。该信息不但可以和 modtm Provider 搭配使用,还可以被用在其他遥测数据方面。例如,AzAPI 中可以设置 create_headers 等数据,我们可以定义这样的 azapi_resource 块:

    resource "azapi_resource" "example" {
    type      = "Microsoft.ContainerRegistry/registries@2020-11-01-preview"
    name      = "registry1"
    parent_id = azurerm_resource_group.example.id
    
    location = azurerm_resource_group.example.location
    identity {
      type         = "SystemAssigned, UserAssigned"
      identity_ids = [azurerm_user_assigned_identity.example.id]
    }
    
    body = {
      sku = {
        name = "Standard"
      }
      properties = {
        adminUserEnabled = true
      }
    }
    
    tags = {
      "Key" = "Value"
    }
    create_headers = {
     User-Agents = "module_source=${one(data.modtm_module_source.telemetry).module_source},module_version=${one(data.modtm_module_source.telemetry).module_version}"
    }
     update_headers = {
     User-Agents = "module_source=${one(data.modtm_module_source.telemetry).module_source},module_version=${one(data.modtm_module_source.telemetry).module_version}"
    }
     read_headers = {
     User-Agents = "module_source=${one(data.modtm_module_source.telemetry).module_source},module_version=${one(data.modtm_module_source.telemetry).module_version}"
    }
     delete_headers = {
     User-Agents = "module_source=${one(data.modtm_module_source.telemetry).module_source},module_version=${one(data.modtm_module_source.telemetry).module_version}"
    }
    
    response_export_values = ["properties.loginServer", "properties.policies.quarantinePolicy.status"]
    }
    

    这样,使用该模块时,通过 azapi_resource.example 发出的增删查改方法,都会在 User-Agents 中附带模块名称和版本信息,这就可以帮助微软在后台确认哪些对 API 的调用是源自于 AVM 模块的,分别源自于哪些模块,版本分布等等非常有用的信息。

    对于 Terraform 1.5+ 的新特性,也可以省略数据源,直接调用 ModTM Provider 提供的函数获取模块来源和版本。例如官方也支持 provider::modtm::module_source(path.module) 这样的语法。无论采用哪种方式,最终都将在不影响主要资源部署的情况下,将模块使用信息发送出去。

  4. 验证与运行 将模块发布并应用后,可以通过查看 Azure Application Insights(如果使用官方端点)或者你自建的遥测服务日志,验证是否成功收到了遥测数据。因为 ModTM 是 非阻断 的,它不会在 Terraform 输出中打印明显的成功 / 失败信息 —— 除非出现网络错误会记录日志提示。通常你可以在日志服务端看到类似 “收到模块 X 版本 Y 的遥测,订阅 ID=..., 时间=...” 的记录,证明 ModTM 工作正常。

借助以上步骤,模块作者几乎无需编写任何复杂代码,就能为模块插上 “遥测之眼”。所有 ModTM 引入的资源(数据源和随机 UUID)都是本地性质的,不会在云中创建额外资源,也不会影响模块对基础设施的主要功能。对于使用模块的最终用户而言,除了在 Terraform 执行时可能产生一个很小的 HTTP 请求流量外,对部署过程和结果几乎无感知。

1.6.13.1.4. 模块治理的价值:数据驱动的决策与优化

在引入 ModTM 之前,模块维护者往往缺乏可靠数据来改进和管理模块。如今,通过 ModTM 收集的遥测数据,可以极大提升 模块治理 的科学性和效率:

  • 使用模式分析:维护团队可以借助 Application Insights 等工具,对收集到的日志进行分析。例如统计某模块每天 / 每月被部署的次数,当前有多少模块实例在各个订阅中存在等。这些数据有助于判定某模块的受欢迎程度和使用趋势。对于使用频率高的模块,可以投入更多资源持续优化;而使用率低甚至为零的模块,可能反映功能冗余或者文档不足,需进一步调查。

  • 版本和升级治理:由于 ModTM 捕获了模块的版本信息,维护者可以了解用户仍在使用哪些旧版本模块。例如发现某旧版本仍有大量实例未升级,就可以评估其原因(也许升级阻力,兼容性问题)并制定相应策略。反之,如果遥测显示大部分用户都已迁移到新版本,则可以考虑 退役 旧版本模块或功能。通过这种方式,大规模模块库的版本迭代和生命周期管理将更加有据可循。

  • 模块依从性和规范推广:在企业内部署中,架构团队常规定使用经过认证的标准模块。ModTM 可以帮助追踪这些标准模块的采用情况。例如,通过收集的 module_source 标签,可以辨别团队是否使用了公司提供的模块源。如果某些团队自行 fork 了模块,遥测中将不会出现相应记录。这是因为团队在 fork 模块时,可能会在模块的 source 路径中包含隐私数据,所以必须对 source 进行严格的限制,避免收集不该收集的数据。虽然 ModTM 本身无法直接发现 “未使用模块” 的情况,但它为 已采用标准模块 的范围提供了量化依据,从侧面推动规范的落实。

  • 异常与问题追踪(间接收益):虽然 ModTM 主要收集使用量数据,但配合时间序列分析,也能间接发现一些异常情况。例如如果某模块的创建 / 销毁事件频繁出现异常峰值,可能提示该模块的资源在抖动(频繁部署和销毁)或者某自动化流程在不停重试。维护者据此可以进一步排查模块是否存在设计问题或使用误区。这类洞察依赖于对遥测数据的深入分析,但一旦建立,对提高模块质量和稳定性很有帮助。

  • 决策透明度与沟通:有了数据支撑,模块的演进决策可以更加透明地与利益相关者沟通。例如在提议弃用某模块时,维护者可以引用遥测统计证明 “过去 6 个月内该模块无新部署且实例数为零”,让决策更易于被接受。同样地,在向管理层展示 DevOps 改进成果时,也可利用模块采用率提升等指标来量化价值。

综上所述,ModTM 为 Terraform 模块生态引入了重要的 遥测反馈环路。模块不再是 “黑盒” 投入使用后就无迹可寻,维护者能够像产品经理对待软件应用那样,持续关注模块的 “用户行为” 数据,从而进行数据驱动的改进。这在大规模模块治理情境下尤为关键 —— 当模块数量众多、用户分散时,只有借助自动化的遥测收集才能全面掌握全局情况。

值得一提的是,Azure 官方在其 Azure Verified Modules 模板中已默认集成了 ModTM,并 默认启用 遥测收集。使用这些模块的用户在遵循开源许可的同时,也帮助模块维护团队收集了宝贵的匿名使用数据(当然用户有权通过变量配置随时关闭)。模块代码仓库中也清楚地包含了数据收集声明和隐私提示,确保符合合规要求。对于广大 Terraform 模块开发者来说,即使不在 Azure 环境,ModTM 这种模式也具有借鉴意义 —— 通过一个轻量级遥测工具,社区和企业可以构建起模块使用的度量体系,提升模块治理水平。

1.6.13.1.5. 总结

ModTM (Terraform Module TeleMetry) 的出现,填补了 Terraform 模块治理中的一块空白。它以简洁的方式解决了模块使用数据采集的难题,帮助大型组织在 DevOps 工具链中实现了 模块级别的遥测。通过 ModTM,我们能够更好地了解 “基础架构即代码” 世界里的模块使用动态,这对优化模块、改进架构以及推动标准化都有显著价值。对开发者而言,ModTM 易于使用、对正常部署零干扰,并提供了高度的自主和隐私控制,是在大规模模块治理中值得信赖的工具。正如官方文档所言,ModTM 为 Terraform 模块赋予了数据洞察能力,使我们能够在保证隐私和稳定性的前提下做出更加明智的决策。借助 ModTM,大型 Terraform 模块库的管理正迈向 更加可视化和智能化 的未来。

results matching ""

    No results matching ""