tjinjin's blog

さらなる高みに1nmずつ近づくブログ

cronに変わるジョブ管理ツールのRundeckのAPIを試す

About

サーバ台数が少ない文にはcronやcronの設定をrubyで行うwheneverでまかなえるのですが、台数が増えてくるとcronでの管理は大変です。何かいいツールはないかなというときにRundeckの存在を知ったので、いろいろ試してみます。

Rundeckとは

rundeck.org

ジョブの管理以外にもドリコムでの使い方の用にデプロイ集約サーバとしての使い方もいいかもしれません。個人的にはサーバのセキュリティアップデートの管理をやらせたいと思っているところ(いい案浮かばず頓挫中です)

サーバが増えた時にインフラ担当者がやってきたこと - Qiita

Rundeckを使ってみる(基礎編)

初期インストール

公式ページにはいろいろな形式のファイルがありますが、どの環境でも使えるjar形式のファイルをDLすることにします。

$ java -version
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

$ mkdir rundeck-test
$ cd rundeck-test
$ wget http://dl.bintray.com/rundeck/rundeck-maven/rundeck-launcher-2.5.3.jar
$ java -jar rundeck-launcher-2.5.3.jar

これでrundeckサーバが起動します!(簡単)

起動するとファイルが展開され下記のような構成になります。

rundeck-test
├── etc
├── libext
├── projects
├── server
├── tools
└── var

すでにサーバが起動しているので、ブラウザからログインしてみます。http://localhost:4440で起動しているので、アクセスします。

f:id:cross_black777:20150815002128p:plain

デフォルトのユーザはadmin/adminなので、ログインしようとしてみるとエラーに。設定ファイルがダメなようです。

$ cat server/config/rundeck-config.properties
#loglevel.default is the default log level for jobs: ERROR,WARN,INFO,VERBOSE,DEBUG
loglevel.default=INFO
rdeck.base=/Users/jin/work/rundeck-test

#rss.enabled if set to true enables RSS feeds that are public (non-authenticated)
rss.enabled=false
grails.serverURL=http://localhost:4440
dataSource.dbCreate = update
dataSource.url = jdbc:h2:file:~/work/rundeck-test/server/data/grailsdb;MVCC=true;TRACE_LEVEL_FILE=4

grails.serverURLをlocalhost:4440に変更しています。デフォルトではPCのホスト名になっていてログインがうまくできないことがあるので、localhostに変更すると良さそうです。

Rundeckを使ってみる(応用編)

APIを使う

rundeckには各種APIが用意されています。

API Reference | Version 13

Tokenを発行する

APIを利用するにはTokenを発行して利用するか、パスワードをリクエストで送る方法があります。セキュリティ上Tokenを利用するほうがよいでしょう。

f:id:cross_black777:20150905175857p:plain

f:id:cross_black777:20150905175854p:plain

Tokenを発行できたので、次にACLの設定をします。

アクセスコントロールを設定する

デフォルトの状態でAPIを叩くとREJECTされることが多いです。

$ curl -X POST -H "Content-type: application/json" -H "X-Rundeck-Auth-Token: XXX" -d "{ "name": "myproject", "config": { "propname":"propvalue" } }" http://localhost:4440/api/11/projects | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   192    0   141  100    51   1918    693 --:--:-- --:--:-- --:--:--  1931
{
  "error": true,
  "apiversion": 13,
  "errorCode": "api.error.item.unauthorized",
  "message": "Not authorized for action \"create\" for Rundeck Project"
}

rundeckはaclpolicyでアクセスコントロールをしていて、正直わかっていないです。ここは難しいので、とりあえず検証するには下記のことをします。

cp etc/admin.aclpolicy etc/apitoken.aclpolicy
vi etc/apitoken.aclpolicy
cat etc/apitoken.aclpolicy
description: Admin, all access.
context:
  project: '.*' # all projects
for:
  resource:
    - allow: '*' # allow read/create all kinds
  adhoc:
    - allow: '*' # allow read/running/killing adhoc jobs
  job:
    - allow: '*' # allow read/write/delete/run/kill of all jobs
  node:
    - allow: '*' # allow read/run for all nodes
by:
  group: api_token_group

---

description: Admin, all access.
context:
  application: 'rundeck'
for:
  resource:
    - allow: '*' # allow create of projects
  project:
    - allow: '*' # allow view/admin of all projects
  storage:
    - allow: '*' # allow read/create/update/delete for all /keys/* storage content
by:
  group: api_token_group

apiを実行するときのユーザはapi_token_groupというグループで実行されるようなので、このグループをadmin相当の権限にします。

ちなみに権限があるかどうかは付属するツールで確認できます。

$ ./tools/bin/rd-acl list -g api_token_group
+ read: system
+ create: project
+ admin: job
+ admin: user

上記のようになれば、APIをほとんど利用することができそうです。

APIを使ってみよう

プロジェクトを生成する

myprojectというプロジェクトを作ってみます。

$ curl -X POST -H "Content-type: application/json" -H "X-Rundeck-Auth-Token: XXX" -d "{ "name": "myproject", "config": { "propname":"propvalue" } }" http://localhost:4440/api/11/projects

ジョブを生成してみる。

ジョブを1から作成するAPIはない(?)ので、適当なジョブを作成したのち、それをエクスポートします。

$ curl -X GET -H "Content-type: application/json" -H "X-Rundeck-Auth-Token: XXX" http://localhost:4440/api/1/jobs/export\?project\=myproject
<joblist>
  <job>
    <sequence keepgoing='false' strategy='node-first'>
      <command>
        <exec>echo 'aaa'</exec>
      </command>
    </sequence>
    <schedule>
      <time seconds='0' minute='00' hour='00' />
      <dayofmonth />
      <month month='*' day='*' />
      <year year='*' />
    </schedule>
    <loglevel>INFO</loglevel>
    <name>test</name>
    <context>
      <project>myproject</project>
    </context>
    <description></description>
    <id>eef838f2-11f5-40fc-be68-e3999d0d9506</id>
    <uuid>eef838f2-11f5-40fc-be68-e3999d0d9506</uuid>
  </job>
</joblist>

ファイルのecho aaaの部分をecho bbbに、nameをtest01に変更してインポートします。

$ curl -H "X-Rundeck-Auth-Token: XXX" -F xmlBatch=@"import.xml" http://localhost:4440/api/9/jobs/import\?uuidOption=remove

exportしたデータにはuuidが付けられており、parameterを渡さないと同じIDでjobを作成しようとしてしまいます。そこでuuidOption=removeを渡すことでuuidはimportしないようにすることができ、新規ジョブが作成できます。removeを付けて何度もコマンドを叩くとジョブがそれだけ作成されるので、注意が必要です。

ジョブを実行させる

先ほどuuidの話がありましたが、uuidを指定することでジョブを即時実行することができます。

$ curl -H "X-Rundeck-Auth-Token: XXX"  http://localhost:4440/api/13/job/321f3cee-3a43-4505-8e3f-dd5fb8620c96/run

api経由でコマンド実行できるので便利ですね。

終わりに

今回APIの検証ということで、基本的な部分をとりあえず動かそうという意図で検証しました。実際に使うとなるともう少し知見が必要な気がしました。

参考

rundeckの基本的な記事はこちらが参考になりそうです。

dev.classmethod.jp