Technology Topics by Brains

ブレインズテクノロジーの研究開発機関「未来工場」で働くエンジニアが、先端オープン技術、機械学習×データ分析(異常検知、予兆検知)に関する取組みをご紹介します。

GreengrassをDocker for Windows上で使用する準備とファイル読み出しテストの手順

こんにちは、ブレインズテクノロジーの岩城です。

2018年11月末に開催されたAWS re:Invent2018で、AWS Greengrass IoTをDockerコンテナ上で起動できるようになったことが発表されました。

aws.amazon.com

この機能を生かしたデータ活用手法について、先日公開した「Dockerコンテナ上で起動したGreengrassとWindowsとの連携で広がる新たなデータ活用の選択肢」という記事でご紹介しました。

本記事では少し技術的な内容に踏み込み、GreengrassをDocker for Windows上で使用するための準備の手順と、チュートリアルを拡張して実施したGreengrassからWindows上のファイル読み込みトライアルをご紹介します。

技術ではなく応用例に関心がある場合は、下記の記事をご参照ください。 blog.brains-tech.co.jp

環境について

使用する環境としては、前回の記事でも紹介した三菱電機製の産業用PC MELIPC1002-Wを使用します。MELIPCは生産設備などから集めたデータを集約・加工する機能と、集めてきたデータを活用するためのインターフェースを備えた産業用途のPCです。MELIPCについての詳細は前回の記事やこちらの製品ページなどご参照ください。 http://www.mitsubishielectric.co.jp/fa/products/edge/melipc/items/mi1000/index.html

今回の取り組みでは、MELIPC上のWindows10にDocker for Windowsをインストールし、このDocker環境でGreengrassを動作させます。

使用したWindowsのスペックについては下記の画像をご覧ください。

f:id:brains_iwaki:20190124184333p:plain

読み込みの対象とするcsvファイルはこちらで準備したダミーのファイル (sample_data1.csv, sample_data2.csv)を使用しています。

実施概要

今回実施した内容は、Docker for Windows上でGreengrassを実行し、ローカル環境にあるcsvファイルを読み込ませてクラウドに送信させるというものです。

基本的な流れはAWSが提供している下記のリンクのチュートリアル通りですが、先々の応用を考え、一部変更を加えています。

docs.aws.amazon.com

大きな変更点は、下記の3点です。

  1. Hello Worldの代わりに、ローカル環境にあるcsvファイルを読みとるLambda関数を用意する。
  2. ローカル環境にcsvファイルを準備しておく。
  3. Dockerコンテナを起動する際に、マウントするホストの情報をコマンドに追加しておく。

今回は出荷状態のMELIPCを使用したので、Dockerのインストールやコマンドのインストールなども一から実施しています。
ユーザーを作成する部分などはさすがに割愛しますが、Greengrassを動かす前の事前準備から一通り行った作業を記載していきます。

Dockerコンテナ上でGreengrassを使用するための下準備

まずは、Dockerコンテナ上でGreengrassを使用できるように環境を整えていきます。

事前準備の概要

今回の一連のトライアル実施のため、まずはチュートリアルの指示通り、下記のソフトウェアをインストールしました(括弧内はバージョン)。

  • Docker (18.09)
  • Python (3.7) (※3.6以上ならOK)
  • pip (18.1)
  • AWS CLI (1.16)

その他、さらに前提として、AWSのアカウントを所有している必要があるので、持っていない場合は事前に作成しておきましょう。

Dockerのインストール

まずはDockerをインストールします。

チュートリアルの中のDockerへのリンクを開き、Docker Community Edition (CE)をダウンロードします。

docs.docker.com

今回はWindowsなので、スクロールしてDocker Desktop for Windows (Microsoft Windows 10)のリンクに飛びます。

(参考)
https://docs.docker.com/docker-for-windows/install/

f:id:brains_iwaki:20190124183815p:plain
Docker for WIndowsのインストールページ

Install Docker Desktop for Windows desktop appの中からDocker Desktop Installer.exeをダウンロードし、実行した後は、ウィザードに従ってインストールを進めていきます。

途中でDocker ToolboxかDocker for Windowsを選択する箇所があります。今回の用途ではDocker for Windowsを選択します。
但し、Docker for Windowsを使用する場合はVirtualBoxが起動できなくなるので注意してください(後述)。

インストール後は一度再起動し、Docker for Windowsのdesktop appを開きます。
この際、有効化が必要等のメッセージが出た場合は、メッセージを読み、問題なさそうであればOKを押して進めていきます。

以上でDockerのインストールは完了…と思ったのですが改めて起動したところ、“Not enough memory to start Docker Desktop”というメッセージが出ました。
これはDocker DesktopのsettingsからMemoryの値を下げることで解決できました。

(参考)
https://qiita.com/chakimar/items/868298096ebf9186d690

最終的な設定はこちらの画像のようになります。

f:id:brains_iwaki:20190124183933p:plain
最終的なDockerのsettingsの内容

再起動などをした時などにDockerがどのような状態になっているかは、右下のステータスバーから確認できます。

f:id:brains_iwaki:20190124184041p:plain

ここの白い鯨のアイコンが上記の画像の状態で停止していれば起動している状態です。

なお、一つ前に記載した設定画面は、このアイコンを右クリックしてsettingsを選んだ画面から開きます。

完全に起動ができたら、最後に、コマンドプロンプトで

docker version

などのコマンドを実行すると正しくdockerがインストールできているかの確認ができます。

Docker Desktop for Windowsのインストールにおける注意点

インストールページに記載されているように、Docker Desktop for Windowsインストールの際は下記の点に注意が必要です。

(1)Docker ToolboxとDocker Machineユーザー向けの注意点

Docker Desktop for Windowsでは、Microsoft Hyper-Vを使用します。 そのため、Hyper-Vが使用可能になっている必要があるのですが、Hyper-Vが使用可能な状態の場合は、VirtualBoxが使用できなくなります。 Hyper-VとVirtualBoxを並行して利用することができないので、注意しましょう。
なお、Hyper-Vの設定変更はインストーラーの方で行なってくれます。

(2)システム要件

こちらもインストールページに記載がある通りです。本記事の執筆時点では、下記のような条件があります。

  • Windows 10 64bit: Pro, Enterprise or Education
  • BIOSのVirtualizationがenableになっていること ( Hyper-Vとは別の話。基本的にenableらしい)
  • CPUがSLAT-capableであること
  • 最低4GBのRAM

今回使用したMELPICに搭載されているWindowsOSは、

  • Windows 10 Enterprise
  • 実装RAM: 4GB
  • システムの種類: 64ビット オペレーティングシステム、x64ベースプロセッサ

となっていたので、この辺りの条件はクリアできていたようです。

参考までに、今回使用したMELIPC M1002-W上のWindows上のスペックを再掲します。 f:id:brains_iwaki:20190124184333p:plain

Pythonのインストール

次に、Pythonの公式サイトからWindows用のPython3.6以上のインストールを行います。

https://www.python.org/downloads/windows/

種類がいくつもありますが、今回はx86-64 executable installerを選択しました。
簡単に補足すると、x86-64は64ビット版 (x86は32ビット版)、 executable installerはインストールに必要な要素を全てまとめてexeファイル内で保持しているようなインストールファイルです。

(参考)
https://stackoverflow.com/questions/38651672/difference-between-web-based-and-executable-installers-for-python-3-on-windows
https://python-forum.io/Thread-Python-3-x86-vs-x64-Inquiry

pipのインストール

pipは上記インストールに標準で入っていました。

updateが必要なので、下記のコマンドプロンプトで下記のコマンドを実行しました。

python -m pip install —-upgrade pip

ここは少々記憶が怪しいのですが、確か普通にpip install —upgrade pipを行うと上手くいかなかったように思います。 エラーメッセージでこのコマンドを提示してくれたかもしれないので、一度試してみて、駄目そうなら使ってみてください。

(参考)
https://qiita.com/icoxfog417/items/278ea9e217ac6fb7f10b

AWS CLIのインストール

AWS CLIのインストールは下記のコマンドです。

pip install awscli --upgrade —user

(参考)
https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html

また、AWS CLIがコマンドプロンプトから実行できるようにパスの追記などを行う必要があります。 この辺りは下記のリンクを参照してください。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-windows.html#awscli-install-windows-path

Greengrass in Docker Containerの実行とファイル読み込みテスト

ここまででようやく下準備が終わりました。 次に、GreengrassをDocker for Windows上で起動し、テストを行います。
改めて、チュートリアルへのリンクを掲載しておきます。

docs.aws.amazon.com

作業としては、

  1. Greengrassを動作させるコンテナのイメージの取得
  2. Greengrassコアとグループの準備 (+Lambda関数の準備)
  3. AWS IoT Greengrassをローカルで起動 (コンテナを立ち上げる)
  4. Greengrassコア側の設定
  5. デプロイ
  6. AWS IoTを使用してのテスト

という流れになります。

1. コンテナイメージのプル

AWSでAWS IoT Greengrassの依存関係などの設定が完了済みのイメージが提供されているので、今回はそれを利用します。

チュートリアル通り、下記のコマンドを順に実行していきます。

(1)ログインコマンドの取得 まずは下記のコマンドを実行します。このコマンドを使うことで、出力としてDockerクライアントの認証に必要なログインコマンドを取得することができます。

aws ecr get-login --registry-ids 216483018798 --no-include-email --region us-west-2

configurationの設定ができていない場合はここでCredential Errorが発生することがあるので、その際は下記のリンクなどを参考に解決してください。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-envvars.html

(2) (1)で出力されたコマンドをそのままコピーして実行します。

(3)下記コマンドでコンテナイメージを取得します。

docker pull 216483018798.dkr.ecr.us-west-2.amazonaws.com/aws-greengrass-docker/amazonlinux:latest

あるいは、FAQの方でイメージを直接ダウンロードできるリンクが掲載されていたので、こちらをダウンロードして、docker loadコマンドでimageを取り込む形も取れるでしょうか。

https://aws.amazon.com/jp/greengrass/faqs/

興味のある方は上記リンク内で、 “Docker コンテナで AWS IoT Greengrass を実行できますか?”という文言で検索してみてください。

2. Greengrassのグループとコアを作成 + Lambda関数の準備

まずは通常のGreengrassのグループおよびコアを作成する作業を行います。

これについては、基本的なGreengrassのチュートリアル通りに進める流れになります。

AWS IoT の AWS IoT Greengrass の設定

この作業が初めての方は、一旦ここは後回しにして、通常のGreengrassのチュートリアルを行うところから始めるのが良いかと思います。

作業の途中でダウンロードする証明書情報と設定ファイルは後ほど使用するので保存しておきます。
また、チュートリアルにも記載がありますが、AWS IoT Greengrassコアソフトウェアは今回使用しているイメージに準備されているので、ダウンロードする必要はありません。

次に、Lambda関数の準備もここで実施しておきます。

今回使用したLambda関数のコードはこちらです。

import greengrasssdk
import platform
import os


client = greengrasssdk.client('iot-data')
my_platform = platform.platform()

TARGET_TOPIC = os.getenv("TARGET_TOPIC", "hello/world")
RETURN_MESSAGE = os.getenv("RETURN_MESSAGE", "Hello world! Sent from Greengrass Core.")
TARGET_DIR_PATH = os.getenv("TARGET_DIR_PATH", "/tmp")

def greengrass_hello_world_run():
    if not my_platform:
        client.publish(topic=TARGET_TOPIC, payload=RETURN_MESSAGE)
    else:
        client.publish(topic=TARGET_TOPIC, payload= RETURN_MESSAGE + ' Running on platform: {}'.format(my_platform))
    if os.path.isdir(TARGET_DIR_PATH):
        file_list = [os.path.join(TARGET_DIR_PATH, item) for item in os.listdir(TARGET_DIR_PATH) if (item.endswith(".csv")) and (item.startswith(".") == False)]
        file_list.sort()
        if len(file_list) > 0:
            for use_file in file_list:
                with open(use_file, "r") as f:
                    first_row = f.readline()
                first_row = str(first_row)
                main_filename = use_file.split("/")[-1]
                client.publish(topic=TARGET_TOPIC, payload="File name is {}".format(main_filename))                
                client.publish(topic=TARGET_TOPIC, payload="First row of this file: {}".format(first_row))
        else:
            client.publish(topic=TARGET_TOPIC, payload="There is no csv file")
    else:
        client.publish(topic=TARGET_TOPIC, payload="The TARGET_DIR_PATH dose not exist.")

def function_handler(event, context):
    greengrass_hello_world_run()
    return

この関数では、環境変数としてファイルの読み込み先のパスやトピックの発行先、ベースになるメッセージの内容を指定できるようにしています。

関数の中でgreengrasssdkなどを使っているので、ライブラリも忘れずにアップロードしてください。 チュートリアルで提供されているHelloWorld.pyを改修すると早いかもしれません。

handlerの設定などについては、下記の画像を参考にしてください。

f:id:brains_iwaki:20190124191402p:plain

これを通常のLambda関数のアップロードの手順に従い、AWS上にアップロードしておきます。
また、latestの状態ではGreengrassにデプロイできないので、バージョン発行と、必要であればエイリアス発行も実施しておきます。

Lambda関数の準備周りの手順はこちらをご参照ください。
Lambda 関数の作成とパッケージ化

3. AWS IoT Greengrassをローカルで実行

まずは先ほどダウンロードしてきた証明書情報などを所定のフォルダに準備しておきます。 最後のdocker runだけは少しコマンドを追加しますが、基本的にはチュートリアル通りに実施すれば問題ありません。

改めてリンクを再掲します。 Docker コンテナでの AWS IoT Greengrass の実行

なお、証明書と設定フォルダが入ったgzファイルを解凍する作業では、Windowsだけで行う場合はWinZipや7-Zipなど、解凍のためのツールが必要になります。 面倒な場合は別のところで解凍しておいたほうが楽かもしれません。

証明書と設定フォルダ、ルートCA証明書の準備ができたら、はじめにダウンロードしてきたイメージをdocker runで起動します。

ここでは、今回の目的であるcsvファイルの読み込みのため、ローカルのcsvファイルへのマウント情報を追加しています。 (-v c:/Users/%USERNAME%/Downloads/gg_data_root:/tmp/gg_data_root のところ)

お手本のコードにマウントに必要なコマンドが記載されているので、書き方はそこを参照すると良いかと思います。

docker run --rm --init -it --name aws-greengrass-docker --entrypoint /greengrass-entrypoint.sh -v c:/Users/%USERNAME%/Downloads/certs:/greengrass/certs -v c:/Users/%USERNAME%/Downloads/config:/greengrass/config -v c:/Users/%USERNAME%/Downloads/gg_data_root:/tmp/gg_data_root -p 8883:8883 216483018798.dkr.ecr.us-west-2.amazonaws.com/aws-greengrass-docker/amazonlinux:latest

無事Greengrassが起動できると、コマンドプロンプトは下記のような状態になります。

f:id:brains_iwaki:20190124185247p:plain

この状態であれば、Greengrassが正しく起動しています。

4. Greengrassグループの設定

次はいよいよクラウド上でGreengrassの設定を行い、エッジ側に情報を配信 (デプロイ)します。

ここでは、コンソール上のAWS IoT Greengrassのページから、2番目の項目で作成したGreengrassのグループに、各種設定をつけていきます。

今回設定を行うのはLambda関数とサブスクリプションの設定の2つだけです。 ローカルリソースアクセスやコネクタ、ML推論などの機能は、コンテナなしの設定では使用できません。

更なる応用を見越した場合、ロールの割り当てやCloudWatchにログをあげる設定などを適宜行うことになりますが、 このトライアルではそれらの設定は不要です。

Lambda関数

まずは関数の設定を3箇所実施します。

下記の画像のように、

  • コンテナ化: コンテナなし
  • タイムアウト: 30秒
  • Lambdaのライフサイクル: 存続時間が長く無制限に稼働する関数にする

という設定にします。

f:id:brains_iwaki:20190124185702p:plain

次に、Lamba関数で使用する環境変数も設定しておきます。

f:id:brains_iwaki:20190124185347p:plain

ここで使用するトピックはサブスクリプションとテストで使用します。

また、データへのパスは、先ほどdocker runさせた時にマウントさせたパスにします。
今回は、/tmp/gg_data_root_data_dir/sample_dataの直下にcsvが入るようにマウントさせていることに注意してください。

サブスクリプション

HelloWorld関数のチュートリアルを元に、相互にやり取りできるように設定します。 今回は下記のような設定にしました。

f:id:brains_iwaki:20190124185802p:plain

解説

もともとのGreengrassではLambda関数の起動のたびにコンテナを立てていたのですが、この設定により、Lambda関数をOSプロセスとして実施できるようになり、 Docker上で動作できるようになった、という話のようです。

一方、「コンテナなし」の設定にすることで、ローカルリソースアクセスやコネクタ、Greengrass ML Inferenceなどの機能が使えなくなるといデメリットがあります。 ローカルリソースアクセスについては、この記事で紹介しているように直接アクセスの設定をすることで回避できますが、 他の機能を使っている場合は何か対策を行う必要が出てきます。

ちなみに、Greengrass ML InferenceはAmazon SageMakerやS3にあるモデルソースを使ってMLワークフローをシンプルに行うためのサービスで、 Lambda上で動かすなどの一般の機械学習とは特に関係ありません。そちらはコンテナなしでも普通に使うことができます。(ライブラリの準備等は必要です)

5. デプロイ実施

無事グループの設定が完了したら、Greengrassをデプロイします。 Greengrassが正しく起動した状態で、設定が適切になされていれば、グループの情報がエッジ側に配信されます。

f:id:brains_iwaki:20190124185927p:plain

配信後、左上の表示が正常に完了したことを示したら、テストを実施します。

6. テスト

最後にテストを行います。ここではGreengrass自体のチュートリアルのHelloWorld関数のテストと同様の設定を行います。 AWS IoTのコンソールのテストのページで下記のようにトピックのサブスクライブを行い、起動側のトピックを発行します。

f:id:brains_iwaki:20190124190050p:plain

すると、次の画像のように、デプロイしたLambda関数が動作し、csvファイルのファイル名と、1行目を読み込んだ結果をAWS IoT側に送信してきます。

f:id:brains_iwaki:20190124190104p:plain

今回はダミーのデータを入れたsample1.csv, sample2.csvという二つのファイルを準備していたので、 それらのファイル名と1行目の内容を送信してきてくれています。

これで、ファイルの読み込みが正しくできたことが確認できました。

今後の応用

以上、Dockerコンテナ上で起動したGreengrassを用いてのWindows上のファイル読み込みの簡単なトライアルを行いました。

ファイルの読み込みができたので、今後は本格的なデータ活用に進めていくことになるかと思います。

今回はAWSが提供したイメージをそのまま使用しましたが、既存ライブラリの活用とLambda関数の容量制限等を踏まえると、 ソフトウェアとして継続的に使用していくためにイメージの拡張が必要になってきそうです。

まとめ

以上で今回の記事は終了です。

長くなってしまいましたが、これでようやく本格的なGreengrassの活用に向けてのスタートラインに辿り着きました。 このステップは前提として、次にどのようにデータを活用していくか、あるいはアプリケーションをどのように構成していくかといった 本格的な取り組みに進んでいくことになると思います。

この技術を生かしてより一層データ活用が進んで行くことを期待しています。


ブレインズテクノロジーでは「共に成長できる仲間」を募集中です。
採用ページはこちら

参考資料