Opscodeのaws cookbookを使ってchefからEBSの操作を行う

2014.05.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。望月です。
最近はChefとPackerを使って色々な自動化に取り組んでいます。今日はOpscodeのAWS cookbookを利用してみたので、その内容をまとめてみます。

目的

起動済みのAmazon Linuxに対して、chefを適用してEBSの新規作成とmkfs、マウントを実施したいと考えました。起動する際はルートボリュームだけがアタッチされているが、cookbookを適用することにより、EBSをアタッチしてディスクが利用可能な状態に持っていこうとしました。
OpscodeのAWS cookbookではEBSやELB、EIPなどを操作するためのLWRP(LightWeight Resource and Provider)を提供しているので、cookbook内でResourceとして、EBSの操作を記述できるようになります。 *1

実行

手元の環境はMac OS X 10.9で、knife soloとBerkshelfはインストール済ということを前提とします。Chefの環境整備に関しては、次のエントリを参考にしてみてください。 AWS EC2サーバに対するknife solo実行環境構築手順 on Mac OS Xを一から整理してみる
まずはknife soloのディレクトリを作成します。

$ knife solo init chef-ebs/
WARNING: No knife configuration file found
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...
Setting up Berkshelf...
$ cd chef-ebs
$

次に、Berkshelfを使ってOpscodeのEC2 cookbookをダウンロードしてきます。

$ vi Berksfile
$ cat Berksfile
source 'https://api.berkshelf.com'

cookbook "aws"

$ berks install
Resolving cookbook dependencies...
Fetching cookbook index from https://api.berkshelf.com...
Using aws <0 class="9 0"></0>

では、新しく自前のcookbookを作成します。新規作成したcookbookからaws cookbookを利用するので、依存しているということをcookbook内のmetadata.rbに記述する必要があります。

# site-cookbooks/ 以下に、cookbookの雛形を作成
$ knife cookbook create attach-ebs -o site-cookbooks/
** Creating cookbook attach-ebs
** Creating README for cookbook: attach-ebs
** Creating CHANGELOG for cookbook: attach-ebs
** Creating metadata for cookbook: attach-ebs
$ ls site-cookbooks/
attach-ebs/

# cookbook内のmetadata.rbを編集し、一行追加
$ vi site-cookbooks/attach-ebs/metadata.rb
depends          "aws"

それでは、いよいよrecipeの記述です。site-cookbooks/attach-ebs/recipes/default.rbを編集します。

device_id = "/dev/sdf"
mount_point = "/data"

aws_ebs_volume "data volume" do
  action [:create, :attach]
  availability_zone "ap-northeast-1a"
  device device_id
  volume_type "standard"
  size 10
end

directory mount_point do
  action :create
  mode 000755
end

execute 'mkfs' do
  command "mkfs -t ext4 #{device_id}"
  # only if it's not mounted already
  not_if "grep -qs #{mount_point} /proc/mounts"
end

mount node.attach_ebs.mount_point do
  device device_id
  fstype "ext4"
  options %w(noatime defaults)
  action [:enable, :mount]
end

ポイントは4行目です。aws_ebs_volumeリソースの部分が、EBS作成に関わる部分になってきます。
リソース名についてですが、レシピに記述するリソース名の規則は[パッケージ名]_[リソース名]となるようです。今回の場合、awsクックブックのebs_volumeリソースを利用するので、aws_ebs_volumeという名前を使用します。以上、余談でした。
このレシピでは、EBSを作成した後、ファイルシステムの作成とマウントまで実行します。ただし、本番に適用するなら、mkfsの部分はもうちょっと冪等性を保証した書き方にしないといけませんね。

それでは、実際に適用してみましょう。EBSを作成するProviderは、内部的にright_awsというRuby gemを利用しています。そのgemをインストールするために、EC2 cookbookのrecipeを先に適用しましょう。

$ knife solo prepare ec2-user@ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com
$ knife solo cook ec2-user@ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com -o "recipe[aws],recipe[detach-ebs]"
<...snip...>

Starting Chef Client, version 11.12.2
[2014-05-23T08:47:41+00:00] WARN: Run List override has been provided.
[2014-05-23T08:47:41+00:00] WARN: Original Run List: []
[2014-05-23T08:47:41+00:00] WARN: Overridden Run List: [recipe[aws], recipe[attach-ebs]]
Compiling Cookbooks...
Recipe: aws::default
  * chef_gem[right_aws] action install
Converging 5 resources
  * chef_gem[right_aws] action install
Recipe: attach-ebs::default
  * aws_ebs_volume[data volume] action create
    - create a volume with id= size=10 availability_zone=ap-northeast-1a and update the node data with created volume's id

  * aws_ebs_volume[data volume] action attach
    - attach the volume with aws_id=vol-ebc363e1 id=i-c45216c2 device=/dev/sdf and update the node data with created volume's id

  * directory[/data] action create (up to date)
  * execute[mkfs] action run
    - execute mkfs -t ext4 /dev/sdf

  * mount[/data] action enable
    - remount /dev/sdf

  * mount[/data] action mount
    - mount /dev/sdf to /data


Running handlers:
Running handlers complete

Chef Client finished, 5/8 resources updated in 23.848966494 seconds

新規にEBSが作成され、マウントがされていることが確認できます。ChefからAWSのリソースが扱えると、インスタンスのセットアップが非常に簡単になりますね。

また、EBSのdetachやスナップショットの作成も、以下の様にレシピに記述することができます。感覚はEBSをcreateする時と同じですね。サンプルレシピは以下のようなものです。

aws_ebs_volume "detach_volume" do
  action :detach
  device device_id # デバイスIDを指定して、そのEBSをdetachする(事前にumountしておきましょう)
end

aws_ebs_volume "take_snapshot" do
  action :detach
  device device_id # デバイスIDを指定して、そのデバイスIDのEBSをスナップショット作成する
end

まとめ

Opscodeのaws cookbookを利用して、EBSを新規に作成する方法についてご紹介しました。aws cookbookでは、EBSの他にもEIPやELBなども操作することができるようです。これについては別のエントリでご紹介しようと思います。

参考資料

脚注

  1. LWRPについては、こちらのサイトが非常に参考になります。 : [LWRPによる]続・ChefでSourceから何かをインストールするCookbookのウォークスルー