AWSでsshするならyogafireも便利

※便乗記事ですごめんなさい><
http://m.igrs.jp/blog/2013/03/14/ec2-ssh/


yogafireはec2を便利に使うためのコマンドラインツールです。
yogafireの機能はsshだけではありませんが、
sshするだけでも便利なのでチラッと紹介してみます。

インストール

# ※cpanmコマンド無い時
brew install cpanminus

# インストール (ncurses-devel / readline-devel / libxml2-devel パッケージが必要)
cpanm https://github.com/toritori0318/p5-Yogafire/tarball/master

初期設定する

yoga use --init

sshする

# 一覧から選択
yoga ssh

# Nameタグが「www01」のサーバにsshログイン
yoga ssh www01

# Nameタグが「www*」のサーバを一覧表示。ユーザはec2-userでログインする
yoga ssh 'www*' --user=ec2-user

# AWS APIの条件から絞り込んで一覧表示
yoga ssh --filter='availability-zone=ap-northeast-1,group-name=base'

ssh踏み台指定

# タグ名「fumidai」のインスタンスを踏み台にする
yoga ssh --proxy=fumidai

または、.yogaファイルに「proxy」を設定してもOKです。

application1:
  access_key_id: xxxxxxxxxxxxxxxxx
...
  proxy: fumidai
...

インタラクティブに絞り込んでみる

1.普通にyoga sshしたあと、「app」を入力してEnter。
タグ名に「app」を含むインスタンスがフィルタされます。

2.さらに「b」で絞込み。

3.さらに「web」で絞り込むと、最後の一つのインスタンスなので自動でsshが実行されます。


もちろん、途中でNoを指定してsshを実行することも可能です。

リモートコマンド実行

# Nameタグが「www01」のサーバでlsを実行
yoga cmd www01 ls

# Nameタグが「www」で始まるサーバでuptimeを実行
yoga cmd 'www*' 'uptime'

# Nameタグが「db」で始まるサーバでsudo+password実行
yoga cmd 'db*' -s -p '/etc/init.d/redis start'

リモートにファイルを get / put

rsyncでリモートサーバのファイルを取得します。

# Nameタグが「www02」サーバの「/tmp/hoge.log」をローカルの「./」に転送
yoga get www02 /tmp/hoge.log ./

# Nameタグが「www」で始まるサーバ全部に「/tmp/hoge.log」をローカルの「./」に転送
yoga get 'www*' /tmp/hoge.log ./

# ホスト名でも可能
yoga get hogehoge.example.com /tmp/hoge.log ./

# dry-runモード
yoga get www02 /tmp/hoge.log ./ --dry-run

# rsyncオプションを追加(node_modulesディレクトリを除外してsync)
yoga get www02 ./nodapp ./ -o '--exclude=node_modules'

# ローカルの「README」ファイルを、Nameタグが「www03」サーバの「/home/tori243」に送信
yoga put www03 README /home/tori243

yogafireには他にも多数のコマンドが実装されているので
ご興味のある方は他の記事もご参照ください。
http://d.hatena.ne.jp/tori243/20130102/1357142925
http://d.hatena.ne.jp/tori243/20130327/1364392574

Yogafireがバージョンアップしてさらに捗る!

機能追加したら捗りすぎてまじつらい。
以下ChangeLog

ChangeLog(主要なもののみ)

  • 大幅なリファクタリング
  • ターゲットインスタンスを決定するロジックを統一化
  • ssh vpc サポート
  • ssh proxy サポート
  • インクリメンタルにフィルタを行えるように
  • 'yogafire'を指定することにより、表示オブジェクトすべてに対してコマンド実行
  • renderコマンドに'template-file'オプション追加
  • 'change-instance-type'コマンド追加
  • 'update-ec2-tags'コマンド追加
  • selfオプション対応
  • 'loop' オプション対応
  • instance-typeを最新にUpdateしたのとカラーリング対応
  • start / stop / reboot/ terminateなど複数同時実行出来ていなかったのを対応
  • 'copy-and-launch' コマンドが外に出ていなかったので出した

ターゲットインスタンスを決定するロジックを統一化

今までコマンドによってまちまちだったりしたので統一しました。
ターゲット元の正規表現によって以下の判定を行います。

  • private_dns
  • public_dns
  • instance_id
  • (上記以外)タグ名
# private dnsとして接続
yoga ssh ip-10-199-60-10.us-west-1.compute.internal
# public dnsとして接続
yoga ssh ec2-50-1-30-251.us-west-1.compute.amazonaws.com
# インスタンスIDとして接続
yoga ssh --proxy=i-9bed5ac3
# タグ名(単独)
yoga get www01 ./getfile ./
# タグ名(複数)
yoga put 'www*' ./putfile /tmp

ipアドレスも対応する予定でしたが、諸事情によりTodo。

ssh vpc / proxy サポート

最近VPC使うことも多くなってきました。
しかしyogafireがバグっててそもそもssh繋がらなかったのでまずはそれを修正しました。
また、踏み台対応もyogafireだけで出来るようにしてみました。
以下のようにすると踏み台指定出来ます。

yoga ssh --proxy=<target_id>

# get / put / cmdも対象。以下は「fumidai」というタグ名のインスタンスを踏み台に指定
yoga cmd www1 ls --proxy=fumidai
yoga put www1 ./putfile.txt ./ --proxy=fumidai
yoga get www1 ./getfile.txt ./ --proxy=fumidai

または、.yogaファイルに「proxy」を設定してもOKです。
共通でプロキシ通したい場合はこちらが良いでしょう。

application1:
  access_key_id: xxxxxxxxxxxxxxxxx
...
  proxy: fumidai
...

インスタンスの一覧表示時、インクリメンタルにフィルタ出来るようにした

※(詳しくは別記事にします)
対象はコマンドは
ssh / start / stop / reboot / terminate / copy-and-launch / change-instance-type / ls -i / ls-ami -i
です。
前バージョンまでは、重複したTagNameを指定すると「一つになるように再度指定してね」と弾いていたのですが
面倒なのでインクリメンタルっぽく絞り込めるようにしてみました。
これはマジで便利すぎて鼻がもげる!


'yogafire'指定で表示しているインスタンスを全対象にして実行

現状は start / stop / reboot / terminate のみ使用可能です。
インタラクティブ実行中に「yogafire」を実行すると
今表示しているオブジェクト全てに対してコマンドを実行します。*1
change-instance-typeも対応する予定ですがこちらはTodo。

renderコマンドに'template-file'オプション追加

yoga render --template-file=<file_name>

# example
yoga render --template-file=./example/render/simple.tt --state=running

前バージョンまでは文字列を直接指定するしかできなかったのですが
それに加えてテンプレートファイルを指定できるようにしました。
この機能により「インスタンスの"ロール"/"状態"などによりコンフィグファイルを生成する」
といったことが可能になりました。

テンプレートエンジン

Text::Xslate(TT2like)を利用しているので、基本Xslateの構文がそのまま使えます。
詳しく知りたい方は以下のドキュメントをご覧ください。
http://search.cpan.org/~gfuji/Text-Xslate-2.0000/lib/Text/Xslate/Syntax/TTerse.pm
http://search.cpan.org/~dmaki/Text-Xslate-Bridge-TT2Like-0.00010/lib/Text/Xslate/Bridge/TT2Like.pod

シンプルな例

テンプレートには条件に一致したインスタンスの配列が
「instances」という名前で渡ってきます。
以下のテンプレートはインスタンス毎にパブリックDNS名を出力します。
インスタンスアトリビュートについてはVM::EC2のメソッドと同等になります。

[% FOREACH i IN instances %]
  [% i.dnsName %]
[% END %]
シンプルな例:条件分岐

従来通り yoga render コマンド時にfilter指定して使うことももちろん可能ですが、
テンプレート内で条件分岐させることも可能です。
以下のテンプレートはタグ名が「www」で始まるインスタンスであれば
プライベートIPをインスタンス毎に出力します。

[% FOREACH i IN instances %]
  [% IF i.tags.Name.match('^www') %]
    [% i.privateIpAddress %]
  [% END %]
[% END %]
シンプルな例:JSONの扱い

カスタムタグにJSON文字列を入れてゴニョゴニョしている方もいると思います。
そういったニーズにお応えしてJSONをデコードする関数も定義しました。
以下の例では「Role」というカスタムタグに
「{"Nagios":"1","Group":"www"}」
という文字列が入力されているのをデコードして利用するパターンです。

[% FOREACH i IN instances %]
  [% SET ROLE = decode_json(i.tags.Role) %]
  [% ROLE.Nagios %] # 「1」が表示される
  [% ROLE.Group  %] # 「www」が表示される
[% END %]
応用例:NagiosやMuninのコンフィグを自動生成してみる

もう少し具体的な例を上げてみましょう。
AWSでインフラ構築している方は
インスタンス名」もしくは「独自タグ」を見て
Nagios/Munin/Capistoranoなどのコンフィグを生成する、といったスクリプト
自前で実装したりしていないでしょうか?(自分はしています)
そのような要件があった時、yogafireがあればスクリプトを書くまでもなく
テンプレートファイルを作るだけで済むようになります!
例としていくつかテンプレートを作ってみました。

muninの場合

基本的な設定だけであれば
このような一つのファイルを作るだけで良いです。

さらに、自動でグルーピングを設定したいときにはIF文を使えば簡単ですね*2
これも一つのファイルだけでOKです。

nagiosの場合

全てに基本監視するだけならこのような一つのファイルを作るだけで良いです。
また、ロールによって監視項目を追加したいこともありますよね。
IF文で条件分岐しても良いですが、今回は例として外部のインクルードファイルを使うパターンを作ってみました。
参考にしてみてください*3
https://github.com/toritori0318/p5-Yogafire/blob/master/example/render/nagios/nagios_include.tt
https://github.com/toritori0318/p5-Yogafire/tree/master/example/render/nagios


他にもnginx のサンプルも置いてありますのでご参照ください。


上記の例題テンプレートをダウンロードして
自分の環境で動かしてみるだけでも感触がつかめると思います。
renderコマンドは標準出力に出すだけなので何も考えずに色々と試してみてください!

'change-instance-type'コマンド追加

yoga change-instance-type <target_id>

その名の通り、instance-typeを変更します。
このコマンドの何が嬉しいかというと、
暗黙的に以下のような手順を行なってくれることです。

  1. インスタンスが起動していたら停止する。(a) EIPがついてたら保持しておく
  2. ステータスがstoppedになるまで待つ
  3. インスタンスタイプ変更
  • 1.を通っている場合
    • インスタンスを起動し直す
    • ステータスがrunninngになるまで待つ
    • (a) のEIPがあれば、EIPを付け直す

EC2classicで運用しているのであれば、より便利なコマンドとなりますね。


また以下のように一度に複数のインスタンスに対しても実行可能です。
複数インスタンスを一気に「t1.micro」から「c1.xlarge」にスケールアップ、といった操作も簡単!

yoga change-instance-type  'www*'  --type=c1.xlarge --force


さらに完全に蛇足ですが、
以前から使える expand-volumeコマンドも似たようなことをしています。

  1. インスタンスが起動していたら停止する。(a) EIPがついてたら保持しておく
  2. ステータスがstoppedになるまで待つ
  3. スナップショット作成
  4. スナップショットステータスが「completed」になるまで待つ
  5. 新しいサイズでボリュームを作る
  6. ボリュームステータスが「available」になるまで待つ
  7. 現在のボリュームをdetachする
  8. ボリュームステータスが「detached」になるまで待つ
  9. 新しいボリュームをattachする
  10. ボリュームステータスが「attached」になるまで待つ
  • 1.を通っている場合
    • インスタンスを起動し直す
    • ステータスがrunninngになるまで待つ
    • (a) のEIPがあれば、EIPを付け直す
  • ※上記のどこかでエラーが発生したら元のボリュームにロールバックする

'update-ec2-tags'コマンド追加

※このAPIは将来コマンドインタフェースを変える可能性があります

yoga update-ec2-tags  <target_id> --key='<tag_name>=<tag_value>'

基本的にはtagを更新するだけのコマンドですが、
自動で連番を付けてくれる機能もあります。
以下のコマンドは「image-id=ami-xxxxx」のインスタンス全てに対し
「Nameタグ=www<連番>」と「Roleタグ=webapp」のタグ更新を実行します。

yoga update-ec2-tags --filter='image-id=ami-xxxxx' --key='Name=www[% seqno %]' --key='Role=webapp'

selfオプション対応

自分自身のサーバを対象とする「self」オプションを追加しました。
もちろん、ec2インスタンス上で実行する場合限定となります。
以下簡単な例ですが、自殺コマンドです。ほげぇ

yoga terminate --self
応用編1

高額インスタンスを起動してテスト中、
インスタンス落とし忘れたらどうしよう…ガクブル」
とビクビクしている人も多いことでしょう。
そんなとき、atコマンドを指定しておくと落とし忘れが無くなって良いですね。*4

# 2013/03/26 23:00 に自動的にインスタンスをstopする
echo "yoga stop --self --force" | at "23:00 26.03.13"
応用編2

時間のかかるようなビルドを実行する時、
インスタンスを一時的に「t1.micorからc1.mediumにアップグレードする」
といったことは日常茶飯事ですね。
しかしインスタンスを戻し忘れて「あ”あ”ー!」となることも度々あります。
そんなときはコマンド終了と同時に
インスタンスをstopする」または「インスタンスをt1.microに戻す」
などとしておくと安眠できますね。

# perlbrewの後は何が何でもstopする
perlbrew install v5.16.3 ; yoga stop --self --force

# コマンドが成功した時だけt1.microに戻す
cpanm Task::Plack && yoga change-instance-type --type t1.micro --force

'loop' オプション対応

インタラクティブに入力できるコマンド全部が対象です。
前バージョンまではコマンド実行後に終了してしまいましたが
loopオプションを付けておくとコマンド終了後にインスタンス一覧選択画面に戻るため、
繰り返しインスタンスに対してコマンド実行することが出来ます。

yoga ls -i -l

instance-typeのUpdateとカラーリング対応

最新情報にUpdateしたのと、グループごとにカラーリング表示するようにしました。


現在実装中(次バージョンで公開予定)のコマンド達

  • 別リージョンにAMIを作るまでを自動化してくれるコマンド
  • 特定のグループ毎にインスタンス数を調整するコマンド。手動AutoScaleみたいな感じ*5

Todo

  • ログ出力整理
  • VPCユーティリティを充実させたい
  • cmd / put/ getのパラレル対応
  • テストの充実(そもそもどうしよう)


まだ少しバギーな部分もあるかもですが、
よろしければアップデートしてみてください〜

*1:本当は「yogaInferno」にしたかったけど打ちづらいので却下

*2:"Role"という独自タグに"www"や"db"などの文字列がそのまま入っていると仮定しています

*3:インクルードパターンでは、ロール名と一致するテンプレートが存在しないとエラーになりますのでご注意を

*4:ただしatコマンドの仕様で、atコマンドを実行しないまま手動でサーバを落としたりすると、次回サーバ起動時に登録したコマンドが実行されてしまうらしいので注意。terminateは危険かも

*5:どっちやねん

MANIFEST.SKIPに#!include_defaultを入れておくと良い

https://github.com/toritori0318/p5-App-RedisTop/issues/5


issueを頂いて知ったのですが、
MANIFEST.SKIPに #!include_default を書いておくと
デフォルトでMANIFESTから除外したほうがよいようなファイルを
SKIPに追加してくれるようです。

blib/
pm_to_blib
#!include_default


こんな感じで書いておくと、make manifest の時に以下のように展開してくれる。

blib/
pm_to_blib

#!start included /Users/toriitsuyoshi/perl5/perlbrew/perls/perl-5.16.2/lib/5.16.2/ExtUtils/MANIFEST.SKIP
# Avoid version control files.
\bRCS\b
\bCVS\b
\bSCCS\b
,v$
\B\.svn\b
\B\.git\b
\B\.gitignore\b
\b_darcs\b
\B\.cvsignore$

# Avoid VMS specific MakeMaker generated files
\bDescrip.MMS$
\bDESCRIP.MMS$
\bdescrip.mms$

# Avoid Makemaker generated and utility files.
\bMANIFEST\.bak
\bMakefile$
\bblib/
\bMakeMaker-\d
\bpm_to_blib\.ts$
\bpm_to_blib$
\bblibdirs\.ts$         # 6.18 through 6.25 generated this

# Avoid Module::Build generated and utility files.
\bBuild$
\b_build/
\bBuild.bat$
\bBuild.COM$
\bBUILD.COM$
\bbuild.com$

# Avoid temp and backup files.
~$
\.old$
\#$
\b\.#
\.bak$
\.tmp$
\.#
\.rej$

# Avoid OS-specific files/dirs
# Mac OSX metadata
\B\.DS_Store
# Mac OSX SMB mount metadata files
\B\._

# Avoid Devel::Cover and Devel::CoverX::Covered files.
\bcover_db\b
\bcovered\b

# Avoid MYMETA files
^MYMETA\.
#!end included /Users/toriitsuyoshi/perl5/perlbrew/perls/perl-5.16.2/lib/5.16.2/ExtUtils/MANIFEST.SKIP


※参考
http://weblog.bulknews.net/post/44251476706/stop-shipping-mymeta-to-cpan
https://gist.github.com/miyagawa/4966350

App::RedisTopをcpanに上げて念願のCPAN Authorになったよ

上がったようです。わーい\(^o^)/
http://search.cpan.org/~toritsuyo/App-RedisTop-0.01/


cpanm App::RedisTop
でインストールできるようになりました。楽ちん!


パッチを送っていただいたfujiwaraさん、hirose31さん、
lingerで相談に乗っていただいたsongmuさん、tokuhiromさん
ありがとうございました!

redis-top というCLIを書いた

追記2013/03/11

2.6対応と差分表示対応いただきました!
@hirose31++
@fujiwara++

とある日

探してみたけどたしかにそれっぽいの無さそうだし
自分も欲しいし書くしか無い!!!!




というわけで書きました。
https://github.com/toritori0318/p5-App-RedisTop

使い方

help引けば大体わかると思いますが、いくつか説明します。

その1

127.0.0.1:6379 のRedis情報を表示します。デフォルトだと3秒更新です。

redis-top
その2

複数インスタンスを同時に表示することも可能です。

redis-top -i 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382

いくつか頑張ってみた点

依存を気にした

cpanとか使わなくても、1ファイルをペロッとコピペして実行権限与えれば
大抵の環境で動くように気にして書いてみました。
どこまで動くかは確認していないですが、AmazonLinuxの生AMI環境で動くのは確認済み。

dstatっぽく

表示をdstatぽくしてみました。表示カテゴリの指定も可能となっております。

今後

現在表示している内容はここの情報を参考にしています。
今後も項目増やしたいなと思っていますが、あまり重要な項目わかってないような気もするので
「この項目はあったほうがいいかも!」というのがあればプルリクお願いします〜
あと画面のリフレッシュ方法ももう少し上手い方法を考えたいですね。
あとcpanにも上げてみたい…

YogafireというAWSツールでヨガの奥義を極める

※注 タイトルに深い意味はありません


https://github.com/toritori0318/p5-Yogafire
だいぶ前からgithubには置いてたんですが
年始だしドキュメントっぽいのを書いてみることにしました。
超長い!でも便利かも!

前置き

仕事上AWS(EC2)を使うことが多いのですが、
自分で使っていて「こんなんあったら便利かなー」というのを寄せ集めたCLIです。
基本的な考え方としては「EC2をタグNameベースで」いろいろと操作できるようなツールですね。*1 *2
貧乏性な自分はスポットインスタンスを定常的に使うので
yoga sshは割と必須だったりしています。

Windows

たぶん動きません!

インストール

cpanm https://github.com/toritori0318/p5-Yogafire/tarball/master

# cpanm無い時
curl -LOk http://xrl.us/cpanm
# 環境によっては sudo 付ける
# ncurses-devel / readline-devel パッケージが必要
perl cpanm https://github.com/toritori0318/p5-Yogafire/tarball/master

依存が多くていらいらするかもしれませんがしばらく待ちましょう。
インストールが成功するともれなく「yoga」コマンドが使えるようになります。


コマンド一覧

設定系
config Yogafireコンフィグを設定
use プロファイル設定
EC2操作系
ls EC2インスタンスのリストを表示/操作
ssh EC2インスタンスssh接続
start EC2インスタンスを起動
stop EC2インスタンスを停止
reboot EC2インスタンス再起動
terminate EC2インスタンスを削除
create-image EC2インスタンスからAMIイメージを作成
expand-volume EC2ボリュームを拡張
info EC2インスタンスの詳細情報を表示
cmd リモートサーバでコマンド実行
get リモートサーバからrsyncでファイルを取得
put リモートサーバへrsyncでファイルを送信
AMI操作系
ls-ami AMIリストを表示/操作
プラグイン
all-region-info 全てのリージョンをまたいで様々な情報を取得
aws-status AWSステータスを表示
hosts hostsファイルユーティリティ
region リージョンリストを表示
sshconfig sshconfigユーティリティ
amiwatcher AMIのステータス監視
ec2watcher EC2のステータス監視
instance-type EC2インスタンスタイプ一覧表示
render EC2レンダリングツール

初期設定

利用するにはyogaコマンド用のコンフィグファイルを設定する必要があります。

yoga config --init

対話形式での設定を開始します。
AWS関連の環境変数を設定していればある程度自動で設定してくれます。
ただしpemファイルの在り処は入力する必要があるでしょう。
デフォルトでは「$HOME/.yoga」にコンフィグファイルが作られます。
コンフィグファイルの場所は環境変数「YOGAFIRE_CONFIG」で指定することも可能です。
このファイルを直接編集することも可能です(YAML形式)。
コンフィグファイルのexample

yoga use

yogafireでは複数のAWSアカウントを管理することができます。
プロファイルを複数用意し、useコマンドでプロファイル名を指定することによって
簡単に切り替えることができます。
通常は「global」プロファイルに紐付けられています。

# プロファイル一覧
yoga use

# "account1"プロファイルに切り替える
yoga use 'account1'

Yoga Core:利用頻度ランキング

自分がよく使う順に説明していきます。

yoga ssh

インスタンスに対してSSHします。runningのインスタンスのみが自動でピックアップされます。

# 起動中の全サーバを一覧表示し、番号を選択してsshログイン
yoga ssh

# Nameタグが「www01」のサーバにsshログイン
yoga ssh www01
(以下でも同じ意味)
yoga ssh --tagsname www01

# Nameタグが「www*」のサーバを一覧表示し、番号を選択してsshログイン
yoga ssh 'www*'

# --filterオプションでAPIのフィルターも自由にかけることも可能
#   ※sshコマンドに限らず、他のコマンドでも同様
#   http://docs.amazonwebservices.com/AWSEC2/2011-05-15/APIReference/index.html?ApiReference-query-DescribeInstances.html
yoga ssh --filter='instance-state-name=running,availability-zone=ap-northeast-1,group-name=base'
yoga ls

インスタンスのリストを表示できます。全てのステータスが対象となります
(オプションで絞り込むことは可能)

# "www"でタグNameが始まるインスタンスのみ表示
yoga ls 'www*'
(以下でも同じ意味)
yoga ls --tagsname 'www*'

また、-iオプションを追加すると、表示したインスタンスに対して更にコマンド(ssh / start /stop /...)を
実行することができます。

# さらに追加コマンドを選択
yoga ls -i

yoga ls-ami

lsのAMI版。
これをよく使うのは、AMI削除するときにスナップショットも一緒に消せるようにしているからですね。*3

# "www"でAMINameが始まるインスタンスのみ表示
yoga ls-ami 'www*'
(以下でも同じ意味)
yoga ls-ami --name 'www*'

lsと同じように、-iオプションを追加するとインタラクティブモードになります。

# さらに追加コマンドを選択
yoga ls-ami -i
yoga get

rsyncでリモートサーバのファイルを取得します。

# Nameタグが「www02」サーバの「/tmp/hoge.log」をローカルの「./」に転送
yoga get www02 /tmp/hoge.log ./

# Nameタグが「www」で始まるサーバ全部に「/tmp/hoge.log」をローカルの「./」に転送
yoga get 'www*' /tmp/hoge.log ./

# ホスト名でも可能
yoga get hogehoge.example.com /tmp/hoge.log ./

# dry-runモード
yoga get www02 /tmp/hoge.log ./ --dry-run

# rsyncオプションを追加(node_modulesディレクトリを除外してsync)
yoga get www02 ./nodapp ./ -o '--exclude=node_modules'
yoga put

getの反対でリモートサーバのファイルを取得します。
dry-runやrsyncオプションもgetと同じように指定できます。

# ローカルの「README」ファイルを、Nameタグが「www03」サーバの「/home/tori243」に転送
yoga put www03 README /home/tori243
yoga cmd

指定したコマンドをリモートサーバで実行します。
並列実行はTodo...

# Nameタグが「www04」のサーバでlsを実行
yoga cmd www04 'ls'

# Nameタグが「www」で始まるサーバでuptimeを実行
yoga cmd 'www*' 'uptime'

# Nameタグが「db」で始まるサーバでsudo+password実行
yoga cmd 'db*' -s -p '/etc/init.d/redis start'

Yoga Plugin:利用頻度ランキング

プラグインで自分がよく使う順に説明していきます。

yoga instance-type

EC2インスタンスタイプの一覧を表示します。
idとタイプの紐付けや、スペックの確認に便利。

yoga region

リージョンのIDも忘れがちなので一覧で見れると便利ですね!

yoga render

割とお気に入りの機能です。EC2インスタンス情報をテンプレートで記述できます。
具体例をいくつか上げてみます。

# ステータスがrunningのサーバ全てを対象にdnsNameを生成
yoga render --template='"[% dnsName %]",\n' --state=running
(結果)
"ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com",
"ec2-yyy-yyy-yyy-yyy.ap-northeast-1.compute.amazonaws.com",
...

# タグNameが'www'で始まるサーバのグローバルIPを生成
yoga render --template='[% ipAddress %]\n' --tagsname='www*'
(結果)
xxx.xxx.xxx.xxx
yyy.yyy.yyy.yyy

# タグNameが'db'で始まるサーバ情報でPerlのコードっぽいのを生成
yoga render --template='{ instance => { instance_id => "[% instanceId %]", private_ip => "[% privateIpAddress %]", launch_time => "[% launchTime %]" } },\n' --tagsname='www*' 
(結果)
{ instance => { instance_id => "i-bbbbbbb", private_ip => "x.x.x.x", launch_time => "2012-03-30T09:00:34.000Z" } },
{ instance => { instance_id => "i-ccccccc", private_ip => "y.y.y.y", launch_time => "2012-03-30T09:01:49.000Z" } }
yoga aws-status

awsステータス情報の通知を時系列に表示します。日付/リージョン/サービス名指定も可能。

yoga hosts

EC2インスタンスipアドレスをhostsに自動更新します。
以下のようなフォーマットでファイルの末尾に追記されます。
更新時も「Yogafire Begin <-> Yogafire End」の間だけが自動で置換されます。
フォーマット

#======== Yogafire Begen ========#
<public_ip or private_ip> <tag_Name>
...
#======== Yogafire End   ========#

実行例

# 更新後のhostsファイルをプレビュー
yoga hosts --preview

# プライベートIPでhostsファイルを置換します(バックアップ有り)
yoga hosts --replace --private-ip --backup

更新後ファイルの例

127.0.0.1	localhost pn-agent pn-broadcast
::1             localhost 
fe80::1%lo0	localhost
...
#======== Yogafire Begen ========#
59.1.1.1         wwwhoge
59.1.1.2         wwwfuga
59.1.1.3         dbpiyo
#======== Yogafire End   ========#
yoga sshconfig

EC2インスタンスipアドレスをsshconfigに自動更新します。
以下のようなフォーマットでファイルの末尾に追記されます。
フォーマット

#======== Yogafire Begen ========#
Host <tag_Name>
    HostName     <dnsName>
    IdentityFile    <.yogaコンフィグの鍵ファイルパス>
    User              <.yogaコンフィグのユーザ名>
    Port               <.yogaコンフィグのポート番号>
...
#======== Yogafire End   ========#

実行例

# 更新後のsshconfigファイルをプレビュー
yoga sshconfig --preview

# sshconfigファイルを置換します(バックアップ有り)
yoga sshconfig --replace --backup

更新後ファイルの例

#======== Yogafire Begen ========#
Host wwwhoge
    HostName     hogehoge.com
    IdentityFile    /path/to/id.pem
    User         ec2-user
    Port         22

Host wwwfuga
    HostName     fugafuga.com
    IdentityFile    /path/to/id.pem
    User         ec2-user
    Port         22

Host dbpiyo
    HostName     piyopiyo.com
    IdentityFile    /path/to/id.pem
    User         ec2-user
    Port         22

#======== Yogafire End   ========#
他にも

割愛しますが、リージョンを横断して情報表示できる all-region-info や、
ステータスを監視して ステータスが変更されたらgrowl表示したりできる
ec2watcherやamiwatcherという機能もあったりします。



Tips的な話

ヘルプ
# 全部のコマンド一覧
yoga

# コマンド毎のヘルプを見る
yoga <command> --help
オートコンプリート

sshやls -iなど、番号/インスタンス名/インスタンスIDを入力するところでは
TABキーでオートコンプリートが効きます。

また、zsh補完を設定しておくと、コマンドラインでもいろいろと補完が効くようになります。

yogaコマンド補完


さらに絞り込んで補完とか。

インスタンス名補完

また、ssh / ls / start / stop /terminate / get /put などのコマンドでは
yoga TABキー でもzsh補完でインスタンス名の補完が可能です。

カラムのカスタマイズ

ssh / ls / ls-ami などで表示される一覧のカラムは
コンフィグファイルでカスタマイズすることが可能です。

app1:
  access_key_id: aaaaaaaaaaaaaaaa
  identity_file: '/path/to/nyoro.pem'
  ###############################################
  # amiリストのカラム
  #  VM::EC2::Imageのメソッドと一致するものを指定
  #   http://search.cpan.org/~lds/VM-EC2/lib/VM/EC2/Image.pm#METHODS
  #  タグの場合は「tags_<タグ名>」で指定可能
  image_column:
    - tags_Name
    - name
    - imageId
    - colorfulImageState
  ###############################################
  # インスタンスリストのカラム
  #  VM::EC2::Instanceのメソッドと一致するものを指定
  #   http://search.cpan.org/~lds/VM-EC2/lib/VM/EC2/Instance.pm#METHODS
  #  タグの場合は「tags_<タグ名>」で指定可能
  instance_column:
    - tags_Name
    - tags_Role
    - instanceId
    - ipAddress
    - privateIpAddress
    - dnsName
    - launchTime
    - colorfulInstanceState
  region: ap-northeast-1
  secret_access_key: bbbbbbbbbbbbbb
  ssh_port: 22
  ssh_user: ec2-user
alias

指定しておくとさらに便利ですね。

# wwwサーバへssh
alias yssh-www='yoga ssh "www*"'
# dbサーバへコマンド実行
alias ycmd-db='yoga cmd "db*"'
# /etc/hostsを置換
alias yhost-replace='sudo YOGAFIRE_CONFIG=/home/toritori0318/.yoga /path/to/yoga hosts --replace'
他のコマンドと連携してみるとか

yoga render コマンドの結果を用いてpsshに食わせたりとか夢ひろがりんぐですね。

Nameタグについての注意点

Nameタグの値が 'www 01 desuyo' のように、間にスペースがあると
動作に影響する可能性があります。スペース禁止!


Todo(たぶんやる)

  • 表示系のソート指定
  • sync や cmdのパラレル実行
  • 入力履歴っぽいのをテンプレートで保存して使えるようにするような仕組み*4

まとめ

自分の用途に特化しているため、まとまりがなかったりAPIが微妙だったりするかもしれないですが
ssh / render / hosts などは割と便利だと思うので
興味がある方は触ってみてください。
また、コマンド自体はMouse::App::Cmdで定義しているだけなのでコマンド追加もコマンドファイル一つ作るだけでいけます。*5
コマンドを自分用に作るのもいいでしょう。

番外編:yogaコマンド依存度

ちなみに自分のコマンドランキングはこんな感じ。

 566 cd
 515 perl
 486 git
 407 yoga
 404 vi
 308 curl
 178 make
 150 ll
 135 node
 101 npm
 101 ack

どんだけyogaコマンドうってるの…

*1:コマンドによってはName関係無かったりしますけどw

*2:任意のタグや、任意の条件も指定可能です

*3:AWSの管理画面でもできるようになって欲しいなー

*4:Launch入力時のパラメータを保持しておくとか

*5:これが例としてわかりやすいかも https://github.com/toritori0318/p5-Yogafire/blob/master/lib/Yogafire/Plugin/Command/allregioninfo.pm

YAPC::Asia 2012感想

毎年恒例のPerl祭り「YAPC::Asia2012」に行って参りましたので
トークや全体の感想などつらつらと。

前夜祭(今年は行けず…)

トークまとめ

Web::Security beyond HTML5

HTML5時代のWebアプリケーションのセキュリティについて
ブラウザ側とサーバ側でどういう脆弱性があるか、
またどういう対策をすべきか、というありがたいお話。
IEほんとひどい。

リアルタイム通知システムの舞台裏

リアルタイム通知システムを開発するにあたって、
課題となったところやそれを解決した方法などのお話。
実は今自分もかなり似たような仕組みを作っていて
課題のところなどは「あーそうですよねー」など妙に納得しながら聞いてました。
通知サーバをクラスタ化するのは自分もRedisで検証してみたんですけど
同時接続15000行かないくらいで頭打ちになってしまい止めてしまいました*1
RabbitMQのpubsubはまだ試してないので一度触ってみたいですね。
後ほど直接お話したかったんですが見つからず…

Perl初心者が作ったサーバ運用ツール

サーバ運用の自動化について。
マニュアルでやると大変だし失敗もするし
そういうことを減らすためにTouryoというツールを作ったというお話。
DSLで設定やテスト書いて(ロールごと?)sshでリモートインストールする、という感じ?
また、LTソンではTouryoをgithubに上げない理由をお話されていました。
もちろんそれらを理解した上なんですが、上げて欲しいなあと思いましたw
*2

Perlと出会い、Perlを作る

世界一高速なPerlをスクラッチで書いている、というお話。
ほとんど趣味の範囲で書いているらしいですが徐々に動くところまではきている様子。
目標は「mixiのhome.plが動くまでがんばる」ということで楽しみですねw
実際のベンチマークでは既存のperlよりだいぶ高いスコアが出ていました。

続・Mobage を支える技術

Prallel::Prefork + Q4M のベストプラクティス的な話からスマートフォン通知やランキングの裏側の話まで。
複数ワーカでQ4Mを利用した時にシグナルを受け取ると子プロセスが処理中でも死んでしまう、
さらにqueue_waitで止まってしまう、などの
問題点を一つ一つ実例を挙げながら解決していくという素晴らしい内容でした。
スマートフォン通知はiPhone向け(APNs)とAndroid(GCM)にどのような仕組みでpush通知が行われているか、
それをPerlでどのように書くか、といった内容。
最後にリアルタイムランキングをRedis+MySQLPerlでどのように実現するかというお話でしたが
だいぶ時間が押していて端折られていました。詳しくお聞きしたかった!

Redmine::Chan で IRC からプロジェクト管理

Redmineの登録フローをIRCから自動で行うというお話。
単にチケット登録するだけではなくて、きちんとフローになっているのが凄いなーと思いました。
実際に使ってみたいです。

平均レスポンスタイム50msをPerlで捌く中規模サービスの実装/運用

現状のWeb広告についてのお話と、DSP(Demand-Side Platform)システムの裏側のお話。
自分も昔ASPアドサーバの開発運用をしていたことがあるのですが、
まあそのサービス自体は「昭和」な感じでしたので中身はもう全然違いますね。
「古典的なことを地道にやる」「事実を積み上げて判断する」
というのはガツンときました。

Perlアプリケーションのベンチマークとプロファイリング

Webアプリケーションのボトルネックをどのように見つけていくか?
そのポイントと手法と考え方についてのお話。
実践的なお話かつ、いままさにプロダクションで負荷テストなど行なっているので
とても参考になりました。
Parallel::Benchmark+Furlでローカルテストしてみましたが、
ApacheBenchと比較しても(思ったより)差がでないくらいのパフォーマンスだったので
仕事でも使わせていただきたいと思います!

Perlハッカーは息をするようにCPANモジュールを書く

どのような動機でCPANモジュールを書いているか、
またCPANに上げる時のポイントやCPAN怖くないよ!というお話。
ドキュメントには「モジュールに対する想いを全部ぶつけるところ」らしい!熱い!
自分はgithubにたくさんモジュール眠らせてるタイプです…

LT

1日目/2日目とも全て楽しませていただきました!が、
やはりどちらもトリをつとめた方々(mayuminさん)(takesakoさん)は秀逸。

Keynote

How Perl Changed My Life

Perl、またはコミュニティから現在の自分にどのように影響しているかというお話でした。
自分も初めて触れたLLがPerlということもあり、
自分自身にも置き換えて考えてしまいました。

LTソン

LTソン本当よかったです。
集中してセッション聴いたあとにリラックスする場*3としてとても良かったと思います。
自分も飛び込みしたかったんですが、2日目の競争率が激しそうだったのもあり断念。

懇親会

ご飯も美味しかったしTwitterで見かけたり絡んだりする方とお話できてとても嬉しかったです!
毎年思っていることですが、もっとアグレッシブに行けばよかった、とか
ひと通り話し終わったあとに「あの話をすればよかった」とか後悔…

まとめ

Closingで「YAPCは懐の広いカンファレンスでありたい」という言葉がありました。
たしかにPerlに限らず他言語の話もたくさんあったにもかかわらず
一緒に盛り上がれるYAPCは凄いなと思いました。
丸々2日間本当に楽しかったです。ありがとうございました&お疲れ様でした!
そしてやっぱり来年も参加したいと思いました!

*1:これだとだいぶ要件に届いてない

*2:自分が参考にしたいというのもあったり><

*3:もちろん盛り上がりもありつつも