「サーバーレス」の次の段階に進むためのキーワード

この記事は、Serverless Advent Calendar 2019の23日目の記事です。

adventar.org

 

Serverlessというキーワードが登場*1して7年、Google App Engine Preview*2から11年、AWS Lambda*3から5年、みなさんサーバーレスしてますか?

FaaS(Function-as-a-Service)を中心としたサーバーレスなシステム開発事例はいよいよ普及フェーズに入ってきたところですが、その一方でステートレス性などプログラミングモデルとしての制約の厳しさなど課題が多くあることも事実です。というわけで、「サーバーレス」という技術ムーブメントで次の段階に進むためのキーワードをいくつか紹介します。

Stateful FaaS

ソフトウェア実行基盤として、プロセス上のメモリやサーバ上のファイルシステム上のデータを永続化しない*4、ステートレスという性質によって、FaaSはクラウド基盤側が「自由に」スケールさせることができ、その結果として消費したCPUやメモリの量によって従量課金されるというのがFaaSの本質的な特徴です。

スケーラブルなソフトウェア実行基盤としては極めて重要なこのステートレス性ですが、プログラミングモデルとしては面倒なことが増えているというのも事実です。そこで、ステートレスなソフトウェア実行基盤の上に、外部のデータストアと連携してプログラミングモデルとしてステートフルなプログラミングモデルを提供しようという仕組みが登場してきています。

最も有名なものがMicrosoft AzureのDurable Functions*5、特にそのEntity Funtions*6ですが、これらはAzure FunctionsというFaaSの上で、Azure Storage*7を組み合わせて実現しています。ほかにも、KnativeとAkka Clusterを組み合わせたCloudstateなどがあります。

このように、FaaSの「今の在り方」にこだわらず、プログラミングモデルとしてどうすべきか、というのがサーバーレス開発の次を考える上で最も重要なことです。

Streaming Processing

FaaSと相性の良いイベントドリブンなアーキテクチャの採用に伴って、これまでビッグデータ分析のような場面が主に想像されていたストリーム処理を、サーバーレス開発でも活用できます。

もともとビッグデータ分析のためのOSSがいくつも開発されてきたためエコシステムとして十分に育っているのが最大の特長です。プログラミングモデルとしてもこなれています。例えば、Apache Flinkを使って、いわゆるワードカウント(英単語ごとの出現回数を数え上げる)をScalaで実装した場合のソースコードです。

val windowCounts = text
  .flatMap { w => w.split("¥¥s") }
  .map { w => WordWithCount(w, 1) }
  .keyBy("word")
  .timeWindow(Time.seconds(5), Time.seconds(1))
  .sum("count")
(省略)
case class WordWithCount(word: String, count: Long)

継続して流れてくるデータストリームに対して、Scala上のDSLとして抽象度の高いソースコードでプログラムを書くことができます。

考え方の基本は、ストリームデータの一つずつに「キー」が存在し(ここでは英単語)、キーごとに状態(ここではこれまでに登場した出現回数)を持って状態をひたすら更新していくというものです。

Cloud 2.0

ちょっと名前には仰々しさがありますが、今年の2月にPaul Johnston氏によって提唱されたキーワード*8です。制約の多いFaaSや、制約しかないDSLのさらに先として、様々なマネージドサービスの活用によってFaaSのような「自分の書いたプログラム」から脱却しようというものです。

複雑なシステムを、ID基盤やMicrosoft GraphのようなAPIの組み合わせに分解し、ワークフローエンジンやBIツールなどで連携させていくことで、従来のようなウェブアプリケーションフレームワークの上でシステムを実現するのでは無く、クラウドサービスを連携させるための設定(これ自体も、極めて制約が強いDSLですが)として実現できることが増えてきました。古くからのキーワードで言うなら、Infrastructure as Codeにおける「Code」の部分を新しい表現にしたものです。

今年はTerraformのDSL(HCL)を大幅に改善したTerraform 0.12の登場に始まり、HCLの癖の強さをそもそもTypeScriptやPythonなどの内部DSLに置き換えることで大幅に改善するPulumiが急速に普及したほか、AWSからもCloudFormationをラップして、やはりTypeScriptやPythonの内部DSLとして記述できるAWS CDKが登場するなど、Cloud 2.0を実現するための下準備が整った年でした。

これは余談ですが、この20年ほどで、プロプライエタリなソフトウェアよりも、コミュニティによるOSSのほうが結果的に良いソフトウェアが生まれやすいという状況になったのはご存知の通りですが、これはある種その「揺り戻し」でもあり「発展」とも言えます。大量の開発者を抱えたメガクラウドと、そこに載っかる大量の利用者からの不具合報告、改善要望があれば、そのクラウドサービスを構成するソフトウェア自体がプロプライエタリであっても十分な品質のサービスが提供されています。その一方で、OSSによって様々なライブラリやミドルウェアが開発され、自分で開発せずOSSミドルウェアを利用するようになったという流れの先にあると言うこともできます。もちろん、クラウドサービスを実現するソフトウェア自体をOSS化する流れもあり、その最大例がKubernetesです。

クラウドサービスの内部で使われているOSSの開発者との軋轢、という問題*9も生じていますが、まず利用者としては自分で書いて運用するべきコードを減らし、少ないコードでやりたい事を実現することを考えていくべきです。

Serverless Spectrum

AWS Lambdaのインパクトが大きかったため、サーバーレスと言えばステートレスな関数型プログラミングという印象が強いですが、実際はここまで紹介したキーワードからも判るとおり様々な実現方法があります。プリズムで分解した虹色のSpecrtum(スペクトル)のように、サーバーレスかどうか1/0ではなく、様々な形態が地続きで存在しています。

インターフェース一つ取っても、AWS Lambdaを代表とする言語内の関数というやり方もあれば、HTTP*10やgRPC*11を使う場合もあります。

サーバーレスにおいて最も重要なことは、クラウドをクラウドらしく活用(Cloud Native)することで、より少ない手数(≒Code量+運用作業量+α)でより大きな価値のあるシステムを構築していこう、そして従量課金を活用してスタートアップ段階のアジリティも高めよう、という継続的な挑戦を続ける気持ちです。

その一方でこれまでのレガシーなシステムの存在や価値は決して無視できるものでは無く、これからその間を埋めるためのものがたくさん登場していくことでしょう。そして「サーバーレス」として表現される対象もまた、より広いスペクトルとなって拡がっていくことでしょう。過去の記事でも書きましたが、言葉の定義にこだわらず、楽しいことを実現するときに考えを整理するための道具、指針ぐらいに捉えていくのが良いと思います。

まとめ

というわけで、4つほどキーワードを紹介しました。

このあたりのキーワードを追いかけていけば、より楽しくサーバーレス業界の動きを捉えられるのではないかなと思います。やっていき!

 

*1:2012年: Why The Future Of Software And Apps Is Serverless - ReadWrite

*2:2008年: Google App Engine Blog: Introducing Google App Engine + our new blog

*3:2014年: Introducing AWS Lambda

*4:プロセスやサーバが再利用され残っている場合もあれば、別のサーバや新しいプロセスに切り替わり消える場合もある

*5:Durable Functions の概要 - Azure | Microsoft Docs

*6:持続エンティティ - Azure Functions | Microsoft Docs

*7:Azure基盤への依存を切り離すためRedisへの対応も進められています。
Durable Redis Provider · Issue #253 · Azure/durabletask

*8:Cloud 2.0: Code is no longer King — Serverless has dethroned it

*9:個人的な立場としては、元となったOSSの開発者に対してそれに見合った利益が支払われるべきという思いが強いです。

*10:KnativeやGoogle Cloud RunはHTTPリクエストがインターフェースとなっているほか、AWS LambdaもCustom RuntimeのインターフェースはHTTPです。

*11:たとえばAzure FunctionsでC#以外を使う場合、Language Workerとの間は最終的にgRPCでやりとりされます。