将 PACS 连接到 Cloud Healthcare API

本页面介绍了如何在 Google Kubernetes Engine (GKE) 上使用开源 Cloud Healthcare API DICOM 适配器来完成以下任务:

  • 将图片归档和通信系统 (PACS) 连接到 Cloud Healthcare API。
  • 将 DICOM 数据从 PACS 导入 Cloud Healthcare API 中的 DICOM 存储区。

本指南提供了使用 Google Kubernetes Engine 和 Compute Engine 虚拟机设置原型的简单方法。Compute Engine 虚拟机模拟本地 PACS。如需了解详情,请参阅 DICOM 适配器自述文件

DICOM 适配器概览

该适配器由两个主要组件组成:导入适配器和导出适配器。本指南介绍如何使用导入适配器将 DICOM 映像存储在 DICOM 存储区中。

使用 DICOM 适配器在传统协议和 RESTful 协议之间进行数据转换。例如,您可以从 C-STORE 格式转换为 STOW-RS 格式。

费用

本指南使用 Google Cloud 的收费组件,包括以下组件:

  • Cloud Healthcare API
  • Google Kubernetes Engine
  • Compute Engine

您可使用价格计算器根据您的预计使用情况来估算费用。Cloud Platform 新用户可能有资格申请免费试用

须知事项

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. 确保您的 Google Cloud 项目已启用结算功能

  4. Enable the Cloud Healthcare API, Google Kubernetes Engine, and Container Registry APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. 确保您的 Google Cloud 项目已启用结算功能

  7. Enable the Cloud Healthcare API, Google Kubernetes Engine, and Container Registry APIs.

    Enable the APIs

  8. 稍作等待,让 GKE API 和相关服务完成启用过程。此过程可能耗时几分钟。
  9. 创建 DICOM 存储区(如果您尚未创建)。

选择 shell

为完成本指南,请使用 Cloud Shell 或本地 shell。

Cloud Shell 是一种 shell 环境,用于管理托管在 Google Cloud 上的资源。Cloud Shell 预安装了以下工具,在本指南中会用到:

  • gcloud CLI:为 Google Cloud 提供主要命令行界面
  • kubectl:提供用于针对 GKE 集群运行命令的命令行界面

如需打开 Cloud Shell 或配置本地 shell,请完成以下步骤:

Cloud Shell

  1. 进入 Google Cloud 控制台。

    Google Cloud 控制台

  2. 在控制台的右上角,点击激活 Google Cloud Shell 按钮:

控制台底部的框中随即打开一个 Cloud Shell 会话。您可以使用此 shell 运行 gcloudkubectl 命令。

本地 shell

如果您更喜欢使用本地 shell,则必须安装 gcloud CLI。如需了解相关说明,请参阅安装 Google Cloud CLI

使用 Google Kubernetes Engine 部署适配器

导入适配器和导出适配器是暂存在 Container Registry 内的预构建 Docker 映像中的容器化应用。在本指南中,您将部署 dicom-import-adapter 映像以在 GKE 集群上运行。

授予 Compute Engine 服务账号权限

按照为实例创建和启用服务账号中的说明,向 Compute Engine 默认服务账号授予 roles/healthcare.dicomEditor 角色。如需了解详情,请参阅 DICOM 存储区角色

创建集群

gcloud

如需在 GKE 中创建名为 dicom-adapter 的集群,请运行 gcloud container clusters create 命令。

在使用下面的命令数据之前,请先进行以下替换:

  • COMPUTE_ZONE:部署集群的可用区。可用区是一个大致区域位置,您在其中部署集群及其资源。例如,us-west1-aus-west 区域中的地区。如果您使用 gcloud config set compute/zone 命令设置了默认可用区,则上一个命令中标志的值会替换默认值。

执行以下命令:

Linux、macOS 或 Cloud Shell

gcloud container clusters create dicom-adapter \
  --zone=COMPUTE_ZONE \
  --scopes=https://www.googleapis.com/auth/cloud-healthcare

Windows (PowerShell)

gcloud container clusters create dicom-adapter `
  --zone=COMPUTE_ZONE `
  --scopes=https://www.googleapis.com/auth/cloud-healthcare

Windows (cmd.exe)

gcloud container clusters create dicom-adapter ^
  --zone=COMPUTE_ZONE ^
  --scopes=https://www.googleapis.com/auth/cloud-healthcare

您应该会收到类似如下所示的响应:

Creating cluster dicom-adapter in COMPUTE_ZONE... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/PROJECT_ID/zones/COMPUTE_ZONE/clusters/dicom-adapter].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/COMPUTE_ZONE/dicom-adapter?project=PROJECT_ID
kubeconfig entry generated for dicom-adapter.
NAME           LOCATION    MASTER_VERSION  MASTER_IP        MACHINE_TYPE   NODE_VERSION   NUM_NODES  STATUS
dicom-adapter  COMPUTE_ZONE 1.18.16-gke.502   123.456.789.012  n1-standard-1  1.18.16-gke.502  3     RUNNING

配置 Deployment

将应用部署到 GKE 时,您可以使用部署清单文件(通常是 YAML 文件)定义 Deployment 的属性。如需了解 Deployment 清单文件,请参阅创建 Deployment

使用文本编辑器为名为 dicom_adapter.yaml 的导入适配器创建一个 Deployment 清单文件,其中包含以下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dicom-adapter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dicom-adapter
  template:
    metadata:
      labels:
        app: dicom-adapter
    spec:
      containers:
        - name: dicom-import-adapter
          image: gcr.io/cloud-healthcare-containers/healthcare-api-dicom-dicomweb-adapter-import:0.2.1
          ports:
            - containerPort: 2575
              protocol: TCP
              name: "port"
          args:
            - "--dimse_aet=IMPORTADAPTER"
            - "--dimse_port=2575"
            - "--dicomweb_address=https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/dicomStores/DICOM_STORE_ID/dicomWeb"

替换以下内容:

  • PROJECT_ID:项目 ID
  • LOCATION:数据集的位置
  • DATASET_ID:DICOM 存储区的父数据集的 ID
  • DICOM_STORE_ID:要向其中导入 DICOM 数据的 DICOM 存储区的 ID

配置 Service

要使 DICOM 适配器可供 GKE 集群外部的应用(例如 PACS)访问,您必须配置内部负载均衡器。利用负载均衡器,您可以在内部公开 DIMSE 端口(在本指南中为端口 2575)。

创建 Service 清单文件以配置负载均衡。在您创建 Deployment 清单文件的目录中,使用文本编辑器创建名为 dicom_adapter_load_balancer.yaml 的文件,其中包含以下内容。您可以创建并部署部署 Service 和内部负载均衡器中的 Service 清单文件。

apiVersion: v1
kind: Service
metadata:
  name: dicom-adapter-load-balancer
  # The "Internal" annotation will result in an load balancer that can only
  # be accessed from within the VPC the Kubernetes cluster is in.
  # You can remove this annotation to get an externally accessible load balancer.
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
spec:
  ports:
  - port: 2575
    targetPort: 2575
    protocol: TCP
    name: port
  selector:
    app: dicom-adapter
  type: LoadBalancer

部署 Deployment

要将适配器部署到 GKE 集群,请在包含 dicom_adapter.yaml Deployment 清单文件的目录中运行以下命令:

kubectl apply -f dicom_adapter.yaml

输出如下所示:

deployment.apps/dicom-adapter created

检查 Deployment

创建 Deployment 后,请使用 kubectl 工具对其进行检查。

要获取有关 Deployment 的详细信息,请运行以下命令:

kubectl describe deployment dicom-adapter

如需查看 Deployment 创建的 Pod,请运行以下命令:

kubectl get pods -l app=dicom-adapter

要获取有关所创建的 Pod 的信息,请使用上一条命令返回的 Pod 的名称运行以下命令:

kubectl describe pod POD_NAME

如果 Deployment 成功,上一条命令的输出的最后部分会包含以下信息。如果 dicom-import-adapter 容器在 Reason 列中具有 Started 值,则说明适配器已准备好处理请求。

Events:
  Type    Reason     Age    From                                                   Message
  ----    ------     ----   ----                                                   -------
  Normal  Scheduled  3m33s  default-scheduler                                      Successfully assigned default/dicom-adapter-69d579778-qrm7n to gke-dicom-adapter-default-pool-6f6e0dcd-9cdd
  Normal  Pulling    3m31s  kubelet, gke-dicom-adapter-default-pool-6f6e0dcd-9cdd  Pulling image "gcr.io/cloud-healthcare-containers/healthcare-api-dicom-dicomweb-adapter-import:0.2.1"
  Normal  Pulled     3m10s  kubelet, gke-dicom-adapter-default-pool-6f6e0dcd-9cdd  Successfully pulled image "gcr.io/cloud-healthcare-containers/healthcare-api-dicom-dicomweb-adapter-import:0.2.1"
  Normal  Created    3m7s   kubelet, gke-dicom-adapter-default-pool-6f6e0dcd-9cdd  Created container dicom-import-adapter
  Normal  Started    3m7s   kubelet, gke-dicom-adapter-default-pool-6f6e0dcd-9cdd  Started container dicom-import-adapter

部署 Service 和内部负载均衡器

要创建内部负载均衡器,请在包含 dicom_adapter_load_balancer.yaml Service 清单文件的目录中运行以下命令:

kubectl apply -f dicom_adapter_load_balancer.yaml

输出如下所示:

service/dicom-adapter-load-balancer created

检查 Service

创建 Service 后,请检查以验证其是否已正确配置。

要检查负载均衡器,请运行以下命令:

kubectl describe service dicom-adapter-load-balancer

输出如下所示:

Name:                     dicom-adapter-load-balancer
Namespace:                default
Labels:                   <none>
Annotations:              cloud.google.com/load-balancer-type: Internal
Selector:                 app=dicom-adapter
Type:                     LoadBalancer
IP:                       198.51.100.1
LoadBalancer Ingress:     203.0.113.1
Port:                     port  2575/TCP
TargetPort:               2575/TCP
NodePort:                 port  30440/TCP
Endpoints:                192.0.2.1:2575
Session Affinity:         None
External Traffic Policy:  Cluster
Events:

Events:
  Type    Reason                Age   From                Message
  ----    ------                ----  ----                -------
  Normal  EnsuringLoadBalancer  1m    service-controller  Ensuring load balancer
  Normal  EnsuredLoadBalancer   1m    service-controller  Ensured load balancer

LoadBalancer Ingress IP 地址最多可能需要一分钟来填充。保存 LoadBalancer Ingress IP 地址。在下一部分中,您将使用它从集群外部访问 Service。

创建 Compute Engine 虚拟机

要模拟本地 PACS,请创建一个 Compute Engine 虚拟机以向 DICOM 适配器发送请求。由于您已部署内部负载均衡器,因此您创建的虚拟机和现有 GKE 集群必须位于同一地区并使用相同的 VPC 网络

完成以下步骤,在 Compute Engine 中创建 Linux 虚拟机实例:

控制台

  1. 在 Google Cloud 控制台中,转到虚拟机实例页面。

    转到“虚拟机实例”

  2. 点击创建实例

  3. 为与您在创建集群时所选可用区匹配的实例选择区域可用区。例如,如果您在创建集群时为 COMPUTE_ZONE 使用了 us-central1-a,请为区域选择 us-central1 (Iowa),并为地区选择 us-central1-a

  4. 启动磁盘部分,点击更改以配置您的启动磁盘。

  5. 公共映像标签页上,选择 Debian 操作系统的版本 9

  6. 点击选择

  7. 防火墙部分,选择允许 HTTP 流量

  8. 点击创建以创建实例。

gcloud

运行 gcloud compute instances create 命令。该命令使用 http-server 标记允许 HTTP 流量。

在使用下面的命令数据之前,请先进行以下替换:

执行以下命令:

Linux、macOS 或 Cloud Shell

gcloud compute instances create INSTANCE_NAME \
  --project=PROJECT_ID \
  --zone=COMPUTE_ZONE \
  --image-family=debian-9 \
  --image-project=debian-cloud \
  --tags=http-server

Windows (PowerShell)

gcloud compute instances create INSTANCE_NAME `
  --project=PROJECT_ID `
  --zone=COMPUTE_ZONE `
  --image-family=debian-9 `
  --image-project=debian-cloud `
  --tags=http-server

Windows (cmd.exe)

gcloud compute instances create INSTANCE_NAME ^
  --project=PROJECT_ID ^
  --zone=COMPUTE_ZONE ^
  --image-family=debian-9 ^
  --image-project=debian-cloud ^
  --tags=http-server

您应该会收到类似如下所示的响应:

Created [https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/COMPUTE_ZONE/instances/INSTANCE_NAME].
NAME          ZONE           MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
INSTANCE_NAME  COMPUTE_ZONE           n1-standard-1               INTERNAL_IP  EXTERNAL_IP    RUNNING

实例启动需要您稍等片刻。实例启动后,会在“虚拟机实例”页面上列出,并带有绿色状态图标。

连接到虚拟机

要连接到虚拟机,请完成以下步骤:

控制台

  1. 在 Google Cloud 控制台中,转到虚拟机实例页面。

    转到“虚拟机实例”

  2. 在虚拟机实例列表中,点击您创建的实例所在行中的 SSH

gcloud

运行 gcloud compute ssh 命令。

在使用下面的命令数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目的 ID
  • COMPUTE_ZONE虚拟机所在的可用区
  • INSTANCE_NAME虚拟机的名称

执行以下命令:

Linux、macOS 或 Cloud Shell

gcloud compute ssh INSTANCE_NAME \
  --project PROJECT_ID \
  --zone COMPUTE_ZONE

Windows (PowerShell)

gcloud compute ssh INSTANCE_NAME `
  --project PROJECT_ID `
  --zone COMPUTE_ZONE

Windows (cmd.exe)

gcloud compute ssh INSTANCE_NAME ^
  --project PROJECT_ID ^
  --zone COMPUTE_ZONE

您现在具有一个用来与您的 Linux 实例互动的终端窗口。

将 DICOM 映像导入 DICOM 存储区

有多种软件可用于通过网络发送 DICOM 映像。在以下部分中,您将使用 DCMTK DICOM 工具包

要将 DICOM 映像导入 DICOM 存储区,请通过您在上一部分中创建的虚拟机完成以下步骤:

  1. 安装 DCMTK DICOM 工具包软件:

    sudo apt-get install -y dcmtk
    
  2. 将 DICOM 映像保存到虚拟机。例如,如果 DICOM 映像存储在 Cloud Storage 存储桶中,请运行以下命令来将映像下载到当前的工作目录中:

    gsutil cp gs://BUCKET/DCM_FILE .

    如需从 gcs-public-data--healthcare-tcia-lidc-idri 数据集使用 Google Cloud 免费提供的 DICOM 映像,请运行以下命令:

    gsutil -u PROJECT_ID cp gs://gcs-public-data--healthcare-tcia-lidc-idri/dicom/1.3.6.1.4.1.14519.5.2.1.6279.6001.100036212881370097961774473021/1.3.6.1.4.1.14519.5.2.1.6279.6001.130765375502800983459674173881/1.3.6.1.4.1.14519.5.2.1.6279.6001.100395847981751414562031366859.dcm .
  3. 运行 DCMTK DICOM 工具包提供的 dcmsend 命令。运行该命令时,请将应用实体 (AE) 标题设置为 IMPORTADAPTER。您可以选择添加 --verbose 标志以显示处理详情。本指南中使用的端口是 2575。

    dcmsend --verbose PEER 2575 DCM_FILE_IN -aec IMPORTADAPTER

    替换以下内容:

    • PEER检查 Service 时返回的 LoadBalancer Ingress IP 地址
    • DCMFILE_IN:虚拟机上 DICOM 映像的路径

    使用单个 DICOM 映像运行 dcmsend 时,输出如下所示:

    I: checking input files ...
    I: starting association #1
    I: initializing network ...
    I: negotiating network association ...
    I: Requesting Association
    I: Association Accepted (Max Send PDV: 16366)
    I: sending SOP instances ...
    I: Sending C-STORE Request (MsgID 1, MR)
    I: Received C-STORE Response (Success)
    I: Releasing Association
    I:
    I: Status Summary
    I: --------------
    I: Number of associations   : 1
    I: Number of pres. contexts : 1
    I: Number of SOP instances  : 1
    I: - sent to the peer       : 1
    I:   * with status SUCCESS  : 1
    
  4. 要验证 DICOM 映像是否已成功导入 DICOM 存储区,请在 DICOM 存储区中搜索实例,并确保新 DICOM 映像在该存储区中。

完成本部分后,您已成功将 DICOM 适配器部署到 GKE 并通过适配器从 PACS 实例向 Cloud Healthcare API 发送了 DICOM 映像。

问题排查

GKE 问题排查

如果 DICOM 适配器部署到 GKE 之后发生故障,请按照已部署工作负载的问题排查中的步骤操作。

适配器问题排查

导入和导出适配器会生成用于诊断任何问题的日志。使用 GKE 运行适配器时,日志将存储在 Cloud Logging 中。如需查看日志,请使用 Google Cloud 控制台或 kubectl 工具完成以下步骤:

控制台

  1. 转到 Google Cloud 控制台中的 GKE Workloads 信息中心。

    转到“GKE 工作负载”

  2. 选择 dicom-adapter 工作负载。

  3. 部署详情页面中,点击容器日志

kubectl

要查看集群中正在运行的所有 Pod,请运行以下命令:

kubectl get pods

查找名称以 dicom-adapter 开头的 Pod。

如需获取 Pod 的日志,请运行以下命令:

kubectl logs POD_NAME

如果您遗漏了本指南中的任何步骤,dcmsend 命令可能无法上传映像。要调查此问题,请使用 -d 标志(表示“调试”)重新运行该命令。该标志会输出操作的更详细日志,包括提供失败相关信息的消息。

权限和授权问题排查

以下部分介绍在错误配置权限或授权时 dcmsend 中可能发生的错误。

“对等取消关联”错误

当网络流量无法从 PACS 流向负载均衡器的端口 2575 时,会出现以下问题:

cannot send SOP instance: Peer aborted Association (or never connected)

如需解决此问题,请确保 PACS 虚拟机和 GKE 集群在同一 VPC 网络中运行。如果它们不在同一 VPC 网络中运行,请检查以下内容:

  • 负载均衡器未配置为“内部”。
  • 没有防火墙规则禁止与端口 2575 的连接。

如果在 GKE 集群中未正确设置负载均衡器服务或适配器 Pod,也可能会发生此错误。为确保它们设置正确,请查看本指南中的检查 Deployment检查 Service

“所需的 API 未启用”错误

在运行具有适配器的 GKE 集群的项目中未启用 Cloud Healthcare API 时,会出现以下问题:

LO [Http_403, PERMISSION_DENIED, Cloud Healthcare API has not been u]

如需解决此问题,请确保按照准备工作中的说明启用所有需要的 API。

范围不足错误

如果运行适配器的 GKE 集群没有设置正确的范围值,则会出现以下问题:

LO [Http_403, PERMISSION_DENIED, Request had insufficient authentica]

如需解决此问题,请使用以下标志更新 GKE 集群或创建新集群:

--scopes=https://www.googleapis.com/auth/cloud-healthcare

“DICOM 存储区权限被拒绝”错误

如果运行适配器的 GKE 集群使用的服务账号没有 roles/healthcare.dicomEditor 角色,则会出现以下错误:

LO [Http_403, PERMISSION_DENIED, Permission healthcare.dicomStores.d]

如需解决此问题,请按照授予 Compute Engine 服务账号权限中的说明操作。

后续步骤

在配置本指南中的原型后,您可以开始使用 Cloud VPN 来加密 PACS 和 Cloud Healthcare API 之间的流量。