はじめに
当記事では、別記事「AWS Lambda + QuarkusでのREST API作成」で作成したAPIに対して、Amazon Aurora(PostgreSQL)にアクセスする機能を追加する手順を示します。
手順にはAuroraのプロビジョニングを含みます。また、LambdaからAuroraへのアクセスは、RDS Proxyを間に置く構成とします。
前提環境
当記事では以下を前提とします(ツールのバージョンは一致しなくても実施は可能)。
- 別記事「AWS Lambda + QuarkusでのREST API作成」記載の内容の実施が完了していること
- Quarkus CLI 3.2.3 Final
- Maven 3.8.7
- AWS CLI 2.13.10
実施手順
Aurora(PostgreSQL)を作成するところから始めていきます。
Auroraの作成
AWSコンソールでRDSのページにアクセスし、「データベースの作成」ボタンをクリックします。
データベースの作成画面で以下の通り設定していきます。「標準作成」を選び、「Aurora(PostgreSQL Compatible)」を選択します。
AuroraのインスタンスとしてServerless v2を選択するため、「Serverless v2をサポートするバージョンを表示」にチェックを入れ、「利用可能なバージョン」でバージョンを選択します(ここでは14.6)。
「テンプレート」では「開発/テスト」を選択します。
「DBクラスター識別子」で任意の名前を入力します。また、マスターパスワードは適当なパスワードを入力します。
「DBインスタンスクラス」で「Serverless v2」を選択し、「最小ACU」「最大ACU」を適当に設定します。
「マルチAZ配置」では、今回可用性は不要のため「Auroraレプリカを作成しない」を選択します。
「Virtual Private Cloud(VPC)」では「新しいVPCの作成」、「DBサブネットグループ」は「新しいDBサブネットグループの作成」を選択します。
ローカルPCからアクセスできるように、「パブリックアクセス」は「あり」を選択します(ただし、セキュリティグループにより、DB作成時の自PCのIPアドレスからのアクセスのみ受け付けるように設定される)。
「VPCセキュリティグループ(ファイアウォール)」は「新規作成」を選び、「新しいVPCセキュリティグループ名」は適当に入力します。
「RDS Proxyを作成」のチェックは外しておきます(後ほど作成する)。
他の設定はデフォルトのままで、「データベースの作成」ボタンをクリックします。
作成したデータベースの「ステータス」が「利用可能」になるまで待ちます。
作成したデータベースの「ライターインスタンス」を選択し、そのVPCを確認・メモします。
Lambda関数のVPC設定
別記事「AWS Lambda + QuarkusでのREST API作成」で作成したLambda関数をVPC Lambdaにします。
Lambda関数をVPCに接続する前に、Lambda関数の実行ロールに追加のポリシーを設定します(AWSのドキュメント)。AWSコンソールでIAMのページにアクセスし、Lambda関数の実行ロール(別記事で作成したlambda-ex
ロール)を選択します。「許可ポリシー」でAWSLambdaVPCAccessExecutionRole
ポリシーを付与します。
次はLambda関数側の設定です。AWSコンソールで対象のLambda関数(QuarkusLambdaExample
)を開き、「設定」→「VPC」を選択し、「編集」ボタンをクリックします。
「VPC」で、AuroraのVPCを選択します。「サブネット」は選択可能なVPCサブネットを全て選択します。「セキュリティグループ」は、デフォルトのセキュリティグループを選択します。
Lambda関数がAuroraのVPCに接続されたことが確認できます。
Lambda - RDS Proxy - Auroraの接続設定 & RDS Proxyの作成
AWSコンソールで、再度Auroraのインスタンスのページにアクセスし、「接続されたコンピューティングリソース」セクションの「Set up Lambda connection」ボタンをクリックします。
「Choose existing function」を選択し、QuarkusLambdaExample
を選択します。
ここでRDS Proxyを作成します。「Connect using RDS Proxy」にチェックを入れ、「Create new proxy」を選択します。「Username」「Password」では、Auroraのマスタユーザ、マスタパスワードを入力します。
「Connection summary」を展開すると、Lambda関数 - RDS Proxy - Aurora(RDS)の関係性が図示されます。
画面最下部の「Set up」ボタンをクリックします。
RDS Proxyの「ステータス」が「利用可能」になるまで待ちます(20分程度かかります)。
さらに、以下のコマンドを実行し、出力されたJSONのTargets[0].TargetHealth.State
がAVAILABLE
であることを確認します。
aws rds describe-db-proxy-targets --db-proxy-name <プロキシ識別子>(例:proxy-1692683664021-database-1)
作成されたRDS Proxyを表示し、エンドポイントを確認・メモします。
ソースコードの修正
次に、QuarkusのJavaコードを修正します。DB(PostgreSQL)にアクセスし、current_timestamp
で現在日時を取得し、レスポンスに含めて返すようにします。
Lambda関数のプロジェクトで以下のコマンドを実行し、Quarkusのエクステンションを追加します。
# DBコネクションプール
quarkus extension add 'agroal'
# PostgreSQLのJDBCドライバ
quarkus extension add 'jdbc-postgresql'
# Hibernate ORM with Panache(不要かもしれない)
quarkus extension add 'hibernate-orm-panache'
application.properties
を以下のように編集します。ここでは、DBとしてPostgreSQLを使用すること、および、接続ユーザ名、コネクションプール数を指定しています。JDBC URL、パスワードは後ほどLambdaの環境変数として設定するためブランクとしています。
quarkus.lambda.handler=test
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=postgres
quarkus.datasource.password=
quarkus.datasource.jdbc.url=
quarkus.datasource.jdbc.max-size=2
Mavenプロジェクト内のProcessingService.java
を以下のように編集します。データソースからコネクションを取得し、select current_timestamp
を実行してAuroraから現在日時を取得し、レスポンスに追加して返しています。
package org.example;
import io.agroal.api.AgroalDataSource;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@ApplicationScoped
public class ProcessingService {
public static final String CAN_ONLY_GREET_NICKNAMES = "Can only greet nicknames";
@Inject
AgroalDataSource defaultDataSource;
public OutputObject process(InputObject input) {
if (input.getName().equals("Stuart")) {
throw new IllegalArgumentException(CAN_ONLY_GREET_NICKNAMES);
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String result = input.getGreeting() + " " + input.getName() + ", date: " + sdf.format(new Date());
try (Connection con = defaultDataSource.getConnection()) {
PreparedStatement ps = con.prepareStatement("select current_timestamp");
ResultSet rs = ps.executeQuery();
rs.next();
System.out.println("Current timestamp: " + rs.getTimestamp(1));
result += ", Aurora PostgreSQL current timestamp: " + rs.getTimestamp(1);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
OutputObject out = new OutputObject();
out.setResult(result);
return out;
}
}
ソースコードの修正が終わったのでビルドします。以下のコマンドを実行します。なお、JUnitテストケースが正常終了しなくなっているので、ここでは一旦テストをスキップするようにしています。
quarkus build --clean --no-tests
ビルドした結果をLambda環境にデプロイします。
sh target/manage.sh update
Lambda関数の環境変数の設定
AuroraのJDBC URL、パスワードは環境変数で設定します。Lambda関数(QuarkusLambdaExample
)のページで、「設定」→「環境変数」を選択し、「編集」ボタンをクリックします。
QUARKUS_DATASOURCE_PASSWORD
にDBのパスワード、QUARKUS_DATASOURCE_JDBC_URL
にJDBC URLを設定します。JDBC URLは以下の通り組み立てます。
jdbc:postgresql://<先ほど確認したRDS Proxyのエンドポイント>:5432/postgres
アクセス確認
最後にAPIにアクセスして稼働を確認します。curl
コマンドを以下のように実行します(APIのエンドポイントは置き換える)。Auroraから取得した現在日時が含まれるようになっています。
❯ curl -X POST -H "Content-Type: application/json" -d '{"name" : "Bill", "greeting" : "hello"}' https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/example
{"result":"hello Bill, date: 2023-08-22 06:51:42.623, Aurora PostgreSQL current timestamp: 2023-08-22 06:51:42.626195","requestId":"6257703d-a50a-4925-9401-1a89b016284f"}