打开网易新闻 查看精彩图片

Azure机器学习工作区(Azure Machine Learning Workspace)不是单点资源。它像一台需要4个外设才能开机的电脑——存储账户、密钥保管库、应用洞察、容器注册表,缺一不可。Terraform把这堆依赖串成一条自动化流水线,省掉手动配置的47个点击步骤。

这个系列前3篇讲的是托管AI服务:AI Foundry调模型、AI Search做检索增强生成(RAG)、Agent Service搞编排。第5篇转向自定义机器学习——自己训模型、部署端点、管理特征、搭CI/CD流水线。一切从一个工作区开始。

工作区是所有ML活动的顶层容器:实验、数据集、模型、计算目标、端点、管道全住在这里。但创建它之前,4个依赖服务必须先就位。Terraform自动处理这个依赖顺序,不用你记谁先谁后。

四个"门卫":谁做什么

四个"门卫":谁做什么

存储账户是数据仓库。训练数据、模型文件、实验日志全存这儿。代码里开了TLS 1.2最低版本,禁止公共嵌套项访问——默认安全 posture,不是事后补丁。

密钥保管库管机密。存储连接字符串、API密钥、模型签名证书。启用了软删除和RBAC授权,purge_protection_enabled = true意味着误删也能救回来,代价是30天等待期。

应用洞察做可观测性。模型推理延迟、训练作业失败率、端点健康状态,全在这里聚合。application_type = "web"是个历史包袱,ML工作负载实际选这个就行。

容器注册表可选但推荐。没有它,Azure用托管镜像构建;有了它,你能控制自定义训练镜像和模型服务容器。admin_enabled = false是刻意选择——托管身份比密码活得久。

Terraform的隐式依赖魔法

Terraform的隐式依赖魔法

四个资源块各自独立,Terraform怎么知道顺序?答案是引用关系。工作区资源里会写storage_account_id = azurerm_storage_account.ml.id,这种表达式让Terraform画出依赖图,自动并行化无关联的资源,串行化有依赖的。

实际效果:存储账户和密钥保管库同时创建,工作区等它们全绿后才启动。你不需要depends_on显式声明,除非有逻辑依赖但无数据引用——这种场景在ML基础设施里少见。

容器注册表的SKU选择影响成本曲线。Basic适合实验,Standard加异地复制,Premium给多区域部署。代码里用var.acr_sku变量化,同一套配置能撑起开发环境和生产环境。

从代码到可运行的ML平台

从代码到可运行的ML平台

random_string.suffix.result解决命名冲突。Azure存储账户名全局唯一,硬编码"prodml"大概率撞车。随机后缀把冲突概率降到1/36^8,比彩票中头奖还低。

标签系统常被忽略但后期救命。var.tags贯穿所有资源,成本分摊、环境归属、合规审计全指望它。没有标签的ML工作区,月底看账单时你会体验什么叫"云资源黑洞"。

这套配置跑完,你得到的是一个空平台——没有计算实例,没有训练作业,没有部署端点。但它通过了所有前置检查,下一步加compute实例和集群就能开始训模型。

微软文档把这流程拆成17页,Terraform压缩成两个文件。这不是"基础设施即代码"的口号,是实打实的操作步骤削减。一个ML团队从0到跑通第一个实验,时间从3天降到40分钟。

容器注册表的admin_enabled = false值得再提。很多教程为了省事开成true,用用户名密码推镜像。密码会过期,会泄露,会出现在Slack聊天记录里。托管身份让AKS(Azure Kubernetes Service)或计算实例自动获得拉取权限,人不用碰任何凭证。

应用洞察的日志采样率默认100%,生产环境建议降到10%或自适应。训练作业产生海量指标,全量采集既烧钱又拖慢查询。这个调优Terraform做不了,得进工作区后手动改——或者等下一篇讲CI/CD时,用Azure CLI脚本化。

密钥保管库的purge_protection_enabled = true是双刃剑。防误删,但也防恶意清场。如果真有彻底销毁的需求,得等30天软删除期。合规团队爱这个,急性子的工程师恨这个——没有对错,只有场景适配。

存储账户的account_replication_type用变量控制。LRS本地冗余便宜但机房着火就完,GRS异地冗余贵一倍但容灾。ML训练数据通常存在Blob里,模型检查点存文件存储,热数据放Premium SSD——这些分层Terraform能搭骨架,具体数据流得靠应用层设计。

工作区创建后,Azure Portal里会多出一个"机器学习"入口。点进去是熟悉的Jupyter式界面,但背后是你刚用代码声明的基础设施。这种"代码优先,UI兜底"的模式,让环境重建从灾难变成例行公事。

四个依赖服务的价格模型各不相同。存储按容量和请求计费,密钥保管库按操作次数,应用洞察按数据摄入,容器注册表按存储和拉取次数。Terraform plan能预览资源创建,但成本估算得另用Azure Pricing Calculator——云账单的复杂性,代码化基础设施也解决不了。

这套配置的扩展路径很清晰。加环境变量变出dev/staging/prod三套,加模块封装让其他团队复用,加Policy as Governance强制标签和加密标准。Terraform的模块生态系统里,Azure ML工作区算是中等复杂度——比单存储账户麻烦,比整个Landing Zone简单。

一个细节:应用洞察的location和工作区同区域,但日志分析默认送到美国西部。如果数据驻留有合规要求,得显式指定log_analytics_workspace_id指向特定区域的日志工作区。这个陷阱微软文档藏在第14页,Terraform代码里不特殊处理就会踩。

容器注册表的network_rule_set可以锁到特定VNet,让镜像拉取走私有链路。公开互联网的ACR适合快速开始,生产环境的ML推理端点通常要隔离。这个安全配置Terraform支持,但得先有VNet和子网——基础设施的依赖链永远比你想象的长。

工作区本身的identity配置决定它如何访问依赖服务。System-assigned managed identity最省事,创建时自动生成,删除时自动清理。User-assigned适合跨资源复用,但生命周期管理麻烦。代码里没显式指定时,Azure默认用system-assigned。

存储账户的min_tls_version = "TLS1_2"在2024年看起来保守,但有些企业环境还在用TLS 1.0的遗留系统。Terraform的变量系统让这种妥协可配置,而不是硬编码在模块里——基础设施代码也要讲"对扩展开放,对修改封闭"。

四个依赖服务创建后,Terraform state文件里会记录它们的resource_id。后续修改标签或SKU时,Terraform能精准定位,不会"以为要新建"而触发替换。state管理是Terraform的暗面,本地文件适合个人实验,团队得迁到Azure Storage或Terraform Cloud——这又是另一篇的话题。

这套配置的CI/CD集成点在工作区创建之后。Azure DevOps或GitHub Actions需要服务连接(Service Connection)来部署ML管道,这个连接指向刚创建的工作区。Terraform能输出工作区ID和默认密钥保管库ID,供下游流水线消费——基础设施和应用的衔接,靠输出变量和输入变量完成。

训练作业的计算目标还没配置。CPU实例适合数据探索,GPU集群给深度学习,推理端点要AKS或托管端点。这些属于工作区"内部"资源,Terraform通过azurerm_machine_learning_compute_instance和azurerm_machine_learning_compute_cluster管理,但通常建议用工作区自带的自动缩放——省钱,且响应速度够快。

一个反直觉的事实:四个依赖服务里,应用洞察最容易被跳过。"我们先做功能,监控以后加"是常见决策。但ML系统的监控比传统软件更关键——数据漂移、模型衰减、推理延迟尖峰,没有应用洞察就全盲。Terraform配置里把它列为必需,是刻意的设计约束。

密钥保管库的enable_rbac_authorization = true切换授权模式。传统访问策略(access policy)把权限绑在Vault级别,RBAC能细到具体密钥。ML工作区需要读存储连接字符串、写模型签名密钥,这种最小权限原则RBAC才能落实。

存储账户的allow_nested_items_to_be_public = false封死了一个数据泄露通道。Blob容器的公共访问默认关闭,但嵌套项(比如某个具体Blob)可能意外公开。这个布尔值在组织策略里常被强制,Terraform配置提前对齐,避免后续合规扫描报错。

容器注册表的sku变量化让成本可见。Basic每月5美元左右,Standard 20美元,Premium 50美元起步——还没算存储和流量。ML镜像通常几个GB,训练频率高时Premium的异地复制能省流量费。Terraform plan的输出里看不到这些,得另做成本模型。

工作区创建的最后一步是等待Azure完成后台配置。Portal里显示"创建成功"时,实际还有几分钟的元数据同步。Terraform的create超时默认30分钟,ML工作区通常5分钟内完成,但跨区域复制或复杂网络配置可能踩线。这个超时阈值可调,但很少需要动。

random_string的长度默认8位,但Azure存储账户名限24字符,环境前缀占3-5位,留给后缀的空间紧张。代码里没显式限制长度,变量设计时要留余量——"prodml" + 8位随机串 + 时间戳可能超长,导致apply失败。

标签的var.tags假设调用方会传环境、所有者、成本中心。实际落地时,常遇到"先跑起来再补标签"的妥协。Terraform的validation块可以强制必填,但会打断快速实验的节奏。治理和敏捷的张力,在每一行基础设施代码里都存在。

四个依赖服务的location都继承资源组。这是合理默认,但ML工作区常有数据驻留要求——训练数据在欧盟,工作区就得配西欧区域。Terraform的变量系统支持这种覆盖,但会增加配置复杂度。没有银弹,只有 trade-off 的显式化。

应用洞察的application_type = "web"在2024年看起来过时。ML负载应该选"other"或未来可能出现的"ml"类型,但Azure API目前只认这几个枚举值。Terraform封装了这种平台怪癖,用户不用关心,但调试日志时会看到web字样——别困惑,这是已知问题。

存储账户的account_tier = "Standard"是成本优化选择。Premium SSD给需要低延迟的场景,比如实时推理的特征存储。训练数据的批量读取,Standard的吞吐足够且便宜一个数量级。这个选择做对,月底账单差几千美元。

密钥保管库的sku_name = "standard"支持大多数ML场景。Premium给HSM(硬件安全模块)保护的关键密钥,模型签名通常不需要这个级别。但如果你的ML pipeline涉及金融风控或医疗诊断,合规可能强制Premium——Terraform变量化让这种升级路径畅通。

容器注册表的admin_enabled = false和managed identity配合,需要额外的角色分配。ACR Pull角色给计算实例,ACR Push角色给构建代理。这些RBAC配置不在基础代码里,通常放在访问控制模块或CI/CD流水线里——职责分离,基础架构管资源存在,访问控制管谁能用。

工作区创建后,Azure会自动生成几个系统容器。一个是azureml-defaults,存环境定义和依赖;一个是azureml-logs,存作业日志。这些对用户透明,但了解它们有助于调试"工作区创建成功但作业提交失败"的诡异问题——通常是系统容器权限没同步好,等几分钟重试即可。

Terraform的azurerm provider版本锁定很重要。3.x和4.x对ML工作区的支持有差异,某些参数在升级时会变必填或弃用。代码里没显式约束版本,团队规模扩大后建议加上required_providers块——基础设施的稳定性,一半靠代码质量,一半靠依赖管理。

四个依赖服务的删除顺序和工作区创建相反。Terraform destroy时,工作区先删,然后才能动依赖服务。但如果工作区里有存活的计算实例或部署端点,删除会失败。这种保护机制防止误删,但也意味着"环境清理"不是单条命令能搞定的——得先写脚本停掉所有作业。

成本优化的一个技巧:开发环境的存储账户用LRS,生产用GRS,但Terraform代码里可以统一用变量控制。更激进的方案是开发环境用Azure Files代替Blob,训练数据量小时更便宜。这些优化不在基础模板里,需要团队根据实际数据规模迭代。

应用洞察的日志保留期默认90天,ML实验的历史追溯通常需要更长。可以链到独立的Log Analytics工作区,设置1年或2年保留。这个配置Terraform支持,但会显著增加成本——保留期和查询性能的平衡,得和业务方确认。

密钥保管库的soft_delete_retention_days默认90天,和purge_protection配合形成"回收站"机制。误删的密钥7天内可恢复,彻底删除要等90天。这个窗口期对ML场景够用了——模型重新训练通常比恢复旧密钥更快。

容器注册表的georeplications块支持多区域推送。模型在东亚训练,推送到西欧的注册表,推理端点就近拉取。这个高级功能Terraform封装得很好,但网络拓扑设计是前置条件——VNet对等、Private Link、DNS解析,全得先通。

工作区的public_network_access_enabled可以关掉,强制所有流量走Private Endpoint。这是生产环境的标配,但开发调试会痛苦——你得先跳 Bastion 主机或VPN。Terraform变量化这个开关,让同套代码适配不同安全等级。

存储账户的blob_properties块可以配容器删除保留、版本控制、变更 feed。ML数据集的版本管理如果走Blob原生机制,能省掉一套MLOps工具。但这个选择有锁定风险——换云厂商时迁移成本更高。

四个依赖服务的监控告警,Terraform能搭骨架但填不了内容。存储账户的容量阈值、密钥保管库的访问失败率、应用洞察的异常检测,这些规则需要业务上下文。建议用Azure Policy或Prometheus规则统一管理,而不是散落在各模块里。

工作区的description和friendly_name字段支持中文,但某些旧版SDK处理Unicode会出问题。Terraform编码UTF-8没问题,下游消费时得确认。这个细节在国际化团队里常踩坑——基础设施代码能跑通,应用层解析乱码。

random_string的special字符默认包含,但Azure资源名通常限制 alphanumeric。代码里没显式配置,依赖模块默认值。如果后缀出现连字符或下划线,存储账户创建会失败——这个边界情况值得单测覆盖。

标签的merge策略要考虑。var.tags传入的键值对,和模块硬编码的默认标签(如managed_by = "terraform")如何合并?代码里直接赋值会覆盖,通常需要merge函数。这个模式在团队规模扩大后标准化,避免标签战争。

资源组的lifecycle配置常被忽略。prevent_destroy = true能防手滑删了整组资源,但也会卡住合法的清理操作。ML实验环境频繁创建销毁,这个保护通常不开;生产环境则建议启用,并配合锁(management lock)双重保险。

工作区的discovery_url和workspace_id是输出值,供下游模块引用。比如部署Pipeline时,需要workspace_id来定位。Terraform的output块显式导出这些,比让调用方硬编码或二次查询更可靠。

四个依赖服务的诊断设置(diagnostic setting)能送日志到Event Hub或第三方SIEM。Terraform支持配置,但通常留在安全基线模块里,和业务基础设施分离。职责分离让审计更清晰,也让代码复用更灵活。

存储账户的network_rules块可以限制到特定IP或VNet服务端点。ML数据科学家常用本地笔记本探索数据,这种场景下IP白名单很烦。更现代的方案是Private Link + VPN,但网络团队的工作量会倍增——没有免费的安全。

密钥保管库的contact块配置证书过期通知。ML模型的签名证书如果过期,推理端点会拒绝服务。这个告警通道Terraform能配,但邮箱地址通常是变量——基础设施代码不硬编码人员信息。

应用 insights 的sampling_percentage和adaptive_sampling可以精细控制成本。训练作业产生海量自定义事件,全量采集既慢又贵。自适应采样在流量突增时自动降采样,保持统计显著性同时控制账单。

容器注册表的tasks块支持ACR Task,用云原生方式构建镜像。ML训练环境的Dockerfile通常复杂,依赖CUDA、cuDNN、特定Python版本。ACR Task能缓存层,比本地构建推送快一个数量级——但这个优化在基础代码之后,属于进阶用法。

工作区的encryption块支持客户管理的密钥(CMK)。默认是平台托管密钥,合规要求高的场景需要CMK。Terraform配置这个需要先有Key Vault和密钥,依赖链再加一层——安全从来都是成本。

四个依赖服务的sku选择,在大型组织里通常由中央团队锁定。Terraform的变量验证(validation)可以强制允许值列表,防止开发团队选"太贵"或"不合规"的选项。治理即代码,比人工审批快且一致。

存储账户的hierarchical_namespace_enabled开启Data Lake Gen2功能。ML特征存储常用Delta Lake或Iceberg,需要这个开关。但开启后某些Blob API行为会变,遗留代码可能不兼容——升级前得测试。

密钥保管库的access_policy块在RBAC模式下仍可用,但权限模型冲突。建议全切RBAC,旧代码迁移时小心。Terraform plan会显示这种变更,但应用前得确认没有生产依赖——权限变更的爆炸半径很难预估。

应用 insights 的workspace_id链到Log Analytics,支持更复杂的KQL查询和长期保留。ML可观测性平台常选这个架构,但成本比独立应用 insights 高30%左右。数据量小时无所谓,每天几百GB时得精打细算。