Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@hdmn54321

【AWS IoT】Greengrass Coreデバイス上でLambdaを起動し、ローカルファイルをS3にアップロードする際の9個のハマりどころをまとめてみた。

はじめに

AIカメラ等のプロジェクトでほぼ必須(だと思います)の「Greengrass Coreデバイス上でLambda(boto3)を動かしローカルファイルをS3にアップロードする」手順と注意点をまとめました。エッジコンピューティングの基礎でもある機能で、一見すごく簡単そうですが、筆者自身かなりハマってしまいました。ラズパイの初期設定から最後の画像のアップロードまでハマりどころが9つあるのでそれを実際の手順にそって解説しています。
(ちなみにGreengrassはversion1を使っています)

概略図

image.png

今回やることの大まかな流れ

初期設定(OSインストール、ラズパイの初期設定、PCからラズパイへSSH接続、Greengrass Coreのインストール&Greengrass初期設定、Filezilla等FTPソフトウェアでラズパイに接続)

Lambdaの作成

Greengrass Groupの設定

ラズパイの追加設定

動作確認(IoT CoreからGreengrass CoreデバイスにMQTTメッセージを送ってLambdaを起動)

9のハマりどころ

Greengrass Core LambdaでS3にローカルファイルをアップロードしたい場合に気をつけたい注意点は以下の10個です。

初期設定時

① ssh接続のときsudo sshとしない

Lambda作成時

② Lambda作成時に必ずGreengrass SDKとまとめてZIPファイルにしてアップロードする
③ Lambdaハンドラーを「Pythonファイル名.関数名」と指定する
④ Lambdaエイリアスには「$LATEST」を指定しない
⑤ Lambdaの新しいバージョンを発行したら必ずエイリアスのバージョンも変える

Greengrass Groupの設定

⑥ 「作成したLambdaの登録」、「リソースの追加」、「サブスクリプションの追加」、「IAMロール&ポリシーの追加」の4つを忘れない
⑦ GreengrassのシステムlogとLambdaのlogを有効にする

ラズパイの追加設定

⑧ リソースパスは実際にラズパイのLinuxOS上に存在しなくてはいけない
⑨ リソースパスで指定したパスに「chmod 775」でアクセス(readとwrite)ができるようにする

これらの注意点は実際に手順を説明していく上で詳しく説明していきます。
※初期設定に関しては色々なところで説明があるので、ポイントの箇条書きにとどめて、内容はかなり省かせていただきます。

1. 初期設定

1-1. ディスクイメージのダウンロードとフォーマッティング

Raspbian OS GUI版が2GBとファイルサイズもそれほど大きくなく十分な機能があるのでおすすめです。
RaspbberyPi OSダウンロード

また慣れないうちはCLI版じゃなくGUI版を落としておいて、スクリーンとキーボード&マウスを用意しておくのが無難です。

ラズパイを初期化したいときが大抵くるのでディスクイメージを複数保存しておくと便利です。フォーマッターはBalena Etcherを使っていますが早くて快適です。

1-2. ラズパイの初期設定

まずデスクトップ右上のアイコンからwifiの設定(SSID、パスワード)をします。LANケーブルの方はケーブルをラズパイに繋ぎます。

ラズパイのターミナルを開いて


raspi-config

この画面になるので、「Interface Options」からSSH接続をONにします。
image.png

1-3. PCからSSH接続

注意点①ssh接続のときsudo sshとしない

sudo ssh pi@xxx.xxx.xxx.xxx

とやると一応

password?
|

といった感じでパスワードを聞いて来ますが、何を入れてもaccess deniedと表示されます。SSHの設定かな?とsshの設定ファイルに飛んでいじってみたり、沼にハマることがあるので注意です。

ラズパイのIPアドレスはラズパイのターミナル上で

hostname -I

で表示します。

1-4. Greengrass CoreのインストールとGGG(Greengrass Group), GGC(Greengrass Core)の作成

こちらにAWS公式と同じ手順をまとめています。ここで作成する
Greengrass Group名、Greengrass Core名等を入力します。

2. Lambdaの作成

2-1. Lambdaに上げるPythonファイルの作成とSDKのダウンロード

今回使用するコードはこちら。Chromiumでダウンロードしてきたマリオの画像をアップロードする想定です。このコードをコピペしてtest.pyという名前で保存してください。

import boto3

s3= boto3.resource('s3')

#S3にあげたいファイルが存在するローカルのパス(絶対参照のみ)
filePath='/home/pi/Downloads/mario.jpeg'
#ファイルをあげたいS3のバケットの名前
bucketName = 'BUCKET_NAME'
#S3バケットの入れたいフォルダとファイル名(Key)を指定
s3Key = 'Pictures/GameCharacter/mario.jpeg'

def function_handler(event, context):    

    # 画像ファイルの場合#をとる
    #data = open(filePath, mode='rb')
    #s3.Bucket(bucketName).put_object(Key = s3Key, Body = data)

    # テキストファイルの場合#をとる
    #data = open(filePath, mode='r')
    #s3.Bucket(bucketName).put_object(Key = s3Key, Body = data.read())

    return

Pythonファイルができたら次はSDKをダウンロードしていきます。
AWSのGithubからGreengrass Core SDK Pythonをダウンロードします。ダウンロードしたら先程のPythonファイルとこのSDKをFinderで選択して圧縮し、.zipファイルにします(こちらの記事を参照してください)。

2-2. ZIPファイルをLambdaに上げる

AWSコンソールからLambdaに飛びます。画像のようにお気に入りを登録しておくと便利です。
image.png

左側から「関数」を選んで右側のオレンジの「作成」のボタンを押します。
image.png
1から作成を選び適当に関数名を入力します。ランタイムには「Python3.7」を選び、「作成」を押します。
image.png
次にコードソースの「アップロード」から「zipファイル」を選び先程圧縮したPythonファイルとSDKのZIPファイルをアップロードします。
image.png

注意点② Lambda作成時に必ずGreengrass SDKとまとめてZIPファイルにしてアップロードする

これが意外と忘れがちなので注意です。これを忘れるとlogに
「ローカルのサーバーから認証情報が取れませんでした」
といった内容のlogが吐かれ、一見SDKの上げ忘れだと気づかないので注意が必要です。

※S3にあらかじめGreengrass SDKをZIPファイルであげておくとそこからLambdaにアップロードができるので便利です。

その後、画像のように情報を入力し、「ランタイムの設定」から「ハンドラー」を、
image.png

test.function_handler

とします。

注意点③ Lambdaハンドラーを「Pythonファイル名.関数名」と指定する

ハンドラーとはLambdaの中のどのPythonファイルを開くかを「.」の右側で指定して、Pythonファイルの中のどの関数を扱うかを「.」の右側で指定しています。一文字でも間違うとエラーになるので注意してください。

2-2.の続き

その後右上の「新しいバージョンを発行する」を押します。Description(メモのようなもの)を必要なら書いて「パブリッシュ」を押します。その後「エイリアスの作成」を押します。
image.png
エイリアスの名前は全て大文字にするのをお勧めします(AWS公式でも色々派閥があるみたいですが)。TESTとかDEVとかわかりやすい名前をつけます。ここではTESTとします。「バージョン」は一番新しい(今は作成したばかりなので1しかないはずですが)ものを選びますが、ここで注意が必要です。
image.png

注意点④ Lambdaエイリアスには「$LATEST」を指定しない

Greengrassは設計思想上、$LATESTを採用していません(2021年3月現在)。$LATESTはimmutabilityの設計思想にもとるとのことです(AWSの公式ドキュメントに書いてありました)。$LATESTを選ぶとGreengrass Groupのデプロイでエラーが出ますが、これまたlogをよくみないと原因がわからないので初めから気をつけましょう。

注意点⑤ Lambdaの新しいバージョンを発行したら必ずエイリアスのバージョンも変える

これも意外と忘れがちです。新しいバージョンパブリッシュ後、画面上部の作成した関数名をクリックし、
image.png
今度は画面下部にある「エイリアス」タブから自分の関数名の左にある○を選択し「編集」をクリック。
image.png
バージョンを最新にして「保存」を押します。これでエイリアスの紐づけもできました。これをしておくとGreengrass Groupのデプロイの際にLambdaのバージョンを変えてあげる必要がなくなります。
image.png
これでLambdaの作成は完了です。

3. Greengrass Groupの設定

AWSコンソールからAWS IoTに飛び、「グリーングラス」「クラシック(V1)」「グループ」に行き、先程作成したGreengrass Groupをクリックします。
image.png

注意点⑥ 「作成したLambdaの登録」、「リソースの追加」、「サブスクリプションの追加」、「ポリシーの追加」の4つを忘れない

Greengrassの設定は主にGroupの設定からおこないます。今回はLambdaの登録に加えてLambdaにローカルファイルへのアクセスを許可するためのリソースの追加、エッジデバイスとのMQTT通信に許可を与えるサブスクリプションの追加、Greengrass Group自体にIAM権限を与えてやるポリシーの追加を忘れずにやっていきます。
image.png

3-1. Lambdaの追加

Lambdaタブから「Lambdaの追加」→「既存のLambdaを追加」で先程作成したLambdaを選択します。
image.png
作成したエイリアスを選択して「確定」をクリックします。
image.png

3-2. リソースの追加

「リソース」から「ローカルリソースの追加」をクリック。
image.png
「リソース名」を入力し、「リソースタイプ」はボリュームを選択(カメラ等を追加する場合はデバイスを選択します)。
image.png
ソースパス(Lambdaにアクセスを許可するフォルダ)とデスティネーションパス(Lambdaコンテナ上仮想フォルダ)は今回は画像のように

#Lambdaにアクセスを許可したいフォルダ
/home/pi/Downloads

#Lambdaコンテナが使用するためのフォルダ(今回は使いませんが、必須です)
/Lambdadirectory

としました。グループオーナーのファイルアクセス許可は「自動的に追加」を選択(詳しい説明はこちら)。

最後に画像のようにLambdaをアタッチして最後に「アップデート」をクリックしてリソースの追加は完了です。

3-3. サブスクリプションの追加

今度はサブスクリプションの追加をしていきます。GreengrassのLambdaは通常のLambdaを少し振る舞いが異なります。常時実行LambdaオンデマンドLambdaの2種類があって(デフォルトではオンデマンドLambdaです)、オンデマンドLambdaはLambdaにMQTT通信でメッセージが届いたらinvokeされます。

「サブスクリプション」から「サブスクリプションの追加」をクリック。ソースには「IoT Cloud」を選びます。ターゲットには先程追加したLambdaを追加します。その後「次へ」をクリック。
image.png
トピックフィルターはなんでも良いですが、覚えやすいinvoke/testにしました。ワイルドカード(#)を使うこともできますが、そうすると大抵Lambdaが意図せず頻繁にキックされてしまうので注意が必要です。「次へ」から「完了」をクリック。
image.png
これでサブスクリプションの追加は完了です。

3-4. IAMロール&ポリシーの追加

最後にポリシーを追加していきます。「設定」から「グループロール」の「・・・」をクリックして「IAMロールを設定」をクリック。
image.png
「Greengrass_ServiceRole」を選択し「保存」をクリック(このロールはGreengrassのクイックスタートインストール時に作成されるロールです)。
image.png
「IAM」サービスから今指定したロールにAdministratorAccessポリシーを付与しておくと楽です(実験段階では権限をゆるく設定しておきます)。
image.png

注意点⑦ GreengrassのシステムlogとLambdaのlogを有効にする

この設定タブでlogファイルの設定ができます。デフォルトだとlogをはかない設定になっていますが、オススメはデバッグレベルのlogです。GreengrassとLambdaどちらもデバッグレベルのlogに設定しましょう。CloudWatch、ローカル(ラズパイ)どちらもにlogがはけます。自分はデバッグはラズパイでやって、記録用のlogはCloudWatchにはかせるため以下のように設定しています。
image.png

ちなみにローカルのlogは


#ルートユーザーに切り替える(/varへのアクセスはルート権限が必要なため)
sudo su

cat /greengrass/ggc/var/log/user/[リージョン]/[アカウントID]/[関数名].log

で見られます。

注意点⑧ リソースパスは実際にラズパイのLinuxOS上に存在しなくてはいけない

デスティネーションパスはLambdaが仮想的に使うフォルダなのでラズパイのOS上に存在している必要はありませんが、リソースパスは存在している必要があります。

4. ラズパイの追加設定

そしてここで最後の注意点があります。

注意点⑨ リソースパスで指定したパスに「chmod 777」でアクセス(readとwrite)ができるようにする

Linuxのデフォルト設定だとGreengrassがフォルダに対してアクセスができないのでLinux側でも特定フォルダに対してアクセスを許可してやる必要があります。

chmod 777 /home/pi/Downloads

でDownloadsフォルダに対してのreadとwriteを許可します。
これでラズパイの追加設定も完了したので、AWSコンソールに戻ってGreengrass Groupのデプロイをしていきます。
先ほどと同様にGreengrass Groupの「アクション」から「デプロイ」を選択します。ステータスがin progress、その後successfully completedに変わったらデプロイ完了です。
image.png

4-1. アップロードしたいファイルをラズパイの所定のフォルダに置く

3-2で指定したフォルダにアップロードしたいファイルを置きます。自分の場合はmario.jpegDownloadsフォルダに置きます。

5. 動作確認(IoT CoreからGreengrass CoreデバイスにMQTTメッセージを送ってLambdaを起動)

最後に動作確認です。IoT Coreの「テスト」タブからMQTTテストクライアントを開きます。そしてワイルドカード(#)にサブスクライブします(これでシャドウの更新等もみられるので便利です)。
image.png
シャドウに関するやりとりが流れた後、
image.png
デフォルトでGreengrass Groupに付属しているHello World Lambdaが機能しているはずなので、下のように5秒おきにメッセージが届いています(Greengrassのクイックスタートインストール時の「Hello World Lambdaをインストールしますか?」に「Yes」と答えている必要あり)。
image.png
次にGreengrass CoreデバイスのLambdaをキックするためにMQTTメッセージを送ります。トピックは3-3で指定したinvoke/testです。最初に「トピックにパブリッシュ」を選んでinvoke/testを入力し「パブリッシュ」を押します。
image.png

これまでのプロセスが全て成功しているとS3内にファイルがアップロードされているはずです。
無事指定したS3バケットのPictures/GameCharacter配下にアップロードできていました。
image.png

無事ファイルも開けました。
image.png

6. もしアップロードができていなかったら

・注意点の①〜⑨を見直す

・リソースパスの指定など、手打ちの箇所で誤字が許されない箇所が多いので、その打ち間違えがないか確認する

注意点⑦で設定したlogを確認する

を試してみてください。

さいごに

AIカメラ等のプロジェクトではほぼ使うであろう「Greengrass LambdaでローカルファイルをS3にアップロード」とその注意点をまとめました。軽い画像ファイルならIoT Coreに直接MQTTで送ってRuleで処理というのも簡単だし良さそうですが、大きめのファイルやRuleをかませないファイルは今回のやり方が良さそうです。Lambdaにもっと処理を足したり新しいLambdaを足していけばエッジコンピューティングも実装できます。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
hdmn54321
よろしくお願いします。
stylez
WEB・業務システム、インフラ構築・運用監視まで、幅広い開発実績と経験豊富なエンジニアによる自社開発体制で、スピーディかつ高クオリティのシステム開発を手掛けています。AWSをはじめ各種クラウドやベンダーパートナーとして総合的なITサービスや、独自移行ツールを使ったマイグレーション、サーバーレスなシステム構築、コンテナを利用したDevOpsコンサルティングなどを提供しています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?