🥦

AWS IoT Greengrass V2のLambdaがすぐ死ぬので、割り当てるメモリを増やした

2021/12/29に公開

前提

  • 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との関係には要注意です。

参照

https://docs.aws.amazon.com/ja_jp/ja_jp/greengrass/v2/developerguide/configure-greengrass-core-v2.html#jvm-tuning

Lambdaのメモリ割り当ての増やし方

方法は2つあります。どちらかで実施してください。本質的には両方同じです。

方法1:Lambdaコンポーネントを作るとき(バージョンを作るとき)に設定を入れる

コンテナパラメータのメモリサイズを増やせばOK

方法2:デプロイ時にコンポーネントの設定でメモリサイズを指定する

デプロイを作成する時に、Lambdaコンポーネントの設定に下記を追加してください(マージする設定の欄に書く)

  • 下記は、メモリを96MB割り当てています。
マージする設定
{"containerParams": {"memorySize": 96000}}

その他

greengrassのデバッグログを出す方法

aws.greengrass.Nucleusのコンポーネントの設定に下記を追加するとデバッグログが出力されるようになるので、調査が捗ります。

マージする設定
{"logging": {"level": "DEBUG"}}

感想という名の愚痴

  • 世の中にGreengrassV2の情報が少なすぎ。
  • メモリが足りてないのに、OSのメトリクス見てもメモリに問題なさそうなのがツラい。
    • IOリードがclass10のSDカードの保証値を余裕で超えてくるのでファイルアクセスばかり疑っていた。
  • Lambdaのメモリ割り当てを増やしただけだと何も変わらないのが地獄。真っ先に試したが結局死ぬので「メモリ関係ないのか」と思ってしまった。
    • JavaVMのメモリ割り当てなんて知らんがな。。。
  • 同じコードをラズパイ上で直接実行しても再現しなかったので、毎回Greengrassにデプロイしないと確認できないのが面倒くさかった。
    • いい感じのdebugツールがほしい。

Discussion