JS7® JobScheduler エージェントレスでの実行

# 概要

JobSchedulerにて、エージェントがインストールされていない環境でJOBを実行する方法について説明します。

# 前提条件

- JS7 jobscheduler の環境準備、初期設定を済ませていること。
  まだの方はこちらから
  [JS7® JobScheduler 初期設定、サンプルWorkFlowの登録](https://qiita.com/natsumadenikimero/items/2d3162b688329f5ecae2)
- WorkFlowの作成、実行、ログ確認などの基本操作ができること。
  こちらで簡単な操作説明をしています
  [JS7 JobScheduler 初めてのWorkFlow実行](https://qiita.com/saitamanokusa/items/1e5ab48cd2e9d38e035c)
- sshで接続可能な環境を、別途用意してください。（パスワードおよび公開鍵認証）
  ※CredentialStore を使う方法もあるようですが、本記事では取り扱いません。
- 本例はエージェントレスで実行する環境がLinuxであることを前提としています。
  （WindowsでもSSH経由でのアクセス環境があれば利用可能なようです）

# エージェントレスの動作概要

エージェントレスといっても、完全にエージェントなしで動くわけではありません。
エージェント経由でssh接続して処理を実行します。

エージェントレスであれば、その分余計な常駐プロセスもなく、JobSchedulerアップデート時に合わせてメンテする必要もありません。したがって既存の環境に手をつけたくない場合に有効な手段となります。

エージェントによる処理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/484acd50-8b06-15ae-390a-e865516a59ac.png)

エージェントレスでの処理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/f9c212e9-056d-9684-989d-ef43cc133b02.png)

# パスワード認証の例

まずパスワード認証での設定例を、基本的な操作と合わせて説明します。

Practice - Workflows より、新規WorkFlow `check_agentless_password` を作ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/ce75b131-1fb1-7c01-0f34-19c78fb21e84.png)

JOBを追加して、JOB名などの項目を適当に設定します。
このとき、Job Classに *JITL*を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/8ffc8f43-59de-e88f-15d6-b6d35963c92e.png)

| 項目名          | 設定値の例    |
| --------------- | ------------- |
| Name    | ssh_job_pass |
| Label   | ssh_job_pass |
| Agent   | `primaryAgent` |
| Job Class  | JITL   |

Wizardをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/ce255b0f-c7bf-f5a3-5425-171b47886360.png)

SSHJob を選んで Next をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/24f0781c-ceb4-0c1d-2b1e-f8fe06a8c4c1.png)

下記のような画面がでてきますので、必要な項目を登録してください。
（入力項目はチェックをつけるのを忘れずに）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/5d6d0827-b79b-fe91-64f5-d909b134f7f4.png)

| 項目名          | 設定値の例    | 説明 |
| --------------- | ------------- | ---- |
| host            | 192.168.11.104 | 接続先 |
| user            | user01        | 認証ユーザー |
| password        | `**********`  |  |
| auth_method     | password      |  |
| command_script  |`echo test`| command と command_delimiter の組み合わせでも同じ  |

終わりましたら、Submitをクリック

Class Name に `com.sos.jitl.jobs.ssh.SSHJob`が入り、Argumentsの欄に、今入力した内容がはいっていることを確認します。
（Wizardを使わずとも、直接編集できます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/0daecda3-c51b-df55-7344-e78c3b863918.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/b379b062-f189-314c-95f4-df1e81e55fa4.png)

ちなみに`command_script`はこちらのほうが編集しやすいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/43bbbf8d-d621-4db1-4c8b-7f994bcd5b31.png)

```shell
'#!/bin/bash
echo "このスクリプトはリモートで実行しています"
echo `hostname`'
```

:::note warn
複数行入力する場合は、シングルクォートで囲ってください。
:::

終わりましたら、Deploy、実行して、結果を確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/f652f487-7248-a055-ca61-00a4534335a6.png)

# 公開鍵認証の例

次に公開鍵認証を利用する場合の設定例です。

あらかじめ秘密鍵をエージェント側に配置し、それを使って接続をします。
下記の例では汎用的な配置を行ってますが、場所やファイル名は任意です。
（エージェントからのread権限があればよい）

```shell
ls -l /home/scheduler/.ssh/id_rsa
-rw------- 1 scheduler scheduler 1676  5月 24 19:51 /home/scheduler/.ssh/id_rsa
```

もしdocker-compose版で環境を用意された方は、`js7-agent-primary`ディレクトリ以下に配置でOKです。
（`JS7_AGENT_DATA`への配置となります）

```shell
# 秘密鍵をマウント先にコピー
cp id_rsa js7-agent-primary/

# 確認
docker-compose exec js7-agent-primary ls -l /var/sos-berlin.com/js7/agent/id_rsa
-rw-rw-r--    1 jobsched jobsched      1676 May 24 10:53 /var/sos-berlin.com/js7/agent/id_rsa
```

次にWorkFlow `check_agentless_pubkey` を作ってください。

JOBを追加し、下記のように設定します。

| 項目名          | 設定値の例    |
| --------------- | ------------- |
| Name    | ssh_job_pubkey |
| Label   | ssh_job_pubkey |
| Agent   | `primaryAgent` |
| Job Class  | JITL   |
| Class Name  | com.sos.jitl.jobs.ssh.SSHJob  |

Argumentsは下記のように設定します。

| 項目名          | 設定値の例    | 説明 |
| --------------- | ------------- | ---- |
| host            | 192.168.11.104 | 接続先 |
| user            | user01        | 認証ユーザー |
| auth_file       | `/home/scheduler/.ssh/id_rsa`<br>または<br>`id_rsa` | フルパスまたはファイル名で指定。<br>ファイル名のみの場合は `JS7_AGENT_DATA` ディレクトリに配置してください。 |
| auth_method     | publickey      |    |
| command_script  | （任意）      |     |

設定できましたら、Deployして、動作確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/08825679-f443-85c6-11a5-33dde7f5f816.png)

# JobResourceを使った設定例

最後に、JobResource変数を使って、上記設定をもう少し効率的に行う方法をご紹介します。
エージェントレス処理が複数ある場合に便利な方法です。

## JobResource定義

まず、JobResource変数を定義します。

Practice - Job Resources より、新規JobResourceを作成してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/8e2f9d79-aa56-44f9-3f44-084e69178375.png)

名前は `JS7_SSH_SAMPLE`とします。

Arguments には 下記の設定を追加してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/edfb3d66-234f-5257-d025-944d23badb7b.png)

|Name|Value|
|-|-|
|js7_ssh_privatekey| (Value Editor を開き、秘密鍵をまるごと貼り付けてください)|
|host|192.168.11.104|
|user|user01|
|auth_file|`$js7WorkflowPath`<br>( ※Builtin変数でWorkFlow名が入ります )|
|auth_method|publickey|
|command_script| `echo "JobResource Default"`|

:::note
（js7_ssh_privatekeyを除いて）JITL SSHジョブのArguments と同一名で定義します
:::

Environment Variables には、下記を定義します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/daf0b06f-05ad-3cc6-a13e-62026a6af223.png)

|Name|Value|
|-|-|
|JS7_SSH_PRIVATEKEY | $js7_ssh_privatekey|
|JS7_SSH_AUTH_FILE | $auth_file |

:::note
シェルジョブ中で利用したい引数を参照します
（値の定義はArguments側に揃えたほうが分かりやすい）
:::

入力したら、Deployしてください。

## WorkFlow定義

次にWorkFlow `check_agentless_jobresource` を作成します。
WorkFlowの設定にて、今作ったJobResource `JS7_SSH_SAMPLE`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/b87801a4-8669-5316-461b-84625b8a3ea0.png)

| 項目名          | 設定値    |
| --------------- | ------------- |
| Name    | check_agentless_jobresource |
| Title   | JobResourceで設定簡略化 |
| Job Resource  | `/Practice/JS7_SSH_SAMPLE` を選択 |

さらに3つのJobを追加し、それぞれ下記のように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/052e1e13-a8c7-6677-2af8-8624478103f1.png)

JOBその１

| 項目名          | 設定値    |
| --------------- | ------------- |
| Name    | create_keyfile |
| Label   | create_keyfile |
| Title   | 秘密鍵配置 |
| Agent   | `primaryAgent` |
| Job Class  | Shell |
| Script | `echo -n "$JS7_SSH_PRIVATEKEY" >"${JS7_AGENT_DATA}/${JS7_SSH_AUTH_FILE}"` |

JOBその２

| 項目名          | 設定値    |
| --------------- | ------------- |
| Name    | ssh_job |
| Label   | ssh_job |
| Agent   | `primaryAgent` |
| Job Class  | JITL   |
| Class Name  | com.sos.jitl.jobs.ssh.SSHJob  |

Argumentsは下記のように設定します。

| Name       | Value    |
| --------------- | ------------- |
| command_script  | `echo "Jobで定義"`（任意）|

JOBその３

| 項目名          | 設定値    |
| --------------- | ------------- |
| Name    | delete_keyfile |
| Label   | delete_keyfile |
| Title   | 秘密鍵削除 |
| Agent   | `primaryAgent` |
| Job Class  | Shell |
| Script | `rm "${JS7_AGENT_DATA}/${JS7_SSH_AUTH_FILE}"` |

設定ができましたら、Deployして、実行してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/b8b1b506-849a-bcb4-65d2-d188be277f0d.png)

## 実行内容

1. `create_keyfile`で、JS7_AGENT_DATA ディレクトリに秘密鍵（ファイル名＝WorkFlow名）を書き出します
   ※JS7_AGENT_DATAはシェルジョブ実行時に自動定義されます。
1. JITL SSHジョブを実行します。このとき`command_script`以外はJobResourceの設定値を使います。
1. `delete_keyfile`で、WorkFlow名の秘密鍵ファイルを削除します

この方法をならば、共通で使う設定は、JobResourceの設定値を利用して、JOB毎に個別に設定が必要な箇所のみの定義で済みます。（ host や command_script など）

また、前後の `create_keyfile`, `delete_keyfile` で、処理の都度、秘密鍵の配置／削除を行うことで、秘密鍵の管理がJOC側1か所となり、あらかじめエージェント側に配置する手間も省いています。

# エージェントレス利用時の注意事項

エージェントレスで実行した場合、JobScheduler側（JOC側）の操作で強制終了しても、リモートホスト側でプロセスが残る場合があります。
終了させる場合は、リモートホスト側の対応も合わせて必要となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529537/36dfb146-3d79-9daa-2c55-45628bd2fdf3.png)

:::note warn
通常は、エージェントで実行中の処理を Cancel/Kill Tasks で強制終了することができるが、エージェントレスでは対応できない
:::

# 最後に

WorkFlow系ツールとの比較の中で、エージェントがないことが選定ポイントにあげられる場合がありますが、今回ご紹介したように、JobSchedulerではエージェントなしでもWorkFlowを組むことが可能です。
また今回は書いておりませんが、シェルジョブと同じように、JobResourceの環境変数を利用したり、後続JOBに変数を渡す処理も組めます。
既存の環境にできるだけ手を加えずにWorkFlowに組み込みたいという場合など、参考にしていただければと思います。

# 参考

[JS7 - Agentless Scheduling](https://kb.sos-berlin.com/display/PKB/JS7+-+Agentless+Scheduling)
[JS7 - JITL SSHJob](https://kb.sos-berlin.com/display/PKB/JS7+-+JITL+SSHJob)