そんなスケジューラで大丈夫か? Rundeck超入門(基礎編)

こんにちは、記事の更新頻度が安定しません。
Rundeckの記事を書くことを今季の目標としてしまったために(勝手に)追い詰められながら記事を書いています。

まぁやるからにはちゃんと書きます。Rundeckは機能が多いから時間がかかるのは仕方ないでしょう?俺は悪くない。

この記事はRundeckの概要・用語・主な使い方について書きます。内容もリファレンスっぽい感じに仕上がってしまいました。
セットアップと応用については別途記事にするつもりです(すぐとはいってない)。

注意:この記事はRundeck 2.5.3を使用しており、バージョンによっては動作が異なる可能性があります。

概要

Rundeckは一言で言うと「すごいcron」です(ドドーン
@hirokiky氏@shimizukawa氏の発表でもそう言っていたからいいよね?

少しだけ補足します。
RundeckはWebアプリ上で操作できるJava製のスケジューラです。

WebUI上から操作・閲覧できるというのは当然ですが、他にも以下のようなメリットが挙げられます。

他にもあると思うけど、これだけあれば使う意味は十分にありますよね?

ちなみにky氏の発表スライドはこちら: 価値を届ける技術 #bpstudy 96 (35ページ目辺りから)

shimizukawa氏のスライドはこちら: Rundeck better crond
この記事でも大体のニュアンスは詰め込みました。

以下の記事も参考にさせていただきました。

すばらしい記事・スライドに多謝。

用語

概要はこのくらいでいいですよね。次はRundeckを知る上で必要な用語を見ていきましょう。

プロジェクト(project)

ジョブをまとめる単位がプロジェクトです。
本番環境/開発環境/ステージング環境/案件のサブプロジェクト等の単位でプロジェクトを分けるのが一般的だと思います。

ジョブ(job)

Rundeckがスケジューリング可能な実行単位です。これは特定のプロジェクトに紐付きます。別プロジェクトのジョブを実行することはできません。
ジョブは1つ以上のステップを持ちます。

ジョブの実行結果はあとから閲覧できます。

ジョブのステータス(Status)

実行後のジョブ履歴は以下のいずれかのステータスを持ちます。

成功(Succeeded)
rundeck-status-succeeded 処理の成功を意味するステータスです。強調します。「成功」を指すのはこのステータスのみです。
後述する「成功率の表示(Success Rate)」も「成功通知」もこのステータスをアテにしています。
失敗(Failed)
rundeck-status-failed 処理の失敗を意味するステータスです。
中断(Aborted)
rundeck-status-aborted 処理が途中で中断した場合のステータスです。画像の表示上では「Killed」となっていますがこの場合の終了ステータスは「Aborted」です。
正確に言うと「Killed」は中断ステータスの1つでジョブの強制終了によって終了した場合には表示上でこのようになるんだと思われます。
タイムアウト(TimedOut)
rundeck-status-timedout タイムアウトによって処理が終了した場合に、このステータスとなります。
リトライ?(Failed-with-retry)

確かに存在はするようですが、これの発生条件は表面上触っているだけではわかりませんでした。
「リトライして最終的に失敗」「リトライして最終的に成功」のいずれかと思ったんですが、どうやら違うみたい。
なくてもそんなに困らない(負け惜しみではない)

ステップ(step)

ステップはジョブを構成する最小単位です。大抵はコマンド、複数行のコマンドはシェルスクリプトとして登録します。やることは同じですけどね。
その他、ジョブをステップとして利用することもできます。

ノード(node)

ノードはジョブを実行する対象ホストです。
これもプロジェクトに紐付くため、別プロジェクトのノードを利用することはできません。
対象ノードの振り分けはジョブ単位で設定されることを理解してください。処理ごとに対象ノードを変えたい場合、ステップではなくジョブ単位で分離する必要があります。

キー(key)

全プロジェクトを横断して参照可能なノードへの認証情報です。
キーはどのプロジェクトからも参照でき、どのノードに対しても設定可能です。

登録可能なキーは「秘密鍵」「パスワード」「公開鍵」があります。
「秘密鍵」に関しては秘密鍵ファイルを設置してもそのまま指定できるので無理にキー登録する必要はありません。RundeckのWebUIから管理できるというメリットはありますが。
「パスワード」はノードの登録ファイル(resources.xml)に直接指定できないのでキー登録したほうが圧倒的に使いやすいです。圧倒的感謝。
キーを使わない場合、ジョブのセキュアリモート認証という機能をつかって指定する必要があります。これはすべてのジョブで指定する必要があるのであまり推奨できません。

キーの登録方法はこちら

ユーザ(user)

Rundeckを操作するためのユーザ(アカウント)です。ユーザの追加はRundeckのUI上からは行えません。
通常は$RDECK_BASE/realm.propertiesにユーザを追加すれば十分です。

デフォルトでは「admin: admin,user,admin」というユーザのみが登録されています。
パスワードにはハッシュ化したものを指定することもできます。

例えば、admin3ユーザにハッシュ化したパスワード「admin3」を作るためには以下のようにします。

[vagrant@localhost ~]$ java -cp /var/lib/rundeck/bootstrap/jetty-all-7.6.0.v20120127.jar org.eclipse.jetty.util.security.Password admin3 admin3
admin3
OBF:1igd1unp1vgj1vgb1uo91idt
MD5:32cacb2f994f6b42183a1300d9a3e8d6
CRYPT:adNjjKXvSro/A

MD5でハッシュ化する場合は「admin: MD5:32cacb2f994f6b42183a1300d9a3e8d6,user,admin」のように指定します。
もちろん「OBF:1igd1unp1vgj1vgb1uo91idt」といったものも指定可能です。どうゆうハッシュ関数かわかってないけど。

LDAPによる管理も行えるようです。
いつか挑戦してみたいですね。

ユーザには以下の権限があるようです。

user

ログインするための権限です。

admin

管理者権限です。この権限があるとプロジェクト(後述します)の作成、および、すべてのプロジェクトを操作できます。
逆にこの権限を持たない一般ユーザは許可されたプロジェクトしか閲覧・操作できません。
admin権限はuser権限の上位互換ではないため、これだけの記述ではログインできません。

その他

architect,deploy,buildという権限が存在しているようですが、何に使うものかわかりませんでした。
参考になりそうな情報を知っている方はぜひ教えてくださいm()m

概念図

言葉だけではわかりにくいかもしれないので以下に概念図を用意しました。

カーソルを当てると関連する要素に色がつきます。強く関連するほど濃い色で表示する謎仕様にしてみました。(わかりにくかったらごめんね)

Rundeck
プロジェクト1
ジョブ1

「ノード1」で以下のステップを実行する

ステップ1

ジョブ2を呼び出す

ステップ2
$ sleep 5
ステップ3
$ echo ‘ステップ3だよ!’
ジョブ2

「ノード2」で以下のステップを実行する

ステップ4
$ echo ‘ステップ4だよ!’
プロジェクト2
ジョブ3

「ノード2」で以下のステップを実行する

ステップ5
$ sleep 5
ステップ6
$ echo ‘ステップ6だよ!’
キー1

「ノード1」にSSHログインするための秘密鍵

キー2

「ノード2」にSSHログインするためのパスワード

キー3

なんかよくわからんけど公開鍵

admin

admin/admin
権限: user, admin

user

user/user
権限: user

ノード1

ジョブを実行する対象ノード

ノード2

ジョブを実行する対象ノード

プロジェクト

ジョブは特定のプロジェクトに紐付くため、先にプロジェクトを作成する必要があります。

rundeck-create-project-0

必須項目は「プロジェクト名(Project Name)」だけで画面最下部の「Create」ボタンを押せば、ひとまずプロジェクトは作成されます。(プロジェクト作成の設定項目は詳しく調べてないので書きません)
作成が完了するとデフォルトで「$RDECK_BASE/projects/」のパスにプロジェクト名のディレクトリが作成されます。

project.name=testproj
resources.source.1.config.requireFileExists=true
project.ssh-authentication=privateKey
service.NodeExecutor.default.provider=jsch-ssh
resources.source.1.config.includeServerNode=true
resources.source.1.config.generateFileAutomatically=true
resources.source.1.config.format=resourcexml
resources.source.1.config.file=/var/rundeck/projects/testproj/etc/resources.xml
project.ssh-keypath=/var/lib/rundeck/.ssh/id_rsa
project.description=test project
service.FileCopier.default.provider=jsch-scp
resources.source.1.type=file

ただし、このままは「localhost」でのみ、つまりRundeckがインストールされているホスト上でしかジョブを実行できません。

ノードの登録

RundeckのノードはWebUI上から追加できません(よね?)
操作対象のノードは「$RDECK_BASE/projects/${project.name}/etc/resources.xml」に記述されます。(以下リソースファイルという
パスは変更でき、フォーマットはXMLYAMLが使えます。

XML

デフォルトはXML形式です。
以下は「node1」「node2」というホストを登録する例です。

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <node name="node1"
        description="target node1"
        tags=""
        hostname="192.168.34.78"
        osArch="amd64"
        osFamily="unix"
        osName="Linux"
        osVersion="3.10.0-123.el7.x86_64"
        ssh-authentication="privateKey"
        ssh-key-storage-path="keys/privatekey/node1.pem"
        username="vagrant" />
  <node name="node2"
        description="target node2"
        tags=""
        hostname="192.168.34.90"
        osArch="amd64"
        osFamily="unix"
        osName="Linux"
        osVersion="3.10.0-123.el7.x86_64"
        ssh-authentication="password"
        ssh-password-storage-path="keys/password/vagrant-password"
        username="vagrant" />
</project>
YAML

YAMLでも表現可能です。
その場合、project.propertiesに「resources.source.1.config.format=resourceyaml」を指定します。
以下は「node3」を登録する例です。

  node3:
    description: target node3
    hostname: 192.168.34.78
    nodename: node3
    osArch: amd64
    osFamily: unix
    osName: Linux
    osVersion: 3.10.0-123.el7.x86_64
    tags: ''
    username: vagrant
    ssh-authentication: privateKey
    ssh-keypath: /vagrant/.vagrant/machines/node3/virtualbox/private_key

ノードの登録が終わるとプロジェクトのノード一覧で確認できます。これについては後述します。

キーの登録

キーはRundeckが共通で参照できる認証情報でしたね。(プロジェクト単位ではありません)
各ノード設定にKeyを指定すると認証に利用できます。

キーの作成は以下のような手順で行います。

  1. 右上のギアマークから設定に移動して、「Key Storage」を選択します。
  2. 「Add or Upload a Key」をクリックするとモーダルが起動します。
    • 「Key Type:」を選択します。「Private Key」は秘密鍵、「Password」はパスワードを登録できます。
    • 登録したい鍵を入力します。手入力もできますし、実際の鍵ファイルをアップロードすることもできます。
    • 「Storage path:」は必須ではありません。入力したパスによってディレクトリが区切られます。省略するとフラットにKeyが置かれます。
    • 「Name:」にKey名を入力します。
    • 「Save」をクリック!

作成されたキーファイルの保存パスは以下のように表示されます。
rundeck-key-storage-path

キーの指定方法はさりげなくこちらの例で紹介しています。
秘密鍵の場合は「ssh-key-storage-path」、パスワードの場合は「ssh-password-storage-path」に指定します。

ちなみにこちらの例ではキーを使わずに秘密鍵ファイルを直接参照しています。
(なんかVagrantのバージョンが上がって毎回鍵ファイルが変わるとか何とからしいので、覚えておいて損はない)
鍵ファイルの所有者およびパーミッションには十分注意してください。「r——–(600)」でrundeckの実行ユーザが見られれば問題ないっす。

ジョブの作成

ジョブを作成するにあたり、それぞれの項目について説明します。

ジョブ名(Job Name)

ジョブを識別するための名称です。
入力は必須ですが、一意である必要はありません。一意性は後述するUUIDによって管理されます。

グループ

ジョブがファイルだとするとグループはディレクトリに相当します。
指定したグループが存在しない場合グループは動的に生成され、既存のグループを指定した場合は同じグループにジョブが入るという感じです。グループだけを作成することはできず、ジョブを持たないグループは存在できません。「/(スラッシュ)」でグループを階層構造にすることができます。これもディレクトリと同じですね。

ジョブの説明(Description)

グループの説明です。入力は必須ではありません。
マルチバイト文字の入力(未変換の先頭文字)が化けるという現象が確認されていますが、確定しちゃえば特に問題ないのです。これくらいは目をつぶってやりましょう。

オプション(Options)

環境や状況に応じて、処理に指定するパラメータを変更したくなるというのはよくある話ですね。こういった箇所はオプションとして定義しましょう。

例えば、日次のバッチでは対象日付が「入力されなかったら常に前日を対象」、「入力された場合はその日付を対象」といった使い分けができますね。他にも対象ホスト、対象ファイルなど状況・環境に応じて手動で指定する可能性がある箇所はオプションにすると便利です。
残念ながら複数のジョブにまたがるオプションというのは書けず、一つ一つ定義するしかありません。

新規でオプションを追加する場合は「Add an Option」です。

オプション名(Option Name)

オプション名を半角英数字で指定します。数値だけのオプション名も可能です。1つのジョブ内での重複は許されません。

説明(Description)

オプションに関するヘルプをお好きなように書いてください。

初期値(Default Value)

オプションの初期値を入力します。入力は必須ではありません。

入力型(Input Type)
プレーン(Plain text)

平文「type=”text”」の入力フィールドです。これがデフォルトです。

セキュア(Secure)

「type=”password”」の入力フィールドです。入力文字列がそのまま表示されません。
Rundeckではジョブの実行、その時に渡したオプションをDBで管理していますが、この入力型を選ぶとDBに保存されません。

セキュアリモート認証(Secure Remote Authentication)

このオプションは特殊です。公式様の説明はこちら

ノード実行するための組み込みの SSH プロパイダは SSH, Sudo 認証メカニズムのため、パスワードを利用します。 パスワードはジョブ内に定義されたセキュアリモート認証オプションで供給することができます。
セキュアリモート認証オプションは平文・セキュアオプションと比較していくつかの制約を持ちます。
通常のスクリプトとコマンドオプション値の展開にユーザが入力した値を使うことはできません。 言い換えると、このオプションはリモート認証のためにしか利用できません。

だめだわからん。いや、なんとなくはわかる。どうやらSSHやsudoなどのパスワードを求められた際の入力に使用できるみたいですね。
とはいえ、単に入力しただけでばっちりうまくいくわけではありません。resourcexml(またはresourceyml)に受け取るオプションとパスワード認証を使用する旨を記述する必要があります。
詳細はドキュメントを参照してください。
後で別途記事を上げるときにこれも取り上げます。

選択肢(Allowed Values)

選択肢の提示です。指定方法は以下の2種類があります。

List

「,(カンマ)」区切りの文字列を入力します。これがデフォルトです。以下のことに注意しましょう。

  • 選択肢文字列前後の半角スペースは無視される。
  • 空文字や半角スペースのみの文字列は選択肢にできない。
  • 選択肢にカンマを含めることができない。「”(ダブルクォート)」や「'(シングルクォート)」で囲ってもダメ。「\(バッククォート)」でカンマのエスケープもできない。
Remote URL

外部から入力可能な値(JSON)を受け取る方法です。状況に応じて選択肢を変更したい場合に使うことになるでしょう。
JSONの取得は閲覧しているブラウザではなくRundeckのホスト経由で行われます。ブラウザから閲覧可能なJSONであっても、Rundeckホストから閲覧不可能であれば選択肢として表示できない(はず)です。
APIとして提供したいが一般の閲覧を制限したい場合は、GETパラメータにトークンを持たせたりIP制限するのがよいでしょう。

JSONのフォーマットは以下の3種類があります。

配列

["x value for test","y value for test"]

配列型の場合、選択肢に表示される値と入力欄の値が同じになります。入力された順番で表示されます。

オブジェクト(ハッシュ)

{ "Name": "value1", "Name2":"value2" }

オブジェクト型の場合、選択肢に「key」、入力欄に「value」が表示されます。
ご覧の通り選択肢の順番は「key」文字列の昇順となります。ハッシュだから仕方ないね。

オブジェクトの配列

[
  {"name":"X Label", "value":"x value"},
  {"name":"Y Label", "value":"y value"},
  {"name":"A Label", "value":"a value"}
]

「順番は指定通り」「選択肢と入力欄を分けられる」という2つのメリットを組み合わせた記述方法です。

その他詳しく知りたい方はこちらを参照してください。

入力値制限(Restrictions)

入力された値が適切かどうかの判断方法を指定します。

なし(None)

どのような値も指定可能です。これがデフォルト。

選択肢に含まれる値のみ(Enforced from Allowed Values)

選択肢の入力を強制させます。選択肢にない入力をするとエラーになります。
逆に言うとこれを選択しないと入力値以外の値をオプションとして入力できるということになりますね。ここ、勘違いポイントな気がするので十分に気をつけてください。

正規表現(Match Regular Expression )

入力可能な値を正規表現で指定します。これがあれば大半は何とかなるでしょう。
選択肢にListを選択している場合、すべての選択肢を満たすような正規表現を書く必要があります。

条件を満たさない場合、実行時点で以下のようなエラーが発生します。

Option 'a' doesn't match regular expression [0-9], value: a 

数値の範囲制限とかはないんですかね?結構需要あると思うんだけど。

省略可否(Required)

オプションの入力を省略できるか否かです。半角スペースは入力に含まれます。デフォルト可能です。

値を複数受け取るか(Multi-valued)

有効にするとオプション入力UIが変化し、複数の値を受け取れるようになります。複数受け取った値を連結するための文字(列)を「Delimiter」に指定します。
デリミタに「,」、入力値を「a」「b」「c」とした場合、それぞれのステップには「a,b,c」と行った文字列がオプションとして渡されます。
Delimiterは入力必須で2文字以上の文字列でも構いません。

勘違いしないで欲しいのは「入力された値を特定の文字で分割して複数値として扱う」ではありません。少なくとも私は最初そう思い込んでました。

オプションの説明はこれで終わり.

処理の流れ(Workflow)

さて、ジョブの中核です。ステップを列挙してジョブを構成していきます。
ここには入力項目がたくさんあります。

ステップの継続設定(If a step fails)

失敗したステップで処理が終了してほしい時は「Stop at the failed step.」
失敗したジョブは置いておいて、残りのジョブを実行したい時は「Run remaining steps before failing. 」
を選択します。後者を選択した場合であっても、途中で失敗した場合ジョブのステータスは失敗となることに注意してください。

ステップの実行規則(Strategy)

この時「ノードごと(Node-oriented)」に実行するか、「ステップごと(Step-oriented)」に実行するかを選択できます。
ステップを「A」「B」「C」とすると、それぞれの実行順は以下のようなイメージです。

ノードごと(Node-oriented) ステップごと(Step-oriented)
  • node1に対して
    • Aを実行
    • Bを実行
    • Cを実行
  • node2
    • Aを実行
    • Bを実行
    • Cを実行
  • Aを実行
    • node1に対して
    • node2に対して
  • Bを実行
    • node1に対して
    • node2に対して
  • Cを実行
    • node1に対して
    • node2に対して
ステップの追加(Add a step)

ステップには以下の種類があります。

コマンド(Command)

シェルのコマンドを実行します。おそらく一番多用する形式になるでしょう。

スクリプト(Script)

複数行のシェルコマンドやスクリプトを実行するのに適した形式です。
単純なシェルスクリプトを実行できるのはもちろん、先頭行にshebang(たとえば!/usr/bin/env python)などのようにインタプリタを指定して実行することもできます。
当然ながら実行対象のホストでそのインタプリタがインストールされていることが前提です。
指定がない場合はシェルスクリプトとして実行されます。shかbashかはわからないので勝手に検証しやがれです。

スクリプトのパスかURL(Script file or URL)

パスかURLに該当したスクリプトファイルを実行します。
パスを指定する場合、Rundeckを実行中のユーザがスクリプトファイルの閲覧権限が必要です。実行権限は必要ありません。

ジョブ参照(Job Reference)

ジョブをステップとして実行するための形式です。ジョブ名で指定します。
指定した名称のジョブが存在しないとエラーになりますが、該当するジョブが複数存在しても一意に特定できないためかエラーになります。

Job [test] not found, project: testproj

また、自分自身のジョブを循環参照させてはいけません。ジョブの登録・編集の時点で警告はでませんが、これも実行時にエラーとなります。

Request: /execution/tailExecutionOutput?format=json
Message: null
Caused by: null
Class: ExecutionController

エラーメッセージとしてはわかりづらい。

ジョブ参照によってジョブを実行する場合、同時実行の制御が効きません。
他ステップの状態を参照して、ジョブの実行を制御する機能があるため、直接実行しているジョブ以外で同時実行を制御したい場合はこちらを利用するとよいでしょう。

引数(Arguments)
「-option1 value1 -option2 value2」のようにオプションに値を指定することができます。

実行位置(Run as a)
ステップ(参照しているジョブ)の実行位置という認識で大体あっていると思います。
「Node Step」はノード毎にステップを実行します。
「Workflow Step」はステップを設定した位置で一度だけ実行されます。
似たような設定がステップの実行規則でもありましたね。

組み合わせによって実行順が若干変化します。
言葉ではわかりづらいですよね。ぼくも説明しづらいです。でも頑張って理解してください。

以下のようなジョブがあったとします。

  1. [Command] echo 1
  2. [Job Ref] testジョブを参照(testジョブは「echo test」コマンドがあるだけ)
  3. [Command] echo 3

このジョブの実行位置(Run as a)、および実行規則(Strategy)の変化によるステップの実行順は以下のようになります。

Run as/Strategy Node-oriented Step-oriented
Node Step rundeck-node-oriented-node-step rundeck-step-oriented-node-step
Workflow Step rundeck-node-oriented-workflow-step rundeck-step-oriented-workflow-step

「Workflow Step」を選択すると強制的に「ステップごと」の実行に固定されるようです。
「Node step」と「ステップ毎の実行」は組み合わせる価値がほとんどなさそうですね。

ファイルのコピー

Rundeckノードのファイルをコピーします。コピーはリモートホストへだけでなく、ローカルホストに対しても行われます。
srcとdestに同じファイルパスを指定するとファイルが空になるので十分に注意してください。バリデーション欲しいこれ。

ローカルコマンド

Rundeck(local)上でのみ実行するコマンドです。
ただし、対象ノードが複数ある場合ノードの数だけ(ローカルで)実行されるということに注意してください。
ローカルで1回だけ実行したい場合はジョブに隔離し、呼び出すことで表現できます。

エラーハンドリング(error handler)

ステップが失敗した場合に実行する処理を指定できます。やることはステップの追加と同じです。

処理の継続可否(Keep going on success)

エラーハンドリングを設定してもステップの終了ステータスが失敗であれば、ジョブの実行はそこでストップしてしまいます。
このオプションを有効にするとエラーハンドリングの処理が成功した時点で終了ステータスが成功となり、処理を継続することができます。

ステップの継続設定にて「Run remaining steps before failing」を設定した場合、エラーハンドリングの処理が失敗しない限りステータスは成功となります。この挙動が仕様として正しいかどうかはわかりません。

ワークフロー制御(Flow Control)

ジョブを任意のタイミングで終了するのに利用されます。

正常終了(Halt)

終了ステータス(Status)に入力したステータスでジョブを終了させます。

異常終了(Fail)

こちらをチェックした場合終了ステータス(Status)の入力及び正常終了のチェックは無視されます。
片方しか意味ないならチェックボックスじゃなくてラジオボタンにするべきじゃないですかね。。?

終了ステータス(Status)

カスタマイズされた終了ステータスです。(以降正式名称は不明だがカスタムステータスという)省略した場合は強制的に異常(エラー)終了となります。
もともとRundeckが持っているステータスを選択すると「Failed」となるようです。(以降あってるかわからないけどビルトインステータスという。正しい呼称を知ってる人は教えてね!)
ビルトインステータスはこちら

ステップの説明(Step Description)

ジョブの定義に表示される説明です。ログに出力されるわけではありません。
いずれの終了方法を選んだ場合でも、複数ノード存在しても終了メッセージの表示は一度だけです。

ジョブの実行状況(Job State Conditional)

ジョブ名(Job Name)かUUID(Job UUID)によって一意に特定されたジョブの状態を見てジョブを制御するステップです。
いずれかの入力は必須ですが、当然バリデーションはありません(*’ω’*)。空のまま保存しちゃうと実行時に以下のエラーがでます。

Configuration invalid: jobUUID or jobName is required
実行中(Running)

参照しているジョブが「実行中」であるかどうかを判断する設定です。
「true」は「実行中であること」、「false」は「実行中でないこと」を期待します。

実行ステータス(Execution State)

指定したジョブの最終実行ステータスに期待する値を記述します。
右のセレクトボックスからビルトインステータスを選択することもできますし、入力した値を変更することも可能です。

ビルトインのステータスはこちら。「Never」というのはステータスというより、まだ一度も実行されていないという意味です。

Runningか、こちら、いずれかの入力が必須です。

実行ステータス条件(Condition)

「Equals(一致する)」か「Not Equals(一致しない)」かのいずれかです。

残りの設定項目はワークフロー制御(Flow Control)と同じです。

重要なのはこの条件を満たしたときには処理は成功(Success)となり、満たさなかったときに指定したステータスによって終了するという点です。

実行ノード(Nodes)

実行対象のノードを指定します。デフォルトでは「(ローカル)Execute locally」のみです。
「Dispatch Node」を選択するとノードの選択UIが展開されます。

フィルタ(Node Filter)

入力した正規表現と一致したノードが抽出されます。このとき抽出されるノードはプロジェクトに登録されているノードに限定されます。「Matched Nodes」に該当したノード名が出力されます。すぐに反映されない場合は「refresh」ボタンを押してみてください。
このことから分かるとおりノードにつける名前は重要です。同じジョブを実行させるノードであれば、同じプレフィックスをつけるなどすれば、簡易な正規表現ですべてのノードを抽出できますね。シンプルで壊れにくい設定を目指しましょう。

並列ノード数(Thread Count)

対象ノードが複数存在する場合の並列数です。デフォルトは「1」で直列実行します。

ノード属性による実行順序制御(Rank Attribute)

そもそも属性ってなんだって話だって思った方もいるでしょう。Rundeckにおける実行ノードはリソースファイルによって管理しているという話を先ほどしました。
ノードには任意の属性値を指定することができます。その属性値の値を元に実行順を設定できるというわけです。

リソースファイルの変更は即座に反映されるため、再起動は必要ありません。

昇順・降順(Rank Order)

昇順は「Ascending」、降順の場合は「Descending」です。昇順がデフォルト。

ノードの継続設定(If a node fails)

ステップが失敗した場合、別ノードのステップを実行するかという設定です。

ステップの継続設定という設定にて失敗時に残りのステップを続行する選択肢がありましたね。両方を選択することによってすべてのステップを網羅できます。
以下のコマンドを「node1」「node2」に対して実行する例で検証してみましょう。

  1. echo 1
  2. false
  3. echo 3
step/node stop run
stop rundeck-fails-stop-stop rundeck-fails-stop-run
run rundeck-fails-run-stop rundeck-fails-run-run

いずれを有効にしても途中の処理が失敗すればジョブの終了ステータスはやはり「失敗」となります。
処理の継続可否(Keep going on success)でも記述しましたが、失敗するステップに対してエラーハンドリングを設定することにより終了ステータスを「成功」させることができます。
この場合ジョブのステータスは成功となるため、ノードの継続設定は必要ありませんが、すべてのノードのすべてのステップを絶対に実行したいような場合は設定しておくのが無難でしょう。

通知(Send Notification?)

デフォルトは「No」、つまり通知なし、「Yes」にチェックを入れると設定項目が展開されます。どうでもいいことですが「Yes」を選んで通知設定せずにSaveすると「No」に戻ります。
通知するタイミングは以下の3種類です。

成功時(On Success)

ジョブのステータスが成功のときにのみ発動します。

失敗時(On Failure)

ジョブのステータスが成功のとき以外に発動します。失敗(Failed)以外のカスタムステータスやタイムアウトでも発動します。

開始時(On Start)

ジョブのステータスにかかわらず、ジョブの開始時に発動します。

それぞれの条件で以下の動作をとることができます。

メール送信(Send Email)

Toには送信先のメールアドレスをカンマ区切りで入力できます。(CCやBCCの設定は見つからなかった)
Subjectはご存知の通りメールタイトルです。
いずれのフィールドからもコンテキストの参照が可能なようです。
例えば失敗通知でタイトルに度のステータスで失敗したかを通知したければ「${notification.eventStatus}」とすればできるようです。
この項目は地味にこちらに載っていました。

Webフック(Webhook)

取得したWebフックのURLを指定します。ここではコンテキストの参照はできません。
もちろんslackの通知も指定できます。
slackの通知をするためにはプラグインが必要です
諸事情により手元では設定できなかったので設定手順は書きません。

定期実行するか(Schedule to run repeatedly? )

「No」だと手動で選択しない限り実行されません。これがデフォルトです。
「Yes」の場合、以下の指定方法により定期実行されます。

Simple

指定した「時刻」「曜日」「月」に一度実行する指定方法です。
「曜日」「月」はデフォルトですべてが指定されており毎日実行されますが、チェックを外すと特定曜日、特定月だけ実行が可能です。

Crontab

cronライクな記述によりSimpleでは実現できない「5分間隔で実行」「1時から5時まで」「5分と30分に実行」などの複雑な指定が可能です。
本家のcronフォーマットに加え、秒(Second)、年(Year)の指定が追加されているので既存のcronルールをそのまま移植できない点に注意してください。
カーソルを当てるとテキストボックスの右にフィールドの案内がでるのでそれにしたがって入力してください。

cron 分(m) 時(h) 日(d) 月(M) 曜日(w)
rundeck 秒(s) 分(m) 時(h) 日(d) 月(M) 曜日(w) 年(y)

cron記法についてわからない方はググってください。

ログレベル(Log level)

Debugを選択すると実行時のログに詳細な情報が出力されます。
通常は「Normal」となっており、これで十分でしょう。

同時実行可否(Multiple Executions?)

ジョブを同時に実行できるか否かです。
デフォルトで「No」。同時実行不可です。

同時実行しようとすると以下のようなエラーが発生します。

Job “test” [5460a29f-b1f0-4cdb-a9e2-82b157547510] is currently being executed (execution [[187]])

タイムアウト(Timeout)

ジョブの制限時間です。ジョブの実行が設定した時間以上かかる場合にエラー終了させる機能です。

0か空白の場合はタイムアウト設定は無効となり、数値の後ろにつける文字によって、時間の単位が変わります。

省略すると「秒(s)」
m 分(m)
h 時間(H)
d 日付(D)

そのほか、大文字の「M」を指定した時は分(m)や秒(s)とは違う結果になりました。もしかしたら月(Month)かもしれませんが、そんな長い期間のタイムアウトは検証していません。

ステップごとの時間ではなく、ジョブ全体の時間であることに注意してください。ステップの実行に多少オーバーヘッドがあることを見込んで設定するようにしましょう。

リトライ(Retry)

ジョブが失敗した場合に再実行する機能です。
当たり前の話かもしれませんが、再実行されるジョブは失敗したジョブとは別に実行され、ログも別途出力されます。

失敗とはシェルの実行ステータス($?)が0以外の場合を指します。
バッチを何らかの言語で自作する場合、何も考えずに例外(エラー)をキャッチし正常終了させると0が返却され、Rundeck側で失敗を検知できないので注意してください。

UUID

ジョブを一意に識別するIDです。これはプロジェクト内で一意であればUUIDフォーマットでなくとも構いません。入力しないと勝手にUUIDが振られます。このときのUUIDは俗に言うUUIDで、こういう「1341c6b8-2169-421e-acf6-3376c7d287a1」やつです。
ジョブを実行するときにURLにこのUUIDが指定されることになります。処理を識別しやすいような値を自分で設定することを推奨します。
一度作ってしまうと編集できないため、間違えてしまった場合は作り直す必要があります。とは言っても、再度入力し直す必要はありません。「Action▼」の「Duplicate this Job…」を選択するとジョブをUUIDを除き全く同じ内容でジョブをコピーできます。

UUIDは全プロジェクトを通して一意である必要があります。重複すると以下のようなエラーメッセージが出ます。

Cannot create a Job with UUID test: a Job already exists with this UUID. Change the UUID or delete the other Job.

以上でジョブの入力項目説明は終了です。
ジョブの定義は時間をかけすぎるとタイムアウトするので気をつけましょう。

ジョブの実行

ジョブがスケジュール設定されていると次の実行予定時間が画面上部に表示されます。

ジョブは「Run Job Now ▶」ボタンクリックで実行されます。
このときボタン下の「Follow execution」がチェックをはずすと、実行後も同じページにとどまります。
チェックしたままだとジョブの実行画面に遷移します。「Log Output」タブを選択すると標準出力の内容をリアルタイムで確認することができます。

rundeck-job-execute-ui

そのほか、ジョブのオプション、ログレベル、対象ノードの書き換えが行えます。
ただし、ノードの書き換えに関しては現在のジョブに設定されているものの中から再選択できるのみで、別のノードを選択できるわけではありません。

また、ジョブの実行には1度限り有効なトークンが必要で、実行後にブラウザバックで戻って再実行すると以下のようなエラーメッセージをお目にかかることができます。

Error
Invalid request token The request did not include a valid token, or the token has expired. Please try your request again.

正しいリンクから遷移するか、ページを再読み込みしましょう。

ジョブの強制終了

  • 実行に時間がかかるジョブを間違って実行してしまった
  • そのタイミングで実行してはならないジョブを実行してしまった
  • 実行直後にパラメータが間違っていることに気付いた

実行を取り消したくなる理由は数えだしたらキリがありません。
ジョブの中断は容易でジョブの実行中に「Kill Job」をクリックするだけです。
ただし、この操作はあまり推奨されていないようです。
どうしてもという時以外は控えましょう。強制終了したジョブは「Aborted」となります。

ジョブの実行結果

実行結果はジョブ画面の下に表示されます。

rundeck-execute-histories

実行結果統計(Statictics)

EXECUTIONS 総実行回数
SUCCESS RATE ジョブの成功率(成功(Succeeded)ステータスの実行履歴だけを成功数としてカウントする)。小数点以下は四捨五入ぽい
AVERAGE DURATION 平均実行時間

実行結果一覧(Activity for this Job)

以下の分類で実行履歴を表示する

running 実行中のジョブ履歴だけを表示
recent 実行履歴を20件ずつ新しい順で表示。この内容はメニューの「Activity」からも確認できます。
failed 失敗したジョブ履歴だけを表示
Ω by you 現在ログイン中のユーザで実行した履歴だけを表示

それぞれの実行履歴には履歴詳細へのリンクが張られており、その時のジョブ実行後画面に遷移することができます。

実行詳細

実行(履歴)詳細からは以下のことがわかります。

  • いつ実行したか
  • だれが実行したか
  • どのノードに実行したか
  • どのくらいかかったか
  • 実行後のステータスはどうなったか
  • どのような処理(ステップ)を実行したか(ステップが変わっても覚えている)
  • どのようなオプションを渡したか(secretでなければ渡した値が保存される)(オプションが変わっても覚えている)
  • どのようなログを出力したか

また、右上の「▶ Run Again …」をクリックすると、同じオプションを与えて再実行することができます。
ただし、オプションが削除されている場合は渡されません。

ワンショットでコマンドを実行したい

Rundeckではジョブ以外にも任意のコマンドを任意のタイミングで登録ノードに対して実行することができます。

rundeck-command
この画面へはメニューの「Commands」から遷移できます。実行結果は同画面にリアルタイムで出力されます。
Rundeckで登録されているノードに対してなんらかのコマンドを実行する場合はログを共有できるのでおすすめです。

いかがだったでしょうか。
多機能すぎてまだ何が何だかわからない方も多いかもしれませんが、慣れてくると心強い味方になってくれることでしょう。
Let’s try!