Amazon RDSとELBでRundeckをクラスタ構成にして履歴をS3とElasticsearchに入れて可視化する

Rundeckをクラスタ構成にする

DevIOでは既に複数回に渡ってRundeckのご紹介をしていましたが、今回は、クラスタ構成にして高可用性を確保したいと思います。

以下は完成イメージです。

Untitled (10)

まずは基本セットアップ

まずはじめにRundeckの単体起動を確認したいと思います。今回は、Amazon Linuxを用いています。また、インスタンス起動時にIAM RoleでPowerUserを指定しました。後でS3コマンドなどを実行するときにキーをベタ書きしないためです。

$ sudo yum update -y
$ sudo rpm -Uvh http://repo.rundeck.org/latest.rpm 
$ sudo yum install rundeck -y
$ sudo service rundeckd start
Starting rundeckd:                                         [  OK  ]
$ sudo chkconfig rundeckd on
$ sudo chkconfig rundeckd --list
rundeckd       	0:off	1:off	2:on	3:on	4:on	5:on	6:off

これで自動起動するようになりました。しかし、このままではサイトが正しく表示されません。

screenshot 2016-07-06 18.05.40

設定ファイルを編集してサイトのホームとなるURLを指定します。

$ cd /etc/rundeck/
$ ls
admin.aclpolicy       jaas-loginmodule.conf  realm.properties
apitoken.aclpolicy    log4j.properties       rundeck-config.properties
cli-log4j.properties  profile                ssl
framework.properties  project.properties

$ sudo vi rundeck-config.properties

#loglevel.default is the default log level for jobs: ERROR,WARN,INFO,VERBOSE,DEBUG
loglevel.default=INFO
rdeck.base=/var/lib/rundeck

#rss.enabled if set to true enables RSS feeds that are public (non-authenticated)
rss.enabled=false
# change hostname here
grails.serverURL=http://localhost:4440
dataSource.dbCreate = update
dataSource.url = jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true;TRACE_LEVEL_FILE=4

grails.serverURL=http://ec2-XXX-XXX-XXX-XXX.ap-northeast-1.compute.amazonaws.com

$ sudo service rundeckd restart
Stopping rundeckd:                                         [  OK  ]
Starting rundeckd:                                         [  OK  ]

これで正しく表示されるようになりました。

screenshot 2016-07-07 14.16.40

ELB配下で実行できるようにする

単体でRundeckの動作確認ができましたら次はELB配下に置いてみましょう。先ほど構築したインスタンスを新規作成したELBの配下に登録します。次に、Rundeckの設定ファイルを編集してホームとなるURLをELBのアドレスに変更します。ELBは、jsessionidによるスティッキーセッションとします。

screenshot 2016-07-07 14.12.14

ヘルスチェックはRundeckの存在するアドレスを指定します。

screenshot 2016-07-06 19.18.48

以上により、ELBのアドレスで表示することができました。実運用では独自ドメインなどを指定することになると思います。

データベースにRDSを指定する

このまま複数EC2インスタンスにするとデータベースをそれぞれ持つことになってしまうので、RDS(MySQL)を指定して共通の設定を見るように変更します。まずはじめにVPC内のプライベートサブネット側にRDSを構築します。そして、Rundeckが入っているインスタンスからRDSにアクセスをしてみます。アクセス確認できたら空のデータベースを作成します。

$ sudo yum install mysql -y

$ mysql -u mydbadmin -p -h mydb.cjazjhqtzXXX.ap-northeast-1.rds.amazonaws.com

mysql> create database rundeck;
Query OK, 1 row affected (0.00 sec)

mysql> grant ALL on rundeck.* to 'rundeckuser'@'172.16.0.0/16' identified by 'rundeckXXXXXXXX';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| rundeck            |
+--------------------+
2 rows in set (0.00 sec)

次に、RundeckからRDSに接続するための設定を記述します。

$ cd /etc/rundeck/

$ sudo vi rundeck-config.properties

dataSource.dbCreate = update

dataSource.url = jdbc:mysql://mydb.cjazjhqtzXXX.ap-northeast-1.rds.amazonaws.com/rundeck?autoReconnect=true
dataSource.username=rundeckuser
dataSource.password=rundeckXXXXXXXX

$ sudo service rundeckd restart
Stopping rundeckd:                                         [  OK  ]
Starting rundeckd:                                         [  OK  ]

変更したRDSに対して実際にアクセスされているのか確認してみたいと思います。

$ mysql -u rundeckuser -p -h mydb.cjazjhqtzXXX.ap-northeast-1.rds.amazonaws.com

mysql> use rundeck;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------------------+
| Tables_in_rundeck          |
+----------------------------+
| auth_token                 |
| base_report                |
| execution                  |
| log_file_storage_request   |
| node_filter                |
| notification               |
| orchestrator               |
| plugin_meta                |
| project                    |
| rdoption                   |
| rdoption_values            |
| rduser                     |
| report_filter              |
| scheduled_execution        |
| scheduled_execution_filter |
| storage                    |
| workflow                   |
| workflow_step              |
| workflow_workflow_step     |
+----------------------------+
19 rows in set (0.00 sec)

これで、Rundeckに関する設定などは共通のデータベースを参照するようになりました。

実行ログをS3に保存する

Rundeckの設定をRDSに書き込むことができましたので、次はログ関連をS3に格納したいと思います。Rundeckのプラグインを用います。

Rundeck S3 Log Storage Plugin

まずは、下準備をします。JDK8とGitとGradleの環境を整えます。sdkmanというSDKの簡単導入ツールを使っています。

$ curl -s "https://get.sdkman.io" | bash

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

$ sdk version
==== BROADCAST =================================================================
* 06/07/16: Final announcement test.
* 06/07/16: Test again.
* 06/07/16: Testing
================================================================================
SDKMAN 5.0.0+51

$ sdk install gradle

Downloading: gradle 2.14

In progress...

######################################################################## 100.0%

Installing: gradle 2.14
Done installing!

Do you want gradle 2.14 to be set as default? (Y/n): y

Setting gradle 2.14 as default.

$ sudo yum install -y git
$ sudo yum install -y java-1.8.0-openjdk-devel

$ sudo alternatives --config java

2 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
*+ 1           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
   2           /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2

下準備ができましたので、ブラグインをインストールします。

$ git clone https://github.com/rundeck-plugins/rundeck-s3-log-plugin.git

$ cd rundeck-s3-log-plugin/

$ gradle clean build

$ cd build/libs/

$ ls
rundeck-s3-log-plugin-1.0.3.jar

$ sudo find / -name libext
/var/lib/rundeck/libext

$ sudo cp rundeck-s3-log-plugin-1.0.3.jar /var/lib/rundeck/libext

$ cd /etc/rundeck/
$ sudo vi rundeck-config.properties
rundeck.execution.logs.fileStoragePlugin=org.rundeck.amazon-s3

ログの出力先としてS3バケットを指定しました。このバケット名は世界中でユニークである必要がありますので気をつけてください。バケットを作成しておきましょう。

$ aws s3 mb s3://satoshi1977-rundeck-logs
make_bucket: s3://satoshi1977-rundeck-logs/

$ sudo vi framework.properties

#name of the bucket
framework.plugin.ExecutionFileStorage.org.rundeck.amazon-s3.bucket=satoshi1977-rundeck-logs

#path to store the logs
framework.plugin.ExecutionFileStorage.org.rundeck.amazon-s3.path=logs/${job.project}/${job.execid}.log

全ての設定を書き終わったらサービスを再起動してブラウザからジョブを実行してみましょう。以下のようにログが吐き出されてることが確認できれば成功です。

$ aws s3 ls satoshi1977-rundeck-logs/logs/MyProject1/
2016-07-07 04:06:41        860 3.log.execution.xml
2016-07-07 04:06:41        972 3.log.rdlog
2016-07-07 04:06:41        723 3.log.state.json

EC2との連携を管理する

ノードとして動かしたいEC2インスタンスと連携するプラグインも入れてみます。

Rundeck EC2 Nodes Plugin

$ cd
$ git clone https://github.com/rundeck-plugins/rundeck-ec2-nodes-plugin.git
$ cd rundeck-ec2-nodes-plugin/

$ cd build/libs/
$ ls
rundeck-ec2-nodes-plugin-1.5.3-SNAPSHOT.jar

$ sudo cp rundeck-ec2-nodes-plugin-1.5.3-SNAPSHOT.jar /var/lib/rundeck/libext

基本的にはこれだけです。Rundeckのサービスを再起動してから、新しいプロジェクトを追加してみてください。オプションが新たに表示されます。

screenshot 2016-07-07 15.22.21

ログをストリーミングしたい

S3にログを吐き出すのは永続化という意味ではとても良いですが、リアルタイムに流して検知したいこともあるかと思います。そこで、logstashプラグインを使ってみます。

Rundeck S3 Log Storage Plugin

$ git clone https://github.com/rundeck-plugins/rundeck-logstash-plugin.git

$ cd rundeck-logstash-plugin/

$ sudo cp LogstashPlugin.groovy /var/lib/rundeck/libext/

インストールしたら設定を追記します。Rundeckと同じサーバーのLogstashを指定しています。

$ cd /etc/rundeck/
$ sudo vi rundeck-config.properties

rundeck.execution.logs.streamingWriterPlugins=LogstashPlugin

$ sudo vi framework.properties

framework.plugin.StreamingLogWriter.LogstashPlugin.port=9700
framework.plugin.StreamingLogWriter.LogstashPlugin.host=localhost

Logstashをインストールします。

$ wget https://download.elastic.co/logstash/logstash/packages/centos/logstash-2.3.3-1.noarch.rpm
$ sudo rpm -ivh logstash-2.3.3-1.noarch.rpm

$ sudo service logstash start
$ sudo chkconfig logstash on
$ sudo chkconfig logstash --list
logstash       	0:off	1:off	2:on	3:on	4:on	5:on	6:off

$ /opt/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }'
hello world
Settings: Default pipeline workers: 1
Pipeline main started
2016-07-07T06:55:14.764Z ip-172-16-0-184 hello world

Elasticsearchと連携します。

Logstashのプラグインをインストールします。Amazon Elasticsearch Serviceとの連携までやってくれます。素晴らしい。

$ sudo /opt/logstash/bin/logstash-plugin install logstash-output-amazon_es
Validating logstash-output-amazon_es
Installing logstash-output-amazon_es
Installation successful

事前にElasticsearchにアクセスできることを確認しておいてください。

$ curl -XGET search-myelastic-heic6rbqefquujhb3yuosXXXXXXX.ap-northeast-1.es.amazonaws.com
{
  "status" : 200,
  "name" : "Jamal Afari",
  "cluster_name" : "XXXXXXXXXXXX:myelastic",
  "version" : {
    "number" : "1.5.2",
    "build_hash" : "62ff98XXXXXXXa0c45860bebb259e21XXXXXXXXXXXX",
    "build_timestamp" : "2015-04-27T09:21:06Z",
    "build_snapshot" : false,
    "lucene_version" : "4.10.4"
  },
  "tagline" : "You Know, for Search"
}

LogstashとElasticsearchが連携するために設定ファイルを書きます。

$ cd /etc/logstash/conf.d
$ vi rundeck-logstash.conf


input {
  tcp {
    port => 9700
    tags => ["rundeck"]
    type => "rundeck"
  }
}

output {
  amazon_es {
    hosts => ["search-myelastic-heic6rbqefquujhb3yuosXXXXXXX.ap-northeast-1.es.amazonaws.com"]
    region => "ap-northeast-1"
    index => "rundeck"
  }
}

動作確認

それでは準備が整いましたので、Rundeckで実行したジョブのログが、Logstash経由でElasticsearchに格納されているか確認してみましょう。まずは、Amazon Elasticsearch Serviceの管理画面で確認してみます。

screenshot 2016-07-07 18.55.22

たしかにデータが入っていますね!Kibanaでも見てみましょう。

screenshot 2016-07-07 19.07.27

見た目をゴニョゴニョすると、、、、、

screenshot 2016-07-07 19.04.34

ステキです。

まとめ

ジョブスケジューラのRundeckについて、ELBとRDSを利用することで高可用性を確保することができました。次に、ログをS3やElasticsearchに格納することで、ジョブの結果を画面で直感的に把握することができました。

参考資料

Rundeck

Rundeck S3 Log Storage Plugin

Rundeck Logstash Plugin

Rundeck EC2 Nodes Plugin

Logstash Plugin for Amazon Elasticsearch Service