背景
趣味で、DiscordだけでTRPGができるbotを作っています。
(元々はslackの内輪向けbotだったのですが)
構成は、AWS Lambda+API Gateway+Dockerコンテナ内Pythonです。
元々はLambdaのPythonのWebテキストエディターで書いていたのですが
色々問題があったら変えて行くうちにDockerで管理するのが一番楽になってしまいました。
そんなLambdaで作ったアプリがデプロイ後、一回だけ失敗する状況に悩まされていたのですが
結局解決できなかった事を記載します。
問題の発生
手製のスクリプトでLambdaのコンテナイメージの更新していました。
それまで色々なデプロイパッケージを使っていてlambrollがとても使いやすかったのですが
コンテナ環境になった時に手製のスクリプトに変えました。
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${accound_id}.dkr.ecr.ap-northeast-1.amazonaws.com
docker build --platform linux/amd64 -t ${tag} .
${tag}:latest
docker push ${accound_id}.dkr.ecr.ap-northeast-1.amazonaws.com/${tag}:latest
aws lambda update-function-code --function-name ${function_name} --image ${account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/cocbotkp-d:latest
毎回エラーが発生するので、 update-function-code
が動作中なんだろうと考え
update中なら待つように以下のコードを加えました。
STATUS="InProgress"
while [ "$STATUS" == "InProgress" ]; do
RESULT=$(aws lambda get-function --function-name cocbotkp-discord-docker)
STATUS=$(echo $RESULT | jq -r .Configuration.LastUpdateStatus)
if [ "$STATUS" == "Successful" ]; then
echo "Update successful."
break
elif [ "$STATUS" == "Failed" ]; then
echo "Update failed."
exit 1
else
echo "Update in progress..."
sleep 3
fi
done
これで初回失敗に悩む事はなくなっただろう、と思ったのですがまだエラーが続きました。
IGWの問題?
そんな時、たまたま外部リクエストとの通信のログを見たところ、初回起動時のみ必ず404が発生していました。
discord botの同一エンドポイントに投げているのに、初回だけ404が発生しているのです。
なんとなくAPI-GWで問題が発生しているのかと思っていたのですが、Lambda内部でのエラーだったのです。
IGWかNAT GWかわかりませんが、なにかがアタッチする前にLambdが利用可能になっていたのです。
最初の一回は必ず失敗する、以上!
じゃあ404を受け取ったら再度リクエスト送るようにしよう。
そう思ってコードを変えたのですが、discord botのエラーは変わらずでした、
問題は、discord botは処理が長くなる場合、deferred_responseを送って
応答を待ってもらわないといけないのですが、deferred_response自体も404で送る事ができなかったのです。
deferred_responseだけを送るLambdaを作るなど、プロダクションだと方法はあるのですが
趣味だしいいか・・・と思って一回目のエラーは見守る事にしたのでした。
同じように、Lambdaを更新した後すぐの挙動に悩む人が出ないように。。。