【翻訳記事】Google Cloud Functions 対 AWS Lambda: サーバーレスクラウドを制する闘いが始まる

  • 253
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに(訳者より)

本稿は以下の、2016年3月22日のブログ記事の翻訳です。
Google Cloud Functions VS AWS Lambda: fight for serverless cloud domination begins

最初に、翻訳を快く許可してくれたAlex(@alex_casalboni)に感謝致します。

Alexが執筆した以降に、変更があった部分については私のほうで分かる限り注釈を付けました。もし他にも現在の仕様と異なるものがありましたら、教えていただけると幸いです。

本内容は、多少の意訳を含んでおり、翻訳に際して私のミスがある可能性も十分にご了承ください。もし間違いがありましたら、コメント欄でご指摘いただけると嬉しいです😇


Google Cloud Functions 対 AWS Lambda: サーバーレスクラウドを制する闘いが始まる

A not-entirely-fair comparison between alpha-release Google Cloud Functions and mature AWS Lambda. My insights into the game-changing future of serverless clouds.

アルファ版の Google Cloud Functions と十分に成長した AWS Lambda のまったくもって公平ではない比較。サーバーレスクラウドの形成を一変する未来に対する私の洞察。

サーバーレスコンピューティングが Google Cloud にやってきた: Google Cloud Functions へようこそ

Google Cloud Platform ソリューションの一部として、2月に Google Cloud Functionsのアルファリリースが公式に発表されました。

この新しいクラウドサービスは、サーバーメンテナンスや、デプロイ、拡張性によって発生する多くの苦労を解消することを目指しています。これは完全に、2014年にAWS Lambdaによって始まったサーバーレス革命に並んでいます。

サーバーレスが意味するのは、少しも(あるいはほとんど)インフラを扱うことなくアプリケーションロジックにフォーカスできることです。
モダンなWebアプリケーションフレームワークはここ5年で急激に進歩したにもかかわらず、苦労なく開発やデプロイ、Web API のメンテナンスがすぐに行える状態にはありません。

サーバーレスコンピューティングは間違いなく流れを変えます。AWS、Azure、そしてGCPといった大手クラウドベンダーによって提供される、上質なクラウドのエコシステムを組合せた、イベント駆動型アプローチによってもたらされる果てしない可能性を考察しましょう。

ここで、Google Cloud Functionsの来たるべき特徴と、現時点のAWS Lambdaの状態とGoogle Cloud Functionsの比較について議論したいと思います。数分以内にLambdaからGoogle Cloud Functionsへの乗り換えることが出来る方法、そしてその際、Google Cloud上でLambdaファンクションをテストする方法について、幾つかの基本的な例を出します。私は、今後数ヶ月でサーバーレスコンピューティングがどのようになっていくのかを探求したいと思います。

Google Cloud Functions と AWS Lambda

まず第一に、アルファ版と2年が経過した安定しているプロダクトを比較するのはまったく公平ではないと認めざるを得ません。とは言うものの、すでに提供されているCloud Functionsのうちの幾つかの機能は、とても良く差別化ができていると思います、特に開発の観点から。

これは両プロダクトのメイン機能の簡単なまとめです。

機能性 AWS Lambda Cloud Functions
拡張性と可用性 オートスケーリング(透過的) オートスケーリング
最大ファンクション数 無制限 20/プロジェクト(α版の間)
同時実行 100並列実行/リージョン(デフォルト上限値) 無制限
最大実行時間 300秒(5分) 無制限
サポート言語 JavaScript, Java, Python JavaScriptのみ
依存関係 デプロイパッケージ npm package.json
デプロイ ZIPアップロードのみ(LambdaまたはS3へ) ZIPアップロード, CloudStorage, Cloud Source Repositories
バージョニング バージョニングとエイリアス CloudSourceのbranch/tag
イベント駆動 イベントソース(S3, SNS, SES, DynamoDB, Kinesis, CloudWatch)※ Cloud Pub/Sub, Cloud Storage オブジェクト変更通知
HTTP(S)起動 API Gateway HTTPトリガー
ログ管理 CloudWatch Cloud Logging
ブラウザ上のコードエディタ 依存関係がない場合に限る Cloud Source Repositoriesでのみ
粒度の細かいIAM IAMロール まだ無い
料金 100万件/月まで無料、$0.20/100万件 β版オープンまで不明

(※訳者注釈:2016年10月現在、AWS Lambdaのイベントソースはこの他にもあります)

さぁお互いの機能を深掘りしましょう

拡張性、可用性、リソース制限

言うまでもなく、これは両サービスで一番の関心事です。主な特徴は、もはやメンテナンスやダウンタイム、またはボトルネックを心配する必要はないことを約束してくれています。

AWS Lambdaに関する限りでは、拡張性は完全にそして明確にLambdaのシステムによって処理されるため、与えられた時間内にLambdaファンクションを動かすためのインスタンスやマシンの数を把握しないことを意味します。Lambdaファンクションの利用状況は常に監視出来ますが、下層アーキテクチャの可視化は制限されています。

大きな違いとして、Google Cloud Functionsは Google Cloud上にインスタンスのセットを明確に作成します。これによりいつでも作成されたマシンの数をチェックでき、クラスタをモニタリングすることができます。
(※訳者注釈:2016年5月時点で完全にマネージドサービスになったためこの記述は現在の仕様とは異なります。)

拡張性やモニタリングの他に、AWS Lambdaの制約は幾つかあります。たとえば、AWS Lambdaでは無制限にファンクションを作成できますが、どれも5分を超える実行はできませんし(以前はもっと短かった!)、リージョン単位に100並列実行と制限されます(デフォルト上限値であり上限緩和で増加が可能)。その上、圧縮したデプロイパッケージは50MBを超えてはいけません(非圧縮状態で250MB)。AWS Lambdaではさらに幾つか制約がありますが、それらは実際には限定された事態への影響にすぎないので、ここでは示しません。

一方で、Google Cloud Functionsはこのような制限は(まだ?)無いように見えます、1プロジェクトで20ファンクションという強い制約があるにもかかわらず。この制約はゆくゆくは無くなるだろうと思っていますが。
(※訳者注釈:1プロジェクトで20個の制約はアルファ版の間だけの制約と思われます)

サポートしている言語と依存管理

Lambdaの初期バージョンではJavaScriptしかサポートしていませんでした、そしてその後Java(2015年1月)やPython(2015年10月)もサポートされました。現在はRuby(JRuby)や、またはサポートされていない任意の実行可能な言語でも書けます(いわゆる子プロセスのspawnによって)。

Google Cloud Functionsが現在サポートしているのはJavaScriptのみです。にもかかわらず公式なロードマップも無いようです。今年中に、追ってPythonやJavaもサポートされると推測しています。
(※訳者注釈: 2016年10月現在まだサポートの発表はありません)

依存管理およデプロイに関する限り、AWS Lambdaの唯一の弱点はデプロイパッケージだと思います。実際にやってみると、外部依存は圧縮したソースコードの中に含めることで使うことができますが、いくつかの理由によりそれは不便であると分かりました。
第一に、それらの外部パッケージをAWS Lambdaが使っている同じOS内にコンパイルおよびインストールすることを強要されます。この後コードに何か変更が必要になると、毎回すべて一緒にアップロードする必要があります。次に、これは依存管理としてモダンな方法ではないということです: Web開発者は、ローカルでコンパイルされたライブラリを提供するより、コードの依存関係のバージョニングや宣言にはもう慣れています

なるほど、プロセス全体は自動化されるのに、設定ファイルは簡単かつ安全に保守できないのでしょうか?

いいえ。:)

事実、Google Cloud Functionsはシンプルな package.json でnpmの依存関係やバージョンの宣言を定義することを許容しています。Pythonもサポートされればすぐに、pip requirements.txt でデプロイするだけになる可能性を期待しています。
(※訳者注釈:pip = Pythonのパッケージ管理システム)

デプロイとバージョニング

前のセクションで触れたように、AWS Lambdaがデプロイパッケージと依存関係を処理する方法が個人的に好きではありません。コードの変更、または依存関係の更新のたびに、1つの(潜在的には膨大な)デプロイパッケージを再デプロイしなければいけないからです。

一方で、同じLambdaファンクションが複数のバージョンを持つことの可能性は好きです。それは新しいバージョンでのデプロイやテストを簡単にします - AWSコンソールからでも。実際のトリックは、数回クリックするだけで新しいバージョンへ簡単に切替え(あるいは古いバージョンへロールバック)ができるよう、各バージョンに紐付けられたエイリアスです。API Gatewayのステージと、永続的なLambdaファンクションのバージョン - たとえば開発、ステージング、プロダクション、他など - との関連付けは、少しだけ手動の設定を求められますが、しかしこれはとても価値があります。API Gateway のステージ変数を設定し、Lambdaのエイリアスを与えて起動する用途はおすすめです。

この件に関して、Google Cloud Functionsは車輪の再発明ではない選択をし、開発者が使いやすいソリューションを考案しました: Cloud Source Repositories上に自身のリポジトリをホストすることを必要としますが、gitによるバージョン管理が可能になります(いわゆるブランチやタグが与えられます)。私は、できればGitHubやBitBucketなどのような、他の主流なGitソリューションを含むもっと総合的なソリューションを期待しています。

起動、イベントおよびロギング

AWS LambdaもGoogle Cloud Functionsも共にイベント駆動型アプローチをサポートしており、クラウド環境内で何か面白い事が発生するたびにfunctionを起動させることができます。シンプルなHTTPアプローチもまたサポートしています。

AWS Lambdaは、S3、SNS、SES、DyanmoDB、Kinesis、Cognito, CloudWatchなど、ほぼどの他のAWSサービスからも起動できます。API Gatewayに与えられたLambdaファンクションを起動させる設定や、(ほぼ)無料でRESTfulなインターフェイスを手に入れることができます。(認証やキャッシュ、パラメータマッピングなどを含む)

Google Cloud Funtionsは現在、内部イベントはCloud Storage(いわゆるオブジェクト変更通知)や、Google Cloud Pub/Subのトピック(必要に応じて自動スケールするGoogleのグローバルな分散メッセージバス)もサポートしています。HTTPでの起動はすでに最初からサポートされています。--trigger-http フラグを付加してfunctionをデプロイするだけです。現在は、異なるトリガータイプそれぞれに対して明確に設定しデプロイする必要があります。

ロギングに関する限り、両サービスは同様のログマネージメントサービスを統合しています: Amazon CloudWatchGoogle Cloud Loggingです。個人的にはCloudWatchのほうが、より統合され、図表(のようなもの)の設定の簡易さや、ドキュメントで勝っていると感じます。

ロードテストと統計データ

純粋な計算(言い換えると、起動ごとに1000のMD5ハッシュ値を生成)を含む任意のJavaScfriptで、ロードテストを時間をかけて実行しました。これは私に2つの異なる依存管理システムで遊ぶ機会を与えてくれました、なぜならMD5のnpmモジュールを含める必要があったからです。

5分で最大約70リクエスト/秒まで、ロード数を線形的に増加させるようにしました。

下に、平均レスポンスタイム秒間の平均リクエスト数を示している2つのフラフを表示しました。

Note: これらの2つのグラフは両方の範囲で同じ尺度を使っています。また、双方のfunctionは同じくEU-westリージョン(アイルランド)にデプロイしてテストをしました。

aws-lambda-load-test.png
$$\style{align: center; font-size: 80%}{\text{AWS Lambda Load Test}}$$

google-cloud-functions-load-test.png
$$\style{align: center; font-size: 80%}{\text{Google Cloud Functions Load Test
}}$$

見て分かるように、平均レスポンスタイムに明確な違いがあります: Cloud Functionsは終始130〜200msをキープしています、最後の1分の間に奇妙な上昇が見られますが。(ロード数の減少が原因かも?)

一方で、AWS Lambdaのレスポンスタイムはかなり遅く、興味深い矩形波パターンが明らかになりました: AWS Lambdaでは20リクエスト/秒を超えた後、内部でスケールアップしているように見えます。30リクエスト/秒付近で一定の時にスケールダウンし(つまりレスポンスタイムは600msまで上昇しました)、そして毎秒40リクエスト以上で再びスケールアップするように見えます。

双方のfunctionの起動は比較的重いJSONレスポンス(ほぼ50KB)を返すので、レスポンス結果において、実際の計算処理とは関係なくネットワークパフォーマンスも影響しているだろうと推測しました。

私はすぐに、双方のfunctionをシンプルに"OK"メッセージを返すだけに修正し、この仮定が正しいかどうか確かめました。新しいAWS Lambdaファンクションは、終始一貫して改善している事に気が付きました、レスポンスタイムは200〜300msに下がっていました。新しいCloud Functionsは大きな影響はありませんでしたが、レスポンスタイムはわずか100msに下がりました。

この結果をふまえて、計算の違いは関係があるものの、もしアプリケーションが重いHTTPレスポンスを伴うなら、おそらくネットワークの影響のほうが大きいだろうと思います。すでに2014年に議論した通り、どうもGoogleのネットワークのほうが単に良く、ネイティブなHTTPのインテグレーションではより速いのではないかと思います - Amazon API Gatewayに関しては。Googleのネットワークは素晴らしいですが、例えば認証とキャッシングといった重大な機能がまだ不足しています。
(※訳者注釈:おそらく、Lambdaのキャッシュ機能とAPI Gatewayのカスタム認証のことを指しているのではないかと思います)

AWSとGoogleのFunctionコードの互換性

残念ながら、AWS LambdaとCloud Functionsは直接的な互換性はお互いありません。以前触れたようにGoogle Cloud Functionsはまだアルファ版で、変更はあるでしょうが、よほどの理由がない限りGoogleはAWS Lambdaと互換性を持たせる努力はしないでしょう。

もし、あなたがすでに幾つかLambdaファンクションを持っているなら、ほとんどの場合、それらは少なくとも別のAWSのサービスと相互作用しています。あなたのLambdaファンクションはおそらく幾つかのIAMロール、多くのAWSの詳細(機能)を使っていて、とにかく別のクラウドベンダーに移るのは簡単ではないでしょう。

それ以外の多くのケースにおいては、あなたのLambdaファンクションは、純粋な計算または単純な入出力ロジック(言い換えれば、キューからの読み込みや、データベースへの書き込み、画像の加工など)を含んでいます。それらのケースでは、あなたのLambdaファンクションをGoogle Cloud Functionsでも試してみてください - たとえサービスを評価、またはコストを縮小させるためだけでも。ここからあなたのアカウントの利用申請をリクエストできます。

自動コンバージョンツールは?

幸いにも、私はあなたのJavaScript Lambdaファンクションの移植作業を、間違いなく高速化するであろうシンプルなコンバージョンツールを開発しました。それは正確には、event/context機能のマッピングを処理し、そして相容れない属性やメソッドを自動的にコメントします。私は本当に手動でのリファクタリングや移植タスクが大嫌いなので、このツールがあなた方の役に立つことを望んでいます。
https://github.com/cloudacademy/awslambda2googlefunctions

例えば、次のような非常にシンプルなfunctionは

lambda
exports.myHandler = function(event, context) {

    console.log("input data: " + event);

    if (!event.name) {
        return context.fail("No name");
    }

    context.succeed("Hello " + event.name);

}

このようにとてもよく似たものになります

CloudFunctions
exports.myHandler = function(context, data) {

    console.log("input data: " + data);

    if (!data.name) {
        return context.failure("No name");
    }

    context.success("Hello " + data.name);

}

想像に容易いですが、変換作業はかなり直感的で2〜3分以上かからないはずです。
しかし、とても複雑な関数(特に、独自のeventまたはcontextオブジェクトの両方を必要とするようなユーティリティファンクションを定義しているなら)の場合、変換作業は困難かつ時間を要するものになっていきます。

アルファ版テストの結論

Google Cloud Functions はとても将来性があるように見えますし、今後来る多くの機能を楽しみにしています。私はテストおよびCloud Functionsのtrusted testersグループのモニタリングを続けます、trusted testersグループには既に多くの提案や改善やフィードバックが含まれています。個人的には、サーバーレスが流行して、クロスプラットフォーム開発を可能にするもっと多くのツールが現れることを期待しています。

もしこの記事を楽しんでくれたら、気軽にコメントを残してください、そしてサーバーレス革命への考えを教えてください。私達はCloud Academyのプラットフォームでも楽しくLambdaファンクションを使っています、そして近い将来起こることが待ち遠しいです。(もしまだ知らないなら、Serverless Frameworkをご覧ください)