AWS LambdaからRuby + Mysql2でAmazon RDSにつないでみた
これまで Amazon EC2
で動かしていた1日1回動作する Ruby
で書かれたバッチを、主にコストダウンを目的として AWS Lambda
に移行し、サーバーレス化した。
バッチの内容としては、RDS
で稼働している MySQL
のデータベースから必要なデータを取得する必要がある。
バッチの内容をできるだけ書き換えずに AWS Lambda
から Amazon RDS
へ接続する際に、少し手順が複雑だったので、今回はその方法を備忘録も兼ねて整理しながらやってみる。
作業ディレクトリ作成
まずは作業ディレクトリの作成。
今回は、mysql2_test
とした。
$ mkdir mysql2_test
$ cd mysql2_test
Dockerfile 作成
Mysql2
の gem
を動かすためには、mysql-devel
のインストールが必要となる。Dockerfile
を下記のように作成する。
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
とタグ付けした。
$ docker build -t my-lambda .
handler.rb 作成
Mysql2
が動作しているか確認するための handler.rb
を作成。
require 'mysql2'
def main(event:, context:)
{
mysql2_version: Mysql2::VERSION
}
end
うまく動作すれば Mysql2
のバージョンが表示されるもの。
Gemfile 作成
Gemfile
を作成する。
source 'https://rubygems.org'
gem 'mysql2'
bundle install
処理のスクリプト作成
コンテナで bundle install
を実行するのだが、bundle config
でいろいろとオプションを設定しないといけないので、スクリプト化する。bundle_install.sh
を下記の内容で作成した。
#!/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/
作成したスクリプトファイルに実行権限付与
作成したスクリプトに、実行権限を付与する。
$ chmod 755 ./bundle_install.sh
bundle_install.sh
実行
bundle_install.sh
を最初の方でビルドした Docker
コンテナ内(my-lambda
)で実行する。
作業ディレクトリを /var/task
にボリュームマウントして実行。
$ docker run --rm -it -v $PWD:/var/task my-lambda ./bundle_install.sh
実行すると、下記のような結果が出て正常に gem
がインストールされるはず。
[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
合わせて作業ディレクトリに lib
や vendor/bundle
ができていることを確認する。
関数をテスト実行
前述の、ローカルマシンで AWS Lambda
環境をほぼ同じように再現可能な lambci/lambda
のコンテナを使って実際に動作をテストしてみる。
コマンドは下記の通り。
$ docker run --rm -v $PWD:/var/task lambci/lambda:ruby2.5 handler.main
問題なく動作していれば下記のような結果が表示される。
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
へ接続する情報を入れて実際の環境で試す。
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
ファイルを作成する。
zip -q -r deploy.zip .
実行
AWS Lambda
を VPC
内のプライベートサブネットに作成、環境変数やセキュリティーグループを適切に設定した上で、先程の deploy.zip
をアップロードする。
実行してみると、下記のように接続できた。
参考URL
- Using Mysql2 gem in AWS Lambda for Ruby
- lambci/docker-lambda: Docker images and test runners that replicate the live AWS Lambda environment
- brianmario/mysql2: A modern, simple and very fast Mysql library for Ruby - binding to libmysql