AWS Lambdaの奮闘記です。
初めて触るAWS Lambdaちゃんに苦戦した様子の備忘録。
やりたいこと
AWS LambdaでRubyを動かして、そこからスクレイピング、Google spread sheetにpostして表にデータ挿入
詰まったポイント感
- SAMって何?とっとこSAM太郎?
- chrome driver動かなさすぎワロタ
- pythonの記事ばっかやん!!
- IAMのポリシーって何
など。
環境なのかわからないけど動かないってケースが多くて結構ハマってました。
ざっくりはじめに見た記事
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-ruby.html
https://qiita.com/Y_uuu/items/85c86df8773f7c225521
AWS IAM ロールを追加
AWS IAMとは?
めちゃ簡単に言うとユーザ管理です。
セキュリティリスクなどを考えると、ユーザには最低限の権限を与えて管理するのが望ましいです。
そのためのサービスですね。
AWS IAM ポリシー
ポリシーってやつが権限ですね。
サービスごとに権限がつけられたりするわけです。
業務委託の人とか権限わけたいですよね、そういうイメージ。
ひとまず、ロールを追加をぽちぽち。 権限については、使いたいサービスのFullAccessでひとまずOKだと思いますが、参考記事があるならそれ通りでよいと思います。
ルートユーザを利用するのは危険なので、避けましょう。
SAM
サーバーアプリケーションモデルです。
今のところの理解は、サーバレスで動かしたいための一式をコードで管理しちゃおうってやつです。
build叩いて 実行も deployもコマンドひとつでできるようになる感じです。 dockerのコンテナでの実行を超楽にまとめてくれてる。すげえよとっとこSAM太郎。
SAMをインストール
dockerなどはすでにはいっているので、sam cliをインストール。
dockerが入ってない人はインストールしましょう。(手順は書いてほしい気持ちはわかるんですが、省略します...)
ruby のversionは記事では2.5だったが、AWSもruby 2.7に対応しているようなので、2.7で入れてみる。 -> あとでやっぱ2.5にしました。
ローカルのrubyの環境整備
2.5.0とかに合わせたかったので、環境を整備。
手元のruby-buildとかが古かったので、更新。
brew update && brew upgrade ruby-build
2.7.0が rbenv install --list
とかしても-dev
だったりしていた。
2.6.6 2.7.0-dev 2.7.0-preview1 2.7.0-preview2 2.7.0-preview3 2.7.0-rc1 2.7.0-rc2 2.7.0 2.7.1 2.8.0-dev
更新するとちゃんとでてくれる。
ということでinstall rbenv install 2.7.0
。
rubyの安定板とかはこちらをチェックしましょう。
https://www.ruby-lang.org/ja/downloads/
sam build
すると
Building resource 'HelloWorldFunction' Running RubyBundlerBuilder:CopySource Running RubyBundlerBuilder:RubyBundle Running RubyBundlerBuilder:RubyBundleDeployment Build Succeeded
いけました。
進める
samの実行自体は以下コマンドでできるみたいですね。
sam local invoke HelloWorldFunction
--event event.json
をつけるとエラったので、一旦なし。
Invoking app.lambda_handler (ruby2.7) Fetching lambci/lambda:ruby2.7 Docker container image................................................................................................................................................ Mounting /Users/sakuraikota/workspace/room_post_sam/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container START RequestId: 74af0a77-3cfa-16a5-c78d-443dee1cd773 Version: $LATEST END RequestId: 74af0a77-3cfa-16a5-c78d-443dee1cd773 REPORT RequestId: 74af0a77-3cfa-16a5-c78d-443dee1cd773 Init Duration: 255.71 ms Duration: 5.67 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 23 MB {"statusCode":200,"body":"{\"message\":\"Hello World!\"}"}
いけたっぽい?
ファイルの修正したあとは、build。
実行には sam local invoke HelloWorldFunction
でいけるようです。
deployもCLIから行えるようで、めちゃ便利だ...!
スクレイピングする際
そのサイトがクロールしても問題ないか、みてあげたほうがいいみたい。
gem 'robotex'
という便利なものがあるみたい。
lambdaがタイムアウトする
Function 'HelloWorldFunction' timed out after 3 seconds
template.yaml のtimeoutの値を増やす。
invokeって強そう
強そうに思える単語ですが、 呼び出すっていう意味です。
そのままですね
chrome driverを先にlambda layersにあげる必要がありそう
何より重たいものっぽく、layersにあげておくとcodeと分離できて軽くなるしよいみたい。
pythonの記事がおおい...
gem 'webdrivers', '~> 3.0'
3.0の方が安定して動いてる、みたいな記事もありました。
Selenium::WebDriver::Chrome.driver_path
driverのpathを指定する。
dir内で完結したい、参照先を配下にしたい。
Selenium::WebDriver::Chrome.driver_path="/layer/bin/chromedriver"
このpathの指定、chromedriverのverなのか、binaryがおかしいのかわかりませんが動きませんでした。。。
ここらへんでsamでやるのは中断。
chrome driver
curl -SL https://chromedriver.storage.googleapis.com/83.0.4103.14/chromedriver_linux64.zip > chromedriver.zip
chrome driver どうもversionがserver-less chromiumとかと合わせないと動作しないケースが多いみたいです。
server-less chromium
うーん、最新版がどれだw
これしかでてこない。。。
curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip
sam deploy --guided
権限がない、とはじかれる。
AWS iamでユーザ作る
ルートユーザじゃなくて、ユーザ作ってそこで管理してねってことなので、 適当に管理権限つけて作成、設定。
https://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html
rubyだと解決に至らず。
Error raised from handler method { "errorMessage": "not a file: \"../layer/bin/chromedriver\"", "errorType": "Function<Selenium::WebDriver::Error::WebDriverError>", "stackTrace": [ "/var/task/vendor/bundle/ruby/2.7.0/gems/selenium-webdriver-3.142.7/lib/selenium/webdriver/common/platform.rb:136:in `assert_file'",
どうも、binaryのchrome driverが読み込めてないと思うんですが,動きません。
くじけそう
https://dev.to/mknycha/serverless-web-scraper-in-ruby-tutorial-50hg
以下からは上記のサイトの手順でやってみたら動きました。
これを試す。samじゃないけど。とにかく動かそう...
bundle install --deployment
とかして、いれても requireする cannot load such file -- selenium-webdriver
えええ。
vendor/bundle 配下を眺めていると、 あ、rubyが2.6.0ではいっている...
vendor/bundle/ruby/2.6.0/gems/selenium-webdriver-3.142.7/selenium-webdriver.gemspec
rbenvですぐさま 2.5.0に整え。
なんとか動いた...
sam利用はできてないけど、ひとまず動いた。
dockerを通して動作を確認。
docker run --rm -v "$PWD":/var/task --mount type=tmpfs,target=/dev/shm,readonly=true lambci/lambda:ruby2.5 lambda_function.lambda_handler
んーと、localでぱっと試せないんだっけか。
ひとまずdeploy、実行できた
実行はできた!
timezoneの設定は、環境変数に TZ, Asia/Tokyoを追加。
実行時間のtimeoutも、 メモリ : 512MB タイムアウト時間: 1分 で設定。
lambdaをちょこっと使うくらいなら無料枠からはみ出さない。
公式サイトで料金計算はできるようになっているので、気になる人は計算してみよう。
リポジトリに追加
binaryファイルとか重たいので、適度に gitignoreしてあげてpushするとよさそう。
一定時間ごとに実行させる
トリガーを追加。
cloud watchを追加。
cronの設定でめちゃはじかれたw ぐぐったらでてきますが、こんな感じにしました。
時差があるので、9時間ひいて。
cron(0 20 * * ? *)
朝5時に実行させます。
google spread sheetへの書き込み
https://qiita.com/takatama/items/e5cb83012d14c0094a79
こちらの記事を参考に、10秒で作れました
まとめ
lambdaの使い方、aws CLI, IAM, ポリシー
とにもかくにも触ってみてわかることってめちゃありますね。
rubyとかbunlderとか環境のこともまた再認識できて、良い機会になりました。