uokadaの見逃し三振は嫌いです

ここで述べられていることは私の個人的な意見に基づくものであり、私が所属する組織には一切の関係はありません。

AWS samでQuarkus アプリケーションをデプロイする

What is quarkus?

quarkus.io quarkus.io

Quarkus はJava製の幅広い分散アプリケーションを構築するのに適したフレームワークです。RHELで有名なRedhat 社が中心となって開発を進めています。

Why I wrote this blog post

quarkus.io

上記の通り、Quarkus自身でAWS lambdaを構築する拡張機能とその使い方を提供しているがここにはいくつか課題があります。まず、mvn packageでlambda関数をデプロイするためのAWS samテンプレートを出力してくれるんですがこれをカスタムすることが出来ません。そして、上の方法だと1つのQuarkusアプリケーション=lambda関数しか管理することが出来ないので複数のlambda関数を管理・デプロイすることになると関数の数だけsamのテンプレートを管理するコストが発生することです。

そこで、AWS samもテンプレートをベースに各言語のアプリケーションをビルドすることが出来るのですが、Java 11用に作られたテンプレートがビルドとデプロイは出来るがそのままでは実行出来ないという問題があります。

aws.amazon.com

Lambda関数をQuarkusで作る理由としては、ロギングなどの拡張機能のサポートが充実しているのも1つの理由です。設定を数行追加するだけでAWS Lamda上で実行する際のロギングフォーマットをJSONに変換することが出来ます。

quarkus.io

Create a lambda function using Quarkus with AWS sam

まず、sam initコマンドでlambda関数とsam テンプレートを作成します。

$ sam --version
SAM CLI, version 1.46.0

$ sam init -r java11 -d maven --app-template hello-world  -o . -n sam-hello-lambda

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)

SAM CLI update available (1.48.0); (1.46.0 installed)
To download: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html

次に、quarkusでアプリケーションを作成してHellowWorldFunction以下のファイルを置き換えます。 quarkusコマンドのインストールはこちらを参照してください。

quarkus.io

$ cd sam-hello-lambda 

$ rm -rf HelloWorldFunction

$ quarkus create app --java 11 --maven --extension quarkus-amazon-lambda io.github.yuokada:HelloWorldFunction
-----------
selected extensions:
- io.quarkus:quarkus-amazon-lambda


applying codestarts...
📚  java
🔨  maven
📦  quarkus
📝  config-properties
🔧  dockerfiles
🔧  maven-wrapper
🚀  amazon-lambda-example

-----------
[SUCCESS] ✅  quarkus project has been successfully generated in:
--> /path/to/sam-hello-lambda/HelloWorldFunction
-----------
Navigate into this directory and get started: quarkus dev

そして、次にHelloWorldFunctionの下にMakefileを作成します。これはsam buildコマンドを実行時にbuild-Helloworldfunctionが呼ばれてs3にアップロードされるファイルの中身を生成するのに利用します。 実際のところ、sam packageでここで作成されたLambda関数ごとのディレクトリをzipファイルに固めたものがs3にデプロイされるので、ここではfunction.zipを一度展開しているだけです。

clean:
  ./mvnw clean
build:
  ./mvnw package

build-Helloworldfunction: clean build
  unzip target/function.zip -d $(ARTIFACTS_DIR)/

そして、上で作成したMakefileを利用するようにtemplate.yamlも修正します。重要なポイントは以下の通りです。

  1. Matadataセクションの追加。 see: Building custom runtimes - AWS Serverless Application Model
  2. Handlerの値をio.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequestに書き換え。これは全てのQuarkusアプリケーションでこの値になります。
  3. Eventsセクションは今回使ってないので削除。
diff --git a/template.yaml b/template.yaml
index 71c9004..a405959 100644
--- a/template.yaml
+++ b/template.yaml
@@ -12,32 +12,24 @@ Globals:

 Resources:
   HelloWorldFunction:
-    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
+    Type: AWS::Serverless::Function
     Properties:
      CodeUri: HelloWorldFunction
-      Handler: helloworld.App::handleRequest
+      Handler: io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest
       Runtime: java11
       Architectures:
         - x86_64
      MemorySize: 256
+      Policies: AWSLambdaBasicExecutionRole
       Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
-        Variables:
-          PARAM1: VALUE
-          JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 # More info about tiered compilation https://aws.amazon.com/blogs/compute/optimizing-aws-lambda-function-performance-for-java/
+         Variables:
+           JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 # More info about tiered compilation https://aws.amazon.com/blogs/compute/optimizing-aws-lambda-function-performance-for-java/
-      Events:
-        HelloWorld:
-          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
-          Properties:
-            Path: /hello
-            Method: get
+    Metadata:
+      BuildMethod: makefile

ここまで変更を加えれば、後は他のsam製アプリケーションと同様にsam package && sam deployをしてやればアプリケーションを構築出来ます。 (今は、sam deployを呼ぶと暗黙的にsam packageが実行されるみたいですが自分はデプロイ用のテンプレートを出力してそれを使ってsam deployを呼び出したいので明示的にsam packageを呼んでいます。)

最終的に、出来上がったlambda関数のリポジトリがこちらです。 github.com

これで、Quarkusuアプリケーションとそれに付随するリソースを1つのAWS samテンプレートで管理出来るようになりました。

関連リンク