Rundeck Config・ジョブ通知・Mysql の設定編
前回はRundeckをローカルで動かすまでのメモを書いた。
Rundeck 基礎編 インストールからジョブ実行までのメモ - 僕とコードとブルーハワイ
今回は、実際に使用するときに設定する色々なことをメモしていく。
環境
Ubuntu 14.04
Rundeckバージョン:2.6.2
Rundeckの設定
公式ページを見ながら設定していく。
Configuration
Config設定が置いてある場所と構成は以下の通り。
今回は最低限の設定だけする。いじるのはframework.properties、project.properties、profileくらい。
omega:~$ sudo tree /etc/rundeck/ /etc/rundeck/ ├── admin.aclpolicy ├── apitoken.aclpolicy ├── framework.properties ├── jaas-loginmodule.conf ├── log4j.properties ├── profile ├── project.properties ├── realm.properties ├── rundeck-config.properties └── ssl └── ssl.properties
framework.properties
Rundeckのコア部分の設定を定義するファイル。
ホスト名やBaseURL、Login User/Passwdなど。
# ---------------------------------------------------------------- # Rundeck server connection information # ---------------------------------------------------------------- framework.server.name = rundeck-example.com framework.server.hostname = rundeck-example.com framework.server.port = 4440 framework.server.url = http://localhost:4440 # 自鯖内で経由するのでlocalhost # Username/password used by CLI tools. framework.server.username = omega framework.server.password = agemo :
rundeck-config.properties
データベース、logレベル、メール通知の設定などをするファイル。
#loglevel.default is the default log level for jobs: ERROR,WARN,INFO,VERBOSE,DEBUG loglevel.default=INFO rdeck.base=/etc/rundeck #rss.enabled if set to true enables RSS feeds that are public (non-authenticated) rss.enabled=false grails.serverURL=http://rundeck-example.com dataSource.dbCreate=update dataSource.url=jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true;TRACE_LEVEL_FILE=4
上記の設定をしてRundeckを再起動すると、設定ファイルが反映される。
http://rundeck-example.com にアクセスしてログイン画面になったらOK。
ジョブ通知の設定
Rundeckではジョブのステータス(Success, Failed, Start)で通知を飛ばせる仕組みがある。
今回はSlack通知と Email通知の設定方法を書いていく。
Slackに通知を飛ばす
前回のRundeckメモに書いたけどもう一回書く。
準備はrundeck-slack-incoming-webhook-pluginの公式ページからrundeck-slack-incoming-webhook-plugin-0.5.jar(この記事を書いた時点での最新版) をダウンロードしてきて、/var/lib/rundeck/libext/配下に設置して、Rundeckを再起動するだけ。
$ sudo mv rundeck-slack-incoming-webhook-plugin-0.5.jar /var/lib/rundeck/libext/
再起動後にWebUIからジョブの作成ページを見てみると、Send Notification?の欄にSlack Incoming WebHookが追加されている。
SlackのIncoming WebHooksからWebhook URLを取得してフォームに入力してあげるだけでOK。
簡単なジョブを実行して、Slackへ実行結果が送信されていることを確認。
実行結果ページへのリンクも貼られているのも便利。
メールで通知する
Email Settings によると、SSL越しに接続したりと高度な設定をしたい場合はrundeck-config.propertiesではなくrundeck-config.groovyに記述しましょうとのこと。
/etc/rundeck/にrundeck-config.groovyを作成する。
今回はGmailのSMTPを使う(楽だから)。
中身は以下のように書くかんじ。
loglevel.default="INFO" rdeck.base="/var/lib/rundeck" rss.enabled="false" grails { serverURL="http://rundeck-example.com" mail { host="smtp.gmail.com" port = 465 username="example@gmail.com" password="example" props = ["mail.smtp.auth":"true", "mail.smtp.socketFactory.port":"465", "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory", "mail.smtp.socketFactory.fallback":"false"] } } grails.mail.default.from = "example@gmail.com" dataSource.url = "jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true;TRACE_LEVEL_FILE=4" dataSource.dbCreate = "update" rundeck.projectsStorageType = "db"
Goovyファイルを書くのが初めてだったのでたまに文法エラーで時間食った。ドキュメントをよく読もう。
Groovy Language Documentation
デフォルトではrundeck-config.propertiesを読み込むようになっているので、rundeck-config.groovyを読み込ませるように以下の1行を/etc/rundeck/profileへ追記する。
RDECK_JVM='$RDECK_JVM -Drundeck.config.location=/etc/rundeck/rundeck-config.groovy'"
Rundekを再起動後、WebUIからジョブの作成ページのSend Notification?をYesにして、Send EmailのTo、Subjectを入力すればメール通知の設定は完了。
Attach output logを選択すると実行の過程で出力されたlogのtxtファイルがメールに添付されてくる。
Mysqlを使用するための設定
デフォルトでは H2 Database が使用される。
公式ページにMysqlを使用するときの設定方法が書かれていたのでメモ。
MysqlにRundeckで使用するデータベースを作成する
mysql> create database rundeckdb; Query OK, 1 row affected (0.00 sec) mysql> grant ALL on rundeck.* to 'rundeckuser'@'localhost' identified by 'rundeckpassword'; Query OK, 1 row affected (0.00 sec)
rundeck-config.groovyにMysql接続のための設定を追記する
以下のように書く。
: dataSource.driverClassName="com.mysql.jdbc.Driver" dataSource.url="jdbc:mysql://example.com/rundeckdb?autoReconnect=true" dataSource.username="rundeckuser" dataSource.password="rundeckpassword" :
mysql connector について
新しいバージョンのRundeckには デフォルトで/var/lib/rundeck/exp/webapp/WEB-INF/lib配下にmysql-connectorが置いてあるけど、もしMysqlがうまく動作しなかったりmysql-connectorが無い/デフォルトバージョンだと動かない場合は、MySQL :: Download Connector/J から mysql-connector-java-5.x.x-bin.jarをダウンロードして /var/lib/rundeck/server/lib/配下に設置するとよい。
上記の設定をしてRundeckを再起動したら設定完了。
テーブルはこんなかんじ。
mysql> show tables; +----------------------------+ | Tables_in_rundeckdb | +----------------------------+ | 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)
mysqldumpしてプロジェクトとかジョブの情報を取っておくとよい。
でもresources.xmlの情報はこの中に入ってないので別途バックアップを取っておく必要がある。
Rundeck 基礎編 インストールからジョブ実行までのメモ
最近触る機会があったので、その記録として導入方法から少しずつ使用方法をまとめていく。
Rundeckとは
とても雑にいうとcron機能の進化版みたいなもの。(とか言ったら各所から怒られそう)
時間毎にジョブを実行させるのはもちろん、複数サーバへのパラレル実行、WebUI操作、外部サービスへの通知連携など、多機能なサービスです。
インストール
環境:Ubuntu 14.04
Rundeckバージョン:2.6.2
公式サイト( Rundeck.org - Downloads )にOSごとのパッケージ取得方法が書かれているので、これを参考に取得する。
$ apt-get install openjdk-7-jdk $ dpkg -i rundeck-2.6.2-GA.deb
上記でローカルでRundeckを使う環境が整うので、早速Rundeckを起動。
$ service rundeckd start
localhost:8000にアクセスすると以下のページが表示される。この画面が表示されれば正常に起動している。
デフォルトはadmin:admin
ユーザとパスワードの設定は後述する設定ファイルで変更可能。
プロジェクト作成
ログイン後、以下の画面に遷移するのでNew Project+を押す。
New Project+を押すと、プロジェクトのConfig画面に遷移するので、Project Nameを入力する。秘密鍵を登録済みなら、Default Node Executor のSSH、 Default Node File CopierのSCP(画像では切れてるがSSHの下にある) を設定する。
ジョブの作成
プロジェクトを作成したらプロジェクト一覧画面に遷移するので、New Jobを押す。
ジョブの設定画面では最低限以下の項目を入力する。
- Job Name: ジョブの名前。どういうコマンドを実行させるジョブかわかる名前をつける。
- Description: このジョブの説明を書く。
- Workflow: コマンドまたはスクリプト実行を設定する。Commandはワンラインコマンド、ScriptはShellスクリプトを登録できる。このプロジェクトではScriptを使用している。
今回はhelloといいう文字列を出力するhello.pyを実行するジョブを作成する。
ローカルで実行するなら必要はないが、リモートサーバでジョブを実行させる場合は以下項目の設定が必要となる。
- Nodes: 実行するリモート環境を選択する。リモート環境を選択するには、/var/rundeck/projects/${project.name}/etc/resources.xml を編集する必要がある。(Webからは設定できないので、Rundeckサーバに入って直接編集する)
resources.xml の設定
- node nage: ジョブ作成ページの Nodes のNode Filterで入力する名前。
- hostname: リモート先のホスト名
- username: リモート先に入るときのユーザ名
以下の例だと、ジョブ作成時にNode Filterでexampleと入力して設定しておくことで、プロジェクト作成時に設定した秘密鍵を使用してRundeckがSSHしてジョブを実行する。ssh -i id_rsa example-user@example.com というようにしているのと同じ。
<?xml version="1.0" encoding="UTF-8"?> <project> <node name="OMEGA.local" description="Rundeck server node" tags="" hostname="OMEGA.local" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.13.0-76-generic" username="omega"/> <node name="example" description="example node" tags="" hostname="example.com" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.13.0-76-generic" username="example-user"/> </project>
その他、オプションで細かな設定ができる。よく使用するものを挙げる。
- Thread Count: 並列数の選択。
- Send Notification: ジョブ結果の通知設定。通知するタイミングは成功・失敗・スタートの3種類選べる。通知方法はEmail、Webhook(Slackも可能)の方法を選べる。
Schedule to run repeatedly: ジョブの実行周期を設定する。
- Log level: 実行結果のログレベルの設定。Nomalならコマンド結果の標準出力、Debugなら- - - Rundeckが実行しているより詳細なログを出力する。Debugにすると、実行終了までの時間が多少遅くなる。
ジョブの実行
Saveボタンを押してジョブを保存すると、登録したジョブの管理画面になる。
ジョブを実行するには、Run job Now を押す。
実行状況を確認する管理画面に遷移する。Log Outputタブを押してみると、「hello.pyの実行」ジョブのタスクによりhelloという表示がされている。成功。
秘密鍵の登録方法
2通りの登録方法がある。
任意の場所に鍵を置いてresources.xmlでPATH指定して読み込む
所定のディレクトリに設置した秘密鍵を、以下の例のようにresources.xml でPATH定義して読み込める。
鍵のパーミッションの設定を忘れずに。
パーミッション・・・.ssh 700、rundeck-key 600 chown rundeck:rundeck
例)秘密鍵が/etc/rundeck/.ssh/rundeck-keyにある場合
<node name="example" description="example node" tags="" hostname="example.com" osArch="amd64" osFamily="unix" osName="Linux" osVersion="3.13.0-76-generic" ssh-authentication="privateKey" ssh-keypath="/etc/rundeck/.ssh/rundeck-key" username="example-user"/>
こっちの方法でやったほうが色々楽だと思う。
また別に書くけど、AnsibleでRundeck環境を諸々構築するときに鍵を配置できるので、基本WebUIからの登録はしない。
slackへ通知するプラグインの追加
デフォルトでは使用できないが便利なプラグインを公開してくれている方がいるので、それを利用させて頂く。
使用方法も以下のページに書いてるのでここを読めばOK。
github.com
rundeck-slack-incoming-webhook-plugin-0.5.jar をダウンロードしてきて、/var/lib/rundeck/libext/配下に設置するだけ。
$ sudo mv rundeck-slack-incoming-webhook-plugin-0.5.jar /var/lib/rundeck/libext/
S3へファイルを並列アップロードする
S3へ大量かつ大きいファイルをアップロードするときには xargs が使える
例)
/tmp/uploads/ にあるファイルを並列(プロセス10)でアップロードする
$ ls /tmp/uploads/ | xargs -L1 -P10 aws s3 cp /tmp/uploads/ s3://bucketname --recursive
2015年振り返りと2016年の抱負を軽く
Django 1.9で追加されたメジャー機能の紹介
この記事は 2015 tech-yuruyuru アドベントカレンダー - connpass 14日目のものです。
Django 1.9 がリリースされたので、メジャー機能だけでもチェックしようということで、ドキュメントとコードみつつ調べたことを簡単に書いてきます。
ここに書いてあるコードは本家documentから引用してます。(わかりやすいので)
今回追加されたメジャー機能
- Performing actions after a transaction commit
- Password validation
- Permission mixins for class-based views
- Running tests in parallel
Performing actions after a transaction commit
- トランザクションが正常にコミットされた後に実行するアクションのフックが追加されました
from django.db import transaction def do_something(): pass # send a mail, invalidate a cache, fire off a Celery task, etc. transaction.on_commit(do_something)
(引用: Database transactions | Django documentation | Django)
Password validation
パスワードのいろんなバリデーション機能がDjango側でできるようになった
settingsのAUTH_PASSWORD_VALIDATORSにバリデーションの種類をいろいろ追加できる
defalutは []、設定しなければ全てのパスワードは受理される
AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': { 'min_length': 9, } }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ]
(引用: Password management in Django | Django documentation | Django)
- UserAttributeSimilarityValidator
Userの入力したパスワードが、username, first_name, last_name, email と類似しているかどうかを検証してくれるclass
lower()で小文字にしたあとSequenceMatcherで文字列比較、quick_ratio()でシーケンスの同一性を測り、類似度が高い場合にエラーメッセージを返す。
- CommonPasswordValidator
よくあるパスワードのリスト.txtと一致したらエラー出すclass
common-passwords.txt.gzというのが、よくあるパスワードリスト。これを解凍してこのパスワードリストの中に入力されたパスワードがあればエラーメッセージを返す。
- MinimumLengthValidator
パスワードの最小の長さを設定できる
- NumericPasswordValidator
数値のみでパスワードが構成されていないかチェックしてくれる
- 実装みれば何やってるかよくわかります
django.contrib.auth.password_validation | Django documentation | Django
Permission mixins for class-based views
Django-bracesにあるアクセス制御関連と似た機能を追加したよという話
requestを受け取ってViewに処理を渡す前にアクセス権限のチェックとかしたりするのを、今まではdecoratorを作ったりDjango-bracesを入れてやっていたけど、これがDjango側でできるようになった。
- 今回追加されたMixin
- AccessMixin
- LoginRequiredMixin
- PermissionRequiredMixin
- UserPassesTestMixin
- LoginRequiredMixin
非認証ユーザをログインページ または 403ページ へリダイレクト
このMixinはUser.is_active フラグはチェックしないというのは覚えていた方が良いかも。
from django.contrib.auth.mixins import LoginRequiredMixin class MyView(LoginRequiredMixin, View): login_url = '/login/' redirect_field_name = 'redirect_to'
(引用: Using the Django authentication system | Django documentation | Django)
- PermissionRequiredMixin
ビューにアクセスするユーザが指定の権限を持っているかチェックする
権限のないユーザの取り扱いをまとめてカスタマイズできる。便利だと思う。
from django.contrib.auth.mixins import PermissionRequiredMixin class MyView(PermissionRequiredMixin, View): permission_required = 'polls.can_vote' # Or multiple of permissions: permission_required = ('polls.can_open', 'polls.can_edit')
(引用: Using the Django authentication system | Django documentation | Django)
Running tests in parallel
別のプロセスで平行してテストを実行できるよという話
-
- pararel=n でプロセス数の調整もできる
- 注意点
(資料: [django-admin and manage.py | Django documentation | Django)
以上です。
他にもいっぱい追加されてたので、少しずつ調べる。
ちなみに (だいたい)新卒エンジニア向け技術交流会 vol.5 - Dark - Developers at Real Kommunity | Doorkeeper で発表した内容とほぼ一緒なので、スライドも置いておく。
www.slideshare.net
本と対話する
この記事は2015 tech-yuruyuru アドベントカレンダー - connpassの6日目です。
tseで遊んだ何か書こうと思ったけど気分乗らなかったので、19日に書こうと思ってたエモい(?)話を書く。(エモい話でもいいよって言ってたから!)
続きを読むメモ: Pythonのパフォーマンスチューニング cProfile
=================
環境:MacOS X 10.4
Python -V:3.4.2
=================
最近パフォーマンスチューニングをすることが多いのでメモ。
ドキュメント: 27.4. Python プロファイラ — Python 3.4.3 ドキュメント
良い例が思いつかなくてアレだけど、とりあえず呼び出し回数と実行時間の違いがわかるものを書いた。
100万回join_textを呼び出して、渡ってきた数字が偶数ならBlue、奇数ならRedのNo.として返してひたすらtext変数にstrでつなげるやつ。
1 def main(): 2 text = '' 3 num_list = range(1000000) 4 for num in num_list: 5 text += join_text(num) 6 7 def join_text(num): 8 if num % 2 == 0: 9 return "Blue_No.{}".format(str(num)) 10 else: 11 return "Red_No.{}".format(str(num)) 12 13 if __name__ == '__main__': 14 import cProfile 15 cProfile.runctx("main()", globals(), locals())
実行結果
2000004 function calls in 1.396 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.001 0.001 1.396 1.396 <string>:1(<module>) 1 0.414 0.414 1.395 1.395 profile_test.py:1(main) 1000000 0.646 0.000 0.981 0.000 profile_test.py:7(join_text) 1 0.000 0.000 1.396 1.396 {built-in method exec} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 1000000 0.335 0.000 0.335 0.000 {method 'format' of 'str' objects}
なんかもっと複雑なやつにcProfile通してみると冗長な書き方とかいっぱいでてきて面白い。