目次


ラムダ関数による迅速なプロトタイピング

プロジェクトを効率化してコスト効果を高める

Comments

この数か月の間、技術関連のカンファレンスやブログで「サーバーレス」という言葉が盛んに飛び交うようになっています。サーバーレスでは、特定のサービスやフレームワークを使用することで、サーバーについて考慮する必要を失くし、コードをそのまま本番環境にプッシュできるようにすることを展望しています。もちろん、サーバーの存在がなくなることはありません。では、現在の IaaS (Infrastructure as a Service) ランドスケープにはどのような新しさがあるのでしょうか?それは、ラムダ・アーキテクチャーという新しいパラダイムです。ラムダ・アーキテクチャーの概念は、プロジェクトを複数のネットワークで使用できる単純な関数に分割することであり、まさに、技術チームが CTO を説き伏せてマイクロサービスへの移行を可能にする概念と同じです。

ラムダ・アーキテクチャーの強みは、プロジェクトが理解しやすいものになり、プロジェクトのコスト効率が大幅に向上するところにあります。その一方で、ラムダ・アーキテクチャーはマイクロサービスと同じように、さまざまな新しい課題を突き付けます。例えば、サービス・ディスカバリー、チームの教育、復元力、マルチ言語、マルチクラウドなど、例を挙げるだけでもきりがありません。ラムダ・アーキテクチャーでは、すべての作業内容とすべての関係者を調整しなければなりません。いずれにせよ、ラムダ関数は初期段階のプロジェクトや実験にはうってつけです。この記事では、皆さんが次回のプロジェクトでスタックに使用できるいくつかのツールを紹介します。

効果的なワークフロー

ラムダに基づくアーキテクチャーでは、基本的に、1 つの処理に特化したサービスのそれぞれに、1 つの計算ユニットをデプロイします。言うまでもなく、管理対象のサービスが何百もあり、それらのサービスが互いの実行ステップをトリガーするとしたら、最終的にはスパゲッティーのようにもつれ合ったロジックのフローになってしまいます (図 1 を参照)。

図 1. 複雑なロジックのフロー
複雑なロジックのフローを示す図
複雑なロジックのフローを示す図

このようなシナリオを深く掘り下げることはしませんが、技術的負担を管理する方法と、マイクロサービスで負担に対処する方法について、シニア・アーキテクトに相談するか、他の記事を読むことをお勧めします。

この記事では差し当たり、新規に開始する、シンプルでわかりやすい、効果的なプロジェクトにフォーカスしましょう。まず、プロジェクトの基本機能 (ランディング・ページ、ユーザー管理、決済) を急いで完成させる必要があります。他の機能については、後から追加していくことができますが、どの機能をユーザーに表示すれば、製品にお金を支払う気にさせられるかについて判断するには、この段階では時期が早すぎます。

最終的な目標は、繰り返し安全に製品を作成できるよう、必要なときにだけ他とは切り離して単独で取り組めるブロックを定義することです。これらのブロックのそれぞれに専用のラムダ関数を割り当てれば、このプロセスがアジャイルなものになり、明確な実用最小限の製品ロードマップが生み出されることになります。

ラムダの下に、専門的なインフラストラクチャーのすべてを移行しなければならないわけではありません。おそらく、必要なフレームワークの数は少なくなり、本当に機能する勝ち残ったフレームワークが増えるでしょう。さらに、絶対不可欠となるのは、数百もの関数をデプロイして保守する方法を定義することです。

既存のスタックがどのようなものであれ、直感に従って、新しいラムダを即座に実行するか、没にするか、交換してください。このように、安全な実験を短期間で繰り返すことになります。

この方法は Docker のようなマイクロサービスと似ているものの、精神的な負担は軽減されていると実感するはずです。この 2 つを区別するとしたら、ラムダはナノと呼ぶこともできますが、コンテナーやラムダは、上述したアーキテクチャー・パターンの恩恵を受ける実装の細部であると私は考えます。ラムダはある特定のサービスを 1 つの関数として適用するため、サービスが不要になったら破棄できるという利点があります。このことから、開発者は小さいステートレスな処理タスクを中心に考えざるを得なくなります。コードは副次効果を最小限に抑えながら 1 つの問題を解決します。この方法は、古き良き UNIX の理念と最新の関数型の傾向を結合した結果だと考えてください。私の偏見ではありますが、この方法にはコミュニティーの強い合意があり、開発者の幸せにつながると考えます。では、この方法を実践するには、どのような形をとればよいのでしょうか?

module.exports = function(context, callback) {
    callback(200, "Hello, world!\n");
}

ほとんどのフレームワークや SaaS では、単一の関数を公開するのに、シークレットを HTTP クエリー属性として保持できるオブジェクトを使用する必要があります。言うまでもなく、module.exportscallback() の間に 2000 行のコードを作成してはならない理由はありません。けれどもそうすると、たちまちアンチパターンの気配が漂います。

さらに、簡単にデプロイできることで、問題を管理しやすいエンドポイント・ソリューションに分割するよりも、たちまち保守しにくくなりがちです。

$ # completely copy/pasted from http://fission.io/


$ fission function create --name hello --env nodejs
--code hello.js

$ fission route add --function hello --url /hello

$ curl http://router.fission/hello

Hello, world!

これで Fission を利用して、HTTP を介して挨拶を表示するちょっとしたコードが用意できました。Fission を使用するには Kubernetes がセットアップされていなければなりませんが、2018 年の今の時代に、セルフホスト型の「コンテナー化アプリケーションのデプロイメント、スケーリング、管理を自動化するオープンソース・システム」を使っていない人がいるでしょうか?真剣な話、分散型クラスターを管理する時間がないか、自分で管理するのは気が進まないとしても、同じような仲間はいます。大手ホスティング会社では、現在、ラムダを推し進めるのに魅力的なプラットフォームを提供しています。例えば Webtask 101 は 30 秒でセットアップが完了し、しかも料金は一切かかりません。

$ # again, shamelessly copy/pasted from
https://webtask.io/docs/101

$ echo "module.exports = function(cb) { cb(null, 'hello world');
 }" > foo.js

$ wt create foo.js

ReactWebpack のようなプロジェクトに取り掛かるチャンスがあったとすれば、それが驚くほど簡単な一方、完全な機能を備えたプロジェクトであることがわかるはずです。

$ wt cron schedule -n mongocron -s

MONGO_URL=mongodb://webtask:supersecret@ds047592.mongolab.com:

47592/webtask-examples 10m foo.js

これで、ラムダ関数が定期的に実行されるようになりました。この手法は、ご存知のように極めて一般的な使用ケースです。

あらゆる側面において、導入する際の障壁はかなり低くなっています。コードは関数として作成できて、新しく学ばなければならないドメイン固有言語も、複雑な構成もありません。あるいは、さまざまなクラウド・プロバイダーでサーバーレスによって行われているように、こういった厄介さはよく使われているフレームワークの背後に隠されていることもあります。これは重要な点です。すべてのことを新たに学びなおす必要がない新しいパラダイムであり、すぐにプロジェクトに使用できて、通常は多くの人の賛同を得られるためです。賛同を得るということは、サービス・ライブラリー、ヘルプ、記事からなる堅牢なエコシステムが展開し、それによってさらに勢いが増すといったことを意味します。

これらのフレームワークとサービスは、サーバーレスには特に重要となります。それは、サーバーレスの本質は、コア・プロジェクトには関連しないものを管理する負担を軽減することだからです。一方、サーバーレスでは、重要なテクノロジーを使用し、トラフィックをルーティングするための動的にゲートウェイにマッピングされる一過性の計算インスタンスからなる複雑なインフラストラクチャーを管理します。

OpenWhisk のようなセルフホスト型の代替手段では、プロキシーやコンテナーなどの手の込んだテクノロジーを使用せずに、社内のサーバーレス・スタックを制御できます。そのような代替手段には、すぐにでも DevOps チームや投資を充てることができるでしょう。つまり、サード・パーティーを頼りにしないということです。非常に特殊なビジネス・ケース (または手っ取り早いソリューション) にも、完全なカスタマイズによって対応できます。けれども、セルフホストはサーバーが後ろに控えていることも意味します。したがって、サーバー関連の課題 (プロビジョニング、構成、保守、モニタリング、パフォーマンス、セキュリティー) に留意することが重要となります。

次は、趣味と実益を兼ねて、既存のツールを利用する方法に目を向けましょう。

初期段階のクラウド・プロジェクト: 開始当初のフィードバックとイテレーション

前に説明したように、コードを簡単に作成できれば、デプロイメントのコストを削減することができます。アイデアをオンラインで実現するまでに、できるだけ摩擦が生じないようにすれば、両刃の剣になります。Twitter の場合と同じく、漠然としたアイデアをすぐさまクラウドに上げることも、リーン・スタートアップの理念に従って迅速に反復作業を進めることもできます。当初のアイデアの品質とは関係なく、そのアイデアを一般公開するか非公開で共有すれば、フィードバックとエクスペリエンスを収集できます。このような他者からの情報は、初期のデザインまたはテクノロジーが適切なものであるかどうかを評価するのに役立つはずです。あるいは、ランディング・ページを作成して関心度を図るという方法もあります。この場合、自分のアイデアが人々の求めているものであるのかどうか、それともさらに時間と作業を費やす価値はないものであるかどうかが、すぐにわかるはずです。エンジニアは一般に、妥協したり、自分が作成したいと思うものを諦めたりすることを好みません (最初からやり直すか、別の魅力的なテクノロジーに乗り換えることを決心した場合は別です)。皆さんがこのような症候群に抗うために、私にできることはありませんが、少なくとも決断を下すための判断材料となる数値を手に入れることはできます。

ラムダは、アーキテクチャー・レベルで DRY (Don't Repeat Yourself) の原則に従って利用することができます。私としては、DRY の論拠は少々説得力に欠けるような気がします。コンピューター・サイエンスにおける数多くのベスト・プラクティスと同じく、DRY の有効性は、これを実装している作成者の能力に比例するからです。そうは言っても、サーバーレス・ワークフローは単一の目的を持つ疎結合されたサービスを促進します。したがって、サービスによっては (決済処理、静的サイト・レンダリング、ユーザー登録など)、共有できるものもあるでしょう。私にはその経験があります。プロジェクトを開発する中で、さまざまなパターンを抽出して、共有するサービスを増やしていけば、プロトタイピング・レベルで作業時間を短縮できるようになるはずです。その一方、プロジェクトが成長するうちに、この仕組みは機能しなくなるにちがいありません。私の経験から言うと、開発者は極めて具体的なエッジ・ケースを解決するようになるまでブロックを特化させる傾向があります。つまり、プロジェクト全体を単純なままに維持し、必要な機能だけを実装して、開放/閉鎖原則に従うようにするのです。

この議論に、いくつかのオープンソースとコミュニティーの要素を追加しましょう。ここでは明らかな境界を定めた疎結合サービスについて話題にしているので、コードを共有すると、独自のスタックの枠内に収まらなくなってくる可能性があります。Stdlib は最近、ネットワークからアクセス可能な関数の共通ライブラリーを提供するために、200 万ドルの資金を集めました。あらゆる動向がこの方向を目指しているように見えますが、私としては、まだそこまでのところに来ているかどうかわかりません。サード・パーティーのコード、社内開発でのトレードオフ、そして採用率を信用することによって得られるものは多くあるかもしれませんが、この機会を利用するプロジェクトの数はそれほど多くありません。ただし、小規模なアイデアとして、このアイデアを実現に向けて加速化させるために実際にできることはやはりあります。例えば、初期の SaaS に一般的なサービスではあるものの、競争上の優位性を表すことのないすべてのサービスは、プラグインとして追加できます。

この手法には明らかに制約事項がありますが、これが開発チームに権限を持たせて組織内部で実現可能である手法であることは、注目に値します。

クラウド・ランドスケープ: コンテナーと最先端のテクノロジー

この記事ではこれまで、小規模なプロトタイプにはラムダ・テクノロジーを使用すべきである論拠を取り上げてきました。これらの論拠が皆さんの経験に反響して、次のプロジェクトにラムダを試してみるきっかけになることを願いますが、私が説明した要点または使ったキーワードの中に気掛かりなものがあった場合に備え、ラムダが現在の DevOps ランドスケープのどこ (公平を期して言うと、どの小さい部分) に適合するかに関する混乱を解消したいと思います。

まず、この記事で使用した用語の中に、互いに排他的なものはありません。マイクロサービス・アーキテクチャーを設計するには、コンテナー内部でコードを実行するラムダを使用できます。たまたまそうであるわけではなく、サーバーレスは Docker とコンテナーが登場した数年後に出現した手法であるためです。Docker とコンテナーはクラウド・オーケストレーションの力を解き放ち、ラムダがイベントに応じて起動して処理の直後に停止するために必要なアジリティーをもたらしました。

私の見方では、この状況は突き詰めると、開発者による使用法と、ビジネスの目標に帰着しています。コンテナー内に巨大なプログラムを格納したり、マイクロサービスをベアメタル・マシン上にデプロイしたりすることを阻むものは何もありません。これらのツールは、特定の制約事項に応じて利用し、組み合わせることができます。例えば、Kubernetes は本番対応のコンテナー・オーケストレーションとして自身を売り込んでいますが、いくつかの調整を加えれば、サーバーレス・フレームワークにすることができます。以上の説明は、次のように要約できます。

  • マイクロサービスは、明確な小さい適用範囲とインターフェースを持つ疎結合サービスを促進するアーキテクチャー・パターンです。
  • コンテナーは、cgroups を利用して、VM よりも軽量のプロセスをそれぞれ分離することを可能にする Linux の機能です。
  • ラムダは、特定のイベントを受けて起動し、そのイベントを処理してから停止する、一時的な関数です。

まとめ

私が最近協力したスタートアップ企業で、初のハッカソンが開催されました。私たちは 24 時間のうちに多くのプロジェクトを作成しましたが、その多くには、ラムダ関数がデプロイされていました。それは、ラムダ関数は高速で安価 (実際のところ、無料) であるためです。ラムダ関数を使用することで、作業を 3 つまたは 4 つのチームで分担することができました。スコープは明確に定義されていたので、イベント・ベースのプロジェクト (スタック・ボットを開発するようなプロジェクト) には最適な方法でした。一部の開発者は初めのうちはフレームワークを使用して作業していましたが、わずか数分でラムダ・コードを作成、デプロイ、モニタリングできるように改良することができました。

このすべての仕組みは、プロジェクトの成長に伴ってたちまち壊れる可能性があります。けれども開発者向けツールを改善していけば、このパラダイムは開発者を正しい方向、つまり遅延実行、効果的なコスト、使いやすさ、共有の容易さという開発の方向に導いていくと思います。ラムダの下に、専門的なインフラストラクチャーのすべてを移行しなければならないわけではありません。おそらく、必要なフレームワークの数は少なくなり、本当に機能する勝ち残ったフレームワークが増えるでしょう。さらに、絶対不可欠となるのは、数百もの関数をデプロイして保守する方法を定義することです。

皆さんも早速試してみてください!ラムダは実用上の理由から、すでに画期的なテクノロジーとなっていますが、貢献する余裕はまだたくさんあります。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing
ArticleID=1062004
ArticleTitle=ラムダ関数による迅速なプロトタイピング
publish-date=06222018