Furyu
[フリュー公式]

Tech Blog

フリュー株式会社の技術ブログです

2013年09月11日

kunihira

Packer+Chef-SoloでAMI作り

こんにちは。 自称Chef導入委員長の国平です。
立て続けの投稿になってしまいますが、今回はPackerの紹介記事を書かせて頂きます。

仮想マシンイメージの作成ツールであるPackerがChef-Soloからのマシンイメージ作成に対応しました。 今回は、その機能を利用して、AWSのEC2 AMIを作成してみます。

Packerとは

仮想環境のマシンイメージを作ってくれるツールです。 一つの設定を元に複数のプラットフォームに対してマシンイメージを作成出来ます。 シェルスクリプトやChef-Soloを使ってマシンイメージを構築します。

ChefやAnsibleの様なプロビジョニングフレームワークはマシン環境の構築にとどまらず、EC2の操作などかなり幅広く利用出来ます。反面、それらのツールで実行する役割を増やすほど設定が複雑化してしまいます。しかし、Packerを利用するとマシンイメージの作成をPackerにまかせることができ、ユーザはマシン設定に集中する事が出来ます。

Packerの利点

Packerを利用する事で以下のメリットを得られます。

  • インフラ構築の高速化
  • 複数プロバイダー間の連携
  • テスタビリティの確保

インフラ構築の高速化

Packerを利用する事で、そのマシンイメージの作成コストを下げることができ、マシンイメージを起動するだけで、利用可能な環境を手に入れる事が出来ます。

複数プロバイダー間の連携

PackerはAWS, VirtualBox, VMWareなど複数のプラットフォームに対応しています。Packerの設定一つで、AWSとローカルマシンの両方に同じ設定を行ったマシンイメージを作成する事が出来ます。 それぞれのプラットフォーム間の違いは、Packerが吸収してくれるので、最終的なマシンイメージを統一して用意する事が出来ます。

テスタビリティの確保

Packerを使う事で上記のように複数のプラットフォームにマシンイメージ作成できます。 そのため、一つの環境でテストを行う事で、他の環境が期待される結果になっている事を保証されます。

気に入った機能

個人的に気に入った機能が、fixコマンドです。 Packerがバージョンアップした際に、古いバージョンのJSONを新バージョンに変換してくれます。 変換結果は、標準出力に吐き出されるので、Linuxであれば以下のコマンドで、最新のJSONを取得できます。

一度書いた設定が動くことが保証される、もしくは、容易に動く状態にできるというのは、運用が長期化したり、運用するサーバ設定が複数ある場合に非常に助かると思います。

インストール

UNIX/Linuxでは、~/packerもしくは/usr/local/packerにインストールすることが推奨されています。 インストールするためには、公開されているzipファイルをhttp://www.packer.io/downloads.htmlからダウンロードし、解凍しパスを通します。

Linuxマシンに対してインストールを行うには以下のコマンドを実行します。 ご利用の環境に応じて、適宜ダウンロードURLは変更してください。

正常にインストールが完了し、パスが通っていれば、packerコマンドを実行すると以下のように、表示されます。

Macの場合は、Homebrewを使ったインストールも可能なようです。 詳しくは、公式サイトを参照してください。

とりあえず使ってみる

Packerを使って、NginxをインストールしたAWSのAMIを作成してみます。 まずは、以下のJSONを作成します。

ami-shell.json

builders には、どの様なマシンイメージを作成するかを設定します。 今回はAMIに設定するために typeamazon-ebsにし、resionなどの設定をしています。 access_key, secret_keyは、それぞれAWSアカウントで作成して入力します。

provisioners には、作成するマシンイメージに対して行う処理を設定します。 まずは、Packerの動作を確認するために、typeにshellを指定し、シェルスクリプトを実行してNginxをインストールしてみましょう。

JSONを作成したら以下のコマンドを実行します。

これでAMIの作成が開始されます。 AWSのConsoleから、EC2が起動する事が確認出来ると思います。 EC2が起動すると、provisionersで指定した通りのシェルが実行されます。 yumコマンドが実行されNginxがインストールされると、AMIの作成に入ります。 最終的にAMIが作成されると起動したEC2インスタンスはterminateされます。 ami_nameに指定したように、”Packer-“後にタイムスタンプが追加された名前のAMIが作成されます。

ProvisionarsにChef-Soloを利用する

Packerのバージョン0.3.6からProvisionersにChef-Soloを指定出来るようになりました。

Packer|ChangeLog

下準備 – 実行するChef Recipeを用意する

まずはChefRepositoryを用意します。 今回のお題もまたまたNginxをソースからインストールします。 レシピの準備を手軽に実施するために、Berkshelfを利用してChefRecipeを取得します。 Berkshelfについては、以前の記事や、以前の発表資料で紹介しています。

Berksfile

これで、site-cookbooks内にNginx Recipeと、Nginx Recipeが依存するRecipeが用意されます。 実行後はpacker-sampleフォルダ内は以下の状態になっていると思います。

Packer設定ファイルの用意

Chefリポジトリが用意出来たので、次にPackerの設定ファイルを記述します。 今回は、EC2 AMI を作成するので、以下のようなファイルを作成します。

ami-chef.json

provisioners には、Chef-Soloを利用するので、typechef-soloを指定し、cookbookのパスや、run_list、attributeを書いたJSONフィールドを設定しています。

まとめ

実は以前にPacker+Chef-Soloと同じ事をしてくれるフレームワークを自作してたりしてました。(ec2_automation)

しかし、当たり前ですがPackerの方がずっと使いやすいです。

  • 複数のプラットフォームに対応
  • Chef-Solo以外のProvisionerも利用可能

など、Packerの優位な点が非常に多くあります。 非常に素性がよく、設定も書きやすいので環境構築の自動化と高速化に取り組まれている方々にはPackerは非常にお勧め出来るツールです。

つい先日バージョン0.3.7がリリースされ、新たにPuppetをProvisionerとして利用出来るようになりました。 開発が活発でこれからどんどん便利になって行く事が期待出来ます。


2013年06月26日

kunihira

関JavaでJavaでなくChefの話をしてきました

皆さま約一ヶ月ぶりです。
国平です。

先日、関西Javaエンジニアの会でChefの話をしてきました。参加してくださった方々にちょっとでもChefに興味を持っていただけたら大成功なのですが、いかんせん限られた時間での発表なので具体的な使い方やサンプルまでは踏み込めませんでした。なので、その分をこのブログで補足したいと思います。

発表内容

私の関Javaでの発表資料はこれです。

Chefとかプロビジョニングまわり from Kiyotaka Kunihira

いろいろと書いていますが、要するに

  • プロビジョニングフレームワークの導入で色々はかどる
  • Chefは便利なツール
  • knife-soloでリモート操作が便利になる
  • Berkshelfでcookbookの依存関係も解決出来る

という内容です。

私の前回の記事のChef周りの内容に加えてknife-soloとBerkshelfの紹介を足しています。 今回の記事では特にknife-soloとBerkshelfの利用についてまとめます。

knife-solo

knife-soloはknifeのサブコマンド群です。
この、knife-soloはChef-Serverで行うようなリモートサーバに対するChefの実行をChef-soloで実現してくれるツールです。

前回のブログ記事で、Chefは各サーバに対しインストールが必要で面倒だと書きましたが、このknife-soloを利用することでChefのリモートインストールが可能になり、Chefの利用が一気にはかどります。

インストール

knife-soloはgemでも提供されており、普通にgem installもできるのですが、デフォルトのバージョンが0.2.0となっています。 https://rubygems.org/gems/knife-solo

しかし、バージョン0.3.0で追加されたオプションもあり、なるべく0.3.0の利用をお勧めします。特に、knife-soloは開発が活発なので、なるべくならgemでなくソースからのインストールをお勧めします。

gemでインストールする

gemからインストールする場合は、バージョン指定せずにインストールすると前述の通り0.2.0がインストールされます。 なるべく最新のバージョンをインストールするために、以下のようにバージョンを指定して取得するといいと思います。

最新バージョンについてはここで確認してください。

]# gem install -v 0.3.0.pre4

ソースからインストールする

knife-soloのソースはGitHubで公開されています。 https://github.com/matschaffer/knife-solo

ソースからのインストールには次の3つがインストールされている必要があります。

  • rake
  • bundler
  • git

インストールの実行手順を下記にまとめました。 注意して頂きたいのは、knife-soloのGitリポジトリはsubmoduleに別れているので、サブモジュールの更新を実行する必要がある点です。

上記手順で、knife-soloのインストールが完了します。

コマンド

knife-soloには以下の5つのコマンドがあります。

  • init
  • prepare
  • cook
  • bootstrap
  • clean

今回は、関Javaで紹介したcook、prepareに加えてinitについて紹介しますが、残りのコマンドについてもhelpで確認出来ます。

knife-solo自体のヘルプを確認したい場合はknife solo -hで、各コマンドについて確認したい場合は、knife solo -h {command}で確認出来ます。

init

initコマンドを使う事で、新しくknife-soloに最適化されたChefRepository(Kitchen)を作成する事が出来ます。

knife solo init {DIRECTORY}

prepare

prepareコマンドは、リモートマシンに対してChef-soloのインストールを行います。 また、同時に指定したリモートマシンに対してデフォルトで実行される設定を書き込むjsonファイルがnodesフォルダに作成されます。

knife solo prepare {user}@{host}

cook

cookコマンドは、リモートマシンに対してChef-soloの実行を行います。 prepareコマンドでjsonが作成されているハズですので、そのjsonのrun_listに書かれているcookbookが順に実行されます。

knife solo cook {user}@{host}

sample

knife-soloを利用するサンプルとして、gitをリモートサーバにソースからインストールしてみます。

今回は、opsocodeが公開しているcookbookをgitから取得して実行します。 なお、今回は既にローカルマシンにはgitがインストール済みの前提で進めます。 もし、まだローカルマシンにgitをインストールしていない場合は、gitをインストールする、もしくはgit cloneを行っている箇所を、zipのダウンロードに読み替えてください.

まずはリポジトリを作成しましょう。

リポジトリの作成が出来たら、リモートサーバにChefをインストールします。

次に必要なcookbooksをダウンロードします。

git cookbookが直接依存するcookbookはhttp://community.opscode.com/cookbooks/gitのCookbooksの項にまとまっていますが、最終的にgit cookbookは次の6つのcookbookに依存します。 これは、git cookbookが依存するcookbookが更に依存するcookbookを持つためです。

  • runit
  • build-essential
  • dmg
  • yum
  • chef_handler
  • windows

これらのcookbookもダウンロードします。

必要なcookbooksがそろったら、実行するrun_listを設定します。

このjsonの設定で、knife-soloを実行するとリモートサーバの/usr/local/gitにgitがソースからビルドされます。 実行するには、knife solo cookコマンドを実行します。

これで、gitのインストールが実行出来るはずです。

Berkself

先ほどのknife-soloのサンプルでは、cookbookの依存関係を手動で解決しました。 しかし、gitだけで6つものcookbookに依存しているのに、さらに他のcookbookを実行するとなると、依存関係の解決は気の遠くなる作業になります。 そんな、cookbookの依存関係を自動的に解決してくれるツールがBerkselfです。

本家サイトでは、Chefを活用するためのbundler的なツールだと説明されていますが、関Javaな人にはMavenをイメージしてもらうのがわかりやすいと思います。 前述のknife-soloを利用したサンプルとしてgitをリモートサーバにインストールしましたが、その際にgitのcookbook以外にもbuild-essentialなどのcookbookをgitから取得しました。 これは、gitのcookbookがそれらのcookbookに依存しているためです。 Chefではrecipe中にinclude_recipe "..."と記述する事で、Chefのpath中にあるcookbooksに依存した処理を記述する事が出来ます。 これにより、誰かが公開しているcookbooksを別のcookbooksから利用しやすくなっているのですが、同時に必要なcookbookの数が増えてしまい、人力での管理が難しくなってしまいます。 こういった問題については、rubyであればbundler、JavaならMaven、Scalaならsbtを利用している方々はよくわかるんじゃないかと思います。

インストール

インストールは簡単でgem経由でインストールするだけです。

]# gem install berkshelf

Berksfile

Berkshelfの設定については、基本的にはリポジトリ直下にあるBerksfileを編集します。 そんなに難しい英語を使っているわけでも無いので公式サイトを一読して頂ければだいたいどんな事が出来るのかわかると思います。

コマンド  

Berksfileの編集が完了していれば、berks installコマンドで依存関係を解決する事が出来ます。

]# berks install

ただし、これだけ実行するとberkshelfの初期設定に従って、~/.berkshelf以下に依存するcookbookがインストールされます。 シンプルにChef-soloを利用するだけであれば、ローカルマシンのChefのパスは通っているのでこれで問題ないのですが、Chef-soloを利用してリモートサーバに対してインストールを実行しようとするとこれでは問題があります。

基本的にChef-soloはリポジトリ内のファイルをrsyncでリモートサーバに対して同期するだけなので、基本的にリポジトリ外の依存ファイルを同期する事が出来ません。 そのため、リポジトリ内にcookbookをダウンロードしてくる必要があります。

指定したpathにcookbookをダウンロードするには–pathオプションを利用します。

サンプル

knife-soloのサンプルとしてgitのcookbookを利用したサンプルを挙げましたが、次は、同じgitをBerkshelfを利用して実行してみます。 knife-sloの時は依存関係のあるcookbookを自力で全て取得していましたが、今回はBerkshelfの力を存分に発揮してもらいます。

まずは、リポジトリを作成します。今回は、berkrepoというリポジトリを作成します。

リポジトリが出来たらBerksfileを編集します。knife-soloのinitコマンドを利用して、リポジトリを作成すればデフォルトでBerksfileは作成されるので、以下のように編集します。

Berksfile

nodes/{host}.json

まとめ

knife-soloとBerkshelfについて、関Javaでの発表を補足しつつ紹介してみました。 ほんとうに、この組み合わせは鼻血が出るほど素敵なので、ご興味のある方は是非お試しください。


2013年05月14日

kunihira

Chef vs Fabric 使用感比較レポート

こんにちは。国平です。

前回の記事で、最後に「viの記事を書こうか」とか書いてましたが、個人的にもっと熱いネタが見つかったので急遽ネタを変更して、ChefとFabricを比較してみます。

目的

本記事の目的は、複数のサーバマシンで全く同じ環境を用意するためのツールの検証です。

Webサービスの開発/運用では、複数のサーバを用意して冗長化を図ります。 また、AWSのようなクラウドサーバを利用していると、サービスの拡大に合せて柔軟にスケールアウトする事が可能となります。

弊社でもこちらの記事にあるように、複数台のサーバでサービスを運用し、更に負荷状況に合せてサーバのスケールアウトが出来るように環境を用意しています。

当然、サービスのリリース時には全てのサーバが同じ設定で動くように用意されていますが、運用が長く続くと各サーバ環境が同じである事を保証するのが難しくなってきます。 例えば、あるサービスの初期リリースでは2台のサーバで運用し、サービスの拡大に合せて新たにサーバを追加する際などに、インストールするツールのバージョンが微妙に異なったり、微妙にパスの通し方やファイルのユーザ権限の設定がズレていたいたりといった問題が発生しがちです。

こういった問題を回避するために、各サーバで全く同じ環境を用意できるツールが必要になります。 そのツールとしてChefとFabricを取り上げ、比較を行ってみます。

Chefとは

http://www.opscode.com/chef/

Chefとは最近話題の構成管理ツールです。 Chefを利用する事により、サーバの環境構築を自動化する事が出来ます。 Ruby製のツールで、Rubyのコードでサーバの環境設定を設定ファイルにまとめる事が出来ます。 (※ Chefではこの設定をレシピと呼びますが、今回はFabricと比較するため設定ファイルと記述します。)

設定内容をソースコードとして残す事が出来るので、何度でもサーバを同じ状態に構築する事が出来ます。 設定内容はDDLとして用意されており、読みやすいだけでなく、Rubyになじんだ人なら拡張もしやすいかもしれません。

Chefの利用方法には2通りあります。 ひとつは単一マシン上で動作するChef-Soloで、環境構築を行いたいマシン上に設定ファイルを配備しそのマシン上でChefを実行します。そのため、各マシンに対して設定ファイルを配備して、Chefを実行することになります。

もうひとつはChef-Serverを利用する方法です。この方法では、設定ファイルを配備するChef-Serverマシンと、Chefを実行して環境構築するChef-Clientマシンを分離することができます。Chef-ClientはChef-Serverから自動的に設定ファイルを取得して実行します。この方法だと、複数のマシンに対する設定ファイルを一元管理できます。さらに、Chef-Serverの設定が変更されると、Chef-Clientは自動的に同期をとるので、変更の反映を各サーバに対し実行する必要がありません。

Chef-Solo、Chef-Server/Clientのどちらを利用するにしても、各マシンに対してChefのインストールが必要になります。

また、今回の調査の範囲に含んでいませんが、自動テストを書くこともできるようです。作成した設定ファイルを保守することを考えると、テスト可能であることは非常に重要ですね。

Fabricとは

http://docs.fabfile.org/en/1.6/

Fabricはアプリケーションのデプロイツールです。 Fabricも自動でサーバを操作する事の出来るツールで、リモートサーバに対して、ファイルの転送・コマンドの実行を行う事が出来ます。

Pythonで作られており、サーバに対する操作内容をPythonで記述します。 Fabricの設定ファイルは、シェルスクリプトに似たコマンド、もしくは直接シェルスクリプトを実行するため、シェルスクリプトを書いた事がある人はなじみやすいかもしれません。

Fabricは、Fabricの実行サーバから実際に環境を構築するリモートサーバにSSH接続を行い、設定ファイルに書かれた処理を実行します。 そのため、Fabricをインストールするマシンは1台だけで済みます。

ChefとFabric

共通点

ChefとFabricでは、どちらでも「サーバに対する操作をソースコードとして記述」するので、Gitなどでバージョン管理する事が可能です。 そのため、複数のサーバを用意する際、サーバ間の微妙な誤差をなくす事が出来ます。

異なる点

前述のように、Chefは構成管理ツール、Fabricはデプロイツールとそもそも対象とする領域が異なっています。

構成管理ツールではサーバ環境の構築を目的としており、デプロイツールではサーバ上にアプリケーションの配備を行う事を目的としています。 ただし、主目的が異なっているだけで、どちらでもそれぞれが得意とする事は実現可能となっています。

また、Chefによる環境構築を行うためには対象となるサーバ全てにChefをインストールする必要がありますが、Fabricでは1台にインストールすればリモートサーバにはインストールの必要がありません。

利用してみる

今回、ChefとFabricを比較するにあたって、試しにNginxのインストール手順をそれぞれのツールで書いてみました。 Nginxインストールの要件として、以下を設定しました。

  • Nginxをソースからビルドする
  • ビルドに必要なライブラリなどもインストールする(g++など)
  • nginx.confを配備する
  • nginx.confはテンプレートを用意し、本番環境/開発環境で設定内容を書き換えられるようにする

本番環境と開発環境でサーバのマシンスペックが異なるということはよくあると思います。 nginxのチューニングでは、マシンのCPU数に合わせてworker_processを設定します。 (Nginx+Play2.0利用時のNginxとAkkaのパフォーマンスチューニング)

ここでは環境に合わせてconfファイルを書き換えて配備できるようにしてみます。 想定しているサーバのマシンスペックは、開発環境がコア数1、本番環境がコア数2を想定しています。 (AWS EC2インスタンスの、m1.smallとm1.largeインスタンスをイメージしています)

ちなみに、nginxをインストールするマシン環境は前回の記事で紹介したVagrantを使って用意しました。 やっぱりVagrantは便利ですね。

Chef

今回、Chef-Serverを用意するのが面倒だったので、Chef-Soloを利用しました。 そのため、1つのサーバですべての作業が完結しています。

設定ファイル

Chefの設定ファイル群の構成は下記の通りです。

これらのうち、主要な部分をgistに載せました。実行は、_run chef-soloのシェルになります。 https://gist.github.com/Kuchitama/5547882

Fabric

Chefは1サーバで完結しましたが、こちらは折角なのでFabricをインストールしたサーバ(サーバA)とNginxをインストールするサーバ(サーバB)を分割しました。 サーバA上でFabricのタスクを実行すれば、サーバBにNginxがインストールされます。

設定ファイル

gistはこちらです。 _run fabricのシェルで実行できます。 https://gist.github.com/Kuchitama/5548125

使った上での比較

実は、どちらのツールでもNginxのインストール設定は既に公開されているのですが、今回は比較のため自分の手を動かして設定ファイルを全て書いてみました。 公開されている設定は下記になります。

私は、RubyもPythonもなじみが無かったのですが、ドキュメントを漁りながら書いて行く事でどちらも2,3時間で作成出来ました。

Chefについて

メリット

実際に触ってみたChefのメリットは以下の点が挙げられます。

  • べき等性が保証される
  • 公開されている設定ファイル(レシピ)が豊富
  • 日本語の資料が多い

べき等性とは、何度実行しても同じ結果になるということです。 複数のマシン上でChefを実行しても同じ設定で動作させれば同じ状態になることが保障されています。

今回は、設定ファイルを自作しましたが、主だったツール、アプリケーションのインストール設定ファイルはGitHubなどで公開されていて、CloneしてChefを実行するだけで環境構築を行うことも可能です。

また、Chefはここ最近で非常に注目を浴びているツールなので日本語の情報も多くあります。

はまりポイント

触ってみてハマったポイントとして、現状のChefではRuby2系に対応していない点です。 今回、rvmを利用してRubyの最新バージョンをインストールしてから利用したのですが、エラーが発生してChefが動作しませんでした。

あと、設定の記述がRubyのDSLのため、慣れるまでは読み書きがしづらいかもしれません。

Fabricについて

メリット

  • インストールするマシンが1台で良い
  • シェルスクリプトの知識がそのまま使える

FabricはPush型の構成になっているので、リモートマシンが増えた際の対応手順が少なく済みます。

また、いくつかのコマンドはPythonの関数として用意されていますが、ほとんどシェルを書くのと同じ感覚で記述できます。 そのため、初期の学習コストはかなり少なくできると思います。 新しく設定ファイルを作成するのも、既にあるシェルスクリプトを元に設定ファイルを作成するのも、それほど難しくはないと思います。

はまりポイント

今回初めてPythonを触ったのですが、FabricのインストールについてはPythonからインストールしなくてはならず、Chefのインストール以上に手間取りました。

ただ、1台にインストールしてしまえば、リモートサーバにはインストールの必要が無いので、全体としてはそれほど手間がかかるということもないのかもしれません。

また、ツールとしてべき等性が保証されているわけではないので、設定ファイルの作成者が保証するか、Fabricの実行者が手順を守る必要があります。

今回作成した設定ファイルですと、g++が既にインストールされていた場合について考慮されていないので、g++のインストールタスクが複数回実行されると予期しない動作を起こしてしまいます。

比較表

項目 Chef Fabric
構成 Chef-Solo Fabricサーバ → リモートマシン
言語 Ruby(1.9系) Python(2.5~)
設定ファイル DSLで記述 Pythonで記述(シェルライク)
日本語ドキュメント 豊富 少ない
サンプル 豊富 少ない
サーバ追加の作業 多少多い: Chefインストールの手間がかかる 少ない:タスクの実行先を追加するだけ

まとめ

今回、ChefとFabricをそれぞれ利用して、比較してみました。 どちらも1度設定を書いたら実行するだけで、がりがりとインストールが進むのが楽しかったです。

使ってみた所感ですが、それぞれの向き不向きとして、Chefはツールなどのインストールに強く、Fabricはシェルコマンドの実行に強いという印象でした。

それぞれを試してみる前は、今後の利用をどちらか一方に絞るつもりでしたが、両方を使い分けるのもいいかもしれません。

どちらにしても、サーバに対する作業内容をソースコードとして管理できるのは非常にメリットが大きく、サーバの運用工数の削減につながると思います。