最終更新: a few seconds agoRemove Netlify-related code from main (grafted, HEAD)

リモート CAD

概要

遠隔地にあるサーバに画像を暗号化して送信し、そこで CAD を実行させ、その結果を暗号化して受信するための仕組みを構築する。

リモートサーバとしては以下のようなものを想定している。

  • AWS Lambda や Google Cloud Run のような従量課金制のクラウド Docker コンテナ実行環境
  • Intel TDX を用いたセキュアな VM

処理の大まかな流れ

現在の CIRCUS の CAD プラグインは Preprocess, Main process, Postprocess から成立しているが、このうち Main process について新たな処理の分岐を導入する。

概要

各ステップの概要をもう少し詳しく述べると以下の通り。詳細は CS Core 概要を参照。

  1. Preprocess:

    • CAD 用の一時作業ディレクトリ (/tmp/circus/${jobId}) を作る。

    • 一時ディレクトリの in に DICOM シリーズをボリュームに変換したものを作っていく。

      /tmp/circus
        /a1b2c3 (job ID)
          /in
            /0.mhd
            /0.json
            /0.vol
            /1.mhd
            /1.json
            /1.vol
      
  2. Main process:

    • 一時ディレクトリの in を外部ボリュームとして /circus/in にマウント (-v /tmp/circus/${jobId}:/circus) しつつ、CAD プラグインとなる Docker イメージを起動する。CAD の実行終了を待つ。結果は /circus/out に書かれる。

      /tmp/circus
        /a1b2cd (job ID)
          /in
            (略)
          /out
            results.json
            log.txt
            image1.png
            image2.png
      
    • またその際にリアルタイムのログをストリームとして受け取ることができる(上記の log.txt)。このリアルタイムログは CIRCUS の責任で out 内に書き込まれる。

  1. Postprocess:
    • out ディレクトリに書かれた result.json の結果が正しいかどうかをバリデーションし、問題なければその結果を MongoDB に書き込む。
    • out に書かれたその他のファイル(ログも含む)をプラグイン結果格納ディレクトリにコピーする。
    • 一時フォルダを削除する。

今回のリモート CAD では Preprocess と Postprocess については全く同じ処理でよい(というか設計上、全く同じ処理であるべき)。Main proces の実行方法のみを以下のように変更する。

  1. Main process: リモート CAD を起動し、preprocess の結果を、暗号化ストリームで転送する。実行ログと CAD 実行結果それぞれ暗号化ストリームで受信し、それを一時ディレクトリの out に一旦書いていく。

「リモート CAD をどう起動するのか」といった部分についてはリモートの CAD 実行環境の要件によって異なる可能性があるため、ここについては拡張可能にする。具体的には以下のインターフェースとサービス定義を参照。

新しい CAD 定義

現在の pluginDefinition"type": "CAD" として Docker イメージを登録するが、ここに新たなプラグインタイプである "type": "CAD+remote" を追加する。

{
  "type": "CAD+remote",
  "adapter": "HttpRemoteCadAdapter",
  "parameters": {
    "endpoint": "https://abcdefg123.execute-api.ap-northeast-1.amazonaws.com/prod/users",
    "authentication": "aaaaabbbbcccccdddddeeeee",
    "maxConcurrency": 5,
    "env": {
      "encryptSecret": "rsa:111122223333"
    }
  }
}
  • endpoint: リモート CAD 実行環境を起動するための URL。
  • authentication: CIRCUS を認証するために必要な文字列。複数の CIRCUS サーバが同じ URL にアクセスする場合にそれらを区別するためにも用いる。
  • env: その他にアダプタによって使用される文字列。
  • maxConcurrency: ここに書いてある数までは CAD を同時に実行できるようにする。AWS Lambda のような環境では無制限でもなんとかなる。一方でリモート環境の制限によっては同時実行数を 1 にする必要があることもある。プリプロセスの部分ではそれなりに CIRCUS 本体に負荷がかかることにも注意が必要。

新しいプロトコル

CIRCUS プラグインマネージャーでは、以下に似たインターフェースのアダプタを「サービス」として実装する(具体的な例はリポジトリを参照)。

interface RemotePluginConfig {
  endPiont: string;
  authentication: string;
  env: Record<string, string>;
}

type RemotePluginResult = {
  logStream: Readable;
  result: Promise<
    | { status: 'finished'; outputFileStream: Readable }
    | { status: 'failed'; message: string }
  >;
};

interface RemoteCadAdapter {
  run: (
    remotePluginDefinition: RemotePluginConfig,
    inputFileStream: Readable,
    signal: AbortSignal // 実行キャンセル用
  ) => RemotePluginResult;
}

CIRCUS がデフォルトで用意する実際のアダプタの実装は HttpRemoteCadAdapter のみ。必要に応じて、HTTP 通信が使えないリモート CAD 環境が出てきた場合などに、このアダプタを差し替えて利用できるようにする。

このアダプタに対応するウェブサーバが必要。以下のようなものを実装する。

  • ダミー(デバッグ用)
  • AWS Lambda や GKE などのリモートコンテナ実行環境を呼び出すアダプタ。