kitchen-dockerでEC2の料金をかけず、高速にAmazon LinuxでのCookbookのテストを行う方法

2014.04.28 追記:

ライセンスについてのご質問をいただいたので追記しました。

 

最近、Kitchen-dockerでCookbookのテストを流すようになり、

捗ってはいたのですが、

仕事ではCentOSとAmazon Linuxの両方を使うことがあり、

お互いRHEL互換で大体同じで通るとはいえ、

ちゃんと両方でテストしないといけないよな〜と思っていました。

でも、Amazon Linuxを使おうと思うと、

kitchen-ec2とかvagrant-awsとかで立ち上げる感じになって、

やっぱり仮想マシンの立ち上げが遅いんですよね。

あと、課金を気にしなきゃいけないのが一番やりにくい。

 

とりあえず、今やってるCookbookの充実&リファクタリングは早く終わらせたかったので、

CentOSだけで作って後で考えようかと思っていたのですが、

ちょっと良い方法を思いついたので試してみました。

 

 

その内容は、

「Amazon LinuxのDocker Imageって作れたらkitchen-dockerで使えたりしないのかな?」

 

って感じです。で、調べてみたら、

Amazon LinuxのDocker Imageを作った例

※「Amazon Linux Docker Image」のセクション

があったので、いけそうな気がしてやってみました。

 

以下、手順です。

※「marcy/amzn」の所は 各々のリポジトリ名に置き換えてください。

 

①まず、上記リンクの通りにDocker Imageを作成します。

 

②kitchen-dockerの実行に必要な変更を施します。

# docker run -t -i local/amzn /bin/bash
bash-4.1# rm -f /etc/ssh/ssh_host_*
bash-4.1# sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config

Docker Registoryへpushします。

# docker ps -a
 # docker commit ${CONTAINER ID} marcy/amzn
 # docker push marcy/amzn

※${CONTAINER ID}にはdocker ps -aで確認したCONTAINER IDが入ります。

④Tagを切ります(これは無くてもいけるけど)

# docker images
 # docker tag ${IMAGE ID} marcy/amzn:2014.03.1
 # docker push marcy/amzn

※${IMAGE ID}にはdocker imagesで確認したIMAGE IDが入ります。

 

実際には②で施した変更は実行してみて動かなくて直しました。

変更して再度pushするのは以下のような感じです。

# docker run -t -i marcy/amzn /bin/bash
 bash-4.1# 変更実施
 # docker commit ${CONTAINER ID} marcy/amzn
 # docker tag ${IMAGE ID} marcy/amzn:2014.03.1
 # docker push marcy/amzn

リポジトリ上だけ更新しても、

一度取得してしまったkithcen-docker実行側には反映されないので更新します。

# docker pull marcy/amzn:2014.03.1

 

こんな感じでできあがったDocker Imageを、

以下のような.kitchen.ymlで指定してやるとAmazon Linux のテストができます。

CentOSとかだとnameに「centos-6.4」と書くだけで良い感じにしてくれるのですが、

「marcy/amzn-2014.03.1」とかにしてしまうと、

nameから自動生成したファイルを使うような処理で、

スラッシュがディレクトリとして扱われて

「Not such file or directory」で落ちるので注意です。

 

これで、EC2の課金を気にせず、

かつ高速にAmazon Linuxでtest-kitchenのテストが回せます。

 

また、今回作成したDocker ImageはPublicにしてあるので、

使っていただいても構いません。

 

 

あれ?

ていうか、自分の所ではEC2上でやったのですが、

もしかしてコレって…

厳密に同じでは無いものの、

Amazon LinuxがAWS以外でも手軽に動かせるようになったってことでは???

 

2014.04.28 追記:

「ライセンスって大丈夫なの?」とご質問をいただきました。

調べた限りではライセンスについての記述は見当たらず、

AMIの公開が万人に許されていることから、

AWS EC2上かつ個人での利用については問題無い or グレーゾーンであると個人的には解釈していますが、

実施の際は自己責任でお願い致します。

また、よくあるご質問に以下の記載があるので、

Q: Amazon Linux AMI は EC2 以外でサポートされますか?

いいえ。Amazon Linux AMI は、Amazon EC2 内のみで使用可能です。

AWS EC2以外での動作は現状辞めておいた方が良さそうです。

 

 

 

全然別件ですが、もしChefネタなので一応宣伝。

札幌に在住の方がもし居ましたら、

こんなんやりますので、ご興味あればどうぞ。

Chef Meetup Sapporo

 

 


Test-Kitchen周りの依存関係でつらみを味わったので書いておく

 

そういえば先週、第2子(女の子)が生まれました。

長男に似過ぎでビビりましたw

でも、やっぱりちょっと女の子っぽい感じで可愛いです。

 

最近、test-kitchen周りのgemの依存関係がメチャクチャになっている気がします…

単純に自分のRuby力が足りなすぎるだけかもですがw

 

第2子の出産で長男と1週間家でお留守番してて全くPCに触らず、

その前も別件とかやってて2〜3週間触っていなかっただけなのですが、

新しいCookbookでテスト流そうとしたらいくつも穴にハマりましたw

 

色々這いずり回って調べて、URL等を控えていませんでしたが、

覚えている範囲で以下のような穴にハマりました。

  • Nokogiriがlibxml2(?)をビルドしようとして落ちる(1.6.?)

  • kitchen-dockerがBerkshelf3.0未対応

  • psychが使っているlibymlに深刻な脆弱性が見つかり、WARNING吐いてCIが落ちる

他にももう一個くらいあった気がしますが忘れましたw

 

そして、それらを解消した、

kitchen-dockerを正常に動かせる(はず)なGemfileを公開しておきます。

※2014.04.16現在のものです

 

全然別件ですが、もしChefネタなので一応宣伝。

札幌に在住の方がもし居ましたら、

こんなんやりますので、ご興味あればどうぞ。

Chef Meetup Sapporo

 

 


CookbookのCIはkitchen-docker on SSDインスタンスRAID0で高速化(2014.04.17追記:しないかも…)

 

ChefのCookbookの開発保守効率向上のために、

Jenkinsによる自動テスト・CIを最近始めましたが、

色々やりながらちょっとずつ試して、

やっと「コレだ!」と思える構成とフローができました。

その全体像は別で述べたいと思いますが、

その中でやっている、テスト実行の高速化が上手くいったのでその話を。

 

Cookbookの開発で一番ネックになるのはやはりテストで、

  • テスト環境の立ち上げ
  • Cookbook適用
  • テスト実行

で、一回の実行にけっこう時間がかかる訳です。

 

git pushをJenkinsでフックして自動実行→終わったら通知

となって待たなくて良くなったとはいえ、できる限り早く結果は知りたい。

 

まず、Virtualbox仮想環境→コンテナ環境でテスト環境の立ち上げを高速化。

そもそも僕の場合はCI環境はEC2仮想サーバなので、

Virtualboxは使えないのですが、

LXCではなく、一応Macでも同じ方法でテストできるDockerを選択しました。

 

その上で、Dockerのコンテナ配置場所を

SSDインスタンスのエフェメラルディスクをRAID0で組んでマウントすることで、

さらに高速化することができました。

 

Dockerやtest-kitchen,kitchen-dockerのインストール方法及びAWSの操作は本筋とそれるので割愛します。

2014.04.17 /var/lib/docker/containers→/var/lib/dockerに修正しました。

/var/lib/docker/containersだと、

起動時にEBS領域から切り取られてコンテナ用のファイルシステムが作られてしまいます。

RAID組んでDockerのコンテナ配置場所にマウントするのはこんな感じです↓

# mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=2 /dev/xvdb /dev/xvdc
# mkfs.ext4 /dev/md0
# mount /dev/md0 /var/lib/docker

※インスタンスタイプがc3.lergeの例なので、エフェメラルディスクは2つ
※HVM AMIを選択すること
※エフェメラルディスクは起動時に割り当てが必要

 

エフェメラルディスクのRAID設定はよく使いそうなので、

「それこそChefの出番だろ」と思ってコチラも作ってはみたのですが、

Stop→StartでRAIDの設定消えたり、

RebootではRAIDの設定は残るけど、RAIDデバイスの名前が変わったりで、

上手くいかない場合があって試行錯誤中です…

とりあえず試作品です。上手くいったらLWRPで手軽に使える感じにしたいです。

 

これをやることで、以下のような結果が得られました。

測定に使用したCookbookはコチラです。

 

EBS

Chef Client finished, 52/60 resources updated in 292.319082057 seconds
Kitchen is finished. (5m44.96s)

Ephemeral disk RAID0

Chef Client finished, 52/60 resources updated in 220.907645243 seconds
Kitchen is finished. (4m37.20s)

iMac(2011 mid)で10分以上、さくらVPS2GBプラン(個人ではAWSまだ高いw)で、

8分ほどかかる特別時間のかかるCookbook(wなので、

かなり良い結果と言えるのではないでしょうか:-)

 

2014.04.17 追記:

上述したように、/var/lib/docker/containersだと、

起動時にEBS領域から切り取られてコンテナ用のファイルシステムが作られてしまっていることが発覚しましたが、

変更してEphemeral disk上になるようにしても優位な結果が得られませんでした。

上の比較で優位な結果が出たのは、起動直後のEBSは性能が悪い聞いたことがあるので、

そういう類で差がついたものと思われます。

 

 

全然別件ですが、もしChefネタなので一応宣伝。

札幌に在住の方がもし居ましたら、

こんなんやりますので、ご興味あればどうぞ。

Chef Meetup Sapporo