Label Studio 接入 Google Cloud Storage(GCS)完整指南:源/目标存储配置、WIF 与 GKE 服务账号模拟
2026/9/12 22:24:18 网站建设 项目流程

Label Studio 接入 Google Cloud Storage(GCS)完整指南:源/目标存储配置、WIF 与 GKE 服务账号模拟

【免费下载链接】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 开源仓库的官方指南 storage_gcp.md 与 GCS 存储模块源码(io_storages/gcs),系统讲解如何将 Google Cloud Storage(GCS)桶接入 Label Studio:既作为源存储动态导入标注任务,也作为目标存储回传标注结果,同时覆盖预签名 URL 与平台代理两种数据加载模式、Workload Identity Federation(WIF)临时凭据方案、GKE 服务账号模拟方案以及 IP 过滤加固。读完本文,你可以独立完成从 GCS 桶权限配置、CORS 设置到 Label Studio 内源/目标存储连接创建与同步的完整落地,并理解每一步背后的源码实现。

GCS 在 Label Studio 中的角色与整体工作流

Label Studio 支持将外部存储动态接入项目:源存储(Source Storage)用于扫描桶中的对象并生成标注任务,目标存储(Target Storage)用于在标注完成后把注解写回桶中。官方文档 Cloud storage for projects 指出,每个源/目标存储连接都是项目级的,同一个项目可以挂接多个桶作为源或目标。

从源码看,GCS 支持在 GCSImportStorage(导入)与 GCSExportStorage(导出)两个模型上实现,它们共享 GCSStorageMixin 提供的公共字段:

模型字段对应 UI 表单说明
bucketBucket NameGCS 桶名称
prefixBucket Prefix桶内目录前缀,如data-set-1data-set-1/subfolder-2
regex_filterFile Filter Regex用于过滤桶内对象的正则表达式
use_blob_urlsImport Methodtrue表示"每个对象创建一个任务"(Files 模式);false表示把 JSON/JSONL 当作任务定义(Tasks 模式)
google_application_credentialsGoogle Application Credentials服务账号凭据 JSON 的文本内容(安全字段,序列化时会被剔除)
google_project_idGoogle Project ID桶所在的 Google 项目 ID

导入存储还有三个特有字段(GCSImportStorageBase):presign(默认True,控制是否生成预签名 URL)、presign_ttl(预签名 URL 有效期,分钟)、recursive_scan(是否递归扫描子目录)。

第一步:配置 GCS 桶的访问权限

在 Label Studio 中创建任何 GCS 连接之前,需要先完成三项前置工作(详见 storage_gcp.md)。

1. 启用对桶的程序化访问

按照 Google Cloud Storage 的 Client Libraries 文档为你的 GCS 桶配置程序化访问。Label Studio 后端实际通过google-cloud-storagePython 客户端与 GCS API 交互(见 io_storages/gcs/utils.py),因此对桶的 API 访问能力是硬性前提。

2. 设置认证与 IAM 角色

你的账号必须具备以下权限:

  • 项目级Service Account Token Creatorroles/iam.serviceAccountTokenCreator)角色
  • 项目级Storage Object Viewerroles/storage.viewer)角色
  • 桶级storage.buckets.get访问权限

如果使用 WIF(Workload Identity Federation)方案,则按后文 WIF 服务账号权限 配置。

3. 配置 CORS

仅当使用预签名 URL时才需要配置 CORS——因为标注者的浏览器会直接向 GCS 发起跨域 GET 请求。如果使用平台代理模式,则无需 CORS(详见 storage.md 中 Pre-signed URLs vs Storage proxies)。

官方推荐的 CORS 配置示例如下。先用echo生成cors-config.json

echo '[ { "origin": ["*"], "method": ["GET"], "responseHeader": ["Content-Type","Access-Control-Allow-Origin"], "maxAgeSeconds": 3600 } ]' > cors-config.json

再将YOUR_BUCKET_NAME替换为真实桶名并应用:

gsutil cors set cors-config.json gs://YOUR_BUCKET_NAME

在生产环境中,建议把origin收敛为 Label Studio 部署的实际域名,而不是*

第二步:使用 Google Application Credentials 建立标准 GCS 连接

这是社区版即可用的基础方案,认证基于服务账号的长期 JSON 密钥。

获取凭据 JSON 文件

在 Google Cloud Console 中依次操作:

  1. 进入IAM & Admin > Service Accounts
  2. 选择需要凭据的服务账号(没有则新建);
  3. 在账号详情页进入Keys标签,点击Add Key > Create new key
  4. 选择JSON密钥类型并点击Create,浏览器会自动下载生成好的 JSON 文件。

如果使用服务账号授权访问 GCP,请确保已通过gcloud auth activate-service-account激活该账号。

创建源存储连接

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

Configure Connection(连接配置)

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

字段说明
Storage Title用于标识该存储连接的名称
Bucket NameGCS 桶名称
Google Application Credentials你创建的服务账号凭据 JSON 内容。On-prem 用户可留空,改用GOOGLE_APPLICATION_CREDENTIALS环境变量或 Application Default Credentials(ADC),让用户无需手动配置凭据(见下文 ADC 章节)
Google Project ID桶所在 Google 项目的 ID(如my-label-studio-project),可在 Console 的IAM & Admin > Settings中查看
Use pre-signed URLs (On) / Proxy through the platform (Off)决定数据加载方式,详见下文"预签名 URL 与平台代理"章节
Expire pre-signed URLs (minutes)控制预签名 URL 的有效时长(表单默认 15 分钟,对应form_layout.ymlpresign_ttlvalue: 15

这些字段与源码模型一一对应:Test connection会调用 GCS.validate_connection,该函数用当前凭据创建客户端、get_bucket校验桶存在,若填写了 prefix 还会用list_blobs(prefix=..., max_results=1)检查该前缀下是否有对象,没有则抛出No blobs found错误。

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开启后递归扫描容器内所有子目录

其中 Import Method 对应源码中的use_blob_urls字段:Files模式下get_data()直接构造{settings.DATA_UNDEFINED_NAME: 'gs://bucket/key'}形式的任务(models.py);Tasks模式下则读取 JSON/JSONL 内容并调用load_tasks_json解析(models.py)。File Name Filter 对应regex_filter,在 GCS.iter_blobs 中通过re.compile(str(regex_filter))编译后逐对象匹配,不匹配的对象直接跳过;Scan all sub-folders对应recursive_scan,为Truelist_blobs不带delimiter递归列举全部对象,否则以delimiter='/'仅列出当前层级。

Review & Confirm(确认与同步)

确认无误后点击Save & Sync立即同步,或点击Save保存设置稍后再同步。也可以调用 import storage sync API 触发同步。

创建目标存储连接

进入Settings > Cloud Storage > Add Target Storage,选择Google Cloud Storage并点击Next,填写:

字段说明
Storage Title存储连接名称
Bucket NameGCS 桶名称
Bucket Prefix可选。导出注解时写入的桶内目录
Google Application Credentials同源存储说明
Google Project ID桶所在项目 ID
Can delete objects from storage开启后,在 Label Studio 中删除标注时同步删除桶中的注解对象,要求凭据具备删除对象的权限

保存后点击Sync完成导出连接配置。

目标存储的写入逻辑在源码中非常清晰:标注被保存(post_save信号)后,export_annotation_to_gcs_storages 会通过 Redis 异步任务把注解写入所有关联的 GCS 导出存储;GCSExportStorage.save_annotation 把注解序列化为 JSON,按prefix + '/' + key作为对象名blob.upload_from_string(json.dumps(ser_annotation))上传。删除时,delete_annotation_from_gcs_storages 会检查storage.can_delete_objects,只有开启该选项才真正调用blob.delete()——这正是 UI 上"Can delete objects"选项的源码级验证(对应测试见 test_cloud_export_race_and_delete.py)。

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

源存储创建时有一个关键开关:Use pre-signed URLs (On) / Proxy through the platform (Off),它决定标注媒体数据如何从桶加载到标注者的浏览器(详见 storage.md)。

对比项预签名 URL(默认开启)平台代理(关闭预签名)
数据流Label Studio 生成带时效的 HTTPS 链接,浏览器收到 HTTP 303 重定向后直接从云存储下载媒体后端从云存储下载文件后流式转发给浏览器,流量全部经过 Label Studio 服务器
性能通常更快、可扩展性更好占用更多 Label Studio worker 资源,可能稍慢
配置要求需要桶上配置正确的 CORS 和签名权限无需 CORS、无需签名权限
安全边界媒体文件尽量与 Label Studio 网络隔离数据始终处于 Label Studio/网络边界内,每次请求都执行任务级访问检查,缓存文件也会受访问控制约束
大文件以 8 MB 分块流式传输(见下文环境变量)

从源码看,预签名由 GCS.generate_http_url 实现:presign=True时调用blob.generate_signed_url(version='v4', expiration=timedelta(minutes=presign_ttl), method='GET')生成 v4 签名 URL;presign=False时则把对象下载下来编码为data:...;base64,...的 data URL。presign开关保存在GCSImportStorage.presign字段(默认True,见 models.py)。

如果开启平台代理模式,需要保证凭据具备以下 GCS 权限:storage.objects.get(读取对象数据与元数据)以及storage.objects.list(使用前缀时列举对象)。

对于 on-prem 部署,大文件流式传输按顺序以 8 MB 分块拆分为多个 GET 请求,可通过以下环境变量调优(定义于 core/settings/base.py):

  • RESOLVER_PROXY_BUFFER_SIZE:缓冲大小,默认 512 KB
  • RESOLVER_PROXY_TIMEOUT:单请求最大耗时,默认 20 秒
  • RESOLVER_PROXY_MAX_RANGE_SIZE:单次请求返回的最大分块大小,默认 8 MB
  • RESOLVER_PROXY_GCS_DOWNLOAD_URL:GCS 下载端点模板,默认https://storage.googleapis.com/download/storage/v1/b/{bucket_name}/o/{blob_name}?alt=media
  • RESOLVER_PROXY_GCS_HTTP_TIMEOUT:GCS HTTP 请求超时,默认 5 秒
  • RESOLVER_PROXY_ENABLE_ETAG_CACHE/RESOLVER_PROXY_CACHE_TIMEOUT:ETag 缓存开关(默认开启)与缓存时长(默认 3600 秒)

使用 Application Default Credentials 增强安全

对于 on-prem 部署,可以不为每个存储连接手动粘贴凭据 JSON,而是通过Application Default Credentials(ADC)在平台层面全局提供云存储认证。推荐方式是通过GOOGLE_APPLICATION_CREDENTIALS环境变量指向凭据 JSON 文件:

export GOOGLE_APPLICATION_CREDENTIALS=json-file-with-GCP-creds-23441-8f8sd99vsd115a.json

源码层面的支持见 GCS.get_client:当google_application_credentials为空时,直接以gcs.Client(project=google_project_id)构造客户端,底层自动回落到 ADC;只有显式提供了凭据 JSON 时,才通过service_account.Credentials.from_service_account_info()解析为服务账号凭据。此外,设置项GCS_CLOUD_STORAGE_FORCE_DEFAULT_CREDENTIALS(默认False,见 base.py)用于控制签名 URL 时是否强制使用默认凭据:开启后,仅当未提供google_application_credentials时才尝试从环境加载 ADC 凭据。

Google Cloud Storage 与 Workload Identity Federation(WIF)

WIF 方案(对应 UI 中的Google Cloud Storage (WIF Auth))与长期应用凭据不同:它使用临时凭据——每次向 GCS 发起请求时,Label Studio 都会连接你的身份池(identity pool)换取临时凭据,避免长期密钥的保管与轮换风险。该功能属于企业版能力。

WIF 服务账号权限

你需要一个具备以下权限的服务账号:

  • 桶级Storage Adminroles/storage.admin
  • 项目级Service Account Token Creatorroles/iam.serviceAccountTokenCreator
  • 项目级Storage Object Viewerroles/storage.viewer

创建 Workload Identity Pool

官方文档提供了三种创建方式:Terraform、gcloud 命令行、Google Cloud Console。

方式一:Terraform

官方示例脚本(原文完整版见 storage_gcp.md)基于 AWS 托管的 HumanSignal Label Studio 身份进行信任配置,需要预先设置以下变量:

  • GCP 项目变量:var.gcp_project_namevar.gcp_region
  • HumanSignal 托管的 SaaS 标识:var.aws_account_id = "490065312183"var.aws_role_name = "label-studio-app-production"

然后依次执行:

terraform init terraform plan terraform apply

脚本核心逻辑是:创建google_iam_workload_identity_pool(如label-studio-pool-${random_id})与google_iam_workload_identity_pool_provider(AWS 类型),通过attribute_condition校验attribute.aws_role(可选叠加external_id条件),并通过google_service_account_iam_bindingroles/iam.workloadIdentityUser授予principalSet://...attribute.aws_role/arn:aws:sts::490065312183:assumed-role/label-studio-app-production。应用成功后即获得一个信任 Label Studio AWS IAM Role 的可用 WIF 池,并输出GCP_WORKLOAD_IDGCP_WORKLOAD_PROVIDER

方式二:gcloud 命令行

将方括号变量([PROJECT_ID][POOL_ID][PROVIDER_ID]等)替换为实际值,注意引号转义。

  1. 创建身份池:

    gcloud iam workload-identity-pools create [POOL_ID] \

--project=[PROJECT_ID]
--location="global"
--display-name="[POOL_DISPLAY_NAME]"

- `[POOL_ID]`:池 ID(如 `label-studio-pool-abc123`),之后需要复用; - `[PROJECT_ID]`:Google Cloud 项目 ID; - `[POOL_DISPLAY_NAME]`:池的人类可读名称(可选但推荐)。 2. 创建 AWS 提供方(provider)。由于发起请求的 Label Studio 资源托管在 AWS,必须允许具有正确 external ID 与 AWS role 的 AWS 主体模拟 Google 服务账号: ```shell gcloud iam workload-identity-pools providers create-aws [PROVIDER_ID] \ --workload-identity-pool="[POOL_ID]" \ --account-id="490065312183" \ --attribute-condition="attribute.aws_role==\"arn:aws:sts::490065312183:assumed-role/label-studio-app-production\"" \ --attribute-mapping="google.subject=assertion.arn,attribute.aws_account=assertion.account,attribute.aws_role=assertion.arn,attribute.external_id=assertion.external_id"
  • [PROVIDER_ID]:提供方 ID(如label-studio-app-production)。
  1. 为前面创建的服务账号授予iam.workloadIdentityUser角色:

    gcloud iam service-accounts add-iam-policy-binding [SERVICE_ACCOUNT_EMAIL] \ --role="roles/iam.workloadIdentityUser" \ --member="principalSet://iam.googleapis.com/projects/[PROJECT_NUMBER]/locations/global/workloadIdentityPools/[POOL_ID]/attribute.aws_role/arn:aws:sts::490065312183:assumed-role/label-studio-app-production"
    • [SERVICE_ACCOUNT_EMAIL]:GCS 服务账号邮箱(如my-service-account@[PROJECT_ID].iam.gserviceaccount.com);
    • [PROJECT_NUMBER]:Google 项目编号(与项目 ID 不同),可通过gcloud projects describe $PROJECT_ID --format="value(projectNumber)"查询。

配置完成后,在 Label Studio 建连前请记下这些值:[POOL_ID][PROVIDER_ID][SERVICE_ACCOUNT_EMAIL][PROJECT_NUMBER][PROJECT_ID]

方式三:Google Cloud Console

  1. 进入IAM & Admin > Workload Identity Pools,点击Get Started启用相关 API;

  2. Create an identity pool中填写Name(即池 ID,如label-studio-pool-abc123,需记住)与Description

  3. Add a provider pool中选择AWS作为提供方(Label Studio 发起请求的组件所在位置),Provider name 可自定义显示名,但Provider ID 必须为label-studio-app-productionAWS Account ID 填入490065312183

  4. Configure provider attributes中:

    • 添加条件:attribute.aws_role=="arn:aws:sts::490065312183:assumed-role/label-studio-app-production"
    • 添加映射:google.subject = assertion.arnattribute.aws_role = ...(含assumed-role的提取表达式,可能已默认填好)、attribute.aws_account = assertion.accountattribute.external_id = assertion.external_id
  5. 点击Save

  6. IAM & Admin > Service Accounts找到允许 AWS(Label Studio)模拟的服务账号,在其Principals with access标签页点击Grant Access

  7. New principals中填入:

    principalSet://iam.googleapis.com/projects/[PROJECT_NUMBER]/locations/global/workloadIdentityPools/[POOL_ID]/attribute.aws_role/arn:aws:sts::490065312183:assumed-role/label-studio-app-production

    [PROJECT_NUMBER]IAM & Admin > Settings查看,[POOL_ID]为第 2 步填写的 Name)

  8. Assign Roles中搜索并选择Workload Identity User角色,点击Save

同样需要记下:池 ID、提供方 ID(应为label-studio-app-production)、服务账号邮箱、Google 项目编号、Google 项目 ID。

创建 WIF 源存储连接

在项目中进入Settings > Cloud Storage > Add Source Storage,选择Google Cloud Storage (WIF Auth)并点击Next,填写:

字段说明
Storage Title连接名称
Bucket NameGCS 桶名称
Workload Identity Pool ID创建身份池时指定的 ID,可在 Console 的IAM & Admin > Workload Identity Pools查看
Workload Identity Provider ID设置提供方时的 ID,同样在IAM & Admin > Workload Identity Pools查看
Service Account Email前置步骤中服务账号的邮箱(如labelstudio@random-string-382222.iam.gserviceaccount.com),在IAM & Admin > Service Accounts的 Details 页查看
Google Project ID项目 ID,IAM & Admin > Settings查看
Google Project Number项目编号,IAM & Admin > Settings查看
Use pre-signed URLs (On) / Proxy through the platform (Off)数据加载方式,同标准 GCS 说明
Expire pre-signed URLs (minutes)预签名 URL 有效期

随后完成Import Settings & Preview(Bucket Prefix / Import Method / File Name Filter / Scan all sub-folders,含义与标准 GCS 一致),确认后点击Save & SyncSave。WIF 导入存储也有对应的 sync API。

创建 WIF 目标存储连接

选择Google Cloud Storage (WIF Auth),除上述字段外还包含Can delete objects from storage(开启后删除标注时同步删除桶内注解,要求凭据具备删除权限)。保存后点击Sync

GCS 与 GKE 场景下的服务账号模拟(SA Impersonation)

当 Label Studio 部署在 Google Kubernetes Engine(GKE)上时,工作负载通常通过 GKE Workload Identity 将 Kubernetes 服务账号映射到 Google Cloud 服务账号,但该直接绑定的服务账号未必对你的 GCS 桶有足够权限。服务账号模拟允许工作负载的 GCP 服务账号临时"扮演"另一个权限更充足的账号,全程无需创建、分发和轮换长期密钥,降低了凭据泄露风险。该功能需企业版并在 GKE 中部署。

该方案涉及两个 Google Cloud 项目:基础 GKE 项目(Label Studio 部署所在,由平台管理员一次性配置)与目标项目(GCS 桶所在,由数据团队配置)。

配置 GKE 项目(平台管理员一次性操作)

启用 feature flag

必须在 Label Studio 部署中启用fflag_feat_bros_763_gcs_sa_impersonationfeature flag。可通过 Helm chart 的 extraEnvironmentVars 注入:

global: extraEnvironmentVars: fflag_feat_bros_763_gcs_sa_impersonation: "true"

注意:环境变量名必须小写,Label Studio 的 feature flag 解析器以区分大小写的方式匹配fflag_前缀。

创建基础服务账号

在 GKE 项目中创建将作为 Label Studio Pod 身份的服务账号(如lse-base),创建时无需授予额外角色,记下其邮箱(如lse-base@your-gke-project.iam.gserviceaccount.com)——这就是后续与数据团队共享的基础服务账号邮箱

将基础服务账号绑定到 Kubernetes 服务账号
  1. 为 Label Studio 使用的 Kubernetes 服务账号添加 Workload Identity 注解:

    kubectl annotate serviceaccount label-studio-sa \ --namespace=label-studio \ iam.gke.io/gcp-service-account=BASE_SA_EMAIL
  2. 授予 Workload Identity User 角色,使 K8s 服务账号能以 GCP 服务账号身份工作:

    gcloud iam service-accounts add-iam-policy-binding BASE_SA_EMAIL \ --role="roles/iam.workloadIdentityUser" \ --member="serviceAccount:GKE_PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
    • BASE_SA_EMAIL:基础服务账号邮箱;
    • GKE_PROJECT_ID:GKE 项目 ID;
    • NAMESPACE:Label Studio 所在命名空间(如label-studio);
    • KSA_NAME:Label Studio 使用的 Kubernetes 服务账号名(如label-studio-sa)。
  3. 验证绑定:运行测试 Pod,输出中应显示基础服务账号邮箱为当前活跃账号:

    kubectl run workload-identity-test \ --image=google/cloud-sdk:slim \ --serviceaccount=label-studio-sa \ --namespace=label-studio \ -it --rm -- gcloud auth list

Terraform 等价配置(原文完整版见 storage_gcp.md):

resource "google_service_account" "lse_base" { project = "your-gke-project" account_id = "lse-base" display_name = "Label Studio Base SA" } resource "google_service_account_iam_member" "workload_identity_binding" { service_account_id = google_service_account.lse_base.name role = "roles/iam.workloadIdentityUser" member = "serviceAccount:your-gke-project.svc.id.goog[label-studio/label-studio-sa]" }

配置目标 Google Cloud 项目

Step 1:在目标项目创建服务账号

在桶所在项目中创建 Label Studio 将模拟访问数据的服务账号(如sa-label-studio-data),记下邮箱(如sa-label-studio-data@your-data-project.iam.gserviceaccount.com)。

Step 2:授予目标服务账号桶访问权限

按用途选择角色:

  • 源存储(导入数据):roles/storage.objectViewer
  • 目标存储(导出注解):roles/storage.objectAdmin

roles/storage.objectAdmin是目标存储必需的,因为 Label Studio 需要在桶中创建、覆盖并按需删除对象。若只需写入无需删除,roles/storage.objectCreator即可,但此时Can delete objects from storage选项将无法工作。

在 Console 中:进入Cloud Storage > Buckets选择桶 →Permissions > Grant Access→ 填入目标服务账号邮箱 → 按用途选择Storage Object ViewerStorage Object Admin(可 Add another role 同时添加)→Save

gcloud 等价命令:

# 源存储(读) gcloud storage buckets add-iam-policy-binding gs://YOUR_BUCKET_NAME \ --member="serviceAccount:TARGET_SA_EMAIL" \ --role="roles/storage.objectViewer" # 目标存储(写与删) gcloud storage buckets add-iam-policy-binding gs://YOUR_BUCKET_NAME \ --member="serviceAccount:TARGET_SA_EMAIL" \ --role="roles/storage.objectAdmin"
Step 3:允许基础服务账号模拟目标服务账号

在目标服务账号上把roles/iam.serviceAccountTokenCreator授予基础服务账号。该角色包含signBlob权限——Label Studio 生成预签名 URL 供浏览器直连读取对象时正好需要它。

Console 操作:IAM & Admin > Service Accounts选择目标服务账号 →Permissions > Grant Access→ New principals 填基础服务账号邮箱 → 角色选Service Account Token CreatorSave

gcloud 等价命令:

gcloud iam service-accounts add-iam-policy-binding TARGET_SA_EMAIL \ --member="serviceAccount:BASE_SA_EMAIL" \ --role="roles/iam.serviceAccountTokenCreator"
Step 4:在桶上配置 CORS(预签名 URL 必需)

创建cors.json(将https://your-label-studio-domain.com替换为 Label Studio 实际域名):

[ { "origin": ["https://your-label-studio-domain.com"], "method": ["GET", "HEAD"], "responseHeader": ["Content-Type", "Content-Range", "Content-Disposition"], "maxAgeSeconds": 3600 } ]

应用并验证:

gcloud storage buckets update gs://YOUR_BUCKET_NAME --cors-file=cors.json gcloud storage buckets describe gs://YOUR_BUCKET_NAME --format="default(cors_config)"

如果使用Proxy through the platform模式而非预签名 URL,则无需配置 CORS(流量全部经过 Label Studio 服务器)。

创建 SA Impersonation 源存储连接

选择Google Cloud Storage (SA Impersonation),字段包括:Storage Title、Bucket Name、Target Service Account Email(Step 1 创建的目标服务账号邮箱)、Google Project ID、Use pre-signed URLs / Proxy、Expire pre-signed URLs。预签名所需的signBlob权限已包含在 Step 3 授予的roles/iam.serviceAccountTokenCreator中。Import Settings 与确认流程同前。

创建 SA Impersonation 目标存储连接

字段包含:Storage Title、Bucket Name、Bucket Prefix、Target Service Account Email、Google Project ID、Can delete objects from storage(需要目标服务账号具备roles/storage.objectAdmin,见 Step 2)。保存后点击Sync

SA Impersonation 排障

错误原因解决方案
Label Studio 中没有Google Cloud Storage (SA Impersonation)选项未启用所需 feature flag在 GKE 部署中设置小写环境变量fflag_feat_bros_763_gcs_sa_impersonation
Permission 'iam.serviceAccounts.getAccessToken' denied on resource基础服务账号无权模拟目标服务账号确认基础服务账号在目标服务账号上拥有roles/iam.serviceAccountTokenCreator(见 Step 3)
404 Service account not found目标服务账号邮箱错误或账号不存在确认邮箱以.iam.gserviceaccount.com结尾且账号存在于 GCP 项目中
Permission 'storage.buckets.get' denied403 Access denied to bucket目标服务账号缺少桶权限在桶上为目标服务账号授予roles/storage.objectViewer(源)或roles/storage.objectAdmin(目标),见 Step 2
图片/媒体加载失败,浏览器控制台报 CORS 错误桶未针对 Label Studio 域名配置 CORS(仅预签名 URL 场景)为桶添加允许从 Label Studio URL 发起GET/HEAD的 CORS 策略(见 Step 4)

用 Label Studio API 编程式添加存储

除 UI 外,所有 GCS 连接均可通过 REST API 创建与管理。源码中为 GCS 定义了完整的视图集(io_storages/gcs/api.py):

  • 导入存储GCSImportStorageListAPI(GET 列表 / POST 创建)、GCSImportStorageDetailAPI(GET / PATCH / DELETE)、GCSImportStorageSyncAPI(POST 触发同步)、GCSImportStorageValidateAPI(POST 校验连接)、GCSImportStorageFormLayoutAPI(表单布局)
  • 导出存储GCSExportStorageListAPIGCSExportStorageDetailAPIGCSExportStorageSyncAPIGCSExportStorageValidateAPIGCSExportStorageFormLayoutAPI

创建/更新请求体由 GCSImportStorageSerializer 与 GCSExportStorageSerializer 约束:导入序列化器强制presign默认True,并将google_application_credentials列为安全字段——序列化输出时会被剔除(to_representationresult.pop(attr)),避免凭据泄露;校验阶段则会调用validate_connection()实际连接 GCS 验证桶与前缀。API 的具体端点语义可通过仓库内 OpenAPI/SDK 生成配置 查看。

用 IP 过滤进一步加固 GCS 桶

GCS 的bucket IP filtering允许基于源 IP 地址限制桶访问,防止未授权访问,并实现细粒度的访问控制(详见 storage_gcp.md 与 security.md 中 Source storage behind your VPC)。

常见用例:

  • 仅允许组织 IP 段访问桶
  • 仅允许基础设施中特定 VPC 网络访问
  • 将敏感数据限制在已知 IP 地址范围内
  • 通过白名单 IP 控制第三方集成的访问

配置步骤:

  1. 通过 Console 或 CLI 创建 GCS 桶;
  2. 创建 JSON 配置文件定义过滤规则。

公网 IP 范围规则:

{ "mode": "Enabled", "publicNetworkSource": { "allowedIpCidrRanges": [ "xxx.xxx.xxx.xxx", // Your first IP address "xxx.xxx.xxx.xxx", // Your second IP address "xxx.xxx.xxx.xxx/xx" // Your IP range in CIDR notation ] } }

VPC 网络来源规则:

{ "mode": "Enabled", "vpcNetworkSources": [ { "network": "projects/PROJECT_ID/global/networks/NETWORK_NAME", "allowedIpCidrRanges": [ RANGE_CIDR ] } ] }
  1. 应用规则:
gcloud alpha storage buckets update gs://BUCKET_NAME --ip-filter-file=IP_FILTER_CONFIG_FILE
  1. 移除规则:
gcloud alpha storage buckets update gs://BUCKET_NAME --clear-ip-filter

已知限制:

  • 所有规则合计最多 200 个 IP CIDR 块
  • IP 过滤规则中最多 25 个 VPC 网络
  • 不支持双区域(dual-regional)桶
  • 可能影响部分 Google Cloud 服务的访问

运维建议与常见注意事项

综合官方指南与源码实现,落地 GCS 集成时需注意以下几点:

  • 同步是单向的:源存储是从桶对象创建任务,目标存储是把注解推回桶。在桶侧直接改动内容并不保证与 Label Studio 结果一致;只有向桶上传新文件(或删除关联任务后重新同步)才能让 Tasks 模式下已导入的文件变更生效(storage.md 排障章节)。
  • 源存储不存数据:从云存储同步的任务数据不落库,而是通过预签名 URL 访问(storage.md)。Files 模式下 Label Studio 只创建对象的"引用"而非导入内容,因此数据访问控制完全掌握在你手中。
  • 权限最小化:Files 导入模式只需 LIST 权限;Tasks 模式还需 GET 权限读取 JSON 转任务;浏览器加载媒体时还需对桶具备 HEAD 与 GET 权限。
  • 每个项目独立目录:官方建议为每个 Label Studio 项目使用独立的桶目录(Bucket Prefix),便于隔离与管理。
  • 区域就近:把桶放在离标注团队更近的区域,而不是贴近 Label Studio 服务器,可降低延迟、提升效率。
  • 凭据保护google_application_credentials属于安全字段,不会出现在任何 API 响应中(serializers.py);建议 on-prem 环境优先采用 ADC 或 WIF 避免在 UI 中粘贴长期密钥。

通过本文的配置路径与源码对照,你已经可以从零开始将 GCS 桶接入 Label Studio,并在预签名直连、平台代理、WIF 临时凭据与 GKE 服务账号模拟之间做出符合自身安全与性能要求的选型。

【免费下载链接】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),仅供参考

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

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

立即咨询