上記の問題を解決したのでメモ。
#手順1:実行バージョンの指定
LambdaからEC2 Run Commandを利用するとき、Run Commandは対象のEC2インスタンスで有効となっているPythonの実行ファイルではなく、そのインスタンスの初期状態で設定されているバージョンを実行します。(Amazon Linux系ならば今日現在は2.7.12)
そのため、標準と異なるバージョンのPythonを実行する場合は、下記のようにLambdaに記述するRun Commandで実行ファイルをフルパスで指定します。
下記の例ではpyenvに構築した環境を指定しています。
Lambdaはroot実行となるため、pyenvをrootで構築していますが、直接指定して実行するのであれば実行用のユーザを構築するで良いと思います。
ssm.send_command(
InstanceIds = instances,
DocumentName = "AWS-RunShellScript",
Parameters = {
"commands": [
"/root/.pyenv/versions/anaconda3-4.4.0/bin/python /work/hoge.py",
],
"executionTimeout": ["3600"]
},
)
#手順2:ライブラリパスの追加
手順1では環境変数に実行するPythonのパスを追加せずに所要のバージョン(環境)を実行するため、そのままではライブラリのimportができません。
そのため、Lambdaから呼ばれるEC2側のスクリプトの先頭でsite-packages
のパスを追加することで、ライブラリを読み込むことができるようになります。
下記の例では手順1で指定した環境配下のsite-packages
を指定しています。
import sys
sys.path.append("/root/.pyenv/versions/anaconda3-4.4.0/lib/python3.6/site-packages/")
#感想
当初からパス周りの問題と想定はしていましたが、Lambda側とEC2側で原因の切り分けに手間取ってしまいました。
また、バージョンが指定が機能として提供されているのか調査することに無駄な労力を使ってしまうといった、マネージドサービスならでは?の失敗がありました。
今後も同様な低レイヤでのつまづきが予見されますが、その際はこの経験を思い出して基本に立ち返って考えたいです。