Furyu

[フリュー公式] Tech Blog

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

2016年09月27日

LambdaでCDNのキャッシュコントロールを最適化し、AWSと仲良くする。

AWSにはS3やCloudFrontという良いものがあり、サーバーを持たぬ者でも静的コンテンツを大規模に効率良く配信する事が可能です。
S3は大容量のコンテンツサーバー、CloudFrontは多拠点型のキャッシュサーバーで、共にAWSのサービスです。
一昔前はこのような事ができるのは一部の人間に限られており、良い世の中になったなあと思います。

S3とCloudFrontで静的コンテンツを扱うと、コンテンツ更新時のキャッシュコントロールに難しさがあります。
「新しくファイルアップロードしたのに、なんでヒョージ変わらへんねん」というアレです。
CloudFrontのキャシュの生存期間はコントロール可能で、TTLの設定を変えてみたり、AWSのコンソールでキャッシュの削除(invalidation)したり。
色々方法はありますが「コンテンツが更新されたら、キャッシュも更新される」をLambdaで自動化できるっぽいのでやってみました。

Lambdaとは

Lambda(ラムダ)を使うと、AWSで起こる色々なイベントを起点にプログラマが書いたプログラムを実行する事ができます。
プログラム実行に使うコンピュータをプログラマが意識する必要は無く、むきだしのサーバーはAWSに隠蔽されている事から「サーバレス○○」だ!と呼ぶ人もいます。
Lambdaはトリガー的に使えるので、invalidateを自動化するプログラムを書けばなんとかなりそうです。

 

 

ロールの作成

Lambdaの実行とCloudFrontの操作が必要になるので、これが可能なロールをIAM(権限コントロール)から作成しておきます。

Lambdaの実行権限から

cf5

ラムダ基本実行権とCFへのフルアクセスを選択します。

cf8
こんなかんじのロールができればオッケーです。

cf10b

LambdaFuntionの設定

AWSコンソールからLambdaFunctionの作成へと進みます。
BluePrint(一般的な利用用途のテンプレ)を使わずに「Configure triggers」に進みます。

cf1
AWSのどのサービスでどのような状態変化が起こった場合にトリガーを発動するのか、を設定します。
ここではS3を選択します。

cf1-5
「furyu-sandbox」というS3バケットに「拡張子がjpgのファイルが作られた(Object Created(All))」場合の設定はこんなかんじです。

cf2
いよいよラムダ関数の登録です。

実行環境はPython2.7を選択します。
コードは下記をそのままコピペして、XXXXXXXXXXの箇所をCFのディストリビューションIDに書き換えます。

 

print()された文字列は、CloudWatchでログとして出力されます。(後述)

先ほど作成したロールを選択します。
こんなかんじになります。

cf11
作成したLambdaFunctionの実行とモニタリング

ファイルS3バケットにアップロードし、反応を観察してみます。
S3へのファイルのアップロード後、作成したFunctionを選択して「Monitoring」タブを選択します。
LambdaFunctionの実行状況が確認できます。

cf12
「View Logs in Cloud Watch」で、詳細なログを確認できます。

cf13

printの内容やエラーもここに出力されます。

cf14

 

CloudFrontの対象ディストリビューションのInvalidationsタブにInProgressが見えます。

cf15

キャッシュ削除が起動された事が確認できます。

 

「雲の上のクラウドに向かってラムダ式を唱えると全ては計算された。サーバーから開放された人々は最も人らしくなった」
ミステリアスなイメージを持つラムダですが、利用用途は無限、うまく使うとAWSと仲良くする事ができます。
日宇


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月14日

受験者が語るAWS認定プログラム – JAWS-UG 京都 #4 –

みなさん、こんにちは!フリューでモバイルサイト開発を行っている鷲見といいます。

去る6月12日、弊社の会議室におきまして『JAWS−UG Kyoto 勉強会 第四回』を開催いたしました。 そこで僭越ながら私もAWS認定プログラムについてお話させていただきました。

AWS認定プログラムについては公式ページをご参照ください。

発表資料はSlideShareにあげておりますので、よろしければ御覧ください。

受験者が語るAWS認定プログラム -JAWS-UG 京都勉強会 #4- from Hiroshi Sumi

  当日の様子については発表者のcloudpack吉田さんがブログにまとめられています。

当日のその他の発表資料については近日中にこちらのページにまとめられると思います。

先日のAWS Summit Tokyo 2013でも感じましたが、AWSがエンタープライズ領域に受け入れられはじめ、非常に盛り上がっている感じがします。その盛り上がりに引っ張られてか昨日のJAWS-UG京都勉強会も大変盛り上がりました。弊社では今後もAWSをウォッチし、当技術ブログにて情報を提供していきたいと思います。


2012年09月27日

EBSブートのAMIのEBS容量変更時の注意点

みなさん、こんにちは!フリューでモバイルサイト開発を行っているAWS大好きっ子の鷲見といいます。

今回はAWSのTIPSを1つ。

今年の7月後半にAWSのManagementConsoleでEBSブートのAMIのEBS容量を指定して起動することが出来るようになりました。

今まではManagementConsoleからはAMIごとに異なるデフォルトの容量でしか起動できず、EBS容量を変更するにはAPIを操作して起動する必要がありました。

これはかなり便利になったと思うのですが、一つだけ落とし穴があります。

起動した直後はEBSの容量の変更が認識されていないため、AMI毎に指定されている容量しか認識できていません。実際にdfコマンドを使って確認すると下のようになります。

上の画像の通り、20GiBを指定して作成したのですが、このAMIで元々指定されている8GiBしか認識されていません。

というわけでresize2fsコマンドを実行して、サイズの変更を認識させます。

上の例のAmazon Linuxの場合は以下のとおりとなります。

resize2fsコマンドの実行完了後に再び容量を確認してみます。

無事、容量が20GiBと正しく認識されました。

というわけでEBSブートのAMIのEBS容量変更時はresize2fsを忘れずに!

ちなみに実行中は少し負荷がかかる上、容量が大きくなると実行完了まで時間もかかるので、既に利用中のEC2インスタンスでは、タイミングを考慮して実行するようにしてください。

以上、AWS TIPSでした。


2012年09月4日

Amazon Glacierを使ってみた

みなさん、こんにちは!フリューでモバイルサイト開発を行っている鷲見といいます。今日はAWSの新しいサービスAmazon Glacierについて実際に触れて検証してみたのでその報告をしてみたいと思います。


Amazon Glacierとは

Amazon Glacier(以下、Glacier)とは2012年8月21日にAWSが発表した低コストなストレージサービスです。低コストと言われている通りなんと1GBあたり月額約1円($0.012/GB)で利用することができます。今まで安いと思っていたS3が1GBあたり約10円(最初の1TBまで$0.13/GB)なのでなんと、S3の10分の1程度のお値段で利用できます。まさに価格破壊のストレージサービスです。

ちなみに上記以外にはファイルのアップロード、ダウンロード、アーカイブデータの一覧取得のリクエストの回数に応じてお金がかかるのと、転送量に応じてお金がかかります。

ちなみに読み方は『グレイシャー』だそうです。


S3との違い

S3の約10分の1のお値段で利用できるならGlacierを使えばいいじゃんと思ってしまいそうです。S3とGlacierはどう違うのでしょうか?

GlacierのS3との違い

GlacierがS3と比べて違う点は

  1. ファイルのダウンロードを開始できるようになるまで時間がかかる
  2. 好きなファイル名をつけることはできずArchiveIdで管理される

の2点です。

特に1つ目の点がS3と違う大きな特徴です。

Glacierでは、ファイルの取得のためにジョブと呼ばれるものを開始します。ジョブはキューに保存され順番に処理が行われます。ジョブがキューから取り出され実行されて完了すると、ファイルがダウンロード出来るようになります。このファイルがダウンロードが出来るようになるまでの時間が4,5時間と言われています。

2つ目の特徴ですが、ファイルのアップロード時にArchiveIdと呼ばれるIDが付与されます。アップロード完了後、ファイルの取得・消去の際にはこのArchiveIdを指定する必要があります。よってこのArchiveIdがどのようなファイルと紐付けられているかを管理する必要がでてきます。

S3との使い分け

上記のようなGlacierの特徴を考えると、Glacierには頻繁に出し入れが発生するファイル、すぐにダウンロードできないと困るようなファイルはGlacierでの保存に向いていません。このようなデータは今までどおりS3に保存するべきでしょう。

逆に一度保存すると出し入れがほとんど発生しない、ダウンロードするのに時間がかかってもよいようなデータはGlacierでの保存に向いています。各種データのバックアップ・アーカイブなどのコールドデータの保存にはGlacierが向いています。

Glacierという名前は英語で「氷河」なので、そもそもコールドデータを保存するのに適したストレージであるということがネーミングにも込められているようです。


Glacierの使い方

Glacierの基本的な使い方は以下の様な感じになります。

1.Vaultの作成

Glacierを使うにはまずはVaultを作成する必要があります。Vaultは貯蔵庫を意味する英語で、S3でいうところのBucketに近い感じでしょうか。Vaultには任意の名前をつけることができるので、用途に応じたわかりやすい名前をつけるのが良いでしょう。

2.ファイルのアップロード

1で作成したVaultにファイルをアップロードします。GlacierではデータはすべてArchiveという名前で扱われ、アップロードされたファイルも以降はArchiveと呼ばれます。Archiveにはそれぞれに一意となるArchiveIdが割り当てられ、アップロード後はArchiveIdでデータを識別します。ファイルのアップロード時にArchiveIdが割り振られますので、ArchiveIdとファイルの紐付けを利用者側で行なっておく必要があります。

3.Archiveのダウンロード

2でアップロードされたArchiveをダウンロードします。ArchiveをダウンロードするにはまずはGlacierに対しデータの取得リクエストを送信し、ジョブを開始します。データ取得のためのジョブが完了するとジョブの結果をダウンロードできるようになります。このリクエストの送信から、ジョブの完了までおよそ4,5時間かかります。


サンプルプログラム

現在、Vaultの作成はManagementConsoleから行うことができますが、Archiveの操作やVault内のアーカイブ一覧の取得などはManagementConsoleでは行うことができません。このような操作はAPIから行う必要があります。今回はAWS SDK for Javaを使ってGlacierの基本的な操作を行なってみます。

※AWS SDK for Javaのバージョンが1.3.18より前だとGlacierに関するバグがあるようです。1.3.18以降のバージョンを利用するようにしてください。

Vaultの作成

まずはプロキシを使っている場合などはプロキシの設定を行います。

次にGlacierを操作するためのクライアントを生成します。クライアント生成後エンドポイントを指定し、リージョンを設定します。

エンドポイントはこちらに整理されています。

AwsCredentials.propertiesにはアカウントのアクセスキーとシークレートキーを記入しておきます。 書き方はこちらを参照してください。

Glacierのクライアントが生成できたので、Vaultの作成リクエストを生成し、クライアントから送信します。

これでVaultの生成は完了です。

次にVaultにたいしてArchive取得・Archive一覧取得のジョブが完了したときにSNSで通知を行うよう設定を行います。

ここでは予めSNSのTOPICを予め生成し、ARNを控えておきます。

withEventsに渡しているのは通知を行うイベントの種類で“ArchiveRetrievalCompleted”を指定するとArchive取得ジョブ完了時に、“InventoryRetrievalCompleted”を指定するとArchive一覧取得ジョブ完了時に通知が行われます。

これでSNSの設定も完了です。これでこのVaultに対するジョブ完了時に通知が行われます。

ファイルのアップロード

ファイルのアップロードにはArchiveTransferManagerを利用します。GlacierクライアントとCrendentialを渡してArchiveTransferManagerを生成し、uploadメソッドでファイルをアップロードします。

uploadメソッドに渡している引数はVault名、Archiveの説明文,アップロード対象ファイルとなります。

これでファイルのアップロードは完了です。uploadメソッドの返り値として渡されるUploadResultにはアップロードしたファイルのArchiveIdが含まれています。アップロードしたファイルは今後ArchiveIdを指定して取得することになるので、ArchiveIdを必ず控えておくようにしましょう。

ちなみに200MBのファイルのアップロードにかかった時間は10回の平均で50.038秒でした。

Vault内のArchive一覧取得

現在Vaultの中に保存されているArchiveの一覧を取得します。こちらはArchive一覧取得ジョブを開始し、ジョブが完了後に、ジョブの結果をダウンロードするという流れになります。

ジョブの開始リクエストを生成し、GlacierクライアントのinitiateJobメソッドを呼び出します。

このinitiateJobメソッドの返り値のInitiateJobResultに、開始したジョブのIDが含まれています。ジョブ完了後に結果をダウンロードするのに必要となるので、JobIdを控えておくようにしてください。

SNSにメールを登録していると、ジョブが完了すると以下の様なJSON形式の内容のメールが送信されます。

ジョブが完了したことがメールからわかるのでジョブの結果をダウンロードすることができます。ちなみにジョブの結果をダウンロードできるのはジョブ完了後24時間以内ですので注意してください。ではジョブの結果をダウンロードしてみましょう。

Vault名とJobIdを指定してジョブの結果取得リクエストを生成し、GlacierクライアントのgetJobOutputメソッドを呼び出します。結果として渡されるGetJobOutputResultのgetBodyメソッドでInputStreamを取り出すことができます。このInputStreamを読み込むことでジョブの結果を読み込むことができます。InputStreamで読み込んだ内容をファイルに書きだすのが良いかと思います。

このcreateFileFromInputStreamメソッドはInputStreamで読み込んだ内容を引数で渡されたファイルに書き込んでいます。

実際に書きだされたファイルの中身は以下のようになります。

Vault内にArchiveが複数ある場合は、”ArchiveList”の配列内にオブジェクトが複数格納されます。

ちなみに検証時は4時間から4時間30分までの間にジョブが完了していました。

Archiveのダウンロード(Low Level API)

Archiveのダウンロードは基本的にArchiveの一覧取得とほぼ同じ方法で行います。

違う点は対象のArchiveIdを指定するところ、withTypeで”archive-retrieval”をしているところとなります。

 

SNSにメールを登録していると、ジョブが完了すると以下の様なJSON形式の内容のメールが送信されます。

ジョブの結果のダウンロードはアーカイブ一覧の取得と全く同じ内容で、JobIdを変えて実行すればダウンロードすることができます。

ちなみに検証時はジョブが完了するまで4時間30分ほどでした。

Archiveのダウンロード(High Level API)

GlacierのAPIには通常のLowLevelAPIとより簡単に利用できるようになっているHighLevelAPIの2種類があります。ArchiveのダウンロードやアップロードにはHighLevelAPIを使うことができます。ここではHighLevelAPIを使ってArchiveをダウンロードしてみます。

ファイルのアップロードと同様ArchiveTransferManagerを使うと簡単にダウンロードすることができます。ただ現在、US-EAST以外のリージョンで利用する場合はSNSとSQSのエンドポイントを個別に設定する必要があります。

ArchiveTransferManagerのdownloadメソッドが呼び出されるとジョブが開始され、ジョブが完了すると引数で渡したファイルにジョブ結果の内容が書き込まれます。なおジョブが完了し、結果をダウンロードし終わるまで制御が返って来ませんので、別スレッドにて実行するか、バックグラウンドで実行することをおすすめします。

ちなみにジョブ完了までの時間はLowLevelAPIとほぼ同じでした。

Jobの状態取得

SNSの設定を忘れてジョブを開始した場合、ジョブが完了したか実行中かわからないということもあるかと思います。そのような場合のためのジョブの現在の状態を取得することができます。

ジョブ実行中の場合はgetCompleted()はtrue,getStatusCode()は”InProgress”を返します。

ジョブが完了している場合はgetCompleted()はfalse,getStatusCode()は”Succeeded”を返します。

これでジョブの現在の状態を把握することができます。


現在の注意点

1.ArchiveIdとファイル内容、JobIdとジョブ内容の紐付けが必要

ファイルはアップロードした時点でVault内のArchiveとして扱われ、アップロード以降ファイルの操作にはArchiveIdが必要となります。ArchiveIdとファイル内容を紐付けて管理しておかないと、どのArchiveIdのファイルがどのような内容かわからなくなってしまいます。

またArchiveの取得、Archiveの一覧取得時にジョブを開始した際、ジョブにJobIdが割り振られ、ジョブの結果をダウンロードする際にこのJobIdが必要となります、JobIdとジョブの内容を紐付けて管理しておかないと、どのジョブが、何をダウンロードしようとしていたのかがわからなくなってしまいます。

このあたりはSimpleDBに紐付けデータを保存しておくのが手間が少なくてスジがよさそうな気がしています。

2.Archiveの取得に時間がかかるうえ、期間内に取得しなければならない

ジョブの開始から完了まで検証中は4時間から4時間30分かかっていました。また、ジョブの結果は完了後24時間以内に取得する必要があります。SNSの設定を行なっているとジョブの完了時にメールが送信されるとはいえ、うっかりしているとダウンロードし忘れてしまいそうですね。ジョブのステータスを取得するプログラムを定期的に実行し、完了している場合はダウンロードするような仕組みがあるといいかもしれませんね。

3.詳細な利用にはプログラミングが必要

現在GlacierへのArchiveの保存、Archiveの取得などはAWS SDKを使ってプログラミングをしないと利用することができません。

Management Consoleでは8月31日現在ではVaultの作成と設定変更・削除のみが可能となっています。このあたりは今後のManagement Consoleの機能追加に期待したいところです。ちなみにS3との間でシームレスにデータを移動するためのオプションが追加される予定とのことなので、今後がとても楽しみです。


利用方法を検討してみる

では、実際にGlacierをどのように使うのかを考えてみます。

弊社ではファイル・データのバックアップに現在S3を利用しており、日次でデータをS3に転送しています。これが毎日続くとなると結構な容量と結構な金額となってしまいそうです。そこでGlacierを活用してみたいと思います。

まず今までの運用通り毎日のバックアップデータはS3に保存します。ただS3に保存後一定期間経過後のデータをGlacierに転送します。

そうするとS3に保存されているデータは常にほぼ一定の容量となります。そして価格の安いGlacier上にどんどんバックアップデータが蓄積されていきます。

今までS3に保存されていたデータをGlacierに移すことができるので、コスト削減が見込めそうですね。


まとめ

今回はAmazon Glacierの概要の説明とサンプルプログラムを解説してみました。

  • Amazon Glacierは1GBあたりの月額が約1円の超低コストストレージサービスです。
  • S3と比べ、ファイルのダウンロードを開始できるようになるまで時間がかかるなどの制限も多いです。
  • 操作にはAWS SDKを用いてプログラミングを行う必要があります。

というのがGlacierの特徴でした。

制限も多いですが、特徴を理解して利用できればかなりのコスト削減になるのではないかと思いますので、ぜひGlacierを利用してコスト削減にチャレンジしてもらいたいと思います。

今回一部公開しましたサンプルプログラムはこちら(GitHub)で公開していますので、ぜひ参考にしてみてください。