MMMブログ

AWS LambdaからRuby + Mysql2でAmazon RDSにつないでみた

これまで Amazon EC2 で動かしていた1日1回動作する Ruby で書かれたバッチを、主にコストダウンを目的として AWS Lambda に移行し、サーバーレス化した。

バッチの内容としては、RDS で稼働している MySQL のデータベースから必要なデータを取得する必要がある。

バッチの内容をできるだけ書き換えずに AWS Lambda から Amazon RDS へ接続する際に、少し手順が複雑だったので、今回はその方法を備忘録も兼ねて整理しながらやってみる。

作業ディレクトリ作成

まずは作業ディレクトリの作成。
今回は、mysql2_test とした。

1
2
$ mkdir mysql2_test
$ cd mysql2_test

Dockerfile 作成

Mysql2gem を動かすためには、mysql-devel のインストールが必要となる。
Dockerfile を下記のように作成する。

1
2
3
4
5
FROM lambci/lambda:build-ruby2.5
WORKDIR /var/task
RUN yum -y install mysql-devel
RUN gem update bundler
CMD "/bin/bash"

上記で利用している lambci/lambda のコンテナイメージは、https://github.com/lambci/docker-lambda に以下のような説明があるとおり、

A sandboxed local environment that replicates the live AWS Lambda environment almost identically – including installed software and libraries, file structure and permissions, environment variables, context objects and behaviors – even the user and running process are the same.

ローカルマシンで、AWS Lambda 環境をほぼ同じように再現するものとなっている。
今回は Ruby 環境を使うので、build-ruby2.5 のタグを指定した。

Dockerコンテナをビルド

以下のコマンドを実行し、コンテナをビルドする。
my-lambda とタグ付けした。

1
$ docker build -t my-lambda .

handler.rb 作成

Mysql2 が動作しているか確認するための handler.rb を作成。

1
2
3
4
5
6
7
require 'mysql2'

def main(event:, context:)
{
mysql2_version: Mysql2::VERSION
}
end

うまく動作すれば Mysql2 のバージョンが表示されるもの。

Gemfile 作成

Gemfile を作成する。

1
2
3
source 'https://rubygems.org'

gem 'mysql2'

bundle install 処理のスクリプト作成

コンテナで bundle install を実行するのだが、bundle config でいろいろとオプションを設定しないといけないので、スクリプト化する。
bundle_install.sh を下記の内容で作成した。

1
2
3
4
5
6
#!/bin/bash
bundle config --local build.mysql2 --with-mysql2-config=/usr/lib64/mysql/mysql_config
bundle config --local silence_root_warning true
bundle install --path vendor/bundle --clean
mkdir -p /var/task/lib
cp -a /usr/lib64/mysql/*.so.* /var/task/lib/

作成したスクリプトファイルに実行権限付与

作成したスクリプトに、実行権限を付与する。

1
$ chmod 755 ./bundle_install.sh

bundle_install.sh 実行

bundle_install.sh を最初の方でビルドした Docker コンテナ内(my-lambda)で実行する。
作業ディレクトリを /var/task にボリュームマウントして実行。

1
$ docker run --rm -it -v $PWD:/var/task my-lambda ./bundle_install.sh

実行すると、下記のような結果が出て正常に gem がインストールされるはず。

1
2
3
4
5
6
7
8
9
[DEPRECATED] The `--clean` flag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please use `bundle config set clean 'true'`, and stop using this flag
[DEPRECATED] The `--path` flag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please use `bundle config set path 'vendor/bundle'`, and stop using this flag
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using bundler 2.1.4
Fetching mysql2 0.5.3
Installing mysql2 0.5.3 with native extensions
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Bundled gems are installed into `./vendor/bundle

合わせて作業ディレクトリに libvendor/bundle ができていることを確認する。

関数をテスト実行

前述の、ローカルマシンで AWS Lambda 環境をほぼ同じように再現可能な lambci/lambda のコンテナを使って実際に動作をテストしてみる。
コマンドは下記の通り。

1
$ docker run --rm -v $PWD:/var/task lambci/lambda:ruby2.5 handler.main

問題なく動作していれば下記のような結果が表示される。

1
2
3
4
5
START RequestId: 7e30ee66-2d38-1ade-6e49-a2f107f206b4 Version: $LATEST
END RequestId: 7e30ee66-2d38-1ade-6e49-a2f107f206b4
REPORT RequestId: 7e30ee66-2d38-1ade-6e49-a2f107f206b4 Init Duration: 1859.26 ms Duration: 25.85 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 22 MB

{"mysql2_version":"0.5.3"}

ちゃんと Mysql2 が動作できているのが確認できた。

AWS 環境に合わせて handler.rb を修正

ここまで確認できれば、Amazon RDS へ接続する情報を入れて実際の環境で試す。

1
2
3
4
5
6
7
8
9
10
require 'mysql2'

def main(event:, context:)
client = Mysql2::Client.new(host: ENV["DB_HOST"],
username: ENV["DB_USER"],
password: ENV["DB_PASSWORD"],
database: ENV["DB_NAME"])
results = client.query("SHOW DATABASES;").to_a
puts results
end

ホスト名、ユーザー名、パスワード、データベース名などは、環境変数から取得できるようにしておくと良い。

zip ファイル作成

AWS Lambda にアップロードするために、deploy.zip という名前で zip ファイルを作成する。

1
zip -q -r deploy.zip .

実行

AWS LambdaVPC 内のプライベートサブネットに作成、環境変数やセキュリティーグループを適切に設定した上で、先程の deploy.zip をアップロードする。
実行してみると、下記のように接続できた。

参考URL

このエントリーをはてなブックマークに追加

お問い合わせ

見積もり依頼や詳しいご相談など、クラウド・AWSに関する困りごとをお気軽にご相談ください。
以下のお問い合わせ先から受け付けています。

お問合わせはこちら

※通常1営業日内にご回答いたします。