多分わかりやすいサーバーレスアーキテクチャ入門その2 〜サーバーレスアーキテクチャのメリデリ!!〜

こんにちは、サイオステクノロジー技術部 武井です。合計3回シリーズの連載「多分わかりやすいサーバーレスアーキテクチャ入門」の2回目は、サーバーレスアーキテクチャのメリデリを解説致します。サーバーレスアーキテクチャの対局をなす仮想マシン(以降はIaaS(Infrastracture as a Service)と呼びます)、IaaSとサーバーレスアーキテクチャの中間に位置するPaaS(Platform as a Service)との違いを説明する中で、サーバーレスアーキテクチャとは何者なのかというのを、私なりにわかりやすくご説明していきたいと思います。

※全シリーズの記事一覧はこちら

IaaS、PaaS、サーバーレスアーキテクチャのメリデリ

いいことづく目のサーバーレスアーキテクチャですが、残念ながらシステム構築におけるあらゆるケースに対応できるような銀の弾丸ではありません。IaaS、PaaS、サーバーレスアーキテクチャのメリット・デメリットをおさえた上で、適材適所を図らなければ、無駄に運用コストがかかったり、制約が多すぎて顧客のニーズを満たせないケースが発生します。

そこで本章では、IaaS、PaaS、サーバーレスアーキテクチャのメリット・デメリットを表にしてみました。アーキテクチャ選択の際の一助になれば幸いです。

表中の◎、◯、△については、以下のとおりです。

◎・・・とってもよい( ´∀`)

◯・・・普通(・∀・)

△・・・イマイチ(´・ω・`)

IaaS PaaS サーバーレスアーキテクチャ
保守性
自由度
開発工数
費用
スケーラビリティ
移植性

以降は表中の各項目について、詳細にご説明します。

保守性

IaaS PaaS サーバーレスアーキテクチャ
保守性

保守性とは、サービス開始後、アプリケーション正常稼働の維持のために発生する作業の効率性を定めた指標になります。OSのセキュリティパッチ適用、アプリケーションフレームワークやライブラリの脆弱性対応、バージョンアップ等、その作業内容は多岐にわたり、しかも不定期に発生します。

こちらについては、サーバーレスアーキテクチャが有利です。

IaaSは、先にご説明したとおり、OSのレイヤーからシステム管理者が面倒を見なければなりません。OSのセキィリティパッチやアプリケーションの脆弱性対応はシステム管理者自身が実施する必要があります。

PaaSについては、アプリケーションのレイヤーより下位の層はパブリッククラウドの責任範囲ですので、OS周りの対応は不要ですが、アプリケーションのレイヤーのメンテナンスは、やはりシステム管理者が実施しなければなりません。昨今話題になっているStrutsの脆弱性対応がその最たる例ですし、記憶に新しいと思います。そのたびにシステム管理者は、各部署や顧客と調整を行い、メンテナンス日程を調整、作業を手順化して、場合によっては休日夜中に対応するという、なんとも大変な作業を強いられるのです。

サーバーレスアーキテクチャでは、インフラのレイヤーは全て抽象化されます。つまり、今までシステム管理者を煩わせていたセキュリティパッチ当てやライブラリのバージョンアップなどは一切気にせず、コーディングのみに集中できるのです。

実際は、サーバーレスアーキテクチャとはいってもサーバーがないわけではありません。パブリッククラウドが管理するデータセンター上にあり、パブリッククラウドのシステム管理者がしっかり運用管理してくれています。そんな人達のおかげで、サーバーレスアーキテクチャでは、利用者はコーディングにのみ集中できるのですから、感謝しなければなりません。

自由度

IaaS PaaS サーバーレスアーキテクチャ
自由度

自由度とは、システムを構築する際に選択するランタイム(開発言語)、ネットワーク構成、ストレージなどをどの程度自由に選択できるかという指標になります。

こちらは、もちろんIaaSに軍配が上がります。OSのレイヤーから扱えるので、開発言語は自由にインストールできますし、接続するストレージのプロトコルもCIFS、NFS、WebDav、iSCSIと種別を選びません。オンプレミス上のサーバーとほぼ同じ自由度で構築が可能です。

対して、PaaSですが、OSのレイヤーは抽象化されており、システム管理者が扱えるのはランタイム(開発言語)より上のレイヤーになりますので、IaaSほどの自由度はありません。実行出来るランタイムは、パブリッククラウドが提供するものに限られ、例えば、node.jsで動作するアプリケーションを実行させたいのであれば、node.jsを提供しているPaaSを利用することになります。

ランタイムより上の層は自由に扱えますので、フレームワークは自由に選定出来ます。PHPであればCakePHPや、今や飛ぶ鳥落とす勢いのBEAR.Sunday、JavaであればSpring Bootなどになりますかね。

ちなみに、2018年9月4日現在、AzureのPaaSサービス「Azure App Service」のWindows版でサポートされるランタイムは以下になります。

  • .NET Framework
  • Java
  • PHP
  • Python
  • node.js

PaaSにおけるネットワークについては、注意が必要です。ネットワーク構成がIaaSほど自由にならないことがあります。例えば、AzureのPaaSサービスである「Azure App Service」では、通常の設定方法では、仮想ネットワーク内に配置することは出来ません。つまり、仮想ネットワーク内のリソースからAzure App Serviceにアクセスすると、インターネット経由で通信が行われます。顧客の要件にとっては、いくらデータがSSL通信で保護されるからと言って、インターネット経由でデータが流れることをよしとしない場合もあると思います。

このケースに備えて、Azureは「App Service Environment」というサービスを用意しており、このサービスを利用すればAzure App Serviceを仮想ネットワークに配置することが可能です。問題なのはそのお値段で、一番低価格のl1インスタンスでさえ、月額約18万円かかります。年間にすると、約216万円、ちょっとした新車が買えるレベルです。つらみー(´・ω・`)

PaaSや、これからご説明するサーバーレスアーキテクチャは、こういったややこしい問題をはらんでおります。

サーバーレスアーキテクチャは、さらに自由度が下がります。ランタイムはある程度自由に選択は可能ですが、コードの実行形態が「関数」という最小単位であるがゆえに、アプリケーションフレームワークのメリット(例えばRuby on RailsのScaffold的な)を活かした設計や、有用な外部ライブラリを使った実装が出来ません。あくまで、パブリッククラウドベンダーが用意した独自の「関数」という箱の中にコードを入れ、パブリッククラウドベンダーが用意したイベント駆動形式(Web Hook、メッセージキューやストレージからのトリガー)によってのみ実行されます。

様々な制約があるがゆえに、設計や実装におけるパラダイムシフトも必要になります。

参考までに2018年9月4日現在、Azure Functionsで利用できるランタイムは以下のとおりです。

  • C#
  • F#
  • Java Script

開発工数

IaaS PaaS サーバーレスアーキテクチャ
開発工数

開発工数は、その名の通り、アプリケーションを完成させるまでに必要な工数になります。この工数にはインフラ周り(OSやミドルウェア、ランタイムのインストール・セットアップ)も含みます。

これは言わずもがな、サーバーレスアーキテクチャが圧倒的に有利な状況です。今までご説明してきましたように、サーバーレスアーキテクチャは「関数」と呼ばれる、アプリケーションを実行する最小形態以外のレイヤーはすべて抽象化されており、アプリケーション開発者は関数の中にコードを記述するだけで、様々な処理を実行出来ます。先程のハロワの例でも実現したとおりです。

しかしながら、「開発工数」は削減が出来ても、「学習工数」は予想以上にかかる可能性があるということは意識しておかなければなりません。

先程も申し上げましたように、サーバーレスアーキテクチャは、様々な制約があるがゆえに、大きなパラダイムシフトを強いられます。

その一例を挙げます。今までのWebアプリケーションは、大きな単一プロセスが複数のスレッドを起動し、スレッド単位でHTTPリクエストを処理していました。こうすることで、CGI隆盛期にあったような、HTTPリクエストごとのプロセス起動コストを抑えて、高速なレスポンスを実現します。

しかしながら、サーバーレスアーキテクチャは、イベント駆動(Web Hook、メッセージキューやストレージからのトリガー)によってコンテナを起動して処理を実行し、その後はコンテナを破棄します(正確に言いますと、ある一定のルールに基づきコンテナを再利用しています)。つまり、動作的にはステートレスなんです。

ステートレスであるということは、リレーショナル・データベースで多く採用されているコネクションプーリングが使えません。コネクションプーリングは、最初に一定数データベースに接続を行い、そのコネクションをプーリングして、HTTPリクエスト単位で使い回すという技術です。先程も申し上げましたように、サーバーレスアーキテクチャはステートレスになるので、それぞれのHTTPリクエストは共有できるコンテキストはありません。つまり、コネクションプーリングは実現出来ないのです。だからといって、イベント駆動をトリガーにして、都度データベースに接続するというのも多大なるコストが発生します。もともと、サーバーレスアーキテクチャは、突発的なリクエストに応じてほぼ無限大にスケールすることを前提としているので、このアーキテクチャでは、コネクションを食いつぶしてしまいます。(ちなみにサーバーレスアーキテクチャでリレーショナル・データベースを用いるのはアンチパターンとされているようです)

そこで、サーバーレスアーキテクチャには、コネクションレスなデータベースを用いることが多くあります。AWSではDynamoDB、AzureではCosmosDBがその代表です。DynamoDB、CosmosDBともにスキーマレスなNoSQLデータベースです。従来のリレーショナル・データベースとはアーキテクチャが大きく異なります。と、いうことは、まずサーバーレスアーキテクチャを導入するということは、NoSQLデータベースの学習コストを必要とする場合が多くあります。こういった理路により、サーバーレスアーキテクチャは、それ自身も多少なりの学習コストを必要としますが、サーバーレスアーキテクチャに依存するアーキテクチャを学習するコストも合わせて発生します。

もう一つ例を挙げさせて頂きます。ステートレスであるがゆえにセッション管理にも工夫が必要になります。ステートフルなアプリケーションの場合は、Webアプリケーション内部でセッションを生成しデータストアに保存、クライアント側にはそのセッションを一意に識別するIDをCookieに乗せて発行し、クライアントはリクエストの都度にそのセッションIDをCookieヘッダーに乗せて、Webアプリケーション側に送信することで、ユーザーを一意に識別します。

しかしながら、先程も説明しましたように、サーバーレスアーキテクチャはステートレスなので、それぞれのHTTPリクエストは共有できるコンテキストはありません。つまり、サーバー側でセッションの管理を行うことができず、クライアント側で状態を持つ必要があります。その手法の最たる例は、JSON Web Tokenを用いた方法になります。(JSON Web Tokenの詳細については、本ブログの記事「JSON Web Tokenによる認証」を参照下さい)

Azure Active DirectoryやGoogle、Yahoo!などのOpenID Connect Providerで認証して、JSON Web Token形式のIDトークンを発行してもらい、サーバーレスアーキテクチャの関数内でIDトークンの検証をするというのがまずは思いつく方法です。しかしながら、その方式だと、全ての関数でIDトークンを検証しなくてはならなくなり、冗長なコードになってしまいます。そのような横断的な処理はAPI Gatewayに任せるというのが、ここ最近の潮流になってきております。詳細は、本ブログの記事「AzureのAPI Gateway(API Management)を用いてOpenID Connect Providerより発行されたJWTを検証」をご覧頂ければと思います。

ここでまた、「API Gateway」という新しいキーワードが出てきました。先程のNoSQLデータベースと同様、サーバーレスアーキテクチャが依存するアーキテクチャを学習しなければいけなくなりました(´・ω・`)

説明がいささか長くなりましたが、このような理路で、サーバーレスアーキテクチャは開発工数を削減することは出来るが、サーバーレスアーキテクチャに依存する新しいアーキテクチャを学習するコスト、また新しいパラダイムの到来による新たな設計技法を学ぶコストが発生することがあります。そこは注意しなければいけない点になります。

費用

IaaS PaaS サーバーレスアーキテクチャ
費用

費用においても、サーバーレスアーキテクチャの勝利です。

仮想マシンを稼働している時間単位で課金されているIaaSやPaaSと違い、サーバーレスアーキテクチャは純粋に関数を実行した時間のみ課金されます。

先程のハロワを例にして、実際に料金を計算してみましょう。ハロワが月に300万回実行されると想定し、その際のIaaSとサーバーレスアーキテクチャの料金を比較してみます。このケースでは、サーバーレスアーキテクチャにはAzure Functionsを利用すると想定します。(2018年9月5日時点での東日本リージョンにおける料金をもとに計算をしております)

■IaaSの場合

D2s_V3シリーズ(CPU2コア、メモリ8GB)を一ヶ月稼働させるとします。

合計:9,821円

仮想マシンは、時間単位の課金なので、どれだけハロワが実行されても、この料金には変更はありません。

■サーバーレスアーキテクチャの場合

Azure Functionsの料金形態は少々複雑で、「リソース使用量」と「実行回数」によって算出した料金を足し合わせたものが最終的な料金となります。

<リソース使用量>

関数単体が消費するメモリ量に、関数の実行時間をかけ合わせ、それに一定のレートをかけ合わせたものになります。

例えば、ハロワのAzure Functionsが一回の実行あたり128MBを消費し、1回あたりの実行時間は2秒かかるとします。

2018年9月5日時点の東日本リージョンでは、1GBを消費する関数を1秒実行すると、0.001792円の料金が発生します。

単位がGBなので、ハロワのAzure Functionsが一回の実行あたりに利用するメモリ128MBをGBに変換します。

128MB /1024MB = 0.125GB ・・・ ハロワ一回あたりのメモリ消費量

これをもとにその月で使用したメモリ量の合計を算出します。

0.125GB(ハロワ一回あたりのメモリ消費量) × 2秒(ハロワ一回あたりの実行時間) × 300万回/月(ハロワ一月あたりの実行回数) = 750,0000GB秒 ・・・一月でハロワが使用したメモリ量の合計

ただし、Azure Functionsには、嬉しいことに400,000GB秒/月の無料実行分がついてきます。それを加味すると、その月で使用したメモリ量の合計は以下のとおりになります。

750,0000GB秒 – 400,000GB秒 = 350,000GB秒・・・一月でハロワが使用したメモリ量の合計(無料実行分を引いたもの)

これに対して、先程ご説明もしましたが、1GBを消費する関数を1秒実行すると、0.001792円の料金が発生します。つまり最終的な料金は以下になります。

350,000GB秒 × 0.001792円/GB秒 = 627.2円

<実行回数>

こちらは単純に実行回数ごとに加算される料金になります。東日本リージョンでは、2018年9月5日現在、100万回実行あたり22.40円です。300万回/月実行するという今回の条件では料金は以下になります。

22.40円(100万回実行したときの料金) × 300万回/100万回 = 67.2円

リソース使用量と実行回数を合わせると、694.4円となり、IaaSの9,821円とはかなり大きい差が開きました。一年間にすると、109,519円も得をしますので、毎年新しいiPhoneに機種変更ができます。うれしみー(^o^)

サーバーレスアーキテクチャは、イベント駆動によるトリガーに応じて必要なときだけコンテナを起動し処理を実行します。処理が終了するとコンテナを破棄しますので、処理をしていないときはリソースを占有していません。このような形でリソースを効率的に利用することにより、低価格を実現しています。

スケーラビリティ

IaaS PaaS サーバーレスアーキテクチャ
スケーラビリティ

スケーラビリティは、スケールアウト(負荷に応じて、サーバーの台数を増やすことで処理能力を向上させること)の柔軟性、つまり負荷に応じた必要な処理能力の提供可否を示す指標となります。

こちらも、サーバーレスアーキテクチャが有利です。

IaaSでスケールアウトを行うためには、パブリッククラウドベンダーによって多少の設定の差異はあるものの、概ね以下の手順になります。

  1. ロードバランサーを構築する。
  2. スケールアウト、スケールインするための指標を設定する。(例えばサーバー全体のCPU使用率の平均値が、80%以上になったらスケールアウト、50%を下回ったらスケールインなど)
  3. スケールアウトするサーバーの台数の上限値を決める。

様々な設定をしなければいけない上に、当然といえば当然なのですが、スケールアウトの上限に限界があります。例えば、スケールアウトするサーバーの台数を10台と決めますと、どれだけ負荷が上がったとしても、10台以上はスケールアウトしません。つまり、ある一定以上の負荷が発生すると、処理能力は頭打ちということになります。

PaaSにおいても同様です。IaaSと比較しますと、スケールアウトの設定がある程度自動化されていることが多いですが、やはりスケールアウトするサーバーの台数に上限があるのには変わりありません。

しかしながら、サーバーレスアーキテクチャは、特に何の設定を行わなくても、負荷に応じてほぼ無限にスケールアウトします。これは、「イベント駆動によってコンテナを生成」→「処理を実行」→「コンテナを破棄」というライフサイクルを実現することで、IaaSのように処理が発生していないときにもリソースを占有するということはなく、必要なときに必要に応じて必要な量だけリソースを確保するというアーキテクチャがもたらす恩恵といえます。

サーバーレスアーキテクチャは、予測できないような突発的なリクエストが発生するユースケース(イベントプロモーション時のWebサイトへのアクセス等)においては、大きなアドバンテージを発揮します。

移植性

IaaS PaaS サーバーレスアーキテクチャ
移植性

移植性とは、開発したアプリケーションを他のパブリッククラウドサービスやオンプレミスに移行する際、どれだけ容易にそして確実に実施出来るかを示す指標となります。

ここまでサーバーレスアーキテクチャの連勝でしたが、さすがにこれはIaaSの勝利です。

IaaSにおいては、OSから上のレイヤーは全てシステム管理者が自由に扱えますので、ネットワーク、ストレージ、ランタイム、もちろんアプリケーションも全て、ほぼ忠実に移植が可能です。

PaaSにおいては、OSを含むそれより下のレイヤーは抽象化されていますので、IaaSと比べると、移行に制約が多くなります。例えば、移行先のパブリッククラウドサービスが提供するPaaSに、移行元のアプリケーションが利用するランタイムが提供されていなかったり、仮に提供されていたとしてもバージョンが合わないと、その分、移行は困難になります。場合によってはアプリケーションの大幅な改修が必要になってしまいます。

サーバーレスアーキテクチャは、さらに移植性が低下します。例えば、Azureが提供するサーバーレスアーキテクチャであるAzure Functionsを一例として考えてみます。

Azure Functionsは、それ単体でサービスを提供することはないのではないでしょうか?アプリケーションには必ず、認証・認可・ロギング・データの永続化などが必要になります。

Azure Functionsでデータの永続化を行う場合、本章の「開発工数」の項でもご説明したようにリレーショナル・データベースを使うことは出来ません(向きません)。必然的に、Azureが提供しているコネクションレスなNoSQLデータベース「CosmosDB」を採用することになります。ここで、「CosmosDB」を使わずとも、例えば、AWSが提供している「DynamoDB」を使うという選択も可能です(多分)。しかしながら、Azure FunctionsとCosmosDBはとても相性がよく、Azure FunctionsからCosmosDBを使う場合は、「バインド」という機能を使うことで、CosmosDBへの面倒な接続処理を記述することなく、CosmosDBへの読み書きを簡単に行うことが可能です。その他、Azure FunctionsからCosmosDBを使うことによって、様々な恩恵を享受出来るので、やはりCosmosDB一択となるでしょう。

認証・認可も同様です。例えばAzure FunctionsでRestfullなAPIを作成する場合に発生する横断的な処理(認証・認可・ロギング)は、API Gatewayに委任するというのが昨今の趨勢となっております(API Gatewayについての詳細は、しつこいようですが、私の記載したブログ「AzureのAPI Gateway(API Management)を用いてOpenID Connect Providerより発行されたJWTを検証」をご参照頂き、「いいね!」を忘れないで下さい)。

Azureが提供するAPI Gatewayサービスに「API Management」というものがあります。これまた、とてもAzure Functionsと相性がよく、セットで使うことで、面倒な設定を簡略化出来るケースが多くあります。例えば、API Managementのバックエンドに設置するAPIを設定するときにも、既に作成済みのAzure Functionsをインポートすることで、簡単にAzure FunctionsをAPI Managementのバックエンドに配置することが可能です。つまり、Azure Functions、CosmosDB、API Managementの組み合わせは、カレーと福神漬け、明太子とごはんのように、相性がよく、お互いの依存度がかなり強いサービスと言えます。

この組み合わせ(Azure Functions、CosmosDB、API Management)をAWSにマッピングすると、2018年9月5日現在では、以下のようになるかと思います。

  • Azure Functions → AWS lambda
  • CosmosDB → DynamoDB
  • API Management → API Gateway

ここで、アプリケーションをAzureからAWSに移行することになったと考えます。上記の機能を移行することは、ほぼほぼ困難と言えます。Azure Functions、CosmosDB、API ManagementともにAzureが提供しているマネージドサービスですので、根底にあるアーキテクチャは、AWSのそれと変わらなくても、設定方法はAzure固有のものとなります。それらをAWSに移行するときの手間は想像に難くありません。

サーバーレスアーキテクチャは、サーバーレスアーキテクチャを提供するパブリッククラウドの他のサービスとかなり強い結びつきを余儀なくされ、移植性が低くなり、いわゆる「ベンダーロックイン」が発生します。

しかしながら、個人的な所感でありますが、それほどベンダーロックインは悪でしょうか?例えば、Azure からAWSへの移行というユースケースがどれだけの確率で発生するのでしょうか?そんな、レアなケースを考えるよりも、パブリッククラウドが提供するサービス間連携によるメリットを最大限に活かしたシステム構築を行ったほうがいいケースもあるのではないでしょうか?

結局どんなときに使うの?

メリデリの話がいささか長くなりました。結局はどんなときにサーバーレスアーキテクチャを使うと、みんなが幸せになれるのでしょうか?私は以下のように考えます。

  • 予測できないような突発的なリクエストが発生することがある(イベントプロモーション時のWebサイトへのアクセス等)
  • セキュリティパッチ当てやライブラリのバージョンアップなどの運用管理コストをできるだけ減らしたい
  • パブリッククラウドのランニングコストをできるだけ減らしたい
  • 新しもの好き

逆に、OSやミドルウェアに細やかなチューニングが必要であったり、ランニングコストを固定化したい(期初に予算を固定化しなければならない企業や団体など)場合には、サーバーレスアーキテクチャは不向きであると言えます。

やはり、ことITの世界においては、全てのケースに通じる「銀の弾丸」はないのだなぁとつくづく感じました。

ちなみに一番最後の「新しもの好き」は最も重要だと思います^^;

今までご説明してきたように、サーバーレスアーキテクチャは、システム開発における新たなパラダイムシフトの到来であり、発想の転換が必要になります。今までの常識が通用しない場面もあり、相当に辛酸を嘗めることもあるかと思います。そんな苦難に耐えるためには「技術が三度の飯より好き」というマインドセットが必要なのではないかと感じます

最後に

いかがでしたでしょうか?サーバーレスアーキテクチャは、あらゆるケースに対応できるような銀の弾丸ではなく,IaaS、PaaS、サーバーレスアーキテクチャのメリット・デメリットをおさえた上で、適材適所を図らなければなりません。しかしながら、ベストマッチすれば、これほど最強な武器はないのではないでしょうか?本記事が、サーバーレスアーキテクチャを検討している方の一助になれば幸いです。

次回は、Azure Functionsで実践的なアプリケーション(LINE風なチャットアプリ)を作ってみたいと思います。

次回はこちら → 多分わかりやすいサーバーレスアーキテクチャ入門その3 〜 「Azure Functions」を使って、クラウドネイティブなLINE風チャットアプリを作ろう!! 〜

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

5人がこの投稿は役に立ったと言っています。

2 COMMENTS

Kazuki Ota

素晴らしい記事ありがとうございます。
細かいところですが Azure の App Sevice の Windows 版は node.js もサポートしてますので気が向いた時に追記していただければ嬉しいです。

あと、一箇所 IaaS を IaaP と typo してる箇所があります。 IaaP で検索すると見つかると思います。

返信する
アバター画像 武井宜行

Kazuki Ota様

武井です。本ブログを読んで下さり誠にありがとうございます。node.jsとタイポの件、ご指摘頂きまして誠にありがとうございました。早速修正させて頂きました。

今後とも、本ブログをよろしくお願い致します。

返信する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です