---
title: OpenLM LicOps をデプロイする
description: OpenLM Router を LicOps モードで、自社ネットワーク内の Linux ホスト上に Docker Compose スタックとして実行します。
product: OpenLM Platform
---

LicOps を、ネットワーク内にあってスケジューラーホストから到達できる Linux ホスト上に、Docker Compose スタックとしてデプロイします。スタックが稼働したら、[OpenLM LicOps を設定する](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/configuration)の手順で OpenLM Platform に接続します。

LicOps を Kubernetes で実行する場合は、[Kubernetes にデプロイする](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/deploy-kubernetes)を参照してください。

## はじめに

次の前提条件を確認してください。

- [システム要件](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/system-requirements)を満たし、Docker Engine と Docker Compose v2 プラグインがインストールされた Linux ホスト。
- ホストから OpenLM Platform への送信方向のアクセスと、スケジューラーホストからポート `8100` への受信方向のアクセス。
- [システム要件](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/system-requirements#暗号化キー)で生成した暗号化キー。

## イメージを取得する

LicOps は OpenLM Router のイメージで動作します。これらのイメージは OpenLM の公開レジストリで公開されており、匿名でプルできます。`docker login` もプルシークレットも必要ありません。

イメージをプルするには、次のコマンドを実行します。

```bash
docker pull public.ecr.aws/r3q3q2f4/olm-routerapi:1.261006.0752
docker pull public.ecr.aws/r3q3q2f4/olm-routerui:1.261008.0932
```

タグは `1.<yymmdd>.<hhmm>` 形式のビルド番号です。`latest` のような、指す先が変わるタグはありません。明示的なタグを固定して指定し、どのビルドをデプロイしたかを記録してください。2 つのイメージは別々にリリースされるため、タグが異なる場合があります。

### 最新のビルドを確認する

このページに記載したタグは、このガイドの対象となるビルドです。レジストリがイメージごとに保持しているすべてのビルドを確認するには、そのイメージのタグを一覧表示します。レジストリはアクセストークンを匿名で発行するため、アカウントは必要ありません。

Linux で `curl` と `jq` を使用する場合は、次のコマンドを実行します。

```bash
repo=olm-routerapi   # or olm-routerui
token=$(curl -s "https://public.ecr.aws/token/?service=public.ecr.aws&scope=repository:r3q3q2f4/$repo:pull" | jq -r .token)
curl -s -H "Authorization: Bearer $token" "https://public.ecr.aws/v2/r3q3q2f4/$repo/tags/list" | jq -r '(.tags // [.errors[0].message])[]' | sort
```

PowerShell では、次のコマンドを実行します。

```powershell
$repo = "olm-routerapi"   # or olm-routerui
$token = (Invoke-RestMethod "https://public.ecr.aws/token/?service=public.ecr.aws&scope=repository:r3q3q2f4/${repo}:pull").token
(Invoke-RestMethod "https://public.ecr.aws/v2/r3q3q2f4/$repo/tags/list" -Headers @{ Authorization = "Bearer $token" }).tags | Sort-Object
```

イメージごとに 1 回ずつコマンドを実行します。タグはビルド順に並ぶため、最後の行が最新のビルドです。出力が `Rate exceeded` の場合、または PowerShell が `TOOMANYREQUESTS` を報告した場合は、レジストリが匿名のリクエストを制限しています。5 秒待ってから、もう一度コマンドを実行してください。

## 環境ファイルを作成する

ホスト上の作業ディレクトリ（例: `~/openlm-licops/`）に、`.env` という名前のファイルを作成します。

```bash
# The MongoDB account the Compose file creates on the first start.
MONGO_USER=router
MONGO_PASSWORD=<your-generated-password>

# The key protecting the stored OpenLM Platform client secret. Paste the string that
# `openssl rand -base64 32` printed, exactly as it printed it.
ADMISSION_PLATFORM_ENCRYPTION_KEY=<your-generated-key>
```

MongoDB のパスワードは `openssl rand -hex 16` で生成します。パスワードは接続文字列の一部になるため、`@`、`:`、`/` などの文字を含むパスワードを使うと、Router から MongoDB への接続が失敗します。MongoDB はデータボリュームが空のときにだけアカウントを作成するため、後からパスワードを変更しても、既存のアカウントは変わりません。

サンプルやテスト用スタックの暗号化キーは再利用しないでください。[システム要件](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/system-requirements#暗号化キー)の説明に従って、独自のキーを生成してください。

## Router UI 用のプロキシファイルを作成する

Router UI を提供するには、`.env` ファイルと同じ場所に `router-ui-proxy.conf` を作成します。Router UI は `/router-management/` パスで提供されます。また、前段にリバースプロキシがあり、そのリバースプロキシがこのプレフィックスを取り除いて、API 呼び出しを Router に転送することを前提としています。

```nginx
server {
  listen 8101;

  # The Router UI, with the /router-management prefix stripped.
  location /router-management/ {
    proxy_pass http://127.0.0.1:8102/;
  }

  # API calls from the browser, forwarded to the Router.
  location /api/routerapi/ {
    proxy_pass http://127.0.0.1:8100/api/;
  }
}
```

## Compose ファイルを作成する

同じディレクトリに `docker-compose.yml` を作成します。

```yaml
services:
  mongo:
    image: mongo:7
    ports:
      - "127.0.0.1:27017:27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_USER}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
    volumes:
      - mongo_data:/data/db
    restart: unless-stopped

  redis:
    image: redis:7
    command:
      - redis-server
      - --appendonly
      - "yes"
      - --appendfsync
      - everysec
      - --maxmemory-policy
      - noeviction
    ports:
      - "127.0.0.1:6379:6379"
    volumes:
      - redis_data:/data
    restart: unless-stopped

  routerapi:
    image: public.ecr.aws/r3q3q2f4/olm-routerapi:1.261006.0752
    depends_on: [mongo, redis]
    # Host networking, so the admission API and the LicOps listen port land on a
    # real host address that your scheduler hosts and compute nodes can reach.
    network_mode: host
    environment:
      - MONGODB__CONNECTIONSTRING=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@localhost:27017/?authSource=admin
      - REDIS__CONNECTIONSTRING=localhost:6379,abortConnect=false
      - ADMISSION_PLATFORM_ENCRYPTION_KEY=${ADMISSION_PLATFORM_ENCRYPTION_KEY}
      # Required. The Router takes its configuration and rules from the OpenLM Platform.
      - licOpsConfiguration__enabled=true
      - LICOPSCONFIGURATION_ENABLED=true
      # Required. Declares a LicOps Router. Fixed at the first start.
      - ROUTER_CONFIG_BOOTSTRAP_MODE=loadBalancer
      - ROUTER_CORRELATION_MODE=Ip
      - ROUTER_PROXY_PROTOCOL_ENABLED=false
      - ROUTER_TRUSTED_CIDR=127.0.0.1/32
      # Keep the background-job dashboard off.
      - hangfire__dashboard__enabled=false
    restart: unless-stopped

  routerui:
    image: public.ecr.aws/r3q3q2f4/olm-routerui:1.261008.0932
    ports:
      - "127.0.0.1:8102:8101"
    environment:
      - LB_FQDN=_
    restart: unless-stopped

  routerui-proxy:
    image: nginx:stable
    depends_on: [routerui]
    network_mode: host
    volumes:
      - ./router-ui-proxy.conf:/etc/nginx/conf.d/default.conf:ro
    restart: unless-stopped

volumes:
  mongo_data:
  redis_data:
```

Router の設定は、記載どおりに維持してください。

- `licOpsConfiguration__enabled` と `LICOPSCONFIGURATION_ENABLED` を指定すると、Router は構成とアドミッションルールを OpenLM Platform から取得します。これらがないと、**LicOps Configuration** で定義した内容は Router に届きません。
- `ROUTER_CONFIG_BOOTSTRAP_MODE=loadBalancer` を指定すると、この Router は LicOps Router になります。Router が接続すると、OpenLM Platform は LicOps の初期構成を作成します。この設定がないと OpenLM Platform は何も作成せず、Router は待機したままになります。モードは Router の初回起動時に確定するため、ここで `basic` を指定すると、フェイルオーバー用の Router になります。変更するには、専用の空の MongoDB データベースを持つ新しい Router をデプロイし、古い Router を停止します。
- `ROUTER_CORRELATION_MODE=Ip` と `ROUTER_PROXY_PROTOCOL_ENABLED=false` は、スケジューラーアダプターや API の直接呼び出しに適した設定です。これらの変数は必須です。表示されているとおりに指定してください。

:::warning[変数名は記載どおりに指定する]

`MONGODB__CONNECTIONSTRING` と `REDIS__CONNECTIONSTRING` では、`CONNECTIONSTRING` の前にアンダースコアが 2 つ必要です。Router は起動時にこれらの名前を構成に代入するため、綴りを誤ると、単に無視されるのではなく値が空になり、コンテナーは起動時に `Mongo ConnectionString cannot be null or empty.` を出力して終了します。

:::

Router はホストネットワークを使用するため、接続文字列には `localhost` を指定します。MongoDB と Redis はポートを `127.0.0.1` にのみ公開するため、Router はホスト上でこれらに到達でき、ホストの外部からは到達できません。既に運用している MongoDB と Redis のサーバーを使用する場合は、2 つの接続文字列をそれらのサーバーを指すように変更してください。

### セッションタイムアウトを設定する

LicOps は、許可したジョブのシートを、ジョブがそのシートを解放するまで、またはセッションがタイムアウトするまで保持します。解放されなかったシートがいつプールに戻るかは、2 つのタイムアウトで決まります。

| 設定 | 既定値 | 対象 |
| --- | --- | --- |
| `admissionController__reconcile__admitTtlSeconds` | `900`（15 分） | 許可されたジョブが開始するまでに待機できる時間。これより遅れて開始したジョブは、シートを失っています。 |
| `admissionController__reconcile__dispatchTtlSeconds` | `7200`（2 時間） | 開始したジョブが、解放せずにシートを保持できる時間。 |

admit タイムアウトは、キューでジョブが通常待機する時間より長く設定してください。admit タイムアウトを過ぎてから開始したジョブはシートを失っており、LicOps がそのシートを既に別のジョブに許可している可能性があります。dispatch タイムアウトは、ライセンスを使用するジョブのうち最も長いものより長く設定し、実行中のジョブが終了するまでセッションを保持できるようにしてください。タイムアウトを変更するには、`routerapi` の環境変数に設定を追加します。例:

```yaml
      - admissionController__reconcile__admitTtlSeconds=3600
```

これらのタイムアウトは安全策であり、通常の経路ではありません。正常に終了したジョブは、直ちにシートを解放します。

## スタックを起動する

スタックを起動して Router のログを確認するには、次のコマンドを実行します。

```bash
docker compose up -d
docker compose logs -f routerapi
```

初回起動時に、Router は自身の ID を作成し、構成を OpenLM Platform から取得することをログに出力します。

```text
Bootstrap seed skipped: the Router is service-managed (LicOps configuration enabled); identity RouterId <guid> established.
Router configuration shape: service-managed; ...
```

この構成では、構成とルールは Router ではなく OpenLM Platform で変更します。

Router が応答することを確認するには、次のコマンドを実行します。

```bash
curl http://localhost:8100/api/v1/status
```

```json
{
  "status": "unconfigured",
  "configurationManagement": {
    "shape": "serviceManaged",
    "routerId": "7c1e5b2a-3f4d-4e8a-9b6c-2d0f8a1e4c37",
    "lastSync": {
      "lastSuccessfulSync": null,
      "lastFailure": "No Platform connection is configured, so the Router has no address for the LicOps Configuration service"
    }
  }
}
```

新しい Router では、これが正しい結果です。Router は稼働していますが、OpenLM Platform に接続されていないため、構成もプールもありません。構成は OpenLM Platform から取得されるため、[OpenLM LicOps を設定する](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/configuration)の説明に従って Router を接続してください。

`routerId` は一度だけ作成され、MongoDB に保存されます。OpenLM Platform はこの ID で、この Router をほかの Router と区別します。データベースを消去すると新しい ID が作成され、OpenLM Platform からは別の Router に見えます。

対話型の API リファレンスは `http://<licops-host>:8100/swagger` にあります。

## デプロイを検証する

コンテナーが実行中であり、Router UI が読み込まれることを確認するには、次のコマンドを実行します。

```bash
docker compose ps
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8101/router-management/
```

2 つ目のコマンドは `200` を出力します。ブラウザーで `http://<licops-host>:8101/router-management/` を開きます。Router UI は **Platform Connection** で開き、OpenLM Platform への接続が構成されていないことを示す通知が表示されます。次の手順を完了するまでは、これが想定どおりの表示です。

Router の準備状態を示すエンドポイント `/readyz` と `/health/ready` は、Router が OpenLM Platform から構成を取得するまで `503` を返します。新規インストールでは、これは想定どおりの動作であり、障害ではありません。

[OpenLM LicOps を設定する](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/configuration)に進み、LicOps を OpenLM Platform に接続します。

## アップグレード

`docker-compose.yml` で、各 Router イメージの新しいタグを固定して指定します。どのビルドがあるかを確認するには、[最新のビルドを確認する](#最新のビルドを確認する)を参照してください。その後、次のコマンドを実行してコンテナーを再作成します。

```bash
docker compose pull routerapi routerui
docker compose up -d routerapi routerui
```

構成とルールは OpenLM Platform に、開いているセッションは Redis に保存されているため、コンテナーを置き換えても失われません。Router の再起動中はアドミッションリクエストが失敗し、スケジューラーアダプターは、[ワークロードを接続する](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/integrations/index#licops-に到達できない場合の動作を決める)で説明している、選択済みのフェイルモードを適用します。再起動後の約 10 秒間は、Router が OpenLM Platform のシート数に追いつくまで、admit が理由 `StaleSnapshot` 付きの `Deny` を返すことがあります。Slurm と LSF のアダプターはこれを拒否として扱い、ジョブ投入を拒否します。そのため、アップグレードは利用の少ない時間帯に予定してください。
