はじめに
RDS Proxy 経由で MySQL にアクセスするLambdaをVPC内で実行させましたので、手順をまとめます。
RDS Proxyの作成
RDS Proxyは、以前作成した記事がありますので、こちらを参考にしてください。
private subnetにLambdaを作成
設定
-
IAMロール
-
AWSLambdaENIManagementAccess
を付与します.これによってVPC上でLambdaが実行できます。
-
-
タイムアウト時間
- 30秒にします。実行に数秒かかります。
-
環境変数
- RDS_HOSTNAME:proxyのライターエンドポイント
- RDS_DB_NAME:データベース名
- RDS_USERNAME:ユーザー名
- RDS_PASSWORD:パスワード
-
VPC
- private subnetに設置
- sgの設定は以下の通り
設定 | タイプ | ポート | ソース |
---|---|---|---|
Lambda | All | All | 0.0.0.0/0 |
Proxy | MySQL/Aurora | 3306 | LambdaのSG |
Aurora | MySQL/Aurora | 3306 | ProxyのSG |
mysqlモジュール
Lambdaは、Nodejsを使用します。
mysql
モジュールを使用するため、ローカルでmysql
モジュールをインストールします。
LambdaLayerでアップロード
$ mkdir nodejs
$ cd nodejs
$ tree
.nodejs
├── package-lock.json
└── package.json
// package name以外はデフォルトにしました
$ npm init -y
$ npm install mysql
$ tree
.nodejs
├── node_modules
├── package-lock.json
└── package.json
$ cd ..
$ zip -r nodejs.zip nodejs
nodejsフォルダごとzip化すること。
zip化したnodejs.zipをLambdaLayerにアップしましょう。
具体的なアップロード方法は、以前作成した記事を参考にしてください
Lambdaに直接アップロード
LambdaLayerを使用しない場合、以下のように作成します。
$ mkdir nodejs
$ cd nodejs
$ tree
.nodejs
├── package-lock.json
└── package.json
// package name以外はデフォルトにしました
$ npm init -y
$ npm install mysql
$ touch index.js
$ tree
.nodejs
├── index.js
├── node_modules
├── package-lock.json
└── package.json
$ zip -r nodejs.zip *
Lambdaのコード
const hostname = process.env.RDS_HOSTNAME;
const databaseName = process.env.RDS_DB_NAME;
const password = process.env.RDS_PASSWORD;
const user_name= process.env.RDS_USERNAME;
const mysql = require('mysql');
const beginTransaction = (connection) => {
return new Promise((resolve, reject) => {
connection.beginTransaction((err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
};
const query = (connection, statement, params) => {
return new Promise((resolve, reject) => {
connection.query(statement, params, (err, results, fields) => {
if (err) {
reject(err);
} else {
resolve(results, fields);
}
});
});
};
const commit = (connection) => {
return new Promise((resolve, reject) => {
connection.commit((err) => {
if (err) {
reject(err);
} else {
resolve(err);
}
});
});
};
const rollback = (connection, err) => {
return new Promise((resolve, reject) => {
connection.rollback(() => {
reject(err);
});
});
};
exports.handler = async (event) => {
// console.log('event:', JSON.stringify(event, null, 2));
const connection = mysql.createConnection({
host: hostname,
user: user_name,
password: password,
database: databaseName,
});
const now = new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' });
const sql = 'INSERT INTO database_table (title, created_at) VALUES (?, ?);';
const inserts = ['test', now];
try {
await beginTransaction(connection);
const results = await query(connection, sql, inserts);
console.log(results);
await commit(connection);
} catch (err) {
await rollback(connection);
throw err;
}
};
今回は、database_table
というテーブルに、タイトルと作成日時を登録してみました。
'INSERT INTO databaseTable (title, created_at) VALUES (?, ?);'
mysqlの使用メソッド
-
createConnection
- mysqlと接続します
-
beginTransaction
- トランザクションを開始します
-
query
- クエリを実行します
-
commit
- トランザクション中のデータ処理を確定します
-
rollback
- トランザクション中のデータ処理を取り消され、トランザクション実行前の状態に戻りトランザクションを終了します。
モジュールを作成し、LambdaLayerで共通ライブラリ化
beginTransaction
、query
、commit
、rollback
の4つは、モジュールにして、LambdaLayerで共通ライブラリ化してもよいです。
module.exports = (connection) => {
return new Promise((resolve, reject) => {
connection.beginTransaction((err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
};
module.exports = (connection, statement, params) => {
return new Promise((resolve, reject) => {
connection.query(statement, params, (err, results, fields) => {
if (err) {
reject(err);
} else {
resolve(results, fields);
}
});
});
};
module.exports = (connection) => {
return new Promise((resolve, reject) => {
connection.commit((err) => {
if (err) {
reject(err);
} else {
resolve(err);
}
});
});
};
module.exports = (connection, err) => {
return new Promise((resolve, reject) => {
connection.rollback(() => {
reject(err);
});
});
};
こちらの記事を参考にしました。
$ tree
.
└── node_modules
├── beginTransaction.js
├── commit.js
├── query.js
├── rollback.js
├── package-lock.json
└── package.json
先程と同様に、nodejsをzip化し、アップロードします。
Lambdaのコード
const hostname = process.env.RDS_HOSTNAME;
const databaseName = process.env.RDS_DB_NAME;
const password = process.env.RDS_PASSWORD;
const user_name= process.env.RDS_USERNAME;
const mysql = require('mysql');
const beginTransaction = require('beginTransaction');
const commit = require('commit');
const query = require('query');
const rollback = require('rollback');
exports.handler = async (event) => {
// console.log('event:', JSON.stringify(event, null, 2));
const connection = mysql.createConnection({
host: hostname,
user: user_name,
password: password,
database: databaseName,
});
const now = new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' });
const sql = 'INSERT INTO databaseTable (title, created_at) VALUES (?, ?);';
const inserts = ['test', now];
try {
await beginTransaction(connection);
const results = await query(connection, sql, inserts);
console.log(results);
await commit(connection);
} catch (err) {
await rollback(connection);
throw err;
}
};
mysql2
2022.07.23 更新
mysql2
モジュールの方がコード量が少ないため、こちらをおすすめします
参考