ただのアニメ感想ブログ

主にアニメの感想を書いていきます。

AWSでシステムのサーバレス化に挑戦してみる(第1回)

世はサーバレス化の時代ですよ(適当
私も会社で今のサービスをサーバレス化して、基盤側の手間を極力減らすよう司令を受けました。
そこで私が比較的使い慣れているAWSで、実際にやりたいことができるかの検証をしてみようと思います。

流石にシステムの詳細は書けませんが、やりたいことは以下の通りです。
・ユーザ向けWebサイトの機能を持つ。
・ユーザからのリクエストを受け付ける。
・リクエストの内容に応じて外部サービスを呼び出す。
・呼び出し結果を格納する。

これらを元にして自分が描いたシステム構成の案はこんな感じです。

f:id:triobog:20180805234543j:plain

フロントのWebサイト部分はElastic Beanstalkを使ってサーバレス化。
ユーザからのリクエストを受け付けてRDSに格納。
RDSへの書き込みをトリガーにしてLambdaでバッチ処理、必要に応じてAPIコール。
結果をRDSに格納するのですが、それだけだと分からないので検証ではSNSを使って結果通知。
今オンプレでやっていることをAWSを使ってそのまま実現しました、的な感じです。

とは言え、BeanstalkやLambdaは自分もあまり知見がないので、1つ1つ検証をしていきます。
まずは表側のBeanstalkの部分から。

今回参考にしたのは以下のページです。

docs.aws.amazon.com
 
サービス一覧からElastic Beanstalkを選択。

f:id:triobog:20180805234647j:plain

まだ何も作っていないので初期画面が表示されます。
[今すぐ始める]を選択。

f:id:triobog:20180805234712j:plain 

ウェブアプリケーションの作成画面に遷移します。
アプリケーション名は適当に、「BeanstalkTest」としましょう。
プラットフォームは[PHP]にします。
今回はサンプルで動きを確認したいので、アプリケーションコードは[サンプルアプリケーション]にします。
[アプリケーションの作成]ボタンを押して次の画面へ。

f:id:triobog:20180805234741j:plain 

環境を作るのに時間がかかるのでしばらく待ちます。

f:id:triobog:20180805234807j:plain

出来ました。
中央右上の方にあるURLにアクセスすると、今回作成した環境にアクセスできます。

 f:id:triobog:20180805234938j:plain

次はこのアプリケーションを更新する方法について説明します。

docs.aws.amazon.com

まず上記ページの「アプリケーションバージョンを更新するには」から、サンプルアプリケーションをダウンロードします。
今回作ったのはPHPの環境なので、「php-v1.zip」をダウンロード。
解凍すると以下のファイルが展開されます。

> .ebextensions
> cron.yaml
> index.php
> logo_aws_reduced.gif
> scheduled.php
> styles.css

「index.php」の中身は以下のようになっています。

<?
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
$file = '/tmp/sample-app.log';
$message = file_get_contents('php://input');
file_put_contents($file, date('Y-m-d H:i:s') . " Received message: " . $message . "\n", FILE_APPEND);
}
else
{
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>PHP Application - AWS Elastic Beanstalk</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Lobster+Two" type="text/css">
<link rel="icon" href="https://awsmedia.s3.amazonaws.com/favicon.ico" type="image/ico" >
<link rel="shortcut icon" href="https://awsmedia.s3.amazonaws.com/favicon.ico" type="image/ico" >
<!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<link rel="stylesheet" href="/styles.css" type="text/css">
</head>
<body>
<section class="congratulations">
<h1>Congratulations!</h1>
<p>Your AWS Elastic Beanstalk <em>PHP</em> application is now running on your own dedicated environment in the AWS&nbsp;Cloud</p>
<p>You are running PHP version <?= phpversion() ?></p>
</section>

<section class="instructions">
<h2>What's Next?</h2>
<ul>
<li><a href="http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/">AWS Elastic Beanstalk overview</a></li>
<li><a href="http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/create_deploy_PHP_eb.html">Deploying AWS Elastic Beanstalk Applications in PHP Using Eb and Git</a></li>
<li><a href="http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/create_deploy_PHP.rds.html">Using Amazon RDS with PHP</a>
<li><a href="http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html">Customizing the Software on EC2 Instances</a></li>
<li><a href="http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-resources.html">Customizing Environment Resources</a></li>
</ul>

<h2>AWS SDK for PHP</h2>
<ul>
<li><a href="http://aws.amazon.com/sdkforphp">AWS SDK for PHP home</a></li>
<li><a href="http://aws.amazon.com/php">PHP developer center</a></li>
<li><a href="https://github.com/aws/aws-sdk-php">AWS SDK for PHP on GitHub</a></li>
</ul>
</section>

<!--[if lt IE 9]><script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script><![endif]-->
</body>
</html>
<? 
} 
?>


今回テストとして、上記コードにいくつか変更を加えてみます。
 

> <title>PHP Application - AWS Elastic Beanstalk</title><title>PHP Elastic Beanstalk Test</title>

 

> <h1>Congratulations!</h1><h1>Test Code Deploy has Succeeded!</h1>


これをダウンロードしたときと同じようにzipファイルに固めます。
この時注意しないといけないのは、index.phpなどのファイルはzipファイルの直下に置くという点です(説明が難しいですが、よくあるミスとして、ソースコードディレクトリごと圧縮してしまい正しくデプロイできない、と言うことがあります)。
サンプルコードをいじる程度であれば、ダウンロードしたzipファイルの中にあるファイルをそのまま上書きするのが失敗も無くて良いと思います。

ではこのzipファイルをアップロードしましょう。
今回はダウンロードした「php-v1.zip」の中に「index.php」をそのまま突っ込みます。

 f:id:triobog:20180805235036j:plain

Elastic Beanstalkのトップ画面にアクセスすると、先程作成した「BeanstalkTest」のアプリケーションが表示されています。

f:id:triobog:20180805235209j:plain 

[BeanstalkTest]を選ぶとダッシュボード画面へ。
画面中央にある[アップロードとデプロイ]ボタンを選びます。

f:id:triobog:20180805235234j:plain 

[ファイルを選択]で作成したzipファイルを選択して、[デプロイ]ボタンを押下します。
バージョンラベルはソースのバージョニングのために必要になります。多分真面目に世代管理したほうが良いのでしょうが、今回はサンプルなのでそのままphp-v1にしておきます。

f:id:triobog:20180805235255j:plain 

デプロイ完了までしばらく待ちます。
完了したら先程と同様、URLにアクセス。

f:id:triobog:20180805235319j:plain 

ちゃんとトップメッセージが更新されていました。
(「Congratulations!」→「Test Code Deploy has Succeeded!」)
画像では確認できませんがタイトルもちゃんと変更されていました。

ちなみにですが、Elastic Beanstalkはアプリケーションの実行環境を提供するとありますが、実際にやっていることはEC2インスタンスとAuto Scalingで環境づくりをしているだけです。
実際にEC2のマネジメントコンソールでインスタンスを見てみましょう。

 f:id:triobog:20180805235338j:plain

このようにインスタンスが立ち上がっています。
インスタンスタイプt1.microなのか、t2じゃなくて・・・。
たぶん複数台立てる場合は勝手にELBに接続してくれると思うのですが、今回は単独のインスタンスなのでEIPが割り当てられています。

f:id:triobog:20180805235357j:plain 

試しにEIPにアクセスしてみると、やはり先程と同様の画面が表示されました。

f:id:triobog:20180805235443j:plain

セキュリティグループ。まあ当然ですけど、インターネットにオープンな状態になっていますね。
22番とかは開いていない模様。

f:id:triobog:20180805235559j:plain 
f:id:triobog:20180805235505j:plain

オートスケールの設定。
見るとインスタンスが常に1つ起動するように設定されていますね。
試しにEC2の画面でインスタンスを手動で終了させてみましょう。

f:id:triobog:20180805235539j:plain

EIPの解放も選択してインスタンスを削除。

 f:id:triobog:20180805235724j:plain
 f:id:triobog:20180805235805j:plain

インスタンスがterminateされました。
さてどうなる。

f:id:triobog:20180805235840j:plain

1~2分ほどしてインスタンスが立ち上がってきました。

f:id:triobog:20180805235916j:plain

インスタンスが完全に立ち上がるまでには5分くらいかかりました。
単独だとこれがサービスダウンの時間になってしまうので、高可用性を求めるのであればやはりELBを使った冗長化が必須ですね。

f:id:triobog:20180805235953j:plain

Beanstalkの画面を見ると、ログにEC2のヘルスチェックに失敗した事と、新しいインスタンスが加えられた事が出力されています。
さて、先程のURLにアクセスしてみて、結果はどうなるかといいますと・・・。

 f:id:triobog:20180806000020j:plain

アクセスできない・・・。
恐らくですが、インスタンスと一緒にEIPまで解放してしまったから、ドメインとEIPの紐づけに失敗してアクセス出来なくなったものと思われます。
試しにEC2の画面で新しく立ち上がってきたインスタンスのパブリックIPにアクセスしてみたところ、ちゃんとページが表示されました。

f:id:triobog:20180806000051j:plain

おそらくインスタンスを立ち上げた後にBeanstalkの方でEIPをインスタンスにアタッチするのだろう。
まあ通常のインスタンス障害が発生した際に、EIPが勝手に解放されるようなことは無いと思いますが、怖いのは今回のような人的なミスによる障害ですね。EIPを解放されてしまったら、同じEIPを取得できる保証は無いので最悪環境を作り直さないといけない(まだ自分が知らないだけで、Beanstalkの画面で設定するだけで復旧できるのかもしれませんが)。IAMで権限が制限されたユーザを払い出すことで、このような事故を防ぐことができると思います。どうせBeanstalkに頼るような輩はEC2の画面で基盤の設定を直接いじるなんてことはしないでしょうし(偏見
 
Beanstalkで環境を作ると、EC2インスタンス以外にも色々と作られます。

f:id:triobog:20180806000126j:plain

IAMのロール。これはBeanstalkがEC2を操作するためにつくられる模様。

f:id:triobog:20180806000231j:plain

S3。ソースがバージョンごとに管理されたり、ログが吐かれるものと思われる。

とりあえず、サンプルを使った一通りの検証はできたので、この環境は消してしまうことにします。
いつまでも残しておくとお金がかかってしまうので。
Beanstalkの画面で[アクション]のプルダウンを選んでアプリケーションの削除。

 f:id:triobog:20180806000313j:plain
f:id:triobog:20180806000331j:plain
f:id:triobog:20180806000349j:plain

アプリケーションの削除が完了しました。
S3の方にもファイルが残っているので、念の為こちらも消しておきます。

 f:id:triobog:20180806000435j:plain

さて、今回サンプルアプリケーションの環境を作って動かしましたが、かかった料金はこんな感じです。

f:id:triobog:20180806000416j:plain

実際安い。
これだけしかかからないのであれば、今後の検証もお金を気にせずにできそうで良かったです。
 

そんな訳で、今日はこれまで。
それでは、ごきげんよう