はじめに
Lambda→RDS Proxy→RDSの接続をやってみたのでその備忘録を残す。
※料金について、Auroraはインスタンスの起動時間で料金が発生するので特に注意。Auroraではなく、MySQLとかにすれば無料枠があるのでそちらの方がいいかもしれない。
Auoraのインスタンスを作成
以下の箇所以外はデフォルトのまま設定。
設定項目 | 画像 |
---|---|
テンプレート | |
インスタンスの設定 |
※RDS(Aurora)のインスタンスを作成するために、また、RDS Proxyの設定のための前提条件(Setting up network prerequisites)として、VPCが必要だがこれはデフォルトのものを利用した。
Using RDS Proxy requires you to have a common virtual private cloud (VPC) between your Aurora DB cluster or RDS DB instance and RDS Proxy. This VPC should have a minimum of two subnets that are in different Availability Zones.(RDS Proxyを使用するには、Aurora DBクラスタまたはRDS DBインスタンスとRDS Proxyの間に共通の仮想プライベートクラウド(VPC)を用意する必要があります。このVPCは、異なるAvailability Zoneにある最低2つのサブネットを持っている必要があります。)
Secrets Managerで認証情報を作成
AWS Secrets Manager でのデータベース認証情報の設定を参考に、Secrets Managerにユーザー名とパスワードの認証情報のセットを保存する。これはRDS ProxyがRDSにアクセスする際の認証情報になる。
ステップ | 画像 |
---|---|
シークレットのタイプを選択 | |
シークレットを設定 |
上記の設定で暗号化キーはデフォルトにしているが、これを自分で生成したものにするとキー1つにつき1$/月
かかるっぽいので注意。また、ローテーションの設定は今回はしない設定にした。
一応シークレットに正しい情報を格納できている事を確認してみると、以下のようにちゃんとRDS用のシークレットが作成できている事が確認できる(今回はRDS Proxyを使った接続のためだけに作ったので、パスワードはマスクしてない)。
[study@localhost .aws]$ aws secretsmanager get-secret-value --secret-id dev/db/mysql
{
"ARN": "arn:aws:secretsmanager:ap-northeast-1:**********:secret:dev/db/mysql-azibNI",
"Name": "dev/db/mysql",
"VersionId": "07181751-2208-4048-aa6a-36616c123fd1",
"SecretString": "{\"username\":\"admin\",\"password\":\"testpassword\",\"engine\":\"mysql\",\"host\":\"database-1.cluster-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com\",\"port\":3306,\"dbClusterIdentifier\":\"database-1\"}",
...
}
※RDSへの接続時の認証方式としてはパスワード認証・IAM認証などあるが、RDS Proxyを利用する場合のIAM認証は、RDS ProxyがSecrets Managerから認証情報を取り出す際に使用される(詳細はConnecting to a proxy using IAM authenticationに書かれている通り)。
The IAM authentication applies to RDS Proxy retrieving the user name and password credentials from Secrets Manager. The connection from RDS Proxy to the underlying database doesn't go through IAM.(IAM認証は、RDS ProxyがSecrets Managerからユーザー名とパスワードの資格情報を取得する際に適用されます。RDS Proxyから基礎となるデータベースへの接続は、IAMを経由しません。)
- 参考:Create a database secret
- 参考:AWS Key Management Service の料金
- IAM認証に関する補足情報:Using the function's permissions for authentication
IAMロールを作成する
Setting up AWS Identity and Access Management (IAM) policiesに沿って、RDS ProxyがSecrets Managerにアクセスし、RDSへ接続するのための認証情報を取り出せるようにする設定を行う。
まずは以下の設定でIAMポリシーを作成する。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": [
"arn:aws:secretsmanager:ap-northeast-1:************:secret:dev/db/mysql-azibNI"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:ap-northeast-1:************:key/5b01b7c4-7556-496c-be8c-c30bf1676c7f",
"Condition": {
"StringEquals": {
"kms:ViaService": "secretsmanager.ap-northeast-1.amazonaws.com"
}
}
}
]
}
kms:Decrypt
についてはシークレットの復号を行う事なので、同じSecrets Managerからの呼び出しのみを許可する設定になっている(より制限をする場合、Conditionの設定が望ましい)。あとは、このポリシーをアタッチできるサービスを設定する(信頼
ちなみに、各ARNが分からなければそれは各ページを見に行けば分かる。
1 | 2 |
---|---|
Secrets Manager | |
KMS |
※マネジメントコンソールではなく、AWS CLIからでも以下のように確認できるだろう。
[study@localhost .aws]$ aws secretsmanager list-secrets
{
"SecretList": [
{
"ARN": "arn:aws:secretsmanager:ap-northeast-1:************:secret:dev/db/mysql-azibNI",
"Name": "dev/db/mysql",
"Description": "for RDS Proxy test",
...
}
]
}
[study@localhost .aws]$ aws kms list-aliases
{
"Aliases": [
...
{
"AliasName": "alias/aws/secretsmanager",
"AliasArn": "arn:aws:kms:ap-northeast-1:************:alias/aws/secretsmanager",
"TargetKeyId": "5b01b7c4-7556-496c-be8c-c30bf1676c7f",
...
},
...
]
}
[study@localhost .aws]$ aws kms list-keys
{
"Keys": [
...
{
"KeyId": "5b01b7c4-7556-496c-be8c-c30bf1676c7f",
"KeyArn": "arn:aws:kms:ap-northeast-1:************:key/5b01b7c4-7556-496c-be8c-c30bf1676c7f"
}
]
}
IAMポリシーが作成できたら、今度はそのポリシーを適用したIAMロールを作成する。IAMロール作成時には信頼されたエンティティを選択
というのがあるが、これについてはIAMロールと信頼されたエンティティの関係性を参照ください。設定内容は以下の通り(「信頼されたエンティティを選択」は「カスタム信頼ポリシー」にJSONを書けるのでJSONを書くのが楽)。
ステップ | 画像 |
---|---|
信頼されたエンティティを選択 | |
許可を追加 |
RDS Proxy の作成
Creating an RDS Proxyに沿って作成していく。
ステップ | 画像 |
---|---|
ナビゲーションペインのプロキシ | |
プロキシ設定 | |
ターゲットグループの設定 | |
接続 |
接続の項目はそれぞれ、
- シークレット
Secrets Managerで認証情報を作成の際に作成したシークレットを設定
これを使ってRDS(Aurora)に認証する - IAM ロール
IAMロールを作成するで作成したIAMロールを設定
Secrets Managerのシークレットを復号化して実際にRDS(Aurora)に接続する際の認証情報を利用できるようにする - IAM 認証
今回はパスワード認証で認証するのでここはデフォルトのまま許可しないにする
のように設定する。
1点注意として、このRDS Proxyは有効になるまで20分程度かかるようで、作成後すぐに使えない。
ちなみに、AWS CLIでRDS Proxyの状態確認でき、TargetHealth
のState
がAVAILABLE
であれば問題なく作成できていると判断できる。
[study@localhost .aws]$ aws rds describe-db-proxy-targets --db-proxy-name aurora-proxy
{
"Targets": [
{
"Endpoint": "database-1-instance-1.cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com",
"TrackedClusterId": "database-1",
"RdsResourceId": "database-1-instance-1",
"Port": 3306,
"Type": "RDS_INSTANCE",
"Role": "READ_WRITE",
"TargetHealth": {
"State": "AVAILABLE"
}
},
{
"RdsResourceId": "database-1",
"Port": 3306,
"Type": "TRACKED_CLUSTER"
}
]
}
※上記のEndpointはRDS(Aurora)のエンドポイントであり、RDS Proxyのエンドポイントではないので注意。
RDS ProxyのエンドポイントはRDS Proxyの設定確認画面から確認できる。
AWS CLIだと以下。
[study@localhost .aws]$ aws rds describe-db-proxy-endpoints --db-proxy-name aurora-proxy
{
"DBProxyEndpoints": [
{
"DBProxyEndpointName": "default",
"DBProxyName": "aurora-proxy",
"Status": "available",
...
"Endpoint": "aurora-proxy.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com",
...
"TargetRole": "READ_WRITE",
"IsDefault": true
},
{
"DBProxyEndpointName": "aurora-proxy-read-only",
...
"DBProxyName": "aurora-proxy",
"Status": "available",
...
"Endpoint": "aurora-proxy-read-only.endpoint.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com",
...
"TargetRole": "READ_ONLY",
"IsDefault": false
}
]
}
ひとまずEC2からRDS(Aurora)に接続してみる
VPC内からでないと接続できないので、最も楽そうなEC2を踏み台にしてRDS(Aurora)に接続してみる。また、RDS Proxy経由でもRDS(Aurora)に接続できるか?を検証してみる。
接続の経路としては以下のようなイメージになる(今回はAWSアカウントを作成した際に自動的に作成されるサブネットを利用するので、パブリックサブネットにRDS(Aurora)も属させるような形式になるが、本来はプライベートサブネットとパブリックサブネットに分けるべきだろう。また、EC2は同じサブネットに属していても、セキュリティグループがRDS(Aurora)と別だと、以下で取り上げる【事前準備③】RDSのセキュリティグループにEC2のプライベートIPを追加するのような追加設定が必要になる)。
※今回のRDS(Aurora)のインスタンスは以下のように、パブリックアクセス可能
を「なし」しているため(パブリックアクセス可能にしているのであれば、MySQL Workbench からの接続などで簡単に接続できるだろう)。
【事前準備①】EC2のインスタンスを作成し、SSHでEC2にローカルから接続する
特にEC2のインスタンス作成については詳細を書かないが、作成した後は以下のようにして接続できる(今回、ローカルマシンはWindows10上に構築しているVirutalBoxのCentOS7.9で、そこからEC2に接続している。WindowsにVirtualBoxでLinux環境を作成する方法はWindows上にLinux(CentOS)のWebアプリ開発環境をvirtualboxで構築するを参照。)。1点、Amazon Linux 2のユーザー名はインスタンスを立ち上げた際にデフォルトでec2-user
になるので注意。詳細はインスタンスに関する情報を取得するに書かれている。
[study@localhost .ssh]$ ls
aurora-stool-server-key.pem authorized_keys config github github.pub known_hosts
[study@localhost .ssh]$ chmod 400 aurora-stool-server-key.pem
[study@localhost .ssh]$ ssh -i aurora-stool-server-key.pem ec2-user@ec2-18-183-53-112.ap-northeast-1.compute.amazonaws.com
Last login: Wed Aug 17 10:30:37 2022 from 133-32-218-61.east.xps.vectant.ne.jp
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
2 package(s) needed for security, out of 10 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-172-31-11-41 ~]$
【事前準備②】Amazon Linux 2にMySQLのクライアントをインストール
インスタンスを作成した後はまだMySQLクライアントがインストールされていない状態なのでインストールを行う。
[ec2-user@ip-172-31-11-41 ~]$ mysql --version
-bash: mysql: コマンドが見つかりません
MySQLのクライアントのインストール方法はMySQL データベースエンジンを実行している DB インスタンスへの接続に書かれている通り。
[ec2-user@ip-172-31-11-41 ~]$ sudo yum install mariadb
...
[ec2-user@ip-172-31-11-41 ~]$ mysql --version
mysql Ver 15.1 Distrib 5.5.68-MariaDB, for Linux (x86_64) using readline 5.1
【事前準備③】RDSのセキュリティグループにEC2のプライベートIPを追加する
MySQLクライアントをインストールした状態でEC2からRDSに接続しようとしても、セキュリティグループの制約で接続できない。
[ec2-user@ip-172-31-11-41 ~]$ mysql -h database-1-instance-1.cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on 'database-1-instance-1.cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com' (110)
というわけでセキュリティグループのインバウンドを変更して、EC2から接続できるようにする。まず、RDS(Aurora)のインスタンス情報を確認すると、セキュリティグループというのがあるのでそれをクリックするとセキュリティグループ一覧が見れる。
インバウンドルールのタブから、インバウンドのルールを編集
をクリックして新しくEC2のプライベートIPからの接続を追加する(MySQLのアクセスしかしないのでタイプをMySQL/Aurora
にする)。
実際にEC2からRDS(Aurora)へ接続してみる
上記の事前準備をした後は、いつものようにDBのホスト・ポート・ユーザー名を指定して接続できるようになる(mydb
が今回Auroraを立ち上げる時に作成していたデータベース)。
[ec2-user@ip-172-31-11-41 ~]$ mysql -h database-1-instance-1.cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 24
Server version: 5.7.12 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mydb |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
※今回セキュリティグループでプライベートIPを指定したが、EC2が属するセキュリティグループを追加するという方法もとれる。
RDS Proxy経由で接続した際にRead・Writeするためのテーブル・データを事前作成する
以下のSQLを実行して、データベースにテーブルとデータを作成しておく(一度行を作成して削除した関係でIDは3~になっている)。
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `users` (`name`) VALUES ('yamada tarou'), ('山田 太郎');
MySQL [(none)]> USE `mydb`;
MySQL [mydb]> CREATE TABLE `users` (
-> `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
-> `name` varchar(128) DEFAULT NULL,
-> `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
-> `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.07 sec)
MySQL [mydb]> INSERT INTO `users` (`name`) VALUES ('yamada tarou'), ('山田 太郎');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
MySQL [mydb]> SELECT * FROM `users`;
+----+---------------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------------+---------------------+---------------------+
| 3 | yamada tarou | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
| 4 | 山田 太郎 | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
+----+---------------+---------------------+---------------------+
2 rows in set (0.00 sec)
ちなみに、RDS Proxy経由ではなく、Auroraのインスタンスに直でアクセスしているので、Read/Writeの両方ができている(RDS Proxy経由ではReadOnlyがあるのでそうはいかない、詳細はEC2からRDS Proxy経由でRDS(Aurora)に接続してみるで)。
EC2からRDS Proxy経由でRDS(Aurora)に接続してみる
イメージとしては以下(AZ・サブネットなどは省略している)。
アクセスエンドポイントが2つあるのでそれぞれで試してみる。エンドポイントはRDS Proxy の作成の章でRDS Proxyを作成した時に確認した以下の2つ。
- aurora-proxy.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com
- aurora-proxy-read-only.endpoint.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com
1点、RDS Proxy経由で接続する場合、RDS Proxyを作成する際にTLSを有効にしたので、その証明書が必要になる。
そのため以下のようにして証明書をEC2上に落としておく。
[ec2-user@ip-172-31-11-41 ~]$ wget https://www.amazontrust.com/repository/AmazonRootCA1.pem
[ec2-user@ip-172-31-11-41 ~]$ ls
AmazonRootCA1.pem
※RDSのMySQLへ直に接続する時にはSSL を使用した MySQL コマンドラインクライアントからの接続 (暗号化)に書かれている方法(--ssl-ca=global-bundle.pem
オプションを追加する)で接続する必要があるが、今回はRDS Proxy経由だったので証明書がAmazonRootCA1.pem
と別物になる(MySQL・Auroraへの接続時の証明書自体はSSL/TLS を使用した DB インスタンスへの接続の暗号化のページにあるglobal-bundle.pem
がそれ)。RDS Proxyに接続する際にglobal-bundle.pem
を指定すると、以下のようにエラーになる。
[ec2-user@ip-172-31-11-41 ~]$ mysql -h aurora-proxy.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com --ssl-ca=global-bundle.pem -P 3306 -u admin -p
Enter password:
ERROR 2026 (HY000): SSL connection error: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
- 参考:Amazon RDS プロキシを使用して、Amazon RDS MySQL DB インスタンスまたは Aurora MySQL DB クラスターに接続する方法を教えてください。
- 参考:IAM認証で RDS Proxy 接続を利用する際は証明書にお気をつけて
1つ目のエンドポイントへ接続してみる
接続自体はひとまずEC2からRDS(Aurora)に接続してみるの章の最後で取り上げた方法と同じで、エンドポイントだけRDS Proxyのものに変わる。
[ec2-user@ip-172-31-11-41 ~]$ mysql -h aurora-proxy.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com --ssl-ca=AmazonRootCA1.pem -P 3306 -u admin -p
...
MySQL [(none)]> USE `mydb`;
MySQL [mydb]> SELECT * FROM `users`;
+----+---------------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------------+---------------------+---------------------+
| 3 | yamada tarou | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
| 4 | 山田 太郎 | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
+----+---------------+---------------------+---------------------+
2 rows in set (0.00 sec)
MySQL [mydb]> INSERT INTO `users` (`name`) VALUES ('山田 花子');
MySQL [mydb]> SELECT * FROM `users`;
+----+---------------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------------+---------------------+---------------------+
| 3 | yamada tarou | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
| 4 | 山田 太郎 | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
| 5 | 山田 花子 | 2022-08-17 10:58:11 | 2022-08-17 10:58:11 |
+----+---------------+---------------------+---------------------+
3 rows in set (0.00 sec)
特にRead/Writeを問題なく実行できる事が確認できる。
※Amazon RDS プロキシを使用して、Amazon RDS MySQL DB インスタンスまたは Aurora MySQL DB クラスターに接続する方法を教えてください。では--ssl-mode=REQUIRED
というオプションを設定するように書かれていたが、このオプションがあると以下のようなエラーになったが、インストールしたものがmariadbだったからだと思っている。ちなみに、MySQLのリファレンスを見ると、
Use --ssl-mode=REQUIRED instead of --ssl=1 or --enable-ssl.
となっているので、--ssl=1
をオプションに付けて実行したらどうなるのか試したところ、問題なく実行できた。が、MySQLとMariaDBは祖先は同じだが今は違う部分もあるのでMariaDBのリファレンスをちゃんと読むのがいいだろう・・・。
[ec2-user@ip-172-31-11-41 ~]$ mysql --version
mysql Ver 15.1 Distrib 5.5.68-MariaDB, for Linux (x86_64) using readline 5.1
[ec2-user@ip-172-31-11-41 ~]$ mysql -h aurora-proxy.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com --ssl-mode=REQUIRED --ssl-ca=AmazonRootCA1.pem -P 3306 -u admin -p
mysql: unknown variable 'ssl-mode=REQUIRED'
[ec2-user@ip-172-31-11-41 ~]$ mysql -h aurora-proxy.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com -u admin -p --ssl=1 --ssl-ca=AmazonRootCA1.pem
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 1941881813
Server version: 5.7.12 MySQL Community Server (GPL)
...
2つ目のエンドポイント(read-only)へ接続してみる
こちらも1つ目のエンドポイントへ接続してみると同じように接続するまでは全く同じ。ただし、INSERT文(Write)はread-onlyのエンドポイントなので実行できない。
[ec2-user@ip-172-31-11-41 ~]$ mysql -h aurora-proxy-read-only.endpoint.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com --ssl=1 --ssl-ca=AmazonRootCA1.pem -u admin -p
Enter password:
...
MySQL [(none)]> USE `mydb`;
MySQL [mydb]> SELECT * FROM `users`;
+----+---------------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------------+---------------------+---------------------+
| 3 | yamada tarou | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
| 4 | 山田 太郎 | 2022-08-17 08:58:35 | 2022-08-17 08:58:35 |
| 5 | 山田 花子 | 2022-08-17 10:58:11 | 2022-08-17 10:58:11 |
+----+---------------+---------------------+---------------------+
3 rows in set (0.01 sec)
MySQL [mydb]> INSERT INTO `users` (`name`) VALUES ('田中 太郎');
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
RDS(Aurora)のリーダーエンドポイント
もしRDSのクラスター・インスタンスを作成する際に、リーダーを作成していなかった場合、以下のようにTarget group doesn't have any associated read-only instances
というエラーが出る。
[ec2-user@ip-172-31-11-41 ~]$ mysql -h aurora-proxy-read-only.endpoint.proxy-cl1btn8tdegb.ap-northeast-1.rds.amazonaws.com --ssl=1 --ssl-ca=AmazonRootCA1.pem -u admin -p
Enter password:
...
MySQL [(none)]> SHOW DATABASES;
ERROR 9501 (HY000): Target group doesn't have any associated read-only instances
これはRDS(Aurora)にリーダーのエンドポイントがないからで、単にリーダーエンドポイントを追加すればいい(スクショがない部分はデフォルトのまま)。
1 | 2 |
---|---|
アクション | |
リーダーの追加 |
作成が完了すると、もし既にRDS Proxyが存在していれば自動で紐づく(RDS Proxyを作成する際に指定したのがAurora DB クラスター(今回だと以下のスクショのdatabase-1
)だったため)。
Lambdaを作成する
今回は手動で設定する部分がある関係で、serverlessFWなどIaCではなくZipを自分で上げるスタイルでLambdaを作成する。まずはデフォルトの設定でマネージメントコンソールから関数を作成する。
コード全体は以下。
webpackのoutputの設定についてはModule Definition Systemsを参照。
READMEの通りの手順で、Build→Deployを行えばLambdaのコードの部分の設定はOK。
以下では、RDS Proxy経由でRDS(Aurora)に接続するための設定を行っていく。
ランタイム設定の変更
デフォルトのハンドラーはindex.handler
なので、自分の実装に合わせてここを変更する。
Lambdaのハンドラーはファイル名.関数名
になるので、今回だとファイルがルートディレクトリにないので相対パスも含めて書く必要があり、./dist/lambda.handler
になる(詳細はNode.js の AWS Lambda 関数ハンドラーを参照)。
関数を設定すると、ハンドラー設定の値はファイル名とエクスポートしたハンドラーメソッドの名前をドットで区切ったものになります。コンソールのデフォルトと、このガイドの例では、index.handler です。これは、handler ファイルからエクスポートされた index.js メソッドを示します。
環境変数を設定
以下のように環境変数を設定する。これを使ってLambdaは動く。
※ここまでの状態ではRDS Proxyのエンドポイントにアクセスできない。続きのVPCの設定などをやってやっと接続できるようになる。
VPCの設定
LambdaからRDS Proxyにアクセスするには、LambdaはRDS Proxyと同じVPCに属している必要がある(LambdaにVPCの設定をせずにデータベースプロキシの設定を追加すると以下のようにInfoが表示される)。
というわけで設定していくが、まずLambdaにはLambdaのVPCがあり、AWSアカウントで作成したVPCとは別物なので、LambdaをアカウントのVPCに接続させるにはIAMが追加で必要になる(以下公式からの引用)。
Lambda 関数は、常に Lambda サービスが所有する VPC 内で実行されます。Lambda はこの VPC にネットワークアクセスとセキュリティルールを適用し、VPC を自動的に維持および監視します。Lambda 関数がアカウント VPC 内のリソースにアクセスする必要がある場合は、VPC にアクセスするための関数を設定します。
必要なIAMは実行ロールとユーザーアクセス許可に書かれている。今回はマネージメントコンソールでLambdaを作成し、その時に特に何も設定しなかったのでデフォルトで新しいLambdaの実行ロールが作成されているので、そこに新しくポリシー(AWSLambdaVPCAccessExecutionRole
)をアタッチする。
1 | 2 |
---|---|
Lambdaの実行ロール | |
IAMロール | |
ポリシーを rds-proxy-lambda-func-role-jdg11om4 にアタッチ |
次にVPCの設定をしていく。RDS ProxyのVPCと同じVPC(AWSアカウントを作成した際にデフォルトで作成されるVPC)になるので、以下のように設定していけばいい。
※Lambdaの実行ロールについてはLambdaの実行ロール Lambda実行時のAWS_ACCESS_KEY_IDとかは何になる?も参照ください。
データベースプロキシの設定
VPCの設定ができたので、最後にデータベースプロキシの設定もする。これは既に作成済みのRDS Proxyを設定するだけなので以下のように簡単にできる。
2022-08-23追記
IAM認証ではなく、パスワード認証の場合にはLambdaにデータベースプロキシの設定をする必要はないようである。実際にデータベースプロキシの設定をせずに、RDS Proxyへ経由でAuroraへの接続もできた。
LambdaからRDS Proxy経由でRDS(Aurora)に接続する
後は実際にLambdaを実行するだけ。実行してみると以下のように問題なくデータが取得できている事が確認できた。あとはread-onlyのエンドポイントを使い分けて実装すれば実装として完成になるだろう。
study@localhost:~/workspace/rds-proxy-lambda (main *)
$ aws lambda invoke --function-name rds-proxy-lambda-func response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
{
"statusCode": 200,
"body": [
{
"id": 3,
"name": "yamada tarou",
"created_at": "2022-08-17T08:58:35.000Z",
"updated_at": "2022-08-17T08:58:35.000Z"
},
{
"id": 4,
"name": "山田 太郎",
"created_at": "2022-08-17T08:58:35.000Z",
"updated_at": "2022-08-17T08:58:35.000Z"
},
{
"id": 5,
"name": "山田 花子",
"created_at": "2022-08-17T09:47:59.000Z",
"updated_at": "2022-08-17T09:47:59.000Z"
}
]
}
※コードについて1点補足として、EC2からRDS Proxy経由でRDS(Aurora)に接続してみるでEC2から接続する時もそうだったが、今回のRDS ProxyはTLSを有効化しているので証明書が必要になる。そのため、myslqのコネクションを作成する時にSSL options(API and Configurationから飛べるページ)に書かれているようなSSLのための追加実装が必要になっている。
const connection = await mysql.createConnection({
host: process.env.HOST,
port: 3306,
user: process.env.USER_NAME,
password: process.env.PASSWORD,
database: 'mydb',
ssl: {
ca: fs.readFileSync(path.join(__dirname, 'AmazonRootCA1.pem'))
}
});
まとめとして
TLSの証明書が必要でそれがどこにあるのかわからず少し躓いた部分があったが、公式の説明通りに比較的に簡単に構築できた。
参考文献
おまけ
IAMユーザーで請求情報を見れるようにする
AWS Billing コンソールへのアクセスのアクティブ化の https://console.aws.amazon.com/billing/home#/account をクリックし、rootアカウントの設定ページに飛ぶ。
ページの真ん中の方にあるIAM ユーザー/ロールによる請求情報へのアクセス
を編集すればOK。
CICD
S3にzipをアップロードするという古典的な方法だが…。以下のソースがそれ。