🥦
AWS IoT Greengrass V2のLambdaがすぐ死ぬので、割り当てるメモリを増やした
前提
- RaspberryPie上にAWS IoT Greengrass V2を導入してLambdaを動かす
- Lambdaは「存続期間の長い Lambda」(Long-Lived Lambda)
発生した現象(メモリ割当を増やしたきっかけ)
-
Lambdaをラズパイにデプロイ後しばらくすると死ぬ
-
ラズパイに入ってログ(
/greengrass/v2/logs
配下)を見るとstatusがbroken
greengrass.log
2021-12-22T05:26:32.793Z [INFO] (lambda-function-lifecycle) com.aws.greengrass.status.FleetStatusService: fss-status-update-published. Status update published to FSS. {serviceName=FleetStatusService, currentState=RUNNING}
2021-12-22T05:26:32.798Z [INFO] (pool-2-thread-30) com.aws.greengrass.lambdamanager.UserLambdaService: Shutdown initiated. {serviceInstance=0, serviceName=lambda-function, currentState=BROKEN}
2021-12-22T05:26:37.182Z [INFO] (pool-2-thread-29) com.aws.greengrass.lambdamanager.LambdaRequestHandler: get-work-item. Get work operation got interrupted. {arn=arn:aws:lambda:ap-northeast-1:000000000000:function:lambda-function:48}
2021-12-22T05:26:37.612Z [INFO] (pool-2-thread-30) com.aws.greengrass.lambdamanager.UserLambdaService: generic-service-shutdown. {serviceInstance=0, serviceName=lambda-function, currentState=BROKEN}
lambdaのログ
2021-12-22T05:26:36.268Z [INFO] (pool-2-thread-21) lambda-function: Caught SIGTERM. Stopping runtime.. {serviceInstance=0, serviceName=lambda-function, currentState=BROKEN}
2021-12-22T05:26:37.586Z [INFO] (pool-2-thread-21) lambda-function: Tearing down overlay tmpfs mounts. {serviceInstance=0, serviceName=lambda-function, currentState=BROKEN}
- lambda動作中に
vmstat
をするとioのbiが異常に大きい。つまりSDカードに対して大量のReadが発生している
# vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 1 1280 95244 172028 423852 0 0 8930 15 1238 2658 16 15 59 10 0
1 1 1280 95276 172036 423608 0 0 16782 126 1744 4032 15 20 44 22 0
1 1 1280 96324 172036 423480 0 0 18354 1 1560 3543 14 19 40 27 0
Lambdaが死ぬ原因
Lambdaが使用できるメモリが足りていない!!
Greengrassを動かしているJVM(Java仮想マシン)のメモリも足りていない!!
対処方法(メモリの割当の増やし方)
下記の両方が必要です
- Greengrassを動かすJVM(Java仮想マシン)が使用できるメモリを増やす
- Lambdaが使用できるメモリを増やす
JVMのメモリ割り当ての増やし方
デプロイを作成する時に、aws.greengrass.Nucleus
のコンポーネントの設定に下記を追加してください(マージする設定の欄に書く)
- メモリの上限を
128MB
にしています。数字を変更すれば、変更できます。
マージする設定
{ "jvmOptions": "-Xmx128m" }
注意
- Nucleusは必須コンポーネントなので、デプロイ時に指定しなくても勝手にインストールされていますが、この設定を入れるために明示的に指定してください。
- 指定の際、Nucleusのバージョンは他コンポーネントの依存関係に大きく影響しますので気をつけてください。特にLegacySubscriptionRouterとの関係には要注意です。
参照
Lambdaのメモリ割り当ての増やし方
方法は2つあります。どちらかで実施してください。本質的には両方同じです。
方法1:Lambdaコンポーネントを作るとき(バージョンを作るとき)に設定を入れる
コンテナパラメータのメモリサイズを増やせばOK
方法2:デプロイ時にコンポーネントの設定でメモリサイズを指定する
デプロイを作成する時に、Lambdaコンポーネントの設定に下記を追加してください(マージする設定の欄に書く)
- 下記は、メモリを
96MB
割り当てています。
マージする設定
{"containerParams": {"memorySize": 96000}}
その他
greengrassのデバッグログを出す方法
aws.greengrass.Nucleus
のコンポーネントの設定に下記を追加するとデバッグログが出力されるようになるので、調査が捗ります。
マージする設定
{"logging": {"level": "DEBUG"}}
感想という名の愚痴
- 世の中にGreengrassV2の情報が少なすぎ。
- Brokenになる原理はclassmethodの記事があるのが救い。
https://dev.classmethod.jp/articles/greengrass-v2-lambda-compoent-broken/
- Brokenになる原理はclassmethodの記事があるのが救い。
- メモリが足りてないのに、OSのメトリクス見てもメモリに問題なさそうなのがツラい。
- IOリードがclass10のSDカードの保証値を余裕で超えてくるのでファイルアクセスばかり疑っていた。
- Lambdaのメモリ割り当てを増やしただけだと何も変わらないのが地獄。真っ先に試したが結局死ぬので「メモリ関係ないのか」と思ってしまった。
- JavaVMのメモリ割り当てなんて知らんがな。。。
- 同じコードをラズパイ上で直接実行しても再現しなかったので、毎回Greengrassにデプロイしないと確認できないのが面倒くさかった。
- いい感じのdebugツールがほしい。
Discussion