---
title: アドミッションルールで配置を制御する
description: OpenLM Platform でアドミッションルールを作成し、各ジョブをどのライセンスサーバーに配置するかを決めたり、リクエストを拒否したり、チェックアウトの集中を抑えたりします。
product: OpenLM Platform
---

各ジョブが取得するライセンスサーバーを制御するには、アドミッションルールを作成します。ルールがない場合、LicOps はプールに空きシートがあればリクエストを許可し、そのシートを最も負荷の低い正常なサーバーに配置します。アドミッションルールを使うと、この動作を変更できます。従量課金のサーバーより先に前払いのサーバーを使い切る、ジョブを均等に分散する、メンテナンスのためにサーバーをローテーションから外す、許可したくないリクエストを拒否する、ライセンスサーバーに過負荷をかけるおそれのあるチェックアウトの集中を抑える、といった用途に使います。

ルールは OpenLM Platform で作成します。LicOps はそれを取得し、すべてのアドミッションリクエストに適用します。ルールの内容にかかわらず、LicOps は最後に必ず容量とヘルスを確認するため、どのルールでも満杯のサーバーや異常なサーバーにシートを配置することはできません。

配置によって、LicOps が各シートをどのサーバーの分として数え、ディスパッチ時にどのサーバーを指定するかが決まります。アプリケーションのチェックアウトをこれに従わせるには、インテグレーションがその応答を使う必要があります。[LicOps にサーバーの選択も任せるかどうかを決める](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/integrations/index#licops-にサーバーも選ばせるかを決める)を参照してください。

## ルールを作成する

アドミッションルールを作成するには、次の手順を実行します。

1. OpenLM Platform で **Navigation** を選択し、**Licenses and Features** の下にある **LicOps Configuration** を選択します。
2. **Rules**、**New Rule** の順に選択します。
3. 識別しやすい **Rule Id** を入力します（例: `matlab-cheaper-first`）。
4. **Priority** を設定します。ルールは優先順位に従って数値の小さいものから実行されるため、`10` は `100` より先に実行されます。既定値は `100` です。
5. **When — conditions** で、ルールを適用するリクエストを設定します。各条件は **Fact**、**Operator**、**Value** で構成されます（例: **feature** **is** `MATLAB`）。条件を追加するには **+ Condition** を選択します。条件の組み合わせ方は、**All Of**、**Any Of**、**Not** のいずれかを選択して決めます。条件のセットを入れ子にするには **+ Group** を選択します。
6. **Then — action** で **+ Add action** を選択します。
7. **Action** を選択し、アクションに応じたフィールドに値を入力します。
8. **Save rule** を選択します。

次のスクリーンショットは、ルールを保存した後の **Admission Rules** 一覧です。

*Admission Rules には、ルールと予約がまとめて一覧表示されます。オフになっているルールには無効ステータスが表示されます。*

ルールを確認するには、エディター上部のバーを読みます。このバーには、`Keep off a server when All Of(feature is …). → Keep off a server` のように、ルールの内容が文章で表示されます。**Saved JSON** には、保存される内容がそのまま表示されます。ルールを保存するには、アクションが 1 つ以上必要です。

移行作業を行う週末など、ルールを特定の期間に限定するには、**Effective from** と **Effective to** を設定します。常に適用するルールでは、両方とも空のままにします。ルールを削除せずに一時停止するには、**Enabled** をオフにします。**Show disabled** は既定で選択されているため、**Rules** ページには一時停止中のルールも表示されます。非表示にするには、選択を解除します。

保存したルールは約 40 秒以内に有効になります。LicOps は約 10 秒以内にルールを取得し、30 秒ごとにルールを再読み込みします。LicOps ホスト上で再起動が必要なものはありません。

## アクションを選択する

アクションと使用する場面を次の表に示します。

| アクション | 動作 | 使用する場面 |
| --- | --- | --- |
| **Cascade across servers in priority order** | 指定したサーバーを順番に使い、サーバーがしきい値に達したときにだけ次のサーバーへ移ります。 | 従量課金のサーバーより前払いのサーバーを、またはリモートサイトよりプライマリサイトを優先する場合。 |
| **Round-robin across servers** | 新しいシートを、順番に次のサーバーへ配置します。 | 負荷に関係なく均等に分散する場合。 |
| **Weighted round-robin by capacity** | 重みに対する使用量が最も低いサーバーに各シートを配置します。 | 各サーバーの規模に比例して分散する場合。 |
| **Prefer a server** | 指定したサーバーを最初に試し、そのサーバーで提供できない場合は他のサーバーにフォールバックします。 | 優先したいサーバーはあるものの、そのサーバーへの絶対的な依存は避けたい場合。 |
| **Send to a specific server** | 指定したサーバーにのみシートを配置します。 | ライセンスを必ず 1 台のサーバーから取得する必要がある場合。 |
| **Keep off a server** | 指定したサーバーを候補から除外します。 | メンテナンス、サーバーのドレイン、またはライセンス条件によってそのサーバーが除外される場合。 |
| **Deny the request** | リクエストを拒否します。呼び出し元は `PolicyDenied` を受け取ります。 | まったく許可したくないリクエスト。 |
| **Throttle or hold dispatch** | 1 秒あたりにチェックアウトを開始できるジョブの数を制限します。 | ライセンスサーバーに過負荷をかけるおそれのあるバースト。 |

**Prefer a server**、**Send to a specific server**、**Keep off a server** では **Target server** を指定します。検索アイコンを選択すると、LicOps が把握しているサーバーから選択できます。選択したサーバーは `host:port` の形式で入力されるため、複数のライセンスサーバーが 1 台のホストを共有していても区別できます。どのサーバーにも一致しないターゲットはエラーなしで無視されるため、入力ミスがあるとルールは何の効果も持ちません。

## よく使うルール

ここでの例では、3 台のサーバーが提供するプール `MLM:MATLAB` を使います。`lic01` と `lic02` は前払いのシートを持ち、`lic03` は従量課金です。

### 前払いのサーバーを先に使う

前払いのサーバーを先に使うには、`lic01`、次に `lic02` を使い切り、両方が満杯になったときにだけ `lic03` を使うルールを作成します。

| 設定 | 値 |
| --- | --- |
| 条件 | **feature** **is** `MATLAB` |
| アクション | **Cascade across servers in priority order** |
| サーバー | `lic01.example.com:27000`、`lic02.example.com:27000`、`lic03.example.com:27000`（この順序） |

サーバーごとに **+ Add server** を選択し、矢印で順序を設定します。ここでのサーバーの順序は、ルールの **Priority** とは別のものです。

各サーバーには **Spill** 設定があり、配置が次のサーバーに移るタイミングを決めます。

| Spill | 配置が次のサーバーに移る条件 |
| --- | --- |
| **until full** | このサーバーに空きシートがないとき、または異常なとき。 |
| **≤ % of total** | 使用中のシートと許可済みのシートの合計が、このサーバー自身の総数に対してこの割合に達したとき。 |
| **≤ abs seats** | 使用中のシートと許可済みのシートの合計が、この数に達したとき。 |

たとえば、`lic01` で **≤ % of total** を `80` にすると、シートの 5 分の 1 を、直接チェックアウトするユーザーのために残せます。しきい値は、リストにあるいずれかのサーバーがしきい値を下回っている間、配置を誘導します。どのサーバーもしきい値を下回っていない場合、LicOps はリクエストを拒否せず、まだ提供できるサーバーのうち最も負荷の低いサーバーにシートを配置します。

*カスケードルールを開いたルールエディター。タイトルの下のバーには、ルールの内容が文章で表示されます。*

`lic01` の上限を 80% にした場合の、このルールの **Saved JSON** です。

```json
{
  "id": "matlab-cheaper-first",
  "ruleSet": "router-admission",
  "when": { "type": "allOf", "items": [ { "type": "compare", "fact": "feature", "op": "eq", "value": "MATLAB" } ] },
  "then": [ { "kind": "Cascade", "params": { "servers": [
    { "target": "lic01.example.com:27000", "maxUsagePct": 80 },
    "lic02.example.com:27000",
    "lic03.example.com:27000"
  ] } } ],
  "priority": 100,
  "enabled": true
}
```

### ジョブを均等に分散する

条件 **feature** **is** `MATLAB` で **Round-robin across servers** を使います。連続するシートは、決まった順序で各サーバーに順番に配置され、最後のサーバーの次は最初のサーバーに戻ります。満杯のサーバーや異常なサーバーはローテーションから外れ、回復すると再び加わります。

代わりにサーバーの規模に比例して分散するには、**Weighted round-robin by capacity** を使います。**+ Add server** を選択し、`lic01` に `3` のように、少なくとも 1 つのサーバーに `0` より大きい重みを指定します。指定しなかったサーバーの重みは `1` になります。名前とは異なり、このアクションは厳密なローテーションではなく、重み付きの最小負荷方式です。重みが等しい場合は既定の動作と同じになります。

### サーバーを配置の対象から外す

`lic02` のメンテナンスの前に、**Keep off a server**、**Target server** `lic02.example.com:27000`、およびそのサーバーのフィーチャーに対するすべてのリクエストに一致する条件（例: **vendor** **is** `MLM`）を指定したルールを作成します。新しいシートは他のサーバーに配置されます。すでに実行中のジョブは、チェックアウトをそのまま保持します。作業が終わったら、ルールを削除するか無効にします。

### 混雑したサーバーから処理を移す

`lic01` を 95% 未満に保ち、あふれた分を他のサーバーに回すには、**All Of** の下に 2 つの条件（**server name** **is** `lic01.example.com` と **server saturation %** **is at least** `95`）を置き、アクション **Keep off a server**、**Target server** `lic01.example.com:27000` を指定したルールを作成します。`lic01` がそこまで混雑している間は候補から外れ、他のサーバーが新しいシートを引き受けます。95% を下回るとすぐに候補に戻ります。

LicOps はサーバー条件を、候補サーバーごとに 1 回、そのサーバー自身の数値で評価します。そのため、保護したいサーバーごとに個別のルールを作成してください。

### リクエストを拒否する

テスト用ログインノードから投入されたジョブに MATLAB を使わせないようにするには、**All Of** の下に **client host** **matches** `login-test*` と **feature** **is** `MATLAB` を置き、アクション **Deny the request** を指定したルールを作成します。一致するリクエストは、シートが数えられる前に `PolicyDenied` で拒否されます。**Deny the request** のルールには、他のルールより小さい **Priority** の数値を指定してください。そうすることで、これらのルールが実行される前に他のルールが評価を終了させることがなくなります。

Slurm と IBM Spectrum LSF のアダプターは、ジョブを投入したホストの IP アドレスではなく、ホスト名を **client host** として送信します。**is in network** は、IP アドレスを送信する呼び出し元にのみ一致します。

### チェックアウトの集中を抑える

数百のジョブが同時に開始すると、チェックアウトがベンダーデーモンに過負荷をかけることがあります。**Throttle or hold dispatch** は、チェックアウトのペースを調整します。フィールドを次の表に示します。

| フィールド | 設定内容 |
| --- | --- |
| **Max checkouts / second** | プール内で 1 秒ごとにチェックアウトを開始できるジョブの数。`1` 以上を指定します。空欄の場合は `100` です。 |
| **Max hold (seconds)** | 制限を超えたジョブが、LicOps から再試行を指示されるまで到着順に待機する時間。`0` を指定すると、すぐに差し戻します。空欄の場合は `5` 秒です。 |

スロットルは、ジョブが許可されたときではなく、ジョブが開始するとき（ディスパッチ時）に作用し、ジョブが使うサーバーを変えることはありません。待機中のジョブはシートを保持したままです。待機時間が切れると、ディスパッチは `ThrottleDeferred` と `Retry-After` ヘッダーを付けて `503` を返し、API を直接使う呼び出し元は待機してから再度問い合わせます。このアクションは、**server saturation %** **is greater than** `90` や **pool admits per second** **is greater than** `100` などの条件と組み合わせて使います。

Slurm と LSF のアダプターでは、スロットルはバーストを止めるのではなく遅らせます。アダプターはディスパッチ時に 1 回だけ問い合わせ、応答にかかわらずジョブを開始させるためです。**Max hold (seconds)** は、アダプターの HTTP タイムアウトである `OL_TIMEOUT`（既定値は 2 秒）より短くしてください。または、それに合わせて `OL_TIMEOUT` を大きくしてください。空欄時の既定値 5 秒は、このタイムアウトより長くなります。タイムアウトより長く待機させると、アダプターは LicOps に到達できないと判断し、設定したフェイルモードを適用します。

## 使用できる条件

条件のファクトを探すには、**Fact** リストを見ます。このリストは、ファクトが表す対象ごとにグループ分けされています。

| グループ | ファクト | 答える内容 |
| --- | --- | --- |
| リクエスト | **vendor**、**feature**、**user**、**client host**、**seats requested**、**time of day** | 誰が、どこから、何を、いつ要求しているか。 |
| プール | **pool admits per second** | このプールへのリクエストがどのくらいの速さで届いているか。 |
| サーバー | **server id**、**server name**、**server is healthy**、**server total seats**、**server seats consumed**、**server seats reserved**、**server free seats**、**server has capacity for this request**、**server constraint headroom**、**server saturation %** | 1 台の候補サーバーの状態。 |

リストで **not available** と表示されているファクト（**user groups** とプールのシート数）は、値を取得できません。これらに対する条件は一致することがありません。

使用できる演算子はファクトによって異なります。次の表に示します。

| ファクトの種類 | 演算子 |
| --- | --- |
| テキスト（**vendor**、**server name** など） | **is**、**is not**、**is one of**、**matches**（`*` と `?` のワイルドカードを使ったパターン。大文字と小文字を区別しません） |
| 数値（**seats requested**、**server saturation %** など） | **is**、**is not**、**is greater than**、**is at least**、**is less than**、**is at most**、**is one of** |
| **client host** | テキストの演算子に加えて **is in network**。`10.40.0.0/16` のような範囲を指定し、呼び出し元が IP アドレスを送信する場合にのみ一致します |
| **time of day** | 開始時刻と終了時刻を指定する **is between**。18:00 から 08:00 のような時間帯は午前 0 時をまたぎます。 |
| はい／いいえ（**server is healthy** など） | **is**、**is not** |

**is**、**is not**、**is one of** によるテキストの比較は、大文字と小文字の区別を含めて完全一致です。`MLM` と `mlm` は別のベンダーとして扱われます。**matches** は大文字と小文字を区別しません。名前は、[OpenLM LicOps を設定する](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/configuration#licops-がライセンスプールを認識していることを確認する)で説明しているとおり、`GET /api/v1/stats` からコピーしてください。

:::note[時刻は LicOps ホストの時計に従います]

**time of day** と予約の期間には、LicOps が動作しているマシンの時計が使われます。タイムゾーンを設定しない限りコンテナーは UTC で動作するため、時間帯を現地時刻で指定する場合は、`routerapi` の環境変数に `TZ=<your-time-zone>`（例: `TZ=Europe/Berlin`）を追加してください。

:::

## ルールの組み合わせ方

LicOps は、アドミッションリクエストごとにルールを 2 回評価します。

1. サーバーを検討する前: ここで値が得られるのは、リクエストとプールのファクトだけです。一致した **Deny the request** ルールは、この時点でリクエストを拒否します。
2. 候補サーバーごとに 1 回: サーバーのファクトには、そのサーバーの数値が使われます。その後、すべての候補のアクションが 1 つの配置にまとめられます。

各回の評価では、ルールは **Priority** の順に、数値の小さいものから実行されます。**Deny the request** と **Send to a specific server** はその回の評価を終了させるため、数値の大きいルールでこれらを上書きすることはできません。その他のアクションは累積されます。

アクションが競合する場合の結果は次のとおりです。

| リクエストが一致するルール | 結果 |
| --- | --- |
| **Deny the request**（どの **Send to a specific server** ルールよりも **Priority** の数値が小さい） | サーバーが検討される前に拒否されます |
| 同じサーバーに対する **Keep off a server** と **Send to a specific server** | 除外されます。そのサーバーは使用されません |
| 異なる 2 台のサーバーに対する **Send to a specific server** | 両方とも無視され、通常の配置が適用されます |
| **Send to a specific server** と分散アクション | そのサーバーに送られます |
| 複数の分散アクション | 1 つだけが適用されます。優先されるのは **Cascade across servers in priority order**、**Weighted round-robin by capacity**、**Round-robin across servers** の順です |
| **Prefer a server** と **Round-robin across servers** | 優先サーバーの間だけでローテーションします |
| **Keep off a server** と分散アクション | まずそのサーバーが除外され、残りのサーバーで分散が行われます |
| **Throttle or hold dispatch** とその他のアクション | 配置には影響しません。ジョブの開始時にチェックアウトのペースが調整されます |

ルールセットは小さく、具体的に保ってください。意図したよりもはるかに多くのリクエストに一致するルールは、最もよくある想定外の原因です。

## LicOps が適用している内容を確認する

LicOps が適用しているルール (2 つの組み込みルールを含む) を表示するには、次のコマンドを実行します。

```bash
curl http://localhost:8100/api/v1/rules/router-admission
```

組み込みルールの `baseline-capacity-guard` と `baseline-saturation-guard` は、編集も削除もできません。これらは取得できないプールのシート数を判定するため、発動することはありません。害はありません。空きシートのあるサーバーがない場合、LicOps はもともと `NoCapacity` でリクエストを拒否するためです。

LicOps のデプロイでは、ルールは Platform で定義されるため、LicOps API はルールの変更を受け付けません。ルールの作成、編集、削除は **LicOps Configuration** で行います。

ルールをテストするには、[OpenLM LicOps を設定する](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/configuration#テストアドミッションを実行する)の説明に従ってテスト用のアドミッションを送信し、ディスパッチがどのサーバーを指定するかを確認します。または、[OpenLM LicOps を運用する](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/operations#licops-が保持している内容を確認する)で説明しているシートの状況を確認します。
