AWS構成図を無料で描く draw.io
draw.ioというドローイングのWebサービスをご存知でしょうか?
結構使ってる人も増えているようです。私は今回初めて使ってみました。 個人的な所感を書いた後に、簡単な使い方を書いて終わりにしたいと思います。
所感
いいところ
無料で登録もないから簡単にスタートできる。
操作が簡単。多分10分くらいいじってれば操作できちゃうと思う。
PDFや各種画像にエクスポートできる(普通有料だったりする)。
Visioであったレイヤーの概念作れる。
素材が豊富。特に今回使いたかったAWS関連素材。PollyやAlexaやPinpointのアイコンもあるぞあるぞ。
新し目のサービスのOrganizationとかもありますね。

Webアイコンなんかあるのはいいですね。

電気図もある!そういえばおれ電気工学科だった。。懐かしい・・

もうちょい
ステンシルのレイヤーを"前に"や"後ろに"はあるのですが、"最前面"や"最背面"がないのがちょい辛い。
補正が少し強いように感じた。矢印の調整時に他のステンシルに引っ張られる感覚があった。込み入った図を書く時少し心配。
プレゼン用に全画面表示があったらよかった。
ん〜、あとはなんだろ、また思いついたら付け足します。
使い方
はじめに
操作は全てブラウザで行います(アプリもあるみたい)。
まずはじめにブラウザでDraw.ioを開くと以下のページになります。
データの保存先はDraw.ioには持ってないのでWebストレージやローカルを選んでください。すでに使ってるWebストレージがあれば連携できて逆にうれしい仕様です。

右下の地球っぽいアイコンをクリックすると言語を日本語にも変更できます。日本語を選んでブラウザをリロードします。

Webストレージは後でも選ぶことができるので後でも構わない場合は"あとで"を選びます。

次の画面になります。

一般のステンシルで書いてみる
ブラウザの画面から左側に各種ステンシルがあります。"一般"の"シリンダ"を画面中央あたりにドラックアンドドロップしてみます。

それ以外のものも同じ要領です。簡単ですね。
テキストも"Text"をドラックアンドドロップで持ってこれます。または何もないところをダブルクリックすることでもテキストステンシルを出現させることができます。
矢印も同じように持ってこれます。矢印を曲げたい場合は画面のように対象の矢印をクリックしたあと、メニューから"カーブ"のタイプを選びます。


自動補正もしてくれます。


AWSの構成図
AWSのステンシル追加
左側のステンシルメニューの一番下の"その他の図形"をクリック。

シェイプが複数出てくるので、"AWS"にチェックを入れて保存する。そうするとAWSのステンシルが追加されます。

あとはこんな風に図が書けます
基本は同じ要領です。好きなステンシルを使って貼っていってください。
例えばこんな感じの図を描くことができます。
ブラウザ上での表示↓

PNG画像↓

AWSステンシル豊富

シートを増やせます
画面下部の"プラスマーク"をクリックすることでシートを増やせます。

ダブルクリックでテキストステンシル出る

ステンシル探すのは検索が便利
検索結構使えます。
pinpoinのアイコンなんかすげー

ステンシルの整列やグループ化
ステンシルをshiftを押しながらクリックで複数選択。 その状態でメニューの"アレンジ"、"整列"できれいに整列させられます。 同じアレンジのメニューにある"グループ化"をすることでステンシルを1つのグループにすることもできます。

テーブル作成
図にテーブルを作れます。画面のルートテーブルとして描いてるものがそれです。
“その他"ステンシルにあります。
対象テーブルをダブルクリックし、行や列の増減などを行えます。操作は画面の右下箇所にあります。

レイヤー構成作れます
メニューの"表示"から"レイヤー"を選択

レイヤー構成を作れます。例えば通信フローの矢印を書いてそれを”通信フロー"レイヤーと定義しておけば、通信フローが見たいときにだけ表示させたり、不要なときは対象のレイヤーを無効にすることで矢印を消すことができます。
見る人によって見やすい図に変更可能な図が一元的に作成できます。Visioなどではよく駆使してました。
“通信フロー"レイヤを表示してる状態です。

”通信フロー”レイヤを非表示にした状態です。

セキュリティグループとかもレイヤ化すると見やすいかもですね

読み取り専用でパブリッシュできます
ファイル->Publish->リンク、これで図をパブリッシュできます。

今回の作成した構成図をパブリッシュします。 リンククリック後、"新しいウィンドウで開く"としてもらえれば編集も可能です。是非お試しを。
スクラッチパッド
ステンシルをコピーしたものを幾つか置いておける場所(パッド)。
例えば下図のルートテーブルの表をドラッグアンドドロップで、画面左側の"スクラッチパッド"に入れる(コピー)。
そしていつでもそこから戻せる(コピー)。
複数ステンシルを"スクラッチパッド"に格納(コピー)できて、同じようにいつでも戻せる(コピー)。(あー、言葉で伝えづらい系だなこれは)
何度もコピペするような時に楽かも。

他にも有用なものがあれば追記できたらと思います
see you..
入社3ヶ月経ちました(I have passed since joining 3 months)
とりあえずクビにならず生きています。
新人らしく「なんでもやる」「失敗したらあやまる」「そしてまたトライ」
※トライしないんだったら転職しないし
こんな感じで周りにご迷惑を撒き散らした3ヶ月をすごし、おかげでチームをはみ出すくらい結構たくさんトライできました(もう半年くらい経ったのかと思ってました^^;)。
そんなこんなでやっていけてるのは本当に周りの仲間がエエ人だから。ただエエ人ってことではなくて、社内には文化がしっかりあって皆同じ志を持ってます。韓国の同僚も同じことを言ってたのがブッ刺さりました。
今は、すぐやらないといけないこと真っ只中なので、引き続きがんばります!
「Still Day One」(毎日が初日)
ジェフベゾスの言葉ですが好きな言葉の1つになりました。
疲れた時は柚子ちゃんに癒してもらってます↓
ではまた。≡≡≡ヘ(*--)ノ

遅刻はなんでいけないんだっけ?と言う稚拙な話

「遅刻はなぜいけないか?」(稚拙な話でごめんなさい。。)
※もちろん体調不良や電車遅延とかは除きます
「小さいころ先生や親に怒られたから」って言う人は
とりあえず遅刻してないならそれでもいいかと;
ただ大人になると良くも悪くもストレス耐性が付いてきます。
ちょっと怒られても響かなくなります(これはこれでチャレンジングに成長する為に必要な能力でもありますが)。
ちなみにうちのチームの勤怠はとてもいいです。
今まで居たメンバーも含めて朝の出勤もそうですが、会議へ遅れや欠席もほぼ皆無と言っていいかもしれません。
以前は定常的に遅刻するメンバーがいたこともありました。
遅刻すると・・
会議や朝会に遅れる場合
複数人の稼働を同時に使う議論や決議をする時間が減ります。チームやプロジェクトの意思決定の質を下げることになります。帰りが遅く朝起きれない場合
計画したタスクがうまくいってないか、緊急な作業を抱えてしまっています。それを定点チェックする仕組か本人がしっかり上長にアラートを上げる文化が必要です。
(うちのチームは各自やばい時はアラート上げる文化有り、逆に夜間対応したなら「今日は早く帰りな」とか言います)そもそも定常的に遅刻している場合
約束を守れない人に大きい仕事は任せられません。その人は会社との最初の約束を果たしていません。
入社した時に出勤時間についての条件に合意したはずですよね?待ってる人はモチベーション下がります
楽しく待つ人はいないでしょう。それが朝一の朝会からだと一日が・・習慣化もできない
自身の学習についても支障をきたします。学習は習慣化できてこそ効果が大きくなります。自身が決めた時間に遅れても誰も怒ってくれません。自分との闘いです。甘え1つで習慣的な学習ができず成長が鈍化します。
※人間、楽な方がいいので周りが遅刻してても何も言われなければ、朱に交わって赤くなりますよね。
・・・以前定常的に遅刻していたメンバーにこのことをしっかり説明したところ、遅刻は改善されていきました。
チームも数年に渡り成果を出し続けております。
遅刻自体は一人が怒られて「ごめんなさい」で済むことに思われがちです。
でも実際は上記のようにチーム全体のパフォーマンスに影響を与えています。
チームが成果を出すかどうかに関わってます。
先日、後輩から「いいチームってなんですか?」と聞かれたことがありました。
いいチームは"成果を出すチーム"です。
ビジネスをやっている以上それ以外にはありません。
その後輩は勤怠はとてもいいです。
もし成果を出すチームにしたいなら、自分がリーダーでなくてもマネージャーでなくても普段考えないディティールについて考えてみるのもいいかもしれませんね。
もちろん遅刻しないだけで成果出るわけではないので^^;
そして私はこれでもう遅刻できなくなった\(^_^)/
朝会で進捗共有はやらない

朝会で進捗共有する。どこの現場も多いと思います。
必要ですかね??
うちのチームでは朝会で進捗共有はやってません。
進捗のステータスはだいたい3つだと思ってます。
「オンスケ」
「早く終わった」
「ちょっと遅れそう」
そもそも3ヶ月くらい先の仕事がある程度チームでスケジューリング出来てる前提ですが
出来てなかったらマネージャがいないかマネージャが無能のどちらかです。
または、明日には明日の風が吹く現場だったらそもそも朝会とかマクロな話してる場合じゃないです。。
「オンスケ」これは明らかにいらないですね。朝会で全員の稼働を使っての共有?。。いらんいらん。だって問題ないんだもん。
「早く終わった」と「遅れてる」という状況は朝会ですべきじゃないです。それじゃ遅い。特に後者は。それがわかった時の新鮮な状態で教えて。なんで朝会待つの??
だいたい「ちょっと遅れそう」はずるずる行くんだし・・。進捗は"Redmine"というツール(ツールはなんでもいい)で可視化してるので、進捗を把握しなければいけない人が任意のタイミングで見たほうがいい(なにも全員でやんなくてもいいし、プロジェクトの規模次第なとこもあるけど)。
じゃあ何をやろうか??
うちのチームは若いチームでまだまだキャッチアップが必要なので
「出来るようになったこと」
を共有することにしました。
「出来るようになったこと」
は教えた人と教えられた人とで完結してしまいがちです。
出来るようになったことのレベル感で言うと、会社でよくあるようなスキルシートに書かれる項目(JavaとかMySQLとかとか?)とかよりもずっと小さいレベルでいいです(粒度を小さくしないと毎朝やるのは辛くなりますね。ちなみにうちは週3で朝会してます)。
例えばNagiosへの監視設定が出来るようになったとか、サーバー構築出来るようなったとか、もっと小さくてもいいと思います。
且つそれは技術者にとって喜びでもあります。
それを朝会の短い時間で共有することで
新しい仕事をメンバーに振る材料にもなるし
他のメンバーも作業のヘルプを誰に頼んでいいかの判断する材料になります
あと、普通は数ヶ月とか経って感じる
「あいつ成長してるな」「自分もがんばらなきゃ」
って刺激や喜び、このサイクルを短くできてると思います
これ成長を加速させる1つのサイクルなんですよね。喜びと刺激って。
現場でインプットアウトプットのサイクルを加速させられてるなら、その共有サイクルもせっかくなので加速させてみてはどうでしょう。
理想ですが、毎日毎日成長を感じられる環境にできたらすんばらしいですね。
Centos6でAnsibleを1から2にしたら 「ERROR! Unexpected Exception: 'AnsibleLoader' object has no attribute 'dispose'」
Ansible2をCentOS6にインスト 今までは1.9系でした
yum install python-jinja2-26 --enablerepo=epel yum --enablerepo=epel-testing install ansible
とりあえずsudo:yesは以下にしとこう become: yes become_user: root
そしてAnsibleを1.9から2.0にしたら以下エラーが出た
[root@ansiblesvr01 ansible]# ansible-playbook -vvv test.yml -i ./hosts --check
/usr/lib64/python2.6/site-packages/pycrypto-2.6.1-py2.6-linux-x86_64.egg/Crypto/Util/number.py:57: PowmInsecureWarning: Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.
_warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning)
Using /etc/ansible.cfg as config file
ERROR! Unexpected Exception: 'AnsibleLoader' object has no attribute 'dispose'
the full traceback was:
Traceback (most recent call last):
File "/usr/bin/ansible-playbook", line 86, in <module>
sys.exit(cli.run())
File "/usr/lib/python2.6/site-packages/ansible/cli/playbook.py", line 128, in run
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory)
File "/usr/lib/python2.6/site-packages/ansible/inventory/__init__.py", line 85, in __init__
self.parse_inventory(host_list)
File "/usr/lib/python2.6/site-packages/ansible/inventory/__init__.py", line 141, in parse_inventory
group.vars = combine_vars(group.vars, self.get_group_variables(group.name))
File "/usr/lib/python2.6/site-packages/ansible/inventory/__init__.py", line 506, in get_group_variables
self._vars_per_group[groupname] = self._get_group_variables(groupname, vault_password=vault_password)
File "/usr/lib/python2.6/site-packages/ansible/inventory/__init__.py", line 524, in _get_group_variables
vars = combine_vars(vars, self.get_group_vars(group))
File "/usr/lib/python2.6/site-packages/ansible/inventory/__init__.py", line 704, in get_group_vars
return self._get_hostgroup_vars(host=None, group=group, new_pb_basedir=new_pb_basedir)
File "/usr/lib/python2.6/site-packages/ansible/inventory/__init__.py", line 743, in _get_hostgroup_vars
results = combine_vars(results, self._variable_manager.add_group_vars_file(base_path, self._loader))
File "/usr/lib/python2.6/site-packages/ansible/vars/__init__.py", line 560, in add_group_vars_file
(name, data) = self._load_inventory_file(path, loader)
File "/usr/lib/python2.6/site-packages/ansible/vars/__init__.py", line 528, in _load_inventory_file
data = loader.load_from_file(new_path)
File "/usr/lib/python2.6/site-packages/ansible/parsing/dataloader.py", line 114, in load_from_file
parsed_data = self.load(data=file_data, file_name=file_name, show_content=show_content)
File "/usr/lib/python2.6/site-packages/ansible/parsing/dataloader.py", line 93, in load
new_data = self._safe_load(new_data, file_name=file_name)
File "/usr/lib/python2.6/site-packages/ansible/parsing/dataloader.py", line 150, in _safe_load
loader.dispose()
AttributeError: 'AnsibleLoader' object has no attribute 'dispose'
どうやらlibyamlが先に入ってないとダメなようで、今回入ってなかったので一度Ansible2をアンインストールして、 そのあとにlibyamlを入れてからAnsible2を入れ直した。 libyamlだけ追加で入れてもダメでした。おそらくライブラリを見てる先が変わってしまってるのかな
ちなみにpython-yamlはAnsibleと依存関係があり同時にインストされます
[root@ansiblesvr001 ansible]# rpm -qa | grep yaml python-yaml-3.09-3.el6.rf.x86_64 libyaml-0.1.3-4.el6_6.x86_64
Rundeck はじめました
うちのワンコ初めてカットしました。スッキリです。

cronやJenkinsでがんばってたジョブスケジューリング機能を一元管理する為"Rundeck"を構築しました。
cronはアレなんでやめたいし、Jenkinsは気が付けばあだ名が付くくらいたくさん居るし、執事やとい過ぎだわ
まぁとは言えプラットフォームごとに出来てしまうのは仕方ないとこもあるので、事前にオンプレもAWSも繋がる便利なVPCを作っておきました。
そこにJenkinsでもいいのですが、「おれの仕事CIだし」って聞こえて来そうなのでやめときます。
最近は、AzkabanやらAirflowやらOozieやらジョブスケジューラー界隈が活況ですが、GUIがある程度充実してて必要最低限のスケジュール機能でいいのと冗長化ができるもので、誰でも使えそうって基準でRundeckに決めました。
今の最新は2.6.2がGAとして出ています。

Javaで動くスケジューラーなので手元にあるMacやWindowsでも試せます(やったことないけど。。)
Salesforceやドリコムやインティメート・マージャーで使ってるようです。
"Rundeckを入れよう"とサブミッションっぽくカジュアルに切ったチケットを見ると1/22に開始している。はや一ヶ月強かかってしまった。
かなり放置して時期もあったが開発側も協力してくれて先週辺りから一気に進んだ。
ググりヒット感で言うと、結構でてきますが、使ってどうこうって話はあまり多くないかなという印象です。
他で書かれてない情報を書ければと思います。
特徴としては
OSSでJava/Groovy製でオーケストレーション機能あり
エージェントレス SSH接続できればジョブを実行できます。Ansibleと同じノリ
ジョブネットを作成可能 ジョブAが正常に終わらないとジョブBを実行したくないと言った依存関係を設定できます。
cronと同様の記述が可能 移行が簡単的な感じです。そこまでメリットかはわからないですが
その他 ジョブの再実行、タイムアウト値、ステップ(あとで説明)ごとのエラーハンドラ設定、ジョブ実行や失敗や成功のメールやWebhookでの通知、ジョブの並列度(やりかたはいくつか)設定ができる
※この辺は他の記事にいっぱいあります
Rundeck用語としては
プロジェクト(project)
ジョブをまとめる単位がプロジェクトです。 プロダクトごとやその本番/ステージング/開発環境ごとに作るのが一般的かなとジョブ(job)
Rundeckがスケジューリング可能な実行単位です。これは特定のプロジェクトに紐付きます。別プロジェクトのジョブを実行することはできません。 ジョブは1つ以上のステップを持ちます。ジョブの実行結果はあとから閲覧できます。ノード(node)
ノードはジョブを実行する対象ホストです。 これもプロジェクトに紐付くため、別プロジェクトのノードを利用することはできません。ステップ(step)
ステップはジョブを構成する最小単位です。リモート先ノードに配置したシェルやコマンド、ローカルにあるシェル、ローカルにあるシェルを転送してリモート先で実行、シェルが置いてあるURLを指定するとそこからダウンロードしてリモート先で実行とか選べます。
また作成したジョブをステップとして登録できます。ジョブの中にジョブをネストする感じです。カオスの臭いがしてきますね;
ただ、これでジョブネットを実現することになると思います。

構成

冗長構成ですが、アクトスタンバイとしました。
rundeck01(アクティブ機) Nginx(Started),Rundeck(Started/Active) rundeck02(スタンバイ機) Nginx(Stoped),Rundeck(Started/Passive)
- スタンバイ側のRundeckはPassiveモード(スケジュールジョブ実行不可)にしておく
- アクティブ機が障害が起ったのを検知した際にActiveモード(スケジュールジョブ実行可能)にする
- さらにTakeover(実行ジョブの引継ぎ処理)をすることでrundeck02がジョブスケジュールも全て引継ぎアクティブな状態と遷移する
ちなみにAPI使ったActiveモードへ移行はこちら(xxxxxxxxxxはトークン)(アカウントごとにトークン発行可)(disableでpassiveモード)
curl -H 'X-RunDeck-Auth-Token:xxxxxxxxxx' -H "Content-Type: application/xml" -d '' -X POST http://rundeck02:4440/api/14/system/executions/enable
APIを使ったTakeoverはこちら
curl -H 'X-RunDeck-Auth-Token:xxxxxxxxxx' -H "Content-Type: application/xml" -d '<takeoverSchedule><server all="true"/><project all="true"/></takeoverSchedule>' -X PUT http://rundeck02:4440/api/14/scheduler/takeover
プラグインはログをS3に置く"rundeck-s3-log-plugin"と
EC2インスタンスを探してくれる"rundeck-ec2-nodes-plugin"を入れてます
おそらく定番です。
その為、ジョブ実行ログはS3にあり、プロジェクト情報はRDSにあり、ノード情報はec2プラグインで動的に取ってくるのでほとんど共有できてるのですが、手動でノード登録が必要なDC側のサーバーだけは共有する必要があります。
こちら
/var/rundeck/projects/プロジェクト名/etc/resources.xml
あと/etc/rundeck/ですね。この辺でACL設定とかします。
プロジェクトをプロダクトごとに分けてマルチテナント的に使う時とかは他の自身のプロジェクトしか見えないように権限付けます(うちがそうです)
なのでバックアップも/etc/rundeck/一式取ればOKかと
うちはAnsible側に持たせてます
消えないログ
逆に肥大化してくポイントがいくつかあります。問題点ですね。
この辺でがんばってる方いますので参考になると思います
うちもマネてとりあえず手を打ちましたが絶賛模索中です
https://gist.github.com/unicolet/af648a97163ce6b44645
http://www.phwitservices.com/2015/05/clearing-rundeck-log-files/
/var/lib/rundeck/logs/*のジョブ実行ログは消えません。
S3にあるジョブ実行ログも消えません。
RDSにあるジョブ実行関連の情報も消えません。
GUIからBulkdeleteが出来るのですが1度に最大20行しか選べず・・
この辺のテーブル
log_file_storage_request base_report execution
リンクを参照し30日を過ぎたジョブ実行IDをfindして
ローカルファイルとDBのレコード削除をしています。
対象テーブルは網羅されてる自信なしです><
#!/bin/sh
cd /var/lib/rundeck/logs/rundeck
JOBS=`find . -maxdepth 3 -path "*/job/*" -type d`
for j in $JOBS ; do
echo "Processing job $j"
ids=`find $j -mtime +30 -iname "*.rdlog" | sed -e "s/.*\/\([0-9]*\)\.rdlog/\1/" | sort -n -r`
declare -a JOBIDS=($ids)
for job in ${JOBIDS[@]};do
echo " * Deleting job: $job"
echo " rm -rf $j/logs/$job.*"
rm -rf $j/logs/$job.*
mysql -h YOURDB -uxxx rundeck -pxxx -e "delete from log_file_storage_request where execution_id=$job"
mysql -h YOURDB -uxxx rundeck -pxxx -e "delete from base_report where jc_exec_id=$job"
mysql -h YOURDB -uxxx rundeck -pxxx -e "delete from execution where id=$job"
done
done
あとはシンプルにAPIから消すことはできます。
が、いついつ以前を削除みたいなことはできず指定JOBIDの実行ログ全て消えます。
curl -H "X-RunDeck-Auth-Token: $RD_OPTION_TOKEN" -H "Content-Type: application/xml" -X DELETE http://rundecksvr:4440/api/12/job/$RD_OPTION_JOBID/executions
$RD_OPTION_TOKEN には権限のあるユーザーのトークン
$RD_OPTION_JOBID には対象のジョブID
cat /etc/rundeck/apitoken.aclpolicy
description: API project level access control
context:
project: '.*' # all projects
for:
resource:
- allow: '*'
adhoc:
- allow: '*'
job:
- allow: '*'
node:
- allow: '*'
by:
group: api_token_group
※注意としてはトークン用のACLファイルが別にあるのでそちらにもDELETE権限を付与してあげる必要がありますがとりあえず上記はapi_token_groupに全権限付与してます
※ここ改善されると信じてます。簡単に標準機能であってほしい;;
KeyStorage
これ便利かも
プロジェクトごとに対象の鍵を選択するだけで済むし、RDS側で鍵を持ってくれるので冗長性もあるのでうれしい。

プロジェクト横断
プロジェクト横断したジョブスケジュール設定したいって絶対でますよね。。
プロジェクトを横断したジョブ連動は、今実現するとなると多分・・
- ファイルができたことを検知するシェルを1つ目のステップに登録したジョブを作る
(ループさせてファイルがあったらexitするよな感じで)
- ファイルがあったら別プロジェクトの前段のジョブが終わってるとして、自分のジョブを走らせる
感じかと
めんどくさそうですが汎用性あるジョブにしてしまえば流用可能かと思います。
もっといい方法あれば教えてください><
ジョブが増えてくるとDBサーバーがCPUリークする
CPUリークします。1ヶ月スパンくらいでCPU使用率が右肩上がりで
これはworkflow_workflow_stepというテーブルにインデックスが張られてないことが原因です。workflow_commands_idにインデックス張ります。劇的に改善します。
ALTER TABLE workflow_workflow_step ADD INDEX workflow_commands_id(workflow_commands_id);
外部からキック
外部のサーバーとの連携したい場合はAPI経由でRundeckのジョブキックが可能です。
ジョブID特定
(ローカルからですが・・)
# curl -H 'X-Rundeck-Auth-Token: xxxxxxxxxxxxxxx' "http://rundeck01:4440/api/15/project/test001/jobs"
<jobs count='2'>
<job id='3a15fbcb-53f3-4cc4-b689-d6f96a9bxxxx' href='http://rundeck01:4440/api/15/job/3a15fbcb-53f3-4cc4-b689-d6f96a9bxxxx' permalink='http://rundeck01:4440/project/test001/job/show/3a15fbcb-53f3-4cc4-b689-d6f96a9bxxxx'>
<name>てすと01</name>
<group />
<project>test001</project>
<description>てすと詳細</description>
</job>
</jobs>
ジョブ実行
# curl -X POST -H 'X-Rundeck-Auth-Token: xxxxxxxxxxxxxxx' "http://rundeck01:4440/api/12/job/3a15fbcb-53f3-4cc4-b689-d6f96a9bxxxx/executions"
<executions count='1'>
<execution id='6635' href='http://rundeck01:4440/project/test001/execution/show/6635' permalink='' status='running' project='test001'>
<user>admin</user>
<date-started unixtime='1455688116789'>2016-02-17T05:48:36Z</date-started>
<job id='3a15fbcb-53f3-4cc4-b689-d6f96a9bxxxx' averageDuration='985' href='http://rundeck01:4440/api/15/job/3a15fbcb-53f3-4cc4-b689-d6f96a9bxxxx' permalink='http://rundeck01:4440/project/test001/job/show/3a15fbcb-53f3-4cc4-b689-d6f96a9bxxxx'>
<name>てすと01</name>
<group></group>
<project>test001</project>
<description>てすと詳細</description>
</job>
<description>ls -l</description>
<argstring />
<serverUUID>xxxxxxxx-400a-403a-828c-xxxxxxxx46ff</serverUUID>
</execution>
</executions>
※どちらもRundeckのCLIもあります
所感
私はジョブスケジュール設計とか素人なのですが
公式ページにも書いてあったのですが、データドリブンな設計がいいと
様々なコマンドやスクリプトをジョブ化できます。 しかし全てのユースケースに対応するジョブを作ろうとすると、 スクリプトの呼び出し方が少し違う程度のジョブを大量に作ること になってしまうでしょう。 それらの違いとは、往々にして環境やアプリケーションバージョンに関連します。 そのほかの部分については人が必要な情報を与えてジョブを実行しているにすぎません。 スクリプトやコマンドをデータドリブンにしましょう。 そうすればより一般化でき、他のコンテキストでも再利用できます。 同じプロセスの変数をメンテナンスするより、 ジョブが外部データからのオプションモデルで駆動するようにすることで、 よりよい抽象化とカプセル化を期待できます。
ジョブの成功か失敗がファイルを出力できたかどうかというのはキレイな設計な気がします。
IMのまっつさん!構築中のアドバイスありがとうございましたmm
という訳で隣の席の同僚がジョブを作りたくなっているのがうれしいです。
作業をカプセル化して運用が楽になったら幸せです。
GCP Autoscalerで遊ぶ
日曜は犬と留守番をしていたので、時間をもてあましたので犬とオートスケールで遊ぶことにした

GCPのオートスケール機能Autoscalerの正式版は去年の9月ころ出たようです。
ウォームアップ不要ってところがAWSとの差別化ですね。5分以内に1000台一気に増やせるってすごくて怖い・・w
SSL終端できないとかもありますがが
まだマネコンにメニューもなくAPIのみの提供で、AWSの最初の頃のAutoscaleみたいな感じ、、って思ってたらインスタンスグループなるところにあった!
AWSのAutoscalingGroupのような感じですねきっと。
HTTPロードバランサを使ったAutoscalerで設定するものは以下
- Global IP(HTTPロードバランサで使う場合タイプをグローバルにする)
- Image File(オートスケールする際の作られるサーバーの元イメージ、これをもとにサーバーが増えていく)
- Instance Template(マシンタイプ、Image File、ディスクタイプ、ディスクサイズ、所属ネットワークなどのインスタンスにまつわる情報をまとめたもの)
- Instance Group(Instance Template、ゾーン、オートスケールのオンオフや閾値設定)
※この下はどちらかというとHTTPロードバランサの構成要素
- Health Check(URLパス、ポート、間隔、タイムアウト)
- Target Proxy(URLマップ、プロキシタイプ)
- Global Transfer Rule(外部IP、プロトコル、Target Proxy)
- Backend Service(リッスンプロトコル、タイムアウト値、バックエンドとなるInstance Group、Health Check)
- HTTP Load Balancer(Backend Service、Global Transfer Rule)
項目多いし文字だとわかりづらいので図にしてみる、が、やっぱわかりはずらい。。 ただこういう機能なんでこんなもんかと

ぽちぽちは大変なので、Terraformでやってみる
(テンプレは↓の方に張ったので変数を変えてよしなに試してみてもらえるとうれしい)
グローバルIPを作る場合、画面からだと以下のようにタイプを地域かGlobalかを選ぶところがある(どちらもグローバルIPではあるが、HTTPロードバランサにはグローバル指定のIPしか使えない)
※多分リージョン跨ぎのロードバランシングの為だと思うが今回は割愛
Terraformで使うResourceは地域IPの場合"google_compute_address"でグローバルIPの場合"google_compute_global_address"と分かれていて最初オプションで指定するものと勝手に思ってたから迷った><

AutoScalerどうだったか?
あたりまえだがAutoScaleしたw
インスタンス台数の最小値、最大値は設定できます。
とりあえず最小値4台、最大値16台、チェックはCPU50%とかで
InstanceGroup単位でCPU使用率を見ますが、4台のうち2台を100%にしました。
予想は行っても60%くらいかと思いきやグラフは一瞬80%くらい行きました。
結果的に無事インスタンスがAutoでScaleしましたがInsntance Groupのメトリクスがどういう計算になってるのか
最初の4台状態↓

CPU負荷かけて増えた状態。
10台に増えた。
AWSだと1度の増加台数を決めれるけどGCPはよしなに増やすっぽい。
だからスパイクにも強いってことだろう。最大数は決めれるけど
10台に増えてる↓

Instance Groupにある初期遅延時間(最初のヘルスチェックまでの時間)がデフォは300秒だけどTerraformだと変えられないっぽい?(いやどっかにある気がするがInstanceGroupとAutoscalerにはなかった。。)
なので多分ですが初期遅延時間(300s)+Cool Down(180s)の8分とインターバルのタイミングなので8分強。
CPU負荷を止めて、ぼーっとF5押しながらストップウォッチ見てたら10分弱くらいで減っていった↓

Cooldown値はあるのですが、AWSでは出来た一度に増設する台数とかきめ細かい設定はGCPはない(?)っぽいですね。
あと、LBのメトリクスがそもそも少ないw
あと、MultiZoneのAutoScaleはできない??これもAWSではできたけどもしできないなら痛い、
ほんとに出来ないかは不明、、Zoneの最小単位となるBackendを同じパス(/とか)で複数選択出来ればいいのだが、"URL MAP"設定でBackendを複数指定する場合、同じパス名でマップすると怒られる。なので同じパスにBackendを複数設定が出来なそうと思ったが違うかなぁ、、来週GCPUGおじゃまするので聞いてみよ。
※自己解決しました。HTTPLBのバランシング範囲はRegionでNWLBのバランシング範囲はZoneなのですね。
ちなみにTerraformのVarsとTemplateはこちら
構成としては
※ GCPのCredentialファイルは各自環境のものをカレントに置いといてね
### GCP project_name = "test-project01" region_asia = "asia-east1" zone_asia1 = "asia-east1-a" zone_asia2 = "asia-east1-b" ### GCE server_name = "test-op01" machine_type = "f1-micro" image_name = "image-1" ### NW http_port = "80" ssh_port = "22" any_port = "0.0.0.0/0" kyoten_ip = "xx.xx.xx.xx" ip_op = "test-opip01" ip_lb = "test-lbip01" fw_name = "test-allow-web"
## vars
variable "project_name" {}
variable "region_asia" {}
variable "zone_asia1" {}
variable "zone_asia2" {}
variable "server_name" {}
variable "machine_type" {}
variable "image_name" {}
variable "any_port" {}
variable "http_port" {}
variable "ssh_port" {}
variable "kyoten_ip" {}
variable "ip_op" {}
variable "fw_name" {}
variable "ip_lb" {}
provider "google" {
credentials = "${file("account.json")}"
project = "${var.project_name}"
region = "${var.region_asia}"
}
## Global IP Address
resource "google_compute_address" "default1" {
name = "${var.ip_op}"
}
resource "google_compute_global_address" "default1" {
name = "${var.ip_lb}"
}
## Instance
resource "google_compute_instance" "default1" {
name = "${var.server_name}"
machine_type = "${var.machine_type}"
zone = "${var.zone_asia1}"
disk {
image = "${var.image_name}"
}
network_interface {
network = "${google_compute_network.default.name}"
access_config {
nat_ip = "${google_compute_address.default1.address}"
}
}
}
## Firewall
resource "google_compute_firewall" "default1" {
name = "${var.fw_name}"
network = "${google_compute_network.default.name}"
allow {
protocol = "tcp"
ports = ["${var.http_port}"]
}
source_ranges = ["${var.any_port}"]
source_tags = ["test-any"]
}
resource "google_compute_firewall" "default2" {
name = "test-allow-ssh1"
network = "${google_compute_network.default.name}"
allow {
protocol = "tcp"
ports = ["${var.ssh_port}"]
}
source_ranges = ["10.10.0.0/16"]
source_tags = ["op01"]
}
resource "google_compute_firewall" "default3" {
name = "test-allow-ssh2"
network = "${google_compute_network.default.name}"
allow {
protocol = "tcp"
ports = ["${var.ssh_port}"]
}
source_ranges = ["${var.kyoten_ip}"]
source_tags = ["test-office"]
}
## Network Address
resource "google_compute_network" "default" {
name = "test-nw"
ipv4_range = "10.10.0.0/16"
}
### LB
## HTTP Health Check
resource "google_compute_http_health_check" "default" {
name = "test-check"
request_path = "/"
check_interval_sec = 5
timeout_sec = 5
}
## TargetPool
resource "google_compute_target_pool" "default" {
name = "test-pool"
health_checks = ["${google_compute_http_health_check.default.name}"]
region = "${var.region_asia}"
}
### AutoScaler
## Instance Template
resource "google_compute_instance_template" "default" {
name = "test-template"
machine_type = "f1-micro"
disk {
source_image = "image-1"
}
network_interface {
network = "${google_compute_network.default.name}"
}
}
## Instance Group
resource "google_compute_instance_group_manager" "default1" {
name = "test-instansgrp1"
instance_template = "${google_compute_instance_template.default.self_link}"
target_pools = ["${google_compute_target_pool.default.self_link}"]
base_instance_name = "test-svr"
zone = "${var.zone_asia1}"
}
## Autoscaler
resource "google_compute_autoscaler" "default1" {
name = "test-as1"
zone = "${var.zone_asia1}"
target = "${google_compute_instance_group_manager.default1.self_link}"
autoscaling_policy = {
max_replicas = 16
min_replicas = 4
cooldown_period = 180
cpu_utilization = {
target = 0.5
}
}
}
resource "google_compute_backend_service" "default1" {
name = "test-backend1"
description = "Hello World 1234"
port_name = "http"
protocol = "HTTP"
timeout_sec = 10
region = "${var.region_asia}"
backend {
group = "${google_compute_instance_group_manager.default1.instance_group}"
}
health_checks = ["${google_compute_http_health_check.default.self_link}"]
}
### LB
resource "google_compute_target_http_proxy" "default" {
name = "test-proxy"
description = "a description"
url_map = "${google_compute_url_map.default.self_link}"
}
resource "google_compute_url_map" "default" {
name = "test-urlmap"
description = "a description"
default_service = "${google_compute_backend_service.default1.self_link}"
host_rule {
hosts = ["mysite.com"]
path_matcher = "allpaths"
}
path_matcher {
default_service = "${google_compute_backend_service.default1.self_link}"
name = "allpaths"
path_rule {
paths = ["/*"]
service = "${google_compute_backend_service.default1.self_link}"
}
}
}
## Forwarding Rule
resource "google_compute_global_forwarding_rule" "default" {
name = "test-forward"
target = "${google_compute_target_http_proxy.default.self_link}"
ip_address = "${google_compute_global_address.default1.address}"
port_range = "${var.http_port}"
}
ちなみにAWSでオートスケール
AWS側のイメージとしては以下は多少参考になるかも。本番実装までしたので。ってか3年前かぁ、、古すぎる・・
www.slideshare.net