第15回:インスタンス上のユーザデータの運用


 今回は前回に引き続き、プロジェクト管理ソフトウェアのKanonと、コラボレーションツールAsakusaSatelliteがインストールされた仮想マシンイメージを利用して、プライベートクラウドでサーバーを運用する際に重要となる「インスタンス上に存在するユーザデータの運用」について説明します。

プロジェクト管理サーバのユーザデータ

 前回の連載で用意したマシンイメージでインスタンスを起動すると、KanonとAsakusaSatelliteがすぐ利用できますが、S3イメージによるインスタンスであるために、インスタンスを停止すると折角のユーザデータも消えてしまいます。

 例えば、前回作成したインスタンスのPublicIPが192.0.2.100でプロジェクト名が「cloudon」の場合、http://192.0.2.100/trac/cloudonでプロジェクト管理(Tracのページが表示されますので、試しに新しいチケットを登録してみます。登録後、チケットはチケット一覧に表示され、正しく登録されていることが確認できます。

チケットの登録

 

登録されたチケットの一覧

 

 ここで、インスタンスを停止し再度マシンイメージからインスタンスを起動してみます。
以下のように、起動しているインスタンスをeuca-terminate-instancesで停止し、euca-run-instancesで再び起動します。

# 起動しているインスタンスを停止
euca-terminate-instances インスタンスID

# 再度インスタンスを起動
euca-run-instances -k キーペア イメージID

 

 インスタンスが起動するのを待ち(PublicIPが前回起動インスタンスと同じか、ElasticIP機能によって同じPublicIPを割り当てていることを前提とする)、http://192.0.2.100/trac/cloudon にアクセスしてみると、先ほど登録したチケットどころか「cloudon」という名前のプロジェクト自体が存在していないため、以下のようにエラーが返ります。

エラー画面

 EucalyptusではAmazon EC2のS3イメージと同様に、インスタンスを停止するとインスタンスが保持していたデータも消失します。これでは一度起動したインスタンスを停止することができず、Eucalyptus上でプロジェクト管理サーバのようなサーバを運用およびサービス提供するのが厳しいことになります。

 インスタンス上にあるユーザデータを永続化するためには、インスタンスを停止する前にeuca-bundle-volコマンドを使用して、新しいイメージとして起動中のインスタンスを保存する方法がありますが、インスタンスが突然停止してしまった場合は最後に保存した以降の変更が保存されていません。

 そのため、ユーザデータのような動的に変更が加わるデータを永続化するためにはEBSボリュームを利用します。

 

EBSボリュームによるユーザデータの永続化

 EBSボリュームは簡単に言うとUSBハードディスクやUSBメモリのようなもので、インスタンスの起動停止にかかわらずデータが永続化される外部記憶装置です。

 KanonやAsakusaSatelliteのプログラムは仮想マシンイメージに保存し、登録されたチケットやチャットのログなどはインスタンスに取り付けたEBSボリュームに保存するようにします。

EBSボリュームを利用したデータの分離

 まずは新しいEBSボリュームを作成し、インスタンスに取り付けます。EBSボリュームのサイズは5G、取り付け先はsdbとしておきます。

# EBSボリュームを作成
euca-create-volume -s 5 -z ゾーン名

# 上記で作成したEBSボリュームをインスタンスに取り付け
euca-attach-volume -i インスタンスID -d /dev/sdb ボリュームID

 

 続いてインスタンスにログインし、取り付けたEBSボリュームにパーティションを作成し、ext3でフォーマットします。

# パーテーションの作成
echo -e ",\n;\n;\n;\n" | sfdisk /dev/sdb
# 作成したパーテーションのフォーマット
mkfs.ext3 /dev/sdb1

 

 取り付けたボリュームに既存のデータを移行します。本連載で使用する仮想マシンイメージでは、Kanonのデータは/var/opt/配下に保存するようになっています(AsakusaSatelliteはプログラムとデータどちらも/var/opt/配下に格納)。ここでは一旦/ebs/vol00にボリュームをマウントし、Apacheを停止後rsyncを使用してデータを移行します。

# ボリュームをマウントする
mkdir -p /mnt/ebs/vol00
mount /dev/sdb1 /mnt/ebs/vol00/

# Apacheを停止する
/etc/init.d/httpd start

# データをコピーする
rsync -XPSHav /var/opt/* /mnt/ebs/vol00/
rsync -XPSHav /etc/opt/kanon /mnt/ebs/vol00/kanon/etc

 

 最後に取り付けたボリュームを以下のようにマウントすることで、KanonとAsakusaSatteliteのデータがボリュームに書き込まれるようになります。

# ボリュームをマウントする
mount -o bind /mnt/ebs/vol00/kanon /var/opt/kanon
mount -o bind /mnt/ebs/vol00/kanon/etc/kanon /etc/opt/kanon
mount -o bind /mnt/ebs/vol00/AsakusaSatellite /var/opt/AsakusaSatellite

# apacheを起動する
/etc/init.d/httpd start

 

 このように、永続化する情報をEBSボリュームに書き込むことで、インスタンスを停止してもデータを残すことができます。

 試しに、新しいKanonのプロジェクトを作成しチケットを登録します。その後、インスタンスの停止と起動をし同じボリュームを取り付けてチケット一覧を表示すると、登録したチケットが残っていることを確認できます。

チケットの一覧

 

EBSボリューム取り付けの自動化

 上記の方法によってユーザデータを永続化することは出来ましたが、このままではインスタンスを起動するたびにボリュームの取り付けとマウントが必要になります。
このような定型的な処理は、インスタンスがEucalyptusから取得できるUserDataやMetaDataを利用することで、自動化できます。

 今回はインスタンスを起動する際にEBSボリュームのIDと取り付けに必要な情報をUserDataとしてインスタンスに渡し、MetaDataを利用してインスタンスがEBSボリュームを取り付ける仕組みを作成します。

ボリューム取り付け自動化

 まずは、UserDataの情報を作成します。euca2oolsではユーザデータとしてファイルを指定することができます。今回はサーバ側の受け取り処理を簡単にするため、下記のようにbashスクリプトのファイルを作成します。

#!/bin/bash

# 前述で作成したボリュームIDを設定
export VOLUME_ID="ボリュームID"
export ATTACH_DEVICE="/dev/sdb"
export MOUNT_PARTITION="/dev/sdb1"
export MOUNT_POINT="/mnt/ebs/vol00"

# eucarcに記述されている値で以下を設定
export EC2_URL=http://CLCのIP:8773/services/Eucalyptus
export EC2_ACCESS_KEY='アクセスキー'
export EC2_SECRET_KEY='シークレットキー'

 

` 続いて、仮想マシンイメージにスクリプトを仕込みます。最初にUserDataを使用してボリュームを取り付けるスクリプトを作成します。スクリプトは下記の内容を実行します。

  ・MetaDataから自身のインスタンスIDを取得する
  ・UserDataを取得する
  ・UserDataとして受けとった内容をevalしパラメータを設定する
  ・必要なパラメータのバリデーション
  ・euca-attach-volumeコマンドを使用して自身にボリュームをアタッチする
  ・ボリュームがアタッチされて/dev/sdbが認識されるのを待つ
  ・ボリュームをマウントする
  ・Apacheを再起動する

 以下のスクリプトを/usr/local/sbin/set-ebs.shとして作成します。

#!/bin/bash
CURL=`which curl`
USER_DATA_URL="http://169.254.169.254/latest/user-data"
META_DATA_URL="http://169.254.169.254/latest/meta-data"

# インスタンスIDを取得する
cmd="${CURL} ${META_DATA_URL}/instance-id"
INSTANCE_ID=`${cmd}`
# ユーザデータを取得する
cmd="${CURL} ${USER_DATA_URL}"
USER_DATA=`${cmd}`
eval "${USER_DATA}"

# ユーザデータに必要なパラメータが設定されているか確認する
EC2_URL=${EC2_URL:?EC2_URL is not set}
EC2_ACCESS_KEY=${EC2_ACCESS_KEY:?EC2_ACCESS_KEY is not set}
EC2_SECRET_KEY=${EC2_SECRET_KEY:?EC2_SECRET_KEY is not set}
VOLUME_ID=${VOLUME_ID:?VOLUME_ID is not set}
ATTACH_DEVICE=${ATTACH_DEVICE:?ATTACH_DEVICE is not set}
MOUNT_PARTITION=${MOUNT_PARTITION:?MOUNT_PARTITION is not set}
MOUNT_POINT=${MOUNT_POINT:?MOUNT_POINT is not set}

# ボリュームをアタッチする
cmd="/usr/bin/euca-attach-volume -i ${INSTANCE_ID} -d ${ATTACH_DEVICE} ${VOLUME_ID}"
echo ${cmd}
`$cmd`

# アタッチしたボリュームが実際にデバイスとして認識されるのを待つ.
ls ${MOUNT_PARTITION}
while [ $? != 0 ]
do
    sleep 1
    ls ${MOUNT_PARTITION}
done

# ボリュームをマウントする
mkdir -p ${MOUNT_POINT}
cmd="mount ${MOUNT_PARTITION} ${MOUNT_POINT}"
echo ${cmd}
`$cmd`
cmd="mount -o bind ${MOUNT_POINT}/kanon /var/opt/kanon"
echo ${cmd}
`$cmd`
cmd="mount -o bind ${MOUNT_POINT}/kanon/etc/kanon /etc/opt/kanon"
echo ${cmd}
`$cmd`
cmd="mount -o bind ${MOUNT_POINT}/AsakusaSatellite /var/opt/AsakusaSatellite
echo ${cmd}
`$cmd`

# Apacheを再起動する.
/etc/init.d/httpd restart

 

 次に、作成したスクリプトを/etc/rc.localに設定し、インスタンス起動時に自動的に実行されるようにします。

# スクリプトの実行権限を追加する
chmod u+x /usr/local/sbin/set-ebs.sh

# 以下を実行し、/etc/rc.local に追記する
echo "/usr/local/sbin/set-ebs.sh" >> /etc/rc.local

 

 これによって、インスタンス起動時にUserDataを指定することで、起動したインスタンスが自動的にEBSボリュームを利用できる状態になります。

euca-run-instances -f UserDataを記述したファイル -k キーペア イメージID

# インスタンス起動後、runningになってしばらくするとボリュームがin-useになる
euca-describe-volumes

 

インスタンスの活性アップデート

 インスタンス起動時に自動的にEBSボリュームを取り付け、インスタンス停止後もデータが保持されるようにするという方法はユーザデータの永続化という側面だけではなく、インスタンスのIPを動的に取り付けるElasticIPの仕組みを活用することで、サービスを停止することなくインスタンスのアップデートを行うことができます。

  1. 新しくインスタンスを起動
  2. ソフトウェアのアップデート
  3. ボリュームからスナップショットを作成
  4. スナップショットからボリュームの作成
  5. 新しいインスタンスへボリュームの取り付け
  6. PublicIPの張り替え

活性アップデートの手順

 具体的にKanonを利用した際の活性アップデートの手順を見てみましょう。まず、プロジェクト管理サーバとして利用していたイメージから新しくインスタンスを起動します。

euca-run-instances -k キーペア イメージID

 

 インスタンス起動後、新しいインスタンスにログインしソフトウェアの更新を行い、ユーザデータを移行するために稼働中のプロジェクト管理サーバに取り付けているボリュームのスナップショットを取ります。

euca-create-snapshot ボリュームID

 

 スナップショットの作成が完了したら、スナップショットから新しいボリュームを作成します。

euca-create-volume -z ゾーン名 --snapshot スナップショットID

 

 作成したボリュームを新しいインスタンスに取り付けます

euca-attach-volume -i インスタンスID -d デバイス名 ボリュームID

 

 最後に、稼働中の古いシステムから新しいシステムにアクセスできるように既存インスタンスのPublicIPを新規インスタンスへ取り付けます。

euca-associate-address -i インスタンスID PublicIP

 

 これで、稼働中のシステムを停止することなく新しいバージョンへの移行が完了しました。ただしこの手法の場合、ボリュームの作成からPublicIPの張り替えまでに発生したトランザクションが消失してしまいます。

 

バックアップ

 ボリュームはいつでもスナップショットを作成することができます。これによりボリュームに保存されているユーザ情報は好きなタイミングでバックアップすることができます。スナップショットの作成はeuca2oolsやAPIを使って作成することができるため、バックアップの自動化も簡単に行うことができます。

 また、Eucalyptusでは仮想マシンイメージも、ボリュームもスナップショットもただのファイルとして管理しています。このためAmandaなどの既存のバックアップツールと組み合わせることでEucalyptus上で管理している情報もバックアップすることができます。

Eucalyptusのバックアップ構成

 

Eucalyptusとデータの配置

 Eucalyptus上で動作するアプリケーションを開発・構築する際は、「どのデータは消えてもよい」「どのデータは消えてはいけない」を明確に定義したうえで開発・構築することをお勧めします。

 たとえば、インスタンス上にインストールしたプログラムのバイナリデータは、インストールした後はバージョン更新の際にしか更新されることがないデータです。このようなデータは、インスタンスのルートデバイスに配置します。そして、データベースの管理ファイルなどは頻繁に更新されるため、EBSボリュームに配置します。

 このように、データの配置を適切に行うことによってディスク領域の効率的な利用とデータを保持したまま、インスタンスの停止など安全な運用を行うことができます。

 次回はEucalyptus上でのオートスケーリングの実現方法について説明します。

 


羽深 修
Eucalyptus歴はまだ1年ですが、周囲からはEucalyptus中毒と勘違いされているようです。Japan Eucalyptus User Groupの活動に参加し、オープンソースカンファレンスでネタなどを披露しています。度々Eucalyptusへのパッチも書いてます。ちなみに仕事ではCentOS + Xenという環境でEucalyptusを利用していますが、自宅のEucalyptus環境はGentoo Linux + KVMで動かしています。

志田 隆弘
主にEucalyptusやクラウドとはあまり関係のない分野でちょこちょこと活動していました。Eucalyptusはバージョン 1.3の頃からいじり始め、かれこれ2年近くEucalyptusに浸かった生活をしています。Eucalyptus 1.4が出たタイミングで、Tanacasinoという名前のGUIクライアントを作ったりしていました。最新のEucalyptusで動作するので、ぜひ使ってみてください。

田中 智文
志田さんとともに初期の頃からEucalyptusの調査・検証・使用してきました。志田さんの作成したTanacasinoのメンテナンスと機能拡張を行っています。新婚ほやほやなので家でのハック活動時間が少ないですが、Walrus Clientを作ってみたりbotoを使ってEucalyptusを操作して遊んでいます。

 

関連情報
(羽深 修/志田 隆弘/田中 智文)
2011/4/15 08:00