はじめに
当ブログはQiita Advent Calendar2023に投降した下記ブログの転載+加筆になります。
初アドカレついでにQiitaを試してたのですが、運営している本ブログにも載せます。
qiita.com
Infrastructure from Code(IfC)とAmptについて少し学習したので、整理して書きたいと思います。
きっかけ
ServerlessDays Tokyo2023のAWS Eric Johnson のセッションでIfCという単語を初めて聞いたのですが、中身について触れなかったので何なのか分からなかったのとIaCと何が違うのか気になったためです。
https://tokyo.serverlessdays.io/
Infrastructure from Codeとは何か
アプリケーションコードから必要なクラウド リソースを推測して、自動でアプリケーションの基盤となるインフラストラク チャをクラウド にプロビジョニングするアプリケーション構築のプロセス。
例えば、アプリケーションコード内にAPI のGETやPOSTが書かれていれば、CDN にAPI サーバが必要だと推測して、AWS ならCloudFrontにAPI Gateway 、Lambdaのリソースを自動でプロビジョニングしてくれるようです。
背景
サーバーレスアーキテクチャ の開発ではクラウド リソースのプロビジョニングにはInfrastructure as Codeのプロセスで行っていましたが、アプリケーションの開発者からすると下記の課題があったようです。
インフラストラク チャコードもコードではあるものの、アプリ開発 者にとってはインフラにあたるので極力インフラストラク チャコードすらも書かないようにしたいという思いがあるようにも見えます。
①多量のインフラストラク チャコードを書く必要がある
②アプリケーションコード側にサービス制御のコードが書けない。
③アプリケーションコードとインフラストラク チャコードが密結合になり変更が容易でない。
①はインフラストラク チャコードは何十、何百行と書く必要があり、さらにサーバーレスだと複数のサービスを組み合わせてアプリを開発するので、サービスの数だけインフラストラク チャコードが増えてしまい作業時間が増えて、アプリケーションコードを書くのに割ける時間が減ってしまう。
②はタイムアウト や処理中断時の制御はアプリケーション側でも検討するが、制御するコードはインフラストラク チャコードに書かないといけない。例えばLambdaのタイムアウト 時間。
③どのアプリケーションコードがどのインフラストラク チャ上で動くのか宣言しておく必要があり、どちらかに変更があると、もう片方への影響調査や改修が発生してしまう。
IaCの例
課題を具体的にコードで例えてみます。
趣味で開発していたBedrockへリクエス ト送受信をするだけのLambda関数をSAMテンプレートコード化してみました。
AWSTemplateFormatVersion : '2010-09-09'
Transform : AWS::Serverless-2016-10-31
Description : An AWS Serverless Specification template describing your function.
Resources :
bedrocktest :
Type : AWS::Serverless::Function
Properties :
CodeUri : .
Description : ''
MemorySize : 128
Timeout : 70-----②
Handler : lambda_function.lambda_handler-----③
Runtime : python3.11
Architectures :
- x86_64
EventInvokeConfig :
MaximumEventAgeInSeconds : 21600
MaximumRetryAttempts : 2
EphemeralStorage :
Size : 512
Layers :
- arn:aws:lambda:us-east-1:XXXXXXXXXX:layer:boto3-1_28_73:2
RuntimeManagementConfig :
UpdateRuntimeOn : Auto
SnapStart :
ApplyOn : None
PackageType : Zip
Policies:----以下②
- Statement :
- Sid : VisualEditor0
Effect : Allow
Action :
- bedrock:*
Resource : '*'
- Effect : Allow
Action :
- logs:CreateLogGroup
Resource : arn:aws:logs:us-east-1:XXXXXXXXXX:*
- Effect : Allow
Action :
- logs:CreateLogStream
- logs:PutLogEvents
Resource :
- >-
arn:aws:logs:us-east-1:XXXXXXXXXX:log-group:/aws/lambda/bedrock_sample:*
たった1つの関数ですがSAMテンプレートコードの場合はインフラストラク チャコードが45行になりました。実際のアプリだともっとたくさんの関数があるでしょうし、他のサービスも使うとその数だけコード量が増えます。また、関数間やサービス間の通信に認証認可のためのコードも書く必要が出てくると思われます。
これが課題①にあたるところになります。
課題②はTimeoutやPoliciesがそれらにあたると思われます。処理のタイムアウト 時間や他サービスとの通信制 御をするためのコードはアプリ側ではなく、インフラストラク チャコードに書かざるえません。
課題③はHandlerと②がそれらにあたると思われます。Lambdaのお約束として、Handlerに書かれたLambda関数ハンドラーをアプリケーションコード側にも書く必要があります。そのため、Lambdaから他サービスに移植したいとなったときはアプリケーションコードを改修が必須となります。また、他AWS サービスと連携させたいときには、アプリケーションコードだけでなく、インフラストラク チャコードに連携するAWS サービスとの認証認可のコードを書く必要が出てきており、アプリケーションコードとインフラストラク チャコードが密結合になっていると言えるのではないでしょうか。
*課題②③はコードスニペット 内の該当コード右側に「②」「③」を付記しています。
Self Provisioning Rumtime
課題に関して、解釈的アプローチで考えていった結果、アプリケーションコードとインフラを紐づける部分を自動的に推測してプロビジョニングさせることを思いつき「Self Provisioning Rumtime」と名付けたようです。
①アプリケーションロジックから必要なリソースとアクセス権限を推測させる
②イベントハンドラ ーでサービス制御を処理
③サービスとの通信を構造から自動的にマッピング させる
この3点について、クラウド アーキテクチャ を設計したことがある方は頭の中の思考や設計書で似たようなことしていた経験があるかと思います。
機能要件で求められているある機能のアーキテクチャ を設計するときに、数分で処理が終わりそうな機能要件に対してはLambdaを選ぼう。もし、数分で終わらないときを考慮してタイムアウト 時間を設けるようにしよう。処理結果をもしS3に保管する必要があるなら、LambdaにS3への書き込み許可を付与するロールを作ろうと言った経験です。
Self Provisioning Rumtimeはまさしくこの思考を自動でやろうというアイデア と言えそうです。
サービス
簡単にですが、IfCのサービスを紹介します。何をベースにしているかで4つに分類できるらしく、既存のアプリケーションコードに簡単に導入できそうなサービスもあれば、一から開発が必要なサービスもあり、使ってみたいときは導入するアプリの状況によって検討することになるかなと思います。
プログラミング言語 ベース :Wing、DarkLang
クラウド リソース定義のための新しいプログラミング言語 を利用する。
SDK ベース :Ampt、Nitric
アプリケーションコードに独自の SDK を導入して利用する。
Annotations + Frameworks :Encore、Shuttle
既存のプログラミング言語 にフレームワーク にライブラリの追加やアノテーション を付けて対応している。
Pure Annotations :Klotho
既存のアプリケーションコードのインラインコメントでアノテーション することで対応する。
ぱっと見ると、プログラミング言語 ベースは最もと導入難易度が高く、記載順に導入難易度が下がっていく感じがします。
実際にどうプロビジョニングされるのか
冒頭の技術カンファレンスで紹介されていたという理由でAmptの場合、Lambdaはどのようなコードからプロビジョニングされるのか見てみます。
コードの前に少しだけAmptの構成を説明します。
簡易構成図と手順
こちらはAmptのサイトにある構成図と実際に操作した経験からイメージした簡単な構成図とアプリ開発 の流れになります。図の右側は学習内容と動きから想定されるイメージのため誤っている可能性がある点ご承知おきください。
先述した通り、AmptはSDK ベースのサービスです。開発するにはSDK が必要です。ソースコード の管理はGitHub になります。
また、クラウド プラットフォームがありRuntimeやアプリ管理のコンソール画面などの機能を備えています。
ユーザーはAmptのSDK をインストールした開発端末上でアプリ開発 を行い、デプロイを行います(図の①)。するとAmptがRumtime機能によりソースコード の解析を行い(図の②)、クラウド 上に必要なリソースをプロビジョニングしてアプリが稼働するクラウド インフラを構築します(図の③)。構築したアプリの状況はAmptのコンソール画面にアクセスして管理を行います(図の④)。
では、どうLambdaだと推測してプロビジョニングされるのかスケジュールタスクのコードを例に説明します。
schedule.every("1 hour" , () => {
console.log("I run every hour!" );
} );
「.every」はスケジューリングを定義するためのメソッドで、時間指定やcron形式を用いて定期実行を可能にします。このコードでは1時間ごとにログ出力を行います。AmptのRumtimeはこのコードから何のサービスをプロビジョニングすべきか推測を行います。例では、スケジューリングを行えるサービスとログ出力を行うコンピューティングサービスが必要だと推測して、AWS にあるそれらに該当するサービスであるEventBridgeとLambdaをプロビジョニングする。という流れになるようです。
もう1つ例をあげてみます。
schedule.every("12 hours" , { timeout:1200000 } () => {
console.log("I run every 12 hours!" );
} );
前と同じスケジューリングのコードですが、「timeout」のハンドラーが存在しています。タスクのタイムアウト をミリ秒で指定でき、例では1200000ミリ秒=20分を指定しています。このスケジュールタスクをプロビジョニングするとき、timeoutの指定通りに最低20分は稼働するコンピューティングサービスを選択する必要があるため、タイムアウト が最大15分であるLambdaではなく、Fargateをプロビジョニングする判断をするようです。
所感
サーバーレスにはインフラストラク チャを意識させないという要素がありますが、背景から推察するとIaCではまだどのインフラにアプリを乗せるかといったインフラストラク チャを意識させる部分があり、真のサーバーレスに近づけるためにも新しいプロビジョニング方法が求められていたのかなと思いました。
Fighting off faux-serverless bandits with the true definition of serverless — Momento
Self Provisionig Rumtimeで自動化する3点は自分も開発で苦労していた部分で、自動化できないのかと考えたこともありましたが、本当に自動化するサービスが実現していたことに驚きました。
触ったサービスの特性やまだ歴史が浅いのもありますが、本格的に導入するのはまだ厳しそうに感じました。でも、クラウド インフラストラク チャを一切意識せずにアプリ開発 ができるので、小規模な個人開発や新規サービスのモックアプリ開発 で導入してみるのはありかもしれないと思います。
今回書けなかったですが、学習にあたってAmptのアカウントを作成し、サンプルアプリをプロビジョニングするところまで触ってみました。CLI やブラウザベースのコンソール画面から操作できるのですが、UIとしてもクラウド インフラストラク チャを意識させるようなところはなく、最初の印象としてはAmptはIfCの考えを徹底しているサービスだなと感じています。触ってみたところは、別途ブログにしたいと思います。
これが本格的に普及したらクラウド エンジニアの仕事が減るかもしれない…
参考
学習のために見たサイトと動画です。
Infrastructure from Code (IfC)
AWS re:Invent 2022 - Unleash developer productivity with infrastructure from code (COM301) - YouTube
State of Infrastructure-from-Code 2023 - Klotho
Infrastructure-from-Code vs Infrastructure-as-Code
Ampt