Label Studio 接入 Microsoft Azure Blob Storage:源存储、目标存储与 Service Principal 完整配置指南
2026/9/13 7:33:18 网站建设 项目流程

Label Studio 接入 Microsoft Azure Blob Storage:源存储、目标存储与 Service Principal 完整配置指南

【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio

本指南围绕 Label Studio 开源仓库中的 Azure Blob 存储集成(storage_azure.md)展开,讲解如何将 Azure Blob Storage 容器同时配置为 Label Studio 的源存储(Source Storage,用于导入标注任务)与目标存储(Target Storage,用于导出标注结果),并覆盖 CORS 配置、存储账户密钥认证、本地部署环境变量以及 Enterprise 版的 Service Principal 认证方式。读完本文,你将能够从零完成 Azure Blob 与 Label Studio 的对接、校验连接、配置同步策略,并通过源码理解其底层数据流转机制。

前置概念:Label Studio 云存储的工作方式

在动手配置之前,先明确两个基础概念。Label Studio 中的云存储分为两类(详见 io_storages/README.md):

  • 导入存储(Source / Import Storage):从云存储容器中把数据文件或任务定义同步进项目,对应源码中的ImportStorage抽象基类;
  • 导出存储(Target / Export Storage):把标注结果写回云存储容器,对应ExportStorage抽象基类。

Azure Blob 在源码中由label_studio/io_storages/azure_blob/目录实现,其中 models.py 定义了AzureBlobImportStorage(导入)与AzureBlobExportStorage(导出)两个模型,URL scheme 为azure-blob

预签名 URL 与平台代理:两种数据加载方式

原文档特别强调了一个关键选择:Use pre-signed URLs(预签名 URL)Proxy through the platform(平台代理)两种模式,这决定了标注媒体文件如何从 Azure 流向标注者的浏览器:

  • 预签名 URL 模式:Label Studio 后端为容器对象生成带 SAS token 的临时 HTTPS 链接,浏览器直接向https://<account>.blob.core.windows.net/<container>/<blob>?<sas>发起请求(HTTP 303 重定向)。媒体流量不经过 Label Studio 服务器,速度更快、扩展性更好,但要求容器正确配置 CORS,且存储账户需要具备预签名(SAS 生成)权限。
  • 平台代理模式:后端从 Azure 下载文件后再以流式方式转发给浏览器,所有媒体流量都经过 Label Studio 服务器。数据始终停留在 Label Studio / 网络边界内,每次请求都会执行任务级访问权限检查,也无需配置 CORS,但会消耗更多 worker 资源,速度略慢。

从源码看,两种模式分别对应 models.py 中的generate_http_url()(生成 SAS 预签名 URL)与get_bytes_stream()AZURE.download_stream_response()流式下载)。UI 中的开关映射到模型的presign字段(默认True),预签名 URL 的有效期由presign_ttl字段控制(默认 1 分钟,UI 默认值 15 分钟,最小 1 分钟,见 form_layout.yml)。

第一步:为 Azure Blob 配置 CORS

如果你计划使用平台代理模式,可以跳过本节。只要使用预签名 URL,就必须配置 CORS。

  1. 登录 Azure 门户,进入存储账户(Storage account)页面;
  2. 从左侧菜单滚动到设置 > 资源共享(CORS)(Settings > Resource sharing (CORS));
  3. Blob service下添加如下规则:
配置项取值
Allowed originshttps://app.humansignal.com(或你实际使用的 Label Studio 域名)
Allowed methodsGET, HEAD, OPTIONS
Allowed headers*
Exposed headers*
Max age3600
  1. 点击保存

配置完成后,浏览器才能通过预签名 URL 跨域读取容器中的媒体对象。若使用 Service Principal 认证且同样启用预签名 URL,也必须在存储账户的 Blob service 上完成上述 CORS 配置。

第二步:使用存储账户密钥连接 Azure Blob Storage

这是 Label Studio 开源版(OSS)的标准接入方式。开始前,请先在 Azure 门户的存储账户资源页面收集以下三项信息:

  • 容器名称(Container Name):位于存储账户资源页数据存储 > 容器(Data storage > Containers)下;
  • 存储账户名称(Account Name):存储账户资源页顶部;
  • 访问密钥(Access Key):位于安全 + 网络 > 访问密钥(Security + networking > Access keys)下。

创建源存储连接(导入数据)

在 Label Studio 中打开项目,进入Settings > Cloud Storage > Add Source Storage,选择Azure Blob Storage并点击Next

配置连接(Configure Connection)

填写以下字段后点击Test connection验证连通性:

字段说明
Storage Title为该存储连接起一个用于标识的名称。
Container Name输入 Azure 存储容器名称,即上文在 Azure 控制台数据存储 > 容器下找到的名称。
Account Name输入 Azure 存储账户名称。
Account Key输入存储账户的访问密钥,位于安全 + 网络 > 访问密钥下。
Use pre-signed URLs (On) / Proxy through the platform (Off)决定容器数据如何加载:预签名 URL 模式生成指向 Azure 对象的临时 HTTPS 链接(浏览器直连,需正确 CORS 与预签名权限);平台代理模式由后端下载并流式转发(数据不离开 Label Studio 边界,每次请求都做任务级访问检查,但更耗 worker 资源)。
Expire pre-signed URLs (minutes)控制预签名 URL 的剩余有效分钟数。
导入设置与预览(Import Settings & Preview)

点击Load preview确认正在同步的数据符合预期:

字段说明
Bucket Prefix可选。填写容器内要使用的目录名,例如data-set-1data-set-1/subfolder-2
Import Method选择“为容器中每个文件创建一个任务”,或使用 JSON/JSONL/Parquet 文件来定义每个任务的数据。
File Name Filter填写正则表达式过滤容器对象,使用.*收集所有对象。
Scan all sub-folders开启后对容器内子文件夹执行递归扫描。
复核与确认(Review & Confirm)

确认无误后点击Save & Sync立即同步,或点击Save保存设置、稍后再同步。

创建目标存储连接(导出标注)

在 Label Studio 中打开项目,进入Settings > Cloud Storage > Add Target Storage,选择Azure Blob Storage并点击Next,填写以下字段:

字段说明
Storage Title输入用于标识该存储连接的名称。
Container Name输入 Azure 存储容器名称。
Container Prefix可选。填写容器内要使用的目录名,例如data-set-1data-set-1/subfolder-2
Account Name输入 Azure 存储账户名称。
Account Key输入存储账户访问密钥。
Can delete objects from storage开启后,当标注在 Label Studio 中被删除时,容器中对应的标注文件也会被删除。

添加完成后点击Sync推送导出数据。

本地部署:使用环境变量代替 UI 输入

如果你运行的是本地/自托管(on-prem)部署,可以不把密钥手动填进 UI,而是通过环境变量注入:

export AZURE_BLOB_ACCOUNT_NAME="<your-storage-account-name>" export AZURE_BLOB_ACCOUNT_KEY="<your-storage-account-key>"

源码中AzureBlobStorageMixin.get_account_name()get_account_key()(models.py)的逻辑是:优先使用模型字段account_name/account_key,字段为空时回退到环境变量。若两者都未提供,连接校验会抛出明确错误提示。底层连接使用 Azure Python SDK 的BlobServiceClient.from_connection_string(),构造的字符串格式为DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net(见 utils.py)。

同时要注意:AzureBlobImportStorageSerializeraccount_nameaccount_key标记为secure_fields(serializers.py),序列化返回时会主动移除这两个字段,避免密钥通过 API 响应泄露。

第三步(Enterprise):使用 Service Principal 认证连接 Azure Blob

Label Studio Enterprise 支持通过 Azure Service Principal 认证连接 Azure Blob Storage,无需使用存储账户访问密钥。该方式基于 Entra ID(原 Azure Active Directory)身份与访问管理,可授予细粒度权限并支持审计,且权限可随时撤销或轮换——相比拥有存储账户完全访问权的账户密钥,安全性更高。

注:本节为 Enterprise 专属能力,开源版(OSS)不支持。

前置条件

  • 一个 Azure 订阅和一个存储账户;
  • 有权限创建应用注册(App Registration)并在存储账户上分配角色;
  • 一个私有的数据容器(如无则先创建)。

在 Entra 中创建 Service Principal

1. 在 Entra 注册应用

  1. 打开 Microsoft Entra 管理中心;
  2. 右侧选择应用注册,点击新注册。填写名称、选择适当的账户类型,重定向 URI 可留空;
  3. 在“概述”页复制应用程序(客户端)ID目录(租户)ID
  4. 进入证书和机密,添加一个新的客户端机密,并复制值(Value)字段。

2. 在 Azure 中授予主体存储访问权限

返回 Azure 门户并进入你的存储账户:

  1. 从存储账户左侧选择访问控制 (IAM)
  2. 选择添加 > 添加角色分配
  3. 使用搜索框定位Storage Blob Data Contributor角色并点击选中;
  4. 选择上方成员标签页;
  5. 选择用户、组或服务主体,然后点击选择成员
  6. 在搜索框中找到之前创建的应用名称并点击选择
  7. 点击审阅 + 分配

3. 创建容器

  1. 仍在存储账户页面,点击左侧数据存储
  2. 选择容器
  3. 如没有容器,创建一个私有访问级别的新容器。

警告:如果计划使用预签名 URL,必须在存储账户 Blob service 上配置 CORS,详见上文“为 Azure Blob 配置 CORS”一节。

4. 所需权限清单

  • 源存储(Source Storage)需要:
    • Microsoft.Storage/storageAccounts/blobServices/containers/read
    • .../containers/blobs/read
  • 目标存储(Target Storage)需要:
    • .../containers/blobs/read
    • .../containers/blobs/write
    • .../containers/read
    • .../containers/blobs/delete(可选)

以上权限均包含在内置的Storage Blob Data Contributor角色中。

创建源存储连接(Service Principal)

进入Settings > Cloud Storage > Add Source Storage,选择Azure Blob Storage with Service Principal并点击Next

配置连接,填写后点击Test connection

字段说明
Storage Title输入该存储连接在 Label Studio 中显示的名称。
Storage Name输入 Azure 存储账户名称。
Container Name输入 Azure 存储账户内的容器名称。
Tenant ID填写应用注册中的目录(租户)ID
Client ID填写应用注册中的应用程序(客户端)ID
Client Secret填写之前复制的客户端机密
Use pre-signed URLs / Proxy through the platform启用或禁用预签名 URL。
Expiration minutes调整预签名 URL 的有效分钟数。

导入设置与预览复核与确认步骤与存储账户密钥方式完全一致:填写 Bucket Prefix、Import Method、File Name Filter、Scan all sub-folders 后点击Load preview校验,最后Save & Sync立即同步或Save稍后同步。

创建目标存储连接(Service Principal)

进入Settings > Cloud Storage > Add Target Storage,选择Azure Blob Storage with Service Principal并点击Next,填写:

字段说明
Storage Title输入该存储连接在 Label Studio 中显示的名称。
Storage Name输入 Azure 存储账户名称。
Container Name输入 Azure 存储账户内的容器名称。
Container Prefix可选,填写容器内要使用的目录名,例如data-set-1data-set-1/subfolder-2
Tenant ID填写应用注册中的目录(租户)ID
Client ID填写应用注册中的应用程序(客户端)ID
Client Secret填写客户端机密
Can delete objects from storage开启后,标注在 Label Studio 中被删除时,容器中对应对象也会被删除;凭据需具备删除容器对象的权限。

添加后点击Sync推送导出。

验证与排错

添加存储后连接会被自动检查,若失败请依次核实:

  • Tenant ID / Client ID / Client Secret:值是否正确(无多余空格、机密未过期);
  • 存储账户名与容器名:区分大小写,需严格匹配;
  • 角色分配:应用注册是否在存储账户上拥有Storage Blob Data Contributor角色;
  • CORS:使用预签名 URL 时必须配置;排查阶段可先切换到代理模式测试。

第四步:通过 Label Studio API 创建与同步存储

除了 UI,你还可以完全通过 REST API 以编程方式管理 Azure 存储连接。仓库中 api.py 与 urls.py 定义了完整的端点:

端点方法用途
api/storages/azure/GET / POST列出 / 创建 Azure 导入存储
api/storages/azure/<id>GET / PATCH / DELETE读取 / 更新 / 删除指定导入存储
api/storages/azure/<id>/syncPOST同步导入存储(拉取任务)
api/storages/azure/validatePOST校验导入存储连接
api/storages/azure/filesGET列出容器内文件
api/storages/export/azure/GET / POST列出 / 创建 Azure 导出存储
api/storages/export/azure/<id>GET / PATCH / DELETE读取 / 更新 / 删除指定导出存储
api/storages/export/azure/<id>/syncPOST同步导出存储(推送标注)
api/storages/export/azure/validatePOST校验导出存储连接

创建时使用type: "azure"标识 Azure 类型(由序列化器StorageTypeField(default='azure')保证)。例如创建一个 Azure 导入存储的请求体大致为:

{ "type": "azure", "title": "my-azure-source", "container": "my-container", "prefix": "data-set-1", "account_name": "<account-name>", "account_key": "<account-key>", "presign": true, "presign_ttl": 15, "regex_filter": ".*", "use_blob_urls": false, "recursive_scan": true, "project": 1 }

创建后调用对应端点的sync接口即可触发同步;校验接口则复用序列化器中的validate_connection()逻辑(serializers.py),异常会被提取为人类可读的错误信息返回。

源码视角:Azure 同步与数据流原理

理解底层实现有助于你在实际项目中排错与调优。

连接校验validate_connection()(models.py)会尝试读取容器属性,容器不存在时抛出KeyError('Container not found: ...');对于导入存储还会校验prefix前缀下是否存在 blob(list_blob_names(name_starts_with=prefix)),找不到则报告azure-blob://<container>/<prefix> not found

对象枚举与导入AzureBlobImportStorageBase.iter_objects()支持两种扫描模式——recursive_scan=True时用list_blobs全量递归;recursive_scan=False时用walk_blobs(delimiter='/')按层级遍历并跳过目录占位符。两种模式下都会应用regex_filter正则过滤(跳过不匹配的对象,见日志is skipped by regex filter)。get_data()则根据use_blob_urls决定导入方式:开启时把每个文件包装成azure-blob://<container>/<key>形式的任务数据(即“每个文件一个任务”);关闭时把 JSON/JSONL/Parquet 文件内容解析成任务定义(load_tasks_json)。

预签名 URL 生成generate_http_url()使用generate_blob_sas()生成带BlobSasPermissions(read=True)权限、有效期presign_ttl分钟的 SAS token,最终 URL 形如https://<account>.blob.core.windows.net/<container>/<blob>?<sas>

标注导出AzureBlobExportStorage.save_annotation()将标注序列化为 JSON,上传到prefix/key对应的 blob(upload_blob(..., overwrite=True)),并创建AzureBlobExportStorageLink建立映射。标注保存后通过 Djangopost_save信号触发异步导出(start_job_async_or_sync);删除标注时,若开启了can_delete_objects,会同步删除容器中对应对象(pre_delete信号 +delete_blob())。

同步状态机:每次同步都会驱动StorageInfo状态流转(queued → in_progress → completed / completed_with_errors / failed),同步失败时的 traceback、已同步任务数、耗时等元数据都会记录在存储连接的last_sync/last_sync_count/traceback/meta字段中(base_models.py),可在存储详情页或通过 API 查看。

流式媒体代理:代理模式下get_bytes_stream()解析azure-blob://URI,通过AZURE.download_stream_response()统一处理 HTTP Range 请求(支持bytes=start-end,包含Content-RangeETagLast-Modified等响应头),并以分块迭代器方式流式输出,避免大文件(音视频、高分图)整块加载占用内存。

常见问题速查

  • Test connection 报 “Container not found”:容器名拼写错误或大小写不匹配,检查 Azure 控制台中的准确名称。
  • 报 “prefix not found”prefix下没有对象,确认目录名正确且存在文件。
  • 预签名 URL 打开后浏览器报 CORS 错误:确认 Blob service CORS 规则中 Allowed origins 包含你的 Label Studio 域名,且方法包含GET, HEAD, OPTIONS
  • 导入时报 “JSONDecodeError / UnicodeDecodeError”:容器内混入了非 JSON 文件而导入方式仍为 “Tasks”,此时应在 Import Method 中开启 “Files” 模式(use_blob_urls=True)让每个文件成为一个任务。
  • 导出后容器中没有文件:确认目标存储已点击Sync,且prefix没有写错;导出由后台 RQ 任务异步执行,可在存储状态中查看last_synctraceback
  • Service Principal 连接校验失败:按“验证与排错”清单逐项核对 Tenant/Client/Secret、账户容器名大小写、角色分配与 CORS。

通过以上步骤,你已完成 Label Studio 与 Azure Blob Storage 的完整对接:既能从容器批量导入任务,也能把标注结果实时写回容器,实现数据标注流程与 Azure 云生态的无缝集成。

【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询