misc.tech.notes

主に技術的な雑記的な

kitchen-azure_vmというTest-Kitchen Driver Pluginを作った

これは何?

Microsoft AzureVirtual Machineを利用してtest-kitchenによるテストを行うためのDriver Pluginです。

動機など

故あってAzureの長期クーポンもらったので有効活用するために作ってみました。
最近、ゆるい環境構築は大半Test-Kitchenでやっちゃってるので。

kitchen-azureっていうのが一応あるんだけど、最終コミットが9ヶ月前でIssueもPRも放置されてて、完全に見込み無い感じだったので自前で作りました。

marcy-terui/kitchen-azure_vm · GitHub

kitchen-azure_vm | RubyGems.org | your community gem host

現状はLinuxのみサポート*1

WinRMがAzureだと簡単に設定できそうなので、WinRM対応してWindowsサポート入れたら有用なプラグインになりそうなんだけど、現状は自分の中に需要がないので様子を見ながら考えます。
*2

Azure SDK for Rubyがアレ *3

命名とか随所の記述とか、にわかRuby使いの自分にも分かるくらい残念だし、オブジェクトを返すべきメソッドで、エラー時に例外握りつぶしてエラー文字列返したりするし、IssueやPRが1ヶ月近く放置されてるし、だいぶアレ。
クラウドにおいてAPIとそれを使いやすくするSDKは凄い大切な存在だと思うので、もっと頑張って欲しい。
他にも色々微妙な苦労があったので、最近Azureのマネージドサービスはいくつか凄い良さそうで興味を引かれていただけにちょっと残念感がある。

ともあれ、これで色々遊べます。

AzureユーザかつChefユーザ(provisioner切り替えれば必ずしもChefじゃなくても)がどれほど居るのかは未知数ですが、良かったら使ってみてください。

詳しい使い方は近いうちにQiitaに書く(かも)

*1:2015.03.11現在

*2:WinRM欲しい方、プルリクくれても良いんですよ…?

*3:2015.03.11現在

「Specinfra Host Inventory Plugin for Fluentd」なるものを作ってみた

最近(?)、Serverspecの基盤となっているSpecinfraに対象ホストのインベントリ収集機能が追加されていました。

Serverspec - Host Inventory

何気なく軽量で実行方式(ローカルとかSSH越しとか)が選べて取り回しの良いインベントリ収集ライブラリは何かに使えるんじゃないかなーとかもやもやと考えてみつつ、プルリク(#324,#330)送ってみたりしていました。

で、とりあえず、思いつく用途としては監視や管理用途等でエージェント型、外部監視型のどちらも使える何かがあると良いかなと思い、Fluentdのプラグインにしちゃえば結果の出力先が柔軟に変えられて良い感じかもしれないということで、作ってみました。

marcy-terui/fluent-plugin-specinfra_inventory · GitHub

fluent-plugin-specinfra_inventory | RubyGems.org | your community gem host

完全に思いつきで作ってみましたが、SpecinfraもFluentdも拡張性が意識されていて、僕みたいなのでも思いついてから数時間とかで拡張できちゃうのが凄いですね。見習いたい。

名前長いのなんとかしたい…

AWS SDK for Goで貧者のためのEC2バックアップCLIツールを作ってみた

AWS SDK for Go(のベータ版)が出たので触ってみたくて作ってみました。

最近の(自分の周りの)EC2バックアップ事情

EC2の定期バックアップは特に受託案件だとほぼ必須で各社・各個人で色々な方法でやっていることと思います。

最近だとお金があるなら「Cloud Automator使え」ってなるんですが、僕らのような貧者は昔からEC2のタグを見てバックアップを行うスクリプトをcronで回していたり、Jenkinsおじさんにお願いしたりするわけです。

で、一括管理できるようにアカウント横断で共用サーバ上で回すのが楽なわけですが、必ずしもそうできないような場面も会って、そうなるとスクリプトを別のサーバに仕込むわけです。

ただ、そうやってバックアップスクリプトが増殖していくと、そのうちAPI仕様変更とかSDKのバージョン違いによるバグ踏んじゃったりとか、Chefとかがあるとはいえそのためだけに何かしらの言語ランタイム入れないと…とか、ツラい未来(一部現在進行形)が色々想像できちゃうわけです。

Goで書いてみた理由

その点、Goなら言語ランタイムは要らないし、API仕様変更は無理ですがSDKのバージョン違いによるバグはテスト済みでコンパイルされたバイナリを使っている限り起きえませんし、万が一何かあってもバイナリ差し替えるだけなので楽です。

WindowsでもLinuxでも同じコードベースで動くのでWindows Server一台案件とかでも問題ありません。

あと、今までのはこのへんを参考に作っていたりするのですが、Nameタグを制御に使うのは微妙だと前々から思っていたので書き直したかった。

ということで作ってみました。

marcy-go/ec2backup · GitHub

使い方

前提

以下の権限のIAM Roleを有するEC2インスタンス

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateImage",
        "ec2:CreateSnapshot",
        "ec2:CreateTags",
        "ec2:DeleteSnapshot",
        "ec2:DeregisterImage",
        "ec2:DescribeImages",
        "ec2:DescribeInstances",
        "ec2:RegisterImage"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
1. バックアップ対象のEC2にBackup-Generationタグを設定

f:id:FumblePerson:20150217232147p:plain
※Valueはバックアップ世代数

2. バイナリを取得してEC2上に配置
バージョン ダウンロード元
HEAD Downloads | ec2backup
Release Releases · marcy-go/ec2backup · GitHub

※実行するOSとArch(amd64 or 386)によってバイナリが別なので注意

3. コマンド実行
/path/to/ec2backup self
  • Linuxアカウント全体
/path/to/ec2backup all
C:¥path¥to¥ec2backup.exe self
C:¥path¥to¥ec2backup.exe all

今後対応したいやつ

  • credentialsファイル指定、profile切り替え
  • Backup-Generationタグを無視するオプション
  • コマンドからの Backup-Generationタグ設定

以上です。
お金がある方はCloud Automator、無い方は良かったら使ってみてください。

クラウドからオンプレへの揺り戻しは無いとは言えない。しかし、戻ってくるとしても、それはあなたが思っているオンプレとは違う。

前置き

ポエムであり、最後の方ステマっぽいです(そんなつもりは全くなかったんですが、思うままに書いていたらそうなったw)
基本的に具体的な論拠に基づかない個人的な感覚で書いてます。ちょっと煽りっぽいですが「そんな風に話をしたくなる時もあるよね」と生暖かい目でお読みいただけると幸いです。

あと、もちろん「今オンプレを使っている人」を否定する意図は全くありません。そこに様々な事情があることは重々理解しておりますし、場面によっては未だオンプレにアドバンテージがある部分も残っていることは承知しております。
言いたいことは、「揺り戻しはクラウドを使わない理由には全くならない」ということです。

まずはじめに

たまにこの言葉を聞く。

クラウドクラウドって言ってるけど、過去の技術がそうであったように、いずれまたオンプレに戻ってくる日が来る」

この後は「だからクラウドは~」と続く。

たしかにそうかもしれない。そうなる可能性は無いとは言えないとは思う。
しかし、だからと言ってクラウドを使わないという理由には一切ならない」と言いたい。

なぜなら、戻ってくるとしてもそれは、

あなたが思っているオンプレとは違うからだ

なぜそう思うのか

揺り戻しが起きる要因は以下のようなものが考えられる。

  • ハードウェアの性能が上がり続け、ハードウェアの構成方法に革新が起こり、安価かつ簡単に大規模な演算能力が誰にでも手に入る用になる
  • クラウド特有のサービスがより優秀なOSSプロダクトに取って代わられる
  • クラウドの強みであるメンテナンスコストやスケーリング、耐障害性や柔軟性も同様に、技術革新によってコモディティ化する

これだけでなんとなく言いたいことに気づかれた方も居るかもしれない。

要はクラウドからオンプレへの揺り戻し」というから紛らわしいのであって、「見える場所に戻ってくる」だけで中身はクラウドないしクラウドの先にある何かであるということ。

技術者が、クラウドによってもたらされたスピード感や利便性や安心感を破棄することはまず考えられない。
また、ハードウェアメンテナンス等といった一般の技術者とっては本質的ではない仕事が増えることを望むはずもない。
だから、「今までのようなオンプレ」に戻ることはない。

揺り戻しが起きるとすれば、そういった環境が技術革新によって安易に手元でメンテナンスフリーに近い形で構築できるようになった時である。

そう考えると、大分道のりは厳しそうで、クラウドの時代はまだ長く続きそうでもある。

では、もしも揺り戻しが来た時のことを考えて今どうすべきか?

低レイヤがやりたい・得意だという方は

クラウドを作る・運用する側に回る

そうでなければ、

クラウドを使う

という選択肢になる。

あとは、完全にソフトウェアに特化してひたすらプログラミング技術を上げるとかいう別の道を探すことである。

「揺り戻しが来た時のオンプレ」に近いのは、「今のオンプレ」ではなく「クラウド」なのだ。

だから、先を見るのであればクラウドの先にある何か」を使いこなしたいなら今はクラウドへ飛び込むべきだ。

最後に

クラウドへダイブするきっかけが欲しければ、JAWS DAYS 2015 | クラウドへダイブ 〜 Dive Deep into the Cloud!に行くと良いかもしれません。

自分も思えば、2年前のJAWS Daysに参加したことが大きな転機になったような気がします。2年前は別世界だった場所で自分が話す機会を貰える(しかもAuroraとか大事っぽい所w)なんて、なんか感慨深いです。

以上。最後はステマっぽくなっちゃいましたが、書いてスッキリしました。

お粗末さまでした。

Azure Job Scheduler + AWS Lambdaで定期的に大量のジョブを並列で実行させるためのパターンを考えてみる

前回の Azure Job Scheduler + AWS Lambdaで夢のサーバレス定期ジョブを実現する - Miscellaneous notes 続きです。
今回はまだ考察・アイデアレベルでまだ試してません(そもそも、このアイデアについてのコメントなどいただけることを期待していたりいなかったりw)

実際にやりたいジョブはそう単純じゃない

単一または少ない数の単純なジョブであれば、S3バケットと1:1で紐づけてやっても良いかと思います。
でも、実際にやりたいことはそうじゃなかったりします。
複数のジョブをまとめて実行したかったり、対象が多いために並列で一気に処理したかったりするわけです。

Azure Job Schedulerに登録できるJob数にもS3バケット数にも上限がありますし、大量のJobを効率的に管理する必要があります。

従来では

ジョブの発行者(Publisher)と実行者(Worker)を分け、その間をSQSなどのキューで繋ぐ方法があります。
Workerを増やすことで並列度を上げることができ、Auto Scalingを適用すればある程度のコスト最適化も図れます。

また、ここでもAzure Job Schedulerを利用することで、以下のようにSPOFの無い構成を作ることができるかと思います。
(Azureのアイコン群で作ってみましたが、青だけだと分かりにくい気がするのはAWSに慣れすぎたせいでしょうか?w)

f:id:FumblePerson:20150119125441p:plain

従来の方法の問題点

  1. 管理すべきサーバが多い
  2. Auto Scalingの閾値が難しい
  3. 極端に多くなった場合に、分散処理できないPublisherが限界を迎える可能性がある
  4. Auto Scalingといえど、やはり並列定期ジョブでは無駄が生じる

1,2はそのままの意味です。
3は、さらにキュー(とWorker)を挟んだりすることで解決する方法もありますが、複雑になります。
そして、一番の問題は4です。
要は例を挙げて説明すると、
「5分に一度1分以内に大量のジョブを処理したい」と思ったときに、ピークは明らかに最初の1分だけであるにも関わらず、Auto Scalingではそこまで細かな制御ができないため、「最初の1分に合わせた台数のサーバが必要になる」ということです。

じゃあ、どうしたら良いだろうか?

答え:それ、全部Lambdaでやっちゃいましょう

こんなのはどうでしょう?

f:id:FumblePerson:20150119123502p:plain

  1. ジョブをグループ化して、それぞれ適切な単位で別々のリストとして保存します。
  2. Azure Job SchedulerからグループIDをURLに含んだPUTリクエストを投げます。
    前回はURLに認証文字列を含みましたが、任意のヘッダを指定できるのでUser-Agentあたりにすると良さそうです。S3 Bucket PolicyUser-Agentでの許可設定が可能です。もちろん、S3 Event Notificationには更新されたオブジェクトのキー情報が含まれています。
  3. グループIDに対応するリストの数だけPublisherとなるLambdaを起動し、処理すべきリストを与えます。
  4. 起動されたPublisherはそれぞれ与えられたリストの中身を見て、その中のジョブ数分だけ一気にLambdaを起動し、Jobを実行させます。

必ずしもこの方法である必要はありません

要点としては以下のような点です。

  • リクエスト処理ジョブ発行ジョブ実行を全て分離する
  • 後ろに行くにつれ並列処理が必要となるが、それぞれが必要な分だけ起動できるようにする
  • 段階的に起動数を増して、粒度を細かくしていくことで、最終的な並列度を極限まで上げる

これによってどうなるか?

  • 管理すべきサーバが存在しない
  • ジョブのリスト分割方法を変えるだけで起動数を調節できる
  • Lambdaの課金は起動リクエスト数100msec単位の実行時間で、適宜必要な分だけ起動して最小の処理で終了して破棄できるため無駄がない
  • 並列度をいくらでも上げられる

最後に

こういう感じの新しいサービスに対応した新しいCDP(Cloud Design Pattern)が欲しい感じする。
MCDP(Multi Cloud Design Pattern)とか収集つかなくなりそうだけど、面白そうw
是非、ご意見お待ちしておりますm(__)m

Azure Job Scheduler + AWS Lambdaで夢のサーバレス定期ジョブを実現する

GoAzureがやっていたので、フラフラとAzureのWebサイトを見ていたりしました。

で、Azureのサービスの中に、AWSには無いJob Schedulerのサービスがあって、

これずっと欲しかったやつや!

ってなったので、ちょっと調べてました。

余談ですが、Jobの発行元の可用性担保と実行保証って面倒くさいんですよね。二重発行させる訳にもいかないですし、そのためだけにHA組む?みたいな所もあり…
発行されたJobを実行する所ではSQSとかELBとか挟めばどうとでもなるんですけど…
そんな訳で、フルマネージドなJob Schedulerはとても魅力的なわけです。

で、まず思ったのが「ここからLambdaキックできたらサーバレス定期ジョブでアツいなー」ってことです。

Job Schedulerができることは大別して以下の2つです。

  1. 同じAzureのStorage Queueへのメッセージキューイング
  2. HTTP(S)リクエスト

この内、2のHTTPリクエストがGET,POST,PUTメソッドに対応しています。
どれも、動的にリクエストの内容は組み立てられないのでLambda:InvokeAsyncAPIをコールするのは無理です。
ただ、一個だけ(?)Lambdaを静的なリクエストで起動する方法があります。

S3 event notifications(S3更新通知)です。

認証付きのSOAP APISDKから呼ぶやつ)ではなく、REST APIPUTなら単純な静的リクエストから更新ができます。

手順など

まず、PUTするS3バケットを作成し、以下のようなバケットポリシーを適用します。

S3 BucketLamda Functionのリージョンが同じになるよう注意しましょう。

{
    "Version": "2008-10-17",
    "Id": "PolicyLambdaScheduler",
    "Statement": [
        {
            "Sid": "StmtLambdaScheduler",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::lambda-scheduler-sample/<random-strings>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "0.0.0.0/0"
                }
            }
        }
    ]
}

許可するのは、万が一のイタズラを考えて十分に長いランダム文字列を含んだパス等にすると良いかと思います。

次に、Lambda Functionを登録します。

lambchopというgemが手元のスクリプトをサクッと上げれて、実行結果のログをtailするように見られて素敵なので、使わせていただいてます。

lambchop 0.0.2: Invoke AWS Lambda function from local as normally script - so what

こんな感じで適当です。

#!/usr/bin/env lambchop
/*
function_name: lambda-scheduler
runtime: nodejs
mode: event
description: 'Lambda scheduled job publish from Azure Job Scheduler'
timeout: 3
memory_size: 128
role: arn:aws:iam::<your-account-number>:role/lambda_exec_role
handler: lambda-scheduler.handler
*/
console.log('Loading event');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
require('date-utils');

exports.handler = function(event, context) {
   var d = new Date();
   console.log('Received event:');
   console.log(JSON.stringify(event, null, '  '));
   console.log('DateTime:',d.toFormat("YYYY-MM-DD HH24:MI:SS"));
   console.log('Invoked from Azure Job Scheduler!!');
};

登録したLambda FunctionをS3 event notificationsで起動するよう設定します。

Lambdaのメニューを開きます。

f:id:FumblePerson:20150117003946p:plain

変更します。

f:id:FumblePerson:20150117003616p:plain

そして、Azure Job Schedulerのジョブを作成します

Job Schedulerを選択します。

f:id:FumblePerson:20150117004156p:plain

先ほどS3のバケットポリシーで許可したURLを入力して作成します。

f:id:FumblePerson:20150118002810p:plain

とりあえず、2分毎で。
※無料トライアル枠の無い方は1時間より大きい周期でないと有料です。

f:id:FumblePerson:20150117004658p:plain

暫く、lambchopの出力を眺めると…

f:id:FumblePerson:20150117005238p:plain

f:id:FumblePerson:20150117005243p:plain

2分毎に起動してる!!

夢のサーバレス定期ジョブや!!

Azure良いかも

良さそうなサービスがけっこうあって、ちょっとAWSを使い始めた頃のワクワクが蘇った感じがしてて良いかもです。
AWSはもちろん素晴らしいし、これからも使っていきますが、色んなクラウドの良いサービスはガンガン使って、組み合わせて良いものが作れるように精進していきたいと思います。

kitchen-docker_cliというTest-Kitchen Driver Pluginを作った

この記事は Chef Casual Advent Calendar 2014 の25日目の記事です。

Chef Advent Calendar 2014 - Qiita

お詫び

元々はCookbookの書き方、あるいはNginxの設定ファイルの書き方というタイトルでエントリーしておりましたが、自分の中で優先順位の変化がありましたので別のテーマで書かせていただきます。
Cookbookの書き方、あるいはNginxの設定ファイルの書き方は自分の書き方、考え方が合っているかの確認も込めて書こうと思っていましたのでまた今度書きます。

これは何?

Dockerコンテナ上でtest-kitchenによるテストを行うためのDriver Pluginです。

インストール方法や使用方法は下記のREADMEをご確認ください。

marcy-terui/kitchen-docker_cli · GitHub

kitchen-dockerと何が違うの?

ssh等は使わず、基本的にdockerコマンドが標準で用意している機能のみで実装しています。

【翻訳】Dockerコンテナ内でSSHDを実行してはいけない理由 | POSTD

また、kitchen-dockerではサポートされていない、コンテナ間を接続するためのオプション群をサポートしています。

Linking containers together - Docker Documentation

加えて、test-kitchenの新サブコマンドexecに対応しています。
未リリース(2014.12.25現在)ですが、masterのHEAD等を指定してインストールすれば利用可能です。

test-kitchenの新しいサブコマンドexec - Qiita

※まだ最低限動いたレベルのalpha版です。上記のうち、まともに動かないものもあるかもしれません。2014.12.29現在、普通に使えているのでbetaとしました。
普通に仕事で使ってて安定してるし、もうそろそろkithcen-dockerよりだいぶ便利になってる感あるので移ってきてもええんやで…

何故、別のgemにしたの?

そもそもの発端としては、kithcen-dockerでMaster/Slaveやクラスタ構成のテストがしたかったので、コンテナ間の接続のためのpull requestを投げたことから始まります。

しかし、待てど暮らせど作者(or Collaborator)の反応が無い…

それだけならまだしも、作者に何の配慮もせずに「こっちにフォーク作ったからおいで」とか言い出す公共の場で言い出す輩が出てきて、それらに対する他のIssueとかでの作者を置き去りにした反応等を見て、若干オワコン感を感じてしまいました(あくまで個人的見解です)

Forkしても良かったのですが、ssh使ってるとか、kitchen execのサポート入れたいとか、できれば変えたい所が色々あって、特にsshを無くそうと思ったら大部分を書き換えないといけない感じだったので、著作権云々を考えるのがめんどくさいのもあり、フルスクラッチで新しく作りました。

Forkしてもupstreamで今後の進展があまり期待できないとなると自分でメンテし続けるしか無くなるので、それなら自分で書いたコードの方が良いかなーというのもあります。
今後リリースされる見込みが無い(と思われる)ものをいちいちgithub: 'marcy-terui/kitchen-docker'とか書きつづけるのもダルイですし。

2014.12.25追記:
Forkに誘導する行為自体を否定しているわけではありません。
まずは周りの理解を得るのが先で、「お前(作者)がやらないから俺がやってやるよ」的なニュアンス(主観です)でまずForkありきで公共の場で誘導するのはどうなのってことです。

2015.01.06追記:
kithcen-dockerでもコンテナ間接続のPRがマージされ、新しいバージョンがリリースされました。
既に業務で使っているのでメンテは続けますが、同時に統合の方向も模索しようと思います。

2015.03.02追記:
結局更新遅いし、PR、Issueも放置気味なので統合は諦めました。
というか最早拙作のやつの方が使い勝手が良くなってきたので戻ることは無いでしょう。

ということで

コンテナ間を接続してテストしたい方、kitchen execを使いたい方等、お試しいただき、フィードバックやpull request等いただけましたら幸いです。

ちなみにフルスクラッチなので同じようなオプションもありますが、無いものも多いですし、オプション名も異なることがあります。
kitchen-dockerからの乗換えを検討される際にはご注意ください。

あと余談ですが、テストは一応ちゃんと書いたんですが、test-kitchen本体から提供されるメソッドが前提条件多いやら、実際にコマンド叩くとテストにならない(特にtravis-ci上)やらが多く、モックやら前提条件揃えるコードやらでとっ散らかってて困ってます。

サンタさん!どうやったらこういうのが綺麗に書けるか教えてください!w

メリークリスマス!