maybe daily dev notes

私の開発日誌

Infrastructure from Code (IfC) ツールまとめ

昨今Infrastructure from Code (IfC)という概念をよく耳にします。先日もAWSのGregor Hohpeが関連する記事を書いていました。

architectelevator.com

この記事では、Infrastructure from Codeとはなにか簡単に紹介し、具体的にどのようなツールがあるか網羅的にまとめます。

Infrastructure from Codeとはなにか

Infrastructure from Code (IfC) とは、その名の通り、Infrastructure as Code (IaC) に関連する概念です。IaCとの根本的な違いは、IaCは開発者がインフラを明示的に意識して構成を記述するのに対し、IfCでは開発者がインフラをできるだけ意識しないよう抽象化を試みていることです。これにより、差別化に繋がらない重労働ができる限り排除された高い開発者体験を目指します。

Infrastructure from CodeにおけるCodeとは、アプリケーションのコードと捉えるのが良いでしょう。インフラはアプリのコードから生成される、というのがfrom Codeの意味するところです。as CodeにおけるCodeとは指すものが違うことに注意してください。

Infrastructure from Codeという言葉の起源は調べた限りは定かでないですが、この記事を見ると、少なくとも2021年には存在した概念のようです。パブリッククラウドの利用が普遍化する中で、頻出のアーキテクチャパターンを徹底的に抽象化する試みと言えるでしょう。

IfCに共通する特徴

今回調べた限り、IfCには以下の共通項があります。インフラを抽象化し、開発者体験を高めるというのがゴールなればこそですね。

  • 高い開発者体験
    • ローカル実行、ホットリロード、デバッガ、REPL、自動計装など
  • 高度に抽象化されたインフラ
    • アプリのコードから、インフラ定義は自動生成される
    • ユーザーはクラウド側の実装を意識する必要がない
    • しばしばマルチクラウド対応を謳っている
  • 特定ユースケースに特化
    • インフラをうまく抽象化するため、あらゆるユースケースに対応するのは難しい
    • REST API、キューワーカー、ウェブアプリ辺りに注力しているものが多い

ここまで読んでピンとこないという方、百聞は一見にしかずですから、IfCを体現するツールたちを具体的に見るのが早いです (次節へ)。

IfCツールの例

それでは具体的なIfCツールを見ていきましょう。芋づる式に見つけていきましたが、番外編まで含めると10近くありました! 以下ではざっくり次の観点でまとめます:

  • 開発元: ツールを開発する会社の概要です
  • 特徴: ツールの特筆すべき点を主観で紹介
  • 言語: プログラミング言語について
    • ツール自体の開発言語: そのツール自体がどの言語で書かれているか。開発者の思想が顕れるポイントです
    • ユーザーが使う言語: ツールのユーザーはどの言語を利用できるか
    • 中間生成物の言語: インフラデプロイのために、どのIaCを生成するか (TerraformやCFnなど)
  • デプロイ先: インフラはどこにデプロイされるか (AWS, Azureなど)
  • ライセンス: ツールがどのライセンス下でコード提供されるか
  • ビジネスモデル: 開発元の会社はいかに利益を得るか
  • その他: その他注目すべき点 (あれば)
  • コード例: 実際にどのようなコードで記述されるか

なお、ツールの順番に大きな意味はありません。

Wing

  • 開発元: Wing Cloud, Inc.
    • AWS CDKの父EladがAWSを辞めて創業したスタートアップ
  • 特徴
    • 専用の言語Winglangを提供することで、最適な開発体験を目指す
    • 同時にJavaScriptCDKなど既存エコシステムには乗っかろうとするしたたかさもあり
  • 言語
    • ツール自体の開発言語: Rust, TypeScript
    • ユーザーが使う言語: Winglang (JavaScriptに似た独自言語)
    • 中間生成物の言語: Terraform
  • デプロイ先: AWS, Azure, Google Cloud (現状はAWSのみ)
  • ライセンス
  • ビジネスモデル
  • その他
    • 最近$20Mの出資を受け勢いづいている様子。
    • Wing社自身は、自分たちがIfCに分類されるとは今のところ明言してない。 しかし体現しているものはIfCに近い。
  • コード例
bring cloud;

let queue = new cloud.Queue(timeout: 2m);
let bucket = new cloud.Bucket();
let counter = new cloud.Counter(initial: 100);

queue.setConsumer(inflight (body: str): str => {
  let next = counter.inc();
  let key = "myfile-${next}.txt";
  bucket.put(key, body);
});

Darklang

  • 開発元: Dark Inc.
  • 特徴
  • 言語
    • ツール自体の開発言語: F# (Rustと迷ったらしい)
    • ユーザーが使う言語: Darklang
    • 中間生成物の言語: n/a (Deploylessというコンセプトがあり、中間生成物は見えない)
  • デプロイ先: Dark社のPaaS
  • ライセンス
  • ビジネスモデル
    • 不明 今はスポンサーを募集中
    • 順当に行けばPaaSの利用料金?
  • その他
    • 今後は生成AIを組み合わせるアプローチ (DarklangAI) にオール・インするらしい
      • こちらはまだ開発中で詳細不明だが、新生Darkとなるのでは
  • コード例
    • IDEのノードエディタでインフラを定義し、Darklangでアプリを実装する (=DarkのIDE上でしか実装できない)
    • Darklang自体はOCamlに似た言語?すごく・・・関数型です・・・

Klotho

  • 開発元: CloudCompiler, Inc.
    • Riot Gamesの同僚同士が起業?
  • 特徴
    • アプリのインラインコメントでアノテーションすることでインフラを定義する
  • 言語
    • ツール自体の開発言語: Go
    • ユーザーが使う言語: C#, Go, JavaScript, Python, Java
    • 中間生成物の言語: Pulumi
  • デプロイ先: AWS, Azure, Google Cloud (現状はAWSのみ)
  • ライセンス: Apache-2.0
  • ビジネスモデル
    • 追加機能があるKlotho Proを有償提供予定か
  • その他
    • 自動生成のPulumiコードをカスタマイズする仕組みもある Changing Pulumi Parameters
    • 生成AIと対話しながらインフラ定義を生成できるツール (InfraCopilot) を提供予定
  • コード例
/* @klotho::expose {
 *  id = "pet-api"
 *  target = "public"
 *  description = "Exposes the Pet API to the internet"
 * }
 */
app.listen(3000, () => console.log('App listening locally on :3000'));

Ampt

  • 開発元: Ampt Web Services, Inc.
  • 特徴
    • Ampt SDK/CLIというnpmパッケージを用いてJS/TSで開発
  • 言語
    • ツール自体の開発言語: 不明 (Ampt CLIはwasmをNode.jsで動かしている)
    • ユーザーが使う言語: JavaScript/TypeScript
    • 中間生成物の言語: n/a 自分のAWSアカウントにデプロイするわけではない
  • デプロイ先: Ampt社のPaaS
  • ライセンス: ソースは非公開
  • ビジネスモデル
    • まだPrivate betaのため不明。おそらくPaaSの利用料金。
  • その他
  • コード例
import { http } from "@ampt/sdk";

import express from "express";
const expressApp = express();

expressApp.use("/express", (req, res) => {
  res.send("hello express");
});

http.useNodeHandler(expressApp);
http.node.use(expressApp);

Nitric

  • 開発元: Nitric Inc.
    • USの会社だが、メンバーを見るかぎりオーストラリア発のスタートアップと言って良さそう
  • 特徴
    • Nitric SDK/CLIを利用し、多様な言語で開発可能
  • 言語
    • ツール自体の開発言語: Go
    • ユーザーが使う言語: JavaScript/TypeScript, Python, C#, Go, Java
      • gRPCのインターフェースを作れば対応言語を増やせる (各言語はNitric Serverと話すだけ)。jsiiに似た仕組み
    • 中間生成物の言語: Pulumi
  • デプロイ先: AWS, Google Cloud, Azure (いずれもある程度のレベルで対応済み)
  • ライセンス: Apache-2.0
  • ビジネスモデル
    • 不明。これはPaaSもないのでどうするのか
  • その他
    • 実は紆余曲折あって今のIfCなアプローチに辿り着いた模様。この記事は面白い
    • "cloud aware application framework" というのは、よく聞く cloud (vendor) agnostic のもじりだと思われる
      • フレームワークがcloudにawareなので、開発者はcloud agnostic、無知で良い。結局ほぼ同じこと
  • コード例
import { api } from '@nitric/sdk'

const galaxyApi = api('far-away-galaxy-api')

galaxyApi.get('/moon', async ({ req, res }) => {
  res.body = "that's no moon, it's a space station."
})

Encore

  • 開発元: Encore
  • 特徴
    • コメントによるアノテーションでインフラを定義
    • 対応言語はGoのみと割り切っている
    • ローカル開発用のダッシュボードやプレビュー環境 (Encore Cloud) があり、実際にデプロイする前に動作確認できる
  • 言語
    • ツール自体の開発言語: Go
    • ユーザーが使う言語: Go
    • 中間生成物の言語: n/a (AWS SDKなど使い直接インフラリソースを作成する)
  • デプロイ先: AWS, Google Cloud (いずれも同レベルで対応済み)
  • ライセンス: MPL-2.0
  • ビジネスモデル
  • その他
  • コード例
package hello

import (
    "context"
)

//encore:api public path=/hello/:name
func World(ctx context.Context, name string) (*Response, error) {
    msg := "Hello, " + name + "!"
    return &Response{Message: msg}, nil
}

type Response struct {
    Message string
}

Shuttle

  • 開発元: Shuttle
    • UKのスタートアップ
  • 特徴
    • RustのAttributeでインフラを定義
    • 対応言語はRustのみと割り切り
  • 言語
    • ツール自体の開発言語: Rust
    • ユーザーが使う言語: Rust
    • 中間生成物の言語: n/a デプロイはShuttleのサーバー側で実行される
  • デプロイ先: Shuttle管理下のAWSインフラ (今はeu-west-1ロンドンのみ)
  • ライセンス: Apache-2.0
  • ビジネスモデル
  • その他
    • Rust x Dockerの開発体験が悪いため、WASMを使っているとのこと
    • 例によって生成AIと組み合わせたソリューションを提供予定 ShuttleAI
  • コード例
async fn hello_world() -> &'static str {
    "Hello, world!"
}

#[shuttle_runtime::main]
async fn axum() -> shuttle_axum::ShuttleAxum {
    let router = Router::new().route("/hello", get(hello_world));

    Ok(router.into())
}
  • 開発元: Modal Labs
    • ニューヨークのスタートアップ
  • 特徴
  • 言語
    • ツール自体の開発言語: Python
    • ユーザーが使う言語: Python
    • 中間生成物の言語: n/a
  • デプロイ先: Modal社のPaas
  • ライセンス: Apache-2.0
  • ビジネスモデル
    • PaaS
  • その他
    • Modalのインフラにデプロイするためのツールと捉えても良さそう
    • MLインフラ用途なので、Pythonだけで良いと判断したのだろう
  • コード例
from modal import Stub, web_endpoint

stub = Stub()

@stub.function(gpu="A100")
@web_endpoint()
def f():
    return "Hello world!"

ということでIfCツール7つでした。それぞれ個性があって面白いですね。各社のサイトでは既存ツールとの比較などもされているので、気になったものがあれば深掘りしてみると良いでしょう。

また参考までに、各GitHubリポジトリスター数はこちらです。それぞれの登場時期や人気度が見て取れますね。

番外編

以下は本流ではないものの本記事の文脈には沿っているので、いくつかのツールを紹介します (メモ程度です。)

AWS Chalice

2016年頃から存在するAWS公式プロジェクト。当時はIfCという概念はなかったが、アプリのコードからAPI GatewayやLambdaのCloudFormationテンプレートが生成されており、やっていることはたしかにIfC。Python専用。

from chalice import Chalice

app = Chalice(app_name='helloworld')

CITIES_TO_STATE = { 'seattle': 'WA', 'portland': 'OR' }

@app.route('/')
def index():
    return {'hello': 'world'}

@app.route('/cities/{city}')
def state_of_city(city):
    return {'state': CITIES_TO_STATE[city]}

Functionless

サーバーレスのサーバーを意識しないで良いというコンセプトから転じて、FunctionlessはLambda関数 (Function) を意識しないで良い。Step FunctionsやAppSyncをLambda意識することなく書くことができた。すでに公式サイトも消滅しており、放棄された様子。

const getItem = new ExpressStepFunction(stack, "Function", async () => {
  $SFN.waitFor(10);

  const status = await $AWS.DynamoDB.GetItem({
    Table,
    Key: { id: { S: "string" } },
  });

  if (status === "FAILED") {
    throw new Error("Failed");
  }
});

CAIOS - Cloud AI Operating System

"IfC"で調べると古い記事によく出てくる名前。ドキュメントもあるが、詳細はあまり見えてこない (そもそも試せない。) PythonSDKで開発するタイプだと思われる。

System initiative

最近登場したノーコードのインフラ開発ツール。CloudFormationデザイナーをとても強くしたものという印象。動画を見る限りは便利そう。 特にこういうのが好きな人はいると思われる (視覚的に理解するタイプというのか)。

youtu.be

所感

今回調査した上での感想です。

各ツールを俯瞰すると、実はそれぞれのアプローチにはパターンがあり、いくつかの観点で分類できます。

インフラの抽象度 は大きく2つに分かれます。自前のプラットフォームにデプロイするタイプ (Dark, Ampt, Shuttle, Modal) と、ユーザーのクラウド環境にデプロイするタイプ (Wing, Klotho, Nitric, Encore) です。個人的には、前者の方が完全にインフラが隠蔽されており、細かいことを気にしなくて良い (気にすることができない)ので好きです。(Heroku 2.0だというそしりも受けそうですが…) 一方後者は、結局細かいところをカスタマイズしたくなり苦労しないかという不安はあります。抽象化に伴う恒例のつらみですね。また、前者のほうがビジネスとして成立させやすそうです (Terraformの苦労を見ていると…)。

対応言語 にも違いがあり、多様な言語をサポートするタイプ (Klotho, Nitric)、単一の既存言語を使うタイプ (Encore, Shuttle)、独自言語を使うタイプ (Wing, Dark)に大別されます。対応言語が多いほどユーザーは新しく言語を覚える必要がなくなります。一方対応言語が少ないほど開発体験を最適化しやすそうです。また独自言語は最適化の極致ですが、エコシステムの問題を抱える不安はあります。AWS CDKが結局ほとんどTypeScriptで使われていることを考えると、あまり手を広げなくても良いのかなという気もしてきますね。

インフラの定義方法 も、コメントによるアノテーション (Klotho, Encore)、デコレータやアトリビュートを使ったアノテーション (Shuttle, Modal)、SDKの利用 (Ampt, Nitric)などに大別されます。これは結局エディタが補完などをうまくサポートしてくれれば、開発体験に大きな差はでないのかなと想像しました。

また、生成AIと組み合わせる 傾向もありました (Darklang, Klotho, Shuttle)。これは単に新しく勢いがあるものが合体しているだけかもしれません。あるいはIfCでは多くのコードが自動生成されるため、開発者=AIが書く必要があるコードはより少なくなります。AIが生成するコードが少なくてよいほど出力の精度は上がると考えられるため、たしかにIaCなアプローチよりも相性は良いのかもしれません。

という分類をしてみたものの、私自身はこれらのツールが流行るのか、そもそも生き残るのか定かではありません。 個人的にはAWS CDKが好きなこともあり、AWSの構築ならもうオールウェイズCDKで良いでしょうという認識が今も強いです。

とはいえ各IfCツールを俯瞰してみると、共通してインフラを意識させたくないという意図を感じます。たしかに典型的なサーバーレスウェブアプリを作るとき、インフラに創意工夫が必要なことは少ないので、割り切って隠蔽してしまうというアプローチはありかもしれませんね。

ただし、やはり複雑で固有な要件を持つシステムでは採用しづらいのは間違いないと思います。抽象化により失われるものは往々にして柔軟性です。このため、IfCがIaCを取って代わるというよりは、これもまた適材適所で使い分けるツールとなるでしょう。

今週のもなちゃん

最後にもなちゃんの写真です。先月から換羽でナーバスなことが多いですが、たまにリラックスした顔を見せてくれます。

参考資料