Cloud Healthcare API에 PACS 연결

이 페이지에서는 Google Kubernetes Engine(GKE)에서 오픈소스 Cloud Healthcare API DICOM 어댑터를 사용하여 다음 태스크를 완료하는 방법을 설명합니다.

  • 사진 보관 및 커뮤니케이션 시스템(PACS)을 Cloud Healthcare API에 연결
  • PACS에서 DICOM으로 Cloud Healthcare API의 DICOM 저장소로 DICOM 데이터 가져오기

이 가이드에서는 Google Kubernetes Engine 및 Compute Engine 가상 머신(VM)을 사용하여 프로토타입을 설정하는 간단한 방법을 제공합니다. Compute Engine VM은 온프레미스 PACS를 시뮬레이션합니다. 자세한 내용은 DICOM 어댑터 README를 참조하세요.

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를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
  2. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  3. Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

  4. Cloud Healthcare API, Google Kubernetes Engine, and Container Registry API를 사용 설정합니다.

    API 사용 설정

  5. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  6. Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

  7. Cloud Healthcare API, Google Kubernetes Engine, and Container Registry API를 사용 설정합니다.

    API 사용 설정

  8. GKE API 및 관련 서비스가 사용 설정될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
  9. 아직 만들지 않았으면 DICOM 저장소를 만듭니다.

셸 선택

이 가이드를 완료하려면 Cloud Shell 또는 로컬 셸을 사용합니다.

Cloud Shell은 Google Cloud에서 호스팅되는 리소스를 관리하는 데 사용되는 셸 환경입니다. Cloud Shell에는 이 가이드에서 사용할 다음 도구가 사전 설치되어 있습니다.

  • gcloud 도구: Google Cloud의 기본 명령줄 인터페이스를 제공합니다.
  • kubectl: GKE 클러스터에서 명령어를 실행하기 위한 명령줄 인터페이스를 제공

Cloud Shell을 열거나 로컬 셸을 구성하려면 다음 단계를 완료하세요.

Cloud Shell

  1. Google Cloud Console로 이동합니다.

    Google Cloud Console

  2. Console의 오른쪽 상단에서 Activate Google Cloud Shell(Google Cloud Shell 활성화) 버튼()을 클릭합니다.

Cloud Shell 세션이 콘솔 아래쪽 프레임 안에서 열립니다. 이 셸을 사용하여 gcloudkubectl 명령어를 실행합니다.

로컬 셸

로컬 셸을 사용하려면 gcloud 도구와 kubectl 도구가 포함된 Cloud SDK를 설치해야 합니다. 자세한 내용은 Cloud SDK 설치를 참조하세요.

Google Kubernetes Engine을 사용하여 어댑터 배포

가져오기 어댑터 및 내보내기 어댑터는 Container Registry에 사전 빌드된 Docker 이미지에 스테이징된 컨테이너화된 애플리케이션입니다. 이 가이드에서는 GKE 클러스터에서 실행할 dicom-import-adapter 이미지를 배포합니다.

Compute Engine 서비스 계정에 권한 부여

인스턴스의 서비스 계정 만들기 및 사용 설정의 안내에 따라 Compute Engine 기본 서비스 계정roles/healthcare.dicomEditor 역할을 부여합니다. 자세한 내용은 DICOM 저장소 역할을 참조하세요.

클러스터 만들기

GKE에서 dicom-adapter라는 클러스터를 만들려면 gcloud container clusters create 명령어를 실행합니다.

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

COMPUTE_ZONE은 클러스터가 배포되는 영역입니다. 영역은 클러스터 및 리소스가 배포되는 대략적인 리전 위치입니다. 예를 들어 us-west1-aus-west 리전에 있는 한 영역입니다. gcloud config set compute/zone 명령어를 사용하여 기본 영역을 설정한 경우 이전 명령어의 플래그 값이 기본값을 재정의합니다.

출력은 다음과 같습니다.

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

배포 구성

GKE에 애플리케이션을 배포할 때는 일반적으로 YAML 파일인 배포 매니페스트 파일을 사용하여 배포의 속성을 정의합니다. 배포 매니페스트 파일에 대한 상세 내용은 배포 만들기를 참조하세요.

텍스트 편집기를 사용하여 다음 콘텐츠가 포함된 dicom_adapter.yaml이라는 가져오기 어댑터의 배포 매니페스트 파일을 만듭니다.

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

서비스 구성:

DICOM 어댑터가 GKE 클러스터 외부의 애플리케이션(예: PACS)에 액세스할 수 있게 하려면 내부 부하 분산기를 구성해야 합니다. 부하 분산기를 사용하면 DIMSE 포트(이 가이드에서는 포트 2575)를 내부적으로 노출할 수 있습니다.

부하 분산을 구성하기 위한 서비스 매니페스트 파일을 만듭니다. 배포 매니페스트 파일을 만든 디렉터리에서 텍스트 편집기를 사용하여 다음 콘텐츠가 포함된 dicom_adapter_load_balancer.yaml이라는 파일을 만듭니다. 서비스 및 내부 부하 분산기 배포에서 서비스 매니페스트 파일을 만들고 배포합니다.

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

배포 실행

GKE 클러스터에 어댑터를 배포하려면 dicom_adapter.yaml 배포 매니페스트 파일이 포함된 디렉터리에서 다음 명령어를 실행합니다.

kubectl apply -f dicom_adapter.yaml

출력은 다음과 같습니다.

deployment.apps/dicom-adapter created

배포 검사

배포를 만든 후 kubectl 도구를 사용하여 배포를 검사합니다.

배포에 대한 자세한 정보를 보려면 다음 명령어를 실행하세요.

kubectl describe deployment dicom-adapter

배포에 의해 생성된 pod를 열람하려면 다음 명령어를 실행하세요.

kubectl get pods -l app=dicom-adapter

생성된 pod에 대한 정보를 가져오려면 이전 명령어에서 반환된 pod의 이름을 사용하여 다음 명령어를 실행합니다.

kubectl describe pod POD_NAME

배포에 성공하면 이전 명령어의 출력 중 마지막 부분에 다음 정보가 포함됩니다. 어댑터는 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

서비스 및 내부 부하 분산기 배포

내부 부하 분산기를 만들려면 dicom_adapter_load_balancer.yaml 서비스 매니페스트 파일이 포함된 디렉터리에서 다음 명령어를 실행합니다.

kubectl apply -f dicom_adapter_load_balancer.yaml

출력은 다음과 같습니다.

service/dicom-adapter-load-balancer created

서비스 검사

서비스를 만든 후 서비스가 올바르게 구성되었는지 확인하기 위해 검사합니다.

부하 분산기를 조사하려면 다음 명령어를 실행하세요.

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 주소가 채워지는 데 최대 1분이 걸릴 수 있습니다. LoadBalancer Ingress IP 주소를 저장합니다. 다음 섹션에서 클러스터 외부의 서비스에 액세스하는 데 사용됩니다.

Compute Engine 가상 머신 만들기

온프레미스 PACS를 시뮬레이션하려면 DICOM 어댑터로 요청을 보내는 데 사용할 Compute Engine VM을 만듭니다. 개발자가 내부 부하 분산기와 생성된 VM을 배포했으므로 기존 GKE 클러스터는 동일한 리전과 동일한 VPC 네트워크에 있어야 합니다.

다음 단계를 완료하여 Compute Engine에서 Linux 가상 머신 인스턴스를 만듭니다.

Console

  1. Cloud Console에서 VM 인스턴스 페이지로 이동합니다.

    VM 인스턴스 페이지로 이동

  2. 인스턴스 만들기를 클릭합니다.

  3. 클러스터를 만들 때 선택한 영역과 일치하는 인스턴스의 리전영역을 선택합니다. 예를 들어 클러스터를 만들 때 COMPUTE_ZONEus-central1-a를 사용한 경우 리전us-central1 (Iowa)를 선택하고 영역us-central1-a를 선택합니다.

  4. 부팅 디스크 섹션에서 변경을 클릭하여 부팅 디스크를 구성합니다.

  5. 공개 이미지 탭에서 Debian 운영체제 버전 9를 선택합니다.

  6. 선택을 클릭합니다.

  7. 방화벽 섹션에서 HTTP 트래픽 허용을 선택합니다.

  8. 만들기를 클릭하여 인스턴스를 만듭니다.

gcloud

gcloud compute instances create 명령어를 실행합니다. 이 명령어는 http-server 태그를 사용하여 HTTP 트래픽을 허용합니다.

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

인스턴스가 시작될 때까지 잠시 기다립니다. 인스턴스가 시작된 후 VM 인스턴스 페이지에서 녹색 상태 아이콘으로 표시됩니다.

VM에 연결

VM에 연결하려면 다음 단계를 완료합니다.

Console

  1. Cloud Console에서 VM 인스턴스 페이지로 이동합니다.

    VM 인스턴스 페이지로 이동

  2. 가상 머신 인스턴스 목록의 바로 전에 만든 인스턴스 행에서 SSH를 클릭합니다.

gcloud

gcloud compute ssh 명령어를 실행합니다.

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

다음을 바꿉니다.

  • INSTANCE_NAME: VM 이름
  • PROJECT_ID: 프로젝트 ID
  • COMPUTE_ZONE: VM의 영역

이제 Linux 인스턴스와 상호작용할 수 있는 터미널 창이 생겼습니다.

DICOM 저장소에 DICOM 이미지 가져오기

네트워크를 통해 DICOM 이미지를 전송하는 데 사용할 수 있는 복수의 소프트웨어 옵션이 있습니다. 다음 섹션에서는 DCMTK DICOM 툴킷을 사용합니다.

DICOM 이미지를 DICOM 저장소로 가져오려면 이전 섹션에서 만든 VM에서 다음 단계를 완료합니다.

  1. DCMTK DICOM 툴킷 소프트웨어를 설치합니다.

    sudo apt-get install -y dcmtk
    
  2. DICOM 이미지를 VM에 저장합니다. 예를 들어 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: 서비스를 검사했을 때 반환된 LoadBalancer Ingress IP 주소
    • DCMFILE_IN: VM의 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에 배포하고 어댑터 및 Cloud Healthcare API를 통해 PACS 인스턴스에서 DICOM 이미지를 전송하게 됩니다.

문제해결

GKE 문제해결

DICOM 어댑터를 GKE에 배포한 후 오류가 발생하면 배포된 워크로드 문제 해결의 단계를 따릅니다.

어댑터 문제 해결

가져오기 및 내보내기 어댑터는 문제를 진단하는 데 사용할 수 있는 로그를 생성합니다. GKE를 사용하여 어댑터를 실행하면 로그가 Cloud Logging에 저장됩니다. 로그를 보려면 Google Cloud Console 또는 kubectl 도구를 사용하여 다음 단계를 완료합니다.

Console

  1. Cloud Console에서 GKE 워크로드 대시보드로 이동합니다.

    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 VM과 GKE 클러스터가 동일한 VPC 네트워크에서 실행 중인지 확인합니다. 동일한 VPC 네트워크에서 실행되지 않는 경우 다음을 확인하세요.

  • 부하 분산기가 '내부'로 구성되지 않았습니다.
  • 포트 2575에 대한 연결을 차단하는 방화벽 규칙이 없습니다.

이 오류는 부하 분산기 서비스 또는 어댑터 pod가 GKE 클러스터에서 올바르게 설정되지 않은 경우에도 발생할 수 있습니다. 올바르게 설정되었는지 확인하려면 이 가이드의 배포 검사서비스 검사를 참조하세요.

필요한 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 간의 트래픽을 암호화할 수 있습니다.