一休.com Developers Blog

一休のエンジニア、デザイナー、ディレクターが情報を発信していきます

Rundeck in practice [導入編]

この記事は一休.comアドベントカレンダー2018の6日目です。

qiita.com


一休では、2016年の10月からRundeckを使ってバッチジョブの実行管理を行なっています。
導入からおおよそ2年たちました。
その間にデータセンターからAWSへの移行やいくつかの運用トラブルなどを経験しました。知見が溜まってきたので導入編と運用編の2つの記事に分けて紹介したいと思います。

今回はまず、導入編として、導入の背景と実際の導入作業で工夫した点、苦労した点を紹介します。また、Rundeckを導入したことで得られた改善についても紹介します。

Rundeckとは

f:id:s-tokutake:20181206084400j:plain

  • Rundeck社が提供するOSSのジョブ管理ソフトウェア。有償版もある。
  • ジョブフロー構築、失敗の自動リトライ、開始終了に対する通知フックなど、 一般的なジョブエンジンの機能を持つ。
  • Java + Groovy + Grailsで実装されている。
  • スケジューリングの定義は、cron形式。
  • 管理画面はWebブラウザで操作できる。
  • SSH経由でリモートのコマンドを実行できる。
  • SSHが通るマシンであれば、OSを問わず、どのマシンのプログラムでも定期実行できる。

脱Windows タスクスケジューラ

Rundeckを導入する前、一休ではサービス運用に必要なバッチ処理をWIndows タスクスケジューラで実行していました。登録されたタスクの数は、100を超えていました。
タスクスケジューラで100を超えたタスクを管理するのはとても辛いです。なにが辛いかというと、

タスクスケジューラのGUIは大量のタスクを管理するのに向いていない。

タスクスケジューラのGUIはフィルタや検索ができません。タスクの数が少なければ問題ないのですが、100以上のタスクを管理しようとするとかなり苦労します。例えば、手動でタスクを動かす必要がある場合、タスク一覧を目視で舐めて目的のタスクを見つけるという辛い作業をしていました。

ジョブフローが組めない。

  • 100以上のタスクがあれば、実行順序に依存関係のあるタスクもあります。しかし、タスクスケジューラでは、「タスクAが正常に実行を完了したらタスクBを動かす」というようなジョブフローが組めません。

なぜRundeckを選んだのか

脱Windows タスクスケジューラを目指すため次の4つの要件を満たすジョブエンジンを探しました。

  • ジョブフローが組めること
  • GUIがわかりやすいこと。ブラウザでアクセスできること。
  • WindowsとLinux両方で動くこと。
    • 一休はWindows系の技術スタックをメインに使っていますので、Windowsで動くことが必要ですが、Linuxサーバも使いますので、Linuxもサポートする必要があります。
  • OSSであること。
    • プロプライエタリな製品だと設計や運用でライセンスを気にする必要が出てきます。また、機能検証しにくいこともあるかもしれないので、まずは、OSSで探して、良さそうなものが見つからなければ市場調査をしようと考えました。

この基準で判断した結果、以下のふたつが、候補になりました。

決め手のひとつはGUIのシンプルさでした。SOS JobschedulerもブラウザでアクセスできるGUIを持っていますが、Rundeckの方がわかりやすいです。 また、日本語の情報もRundeckの方が多かったため、Rundeckを選択しました。
そして最大の決め手は、「SSHさえ疎通すれば、どんなマシンのどんなコマンドでもcron実行できる」という柔軟さです。これによって、ジョブ管理をするサーバとジョブを実行するサーバを分離できます。ジョブ実行に必要なリソースが足りなくなったら、ジョブ実行をするサーバだけ増やせば済みます。そして、ジョブを実行するサーバはOSを問いません。

構成

現在の構成は以下の通りです。 f:id:s-tokutake:20190106110930p:plain

RundeckサーバもジョブサーバもすべてEC2です。導入当時はデータセンターの物理マシンでしたが、構成自体は上の図とほとんど変わりません。 ジョブの実行ログはS3に保存し、RundeckのデータベースにはRDSを利用しています。AWSのサービスを最大限利用した構成にしました。 現時点では、RundeckサーバもジョブサーバもWindows Serverです。

導入にあたって、工夫した点、苦労した点を紹介します。

管理画面の認証

Rundeck自身がユーザー管理の機能を持っています。しかし、50人近くいる開発者全員のアカウントをRundeckに登録して適切に管理するのは大変です。外部の認証機構と連携する必要があるのは自明でした。 RundeckにはActive Directoryと連携する機能があります。また、oauth2_proxyに対応しているので外部のOAuth 2.0 サービスプロバイダーとも連携できます。 一休ではデータセンターにRundeckがあった時代は、AD連携機能を使って認証を行なっていました。クラウドに移行したときに、Rundeckサーバから社内のADが見えなくなってしまったので、oauth2_proxyとGitHubのOauth2の仕組みを使って、GitHubアカウントでログインできるようにしました。

oauth2_proxy は bitly社が開発しているOSSで、リバースプロキシとして動作し、oauthプロバイダとのやりとりを代理してくれる便利なツールです。Goで開発されているのでWindowsでも問題なく動作します。

※ このoauth2_proxy+GitHubでの認証の仕組みの構築には、minamijoyoさんの記事を参考にさせていただきました。ありがとうございます!

EC2プラグイン

RundeckにはEC2プラグインがあります。このプラグインを使うと特定のタグがついているEC2インスタンスを自動的にRundeckのジョブサーバにできます。

f:id:s-tokutake:20190106111304p:plain

これによって、なんらかのメンテナンスでジョブサーバの入れ替えや再構築が必要なときも簡単に対応できます。 また、動的にジョブサーバを追加することもできます。例えば、常時動作しているバッチサーバのスペックでは処理しきれないような大規模バッチ処理がある場合、高スペックなEC2インスタンスを起動して処理をさせ、完了したら、そのEC2インスタンスを停止する、という一連の流れを手動操作を介在させることなく実現できます。

sshサーバ

Linuxサーバなら悩む必要はないのですが、一休ではジョブを実行するサーバはWindowsサーバです。環境を構築した時点では、公式のWindows環境のOpenSSHの実装は、動作が不安定で使えませんでした。そこで、Windows環境で動作するSSHサーバを有償無償問わず、調査したところ、bitvise ssh server 最適と判断しました。

  • 有償ですが、安い。ライセンス買い切り。
  • 設定が簡単でシンプル。

当初は、無償のfreesshdで進めようと思っていたのですが、動作が安定せず、断念しました。

タスク移行

タスクスケジューラ上の100以上あるタスクを手動でRundeckのジョブとして移行していたら絶対にミスをします。また、当然、移行作業中も通常のサービス開発は行われています。新しいバッチ処理が追加されているかもしれません。移行作業と開発との間の齟齬が起きないようにする必要がありました。 そこでタスクスケジューラからxml形式でタスクをエクスポートし、Rundeckのジョブ定義xmlに変換するプログラムを書き、そのジョブ定義xmlをRundeckにインポートすることで、スムーズかつ齟齬がないように移行しました。

ジョブのエラー通知

Rundeckには、タスクの完了(成功、失敗)を通知する仕組みがあります。メール通知、webフックの呼び出しができます。また、プラグインを利用することでslackにも通知が飛ばせます。一休ではサービスのエラー通知はすべてslackに飛ばしています。なので、プラグインを使ってslackに通知しようと考えました。しかし、以下のふたつの理由でこのプラグインを使ってのslack通知はやめました。

  • ひとつひとつのジョブに設定しなければならないのが面倒。新しく追加したジョブに設定漏れが起きそう。
  • 通知内容が少ない。特にエラーになった場合は、実行したコマンドのステータスコードや標準出力の内容も通知したい。

そこで、以下のような方法にしました。

  • S3プラグインを使ってジョブの実行ログをS3に出力する。
  • S3へのログのPutをトリガにして動作するAWS Lamdbaを実装する。
  • このLamdbaはログの中身をみてエラーだったら、エラー内容(ステータスコードや標準出力)をSlackに通知する。成功の場合は通知しない。

このようにすることで、ジョブの通知設定に関わらず全てのエラーをslackに通知することができました。

ansibleを使って環境構築

oauth2_proxyのインストールやRundeckのインストール、各種構成ファイルの設定、監視の設定はすべてansibleで行うようにしました。こうすることでトライアンドエラーを繰り返しながら上述したような技術検証ができました。また、ansibleがWindows環境でも問題なく使えることがわかったのも収穫でした。

改善ポイント

  • 当初導入によって目論んでいた改善はほばすべて達成しました。
  • ブラウザから管理画面にアクセスできるようになったのでタスクスケジューラよりもはるかに簡単に管理できるようになりました。ジョブのフィルタもできます。また、タスクスケジューラ時代はさまざまな事情がありジョブの登録や変更は特権を持った特定のエンジニアしかできないようになっていました。このルールもRundeck移行によって見直すことができました。

  • ジョブフローも活用されています。導入当初は、使われていませんでしたが、数ヶ月経つと、特定のエンジニアが導入を推進する、ということをしなくても、自然と使われるようになっていきました。

  • また、当初見込んでいた改善ではないですが、タスクスケジューラを使ったバッチ処理よりもインフラの可用性は大きく向上しました。バッチの実行管理をするRundeckサーバと実行の定義のストアであるRDS、そして実際にバッチを実行するバッチサーバの3つを分離できました。この3つそれぞれ別々に障害対策を考えればいいので運用がしやすいです。フェールオーバの手順はタスクスケジューラ時代の障害時フェールオーバの手順よりもかなりシンプルになりました。

終わりに

今回紹介した内容は1年半くらい前に実施したことなので少し情報が古いかもしれません。しかし、LinuxのcronではなくWindowsのタスクスケジューラからRundeckに移行した例はあまりないのでは、と考え、紹介しました。RundeckはWindows環境でも十分に活用できます。 次回は、運用編として、この2年間で起こった運用トラブルとその対処について、紹介したいと思います。

この記事の筆者について

  • システム本部CTO室所属の 徳武 です。
  • サービスの技術基盤の開発運用、宿泊サービスの開発支援を行なっています。