TensorFlow with GPU on Docker を AWS で起動する

構成

https://github.com/NVIDIA/nvidia-docker にある以下の図が分かりやすい。

図

今回、Server は AWS の p2 インスタンス (GPU インスタンス)。
Host OS は Ubuntu 16.04 を利用する。

手動でインストールが必要なものは以下の通り。

  • CUDA Toolkit / CUDA Driver

    • NVIDIA GPU をコントロールするために必要
    • 2つ同時にインストールされる
  • Docker Engine
  • nvidia-docker
    • Docker コンテナ内から CUDA Toolkit 経由で GPU を触るために必要

1. AWS インスタンス起動

GPU インスタンスの p2 系を起動する。

AMI
Ubuntu Server 16.04 LTS (HVM), SSD Volume Type
備考
ディスクサイズは 100 GB に変更する (デフォルトは 8 GB、足りない)

2. CUDA のインストール

公式ドキュメント 通りに進める。
ただ、ドキュメントが長いので読まない方が良い。ハマると果てしなくハマって辛い。

実際に必要なのは3箇所のみ。

  • “2. Pre-installation Actions” > “2.6. Download the NVIDIA CUDA Toolkit”
  • “3. Package Manager Installation” > “3.6. Ubuntu”
  • “6. Post-installation Actions” > “6.1.1. Environment Setup”

実際のコマンドは以下の通り。

## 2.6 Pre-installation Actions (Download the NVIDIA CUDA Toolkit)
$ wget https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64-deb

## 3.6 Package Manager Installation (Ubuntu)
$ sudo dpkg -i cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64-deb
$ sudo apt-get update
$ sudo apt-get install cuda

## 6.1.1 Post-installation Actions (Environment Setup)
$ echo 'export PATH=/usr/local/cuda-8.0/bin${PATH:+:${PATH}}' >> ~/.bashrc
$ source ~/.bashrc

nvcc が入れば成功。

$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2016 NVIDIA Corporation
Built on Tue_Jan_10_13:22:03_CST_2017
Cuda compilation tools, release 8.0, V8.0.61

3. Docker のインストール

公式ドキュメント (Install using the repository) 通りに、Docker CE をインストールする。

インストール完了したら、sudo 無しで動作するよう ubuntu ユーザを docker グループに追加して、SSH ログインし直す。

$ sudo usermod -aG docker ubuntu

hello-world が動けば完了。

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
78445dd45222: Pull complete
Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

4. nvidia-docker のインストール

公式ドキュメント 通りに進める。

“Quick start” > “ubuntu distributions” のコマンドを実行すればOK。

$ wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.1/nvidia-docker_1.0.1-1_amd64.deb
$ sudo dpkg -i /tmp/nvidia-docker*.deb && rm /tmp/nvidia-docker*.deb

以下のコマンドで Docker コンテナがホスト (p2 インスタンス) の GPU を認識していることが確認できる。

$ nvidia-docker run --rm nvidia/cuda nvidia-smi
Sun Apr 23 06:10:55 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.39                 Driver Version: 375.39                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 0000:00:1E.0     Off |                    0 |
| N/A   47C    P8    28W / 149W |      0MiB / 11439MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

TensorFlow

あとは TensorFlow でもなんでもコンテナ内から GPU が触れる。

https://hub.docker.com/r/tensorflow/tensorflow/

$ nvidia-docker run -it -p 8888:8888 tensorflow/tensorflow:latest-gpu

続きを読む

Docker for Mac で Amazon Linuxのコンテナイメージを動かす

はじめに

macbook air をクリーンインストールしたついでに、開発環境をイチから構築していました。
Docker の コンテナイメージ何にしようかと探していたら Amazon Linuxがコンテナ化されていたんですね。
(今更しりました…。)
ということで、折角知ったので macで Amazon Linuxのコンテナを動かしてみます。

前準備

docker for mac のインストール

$ brew cask install docker
$ docker -v

Docker version 17.03.1-ce, build c6d412e

aws cli の インストール と 設定

$ brew install awscli
$ aws --version

aws-cli/1.11.76 Python/2.7.10 Darwin/16.5.0 botocore/1.5.39
$ aws configure

AWS Access Key ID [None]: `IAMのアクセスキー`
AWS Secret Access Key [None]: `上記IAMのシークレットキー`
Default region name [None]: ap-northeast-1
Default output format [None]: json

ここから本番

AmazonLinuxコンテナが配布されているECRへのログインコマンドを取得します。

$ aws ecr get-login --region ap-northeast-1 --registry-ids 137112412989
docker login -u AWS -p 'パスワード' -e none https://137112412989.dkr.ecr.ap-northeast-1.amazonaws.com

上記のコマンドが表示されるので、コピペして実行します。

Flag --email has been deprecated, will be removed in 1.14.
Login Succeeded

ログイン成功したようなので、イメージの種類を aws ecr list-imagesで確認してみます。

$ aws ecr list-images --region ap-northeast-1 --registry-id 137112412989 --repository-name amazonlinux | grep 'imageTag'

"imageTag": "2016.09.0.20161028-with-sources",
"imageTag": "2016.09.1.20161221",
"imageTag": "with-sources",
"imageTag": "2016.09.0.20161118",
"imageTag": "2016.09-with-sources",
"imageTag": "latest-with-sources",
"imageTag": "latest",
"imageTag": "2016.09.1.20161221-with-sources",
"imageTag": "2016.09",
"imageTag": "2016.09.0.20161118-with-sources",
"imageTag": "2016.09.0.20161028"

ここでは もちろん latestをローカルにpull してみます。

$ docker pull 137112412989.dkr.ecr.ap-northeast-1.amazonaws.com/amazonlinux:latest
$ docker images

REPOSITORY                                                      TAG                 IMAGE ID            CREATED             SIZE
137112412989.dkr.ecr.ap-northeast-1.amazonaws.com/amazonlinux   latest              ff59a593059d        3 months ago        292 MB

試しに実行してみます。 docker run

$ docker run -it 137112412989.dkr.ecr.ap-northeast-1.amazonaws.com/amazonlinux:latest /bin/bash

bash-4.2# cat /etc/system-release
Amazon Linux AMI release 2016.09

おお。できてますね!
必要最低限のパッケージしか入っていないみたいなので、次回はこれを使って環境構築をしていきます。

image

classmethodさんの記事に cawsayが載っていたので、真似してみました。:-)

SEE ALSO

続きを読む

AmazonLinuxにClamAVをインストールしちゃったよ

Amazon LinuxにClamAVをインストール方法について記載しますー

環境

  • InstanceType:t2.medium
  • OS:Amazon Linux AMI release 2015.03

ClamAVインストール

$ sudo yum -y install clamav
$ sudo yum -y install clamav-update

パターンファイル更新

設定ファイルの編集しますー

$ sudo vim /etc/freshclam.conf
### Exampleをコメント化
# Comment or remove the line below.
Example
↓
# Comment or remove the line below.
# Example

### コメント外す
#UpdateLogFile /var/log/freshclam.log
↓
UpdateLogFile /var/log/freshclam.log

### コメントアウトを外す
#LogTime yes
↓
LogTime yes

パターンファイル自動更新

5分単位で自動更新されるように設定します。

$ sudo vim /etc/cron.d/clamav-update
### 時間間隔を変更
0  */3 * * * root /usr/share/clamav/freshclam-sleep
↓
0  */5 * * * root /usr/share/clamav/freshclam-sleep

自動更新の有効化

自動更新の有効化を実施します。

$ sudo vim /etc/sysconfig/freshclam
### コメント化
FRESHCLAM_DELAY=disabled-warn  # REMOVE ME#FRESHCLAM_DELAY=disabled-warn  # REMOVE ME

バージョン確認

$ sigtool --version
ClamAV 0.98.7/20394/Thu Apr 30 01:37:08 2015

パターンファイルのダウンロード先変更

パターンファイルのダウンロード先を日本とアメリカに設定します。
 ※ダウンロードが集中すると失敗する可能性があるため

### デフォルトをコメントアウト
#DatabaseMirror database.clamav.net

### 追加
DatabaseMirror db.jp.clamav.net
DatabaseMirror db.us.clamav.net

パターンファイルの更新

手動でパターンファイルの更新をします。

$ sudo freshclam

スキャンテスト

アンチウィルスのテストファイルとして利用されるeicarを作成します。
テキストファイルにテストコードを埋め込みます。

$ vim ~/eicar.com
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

準備できたので、スキャンしますー

$ sudo clamscan -r -i ~

----------- SCAN SUMMARY -----------
Known viruses: 6260545
Engine version: 0.98.7
Scanned directories: 1
Scanned files: 7
Infected files: 1
Data scanned: 0.02 MB
Data read: 0.01 MB (ratio 2.00:1)
Time: 11.612 sec (0 m 11 s)

スキャン結果に「Infected files: 1」と検出されましたね。
ということで、以上でClamAVのインストール方法でしたーヽ(*゚д゚)ノ

補足

ClamAVのバージョンが低いと以下のように怒られます。
最新版にアップデートするか、もしくは、2017.3のAmazon Linux AMIを使用することで、ClamAVのパッケージが最新化できます。
Amazon Linux AMI 2017.3 Packages

$ sudo freshclam
ClamAV update process started at Sun Apr 16 11:05:13 2017
WARNING: Your ClamAV installation is OUTDATED!
WARNING: Local version: 0.98.7 Recommended version: 0.99.2

続きを読む

Amazon Linuxに最新版のRabbitMQをインストール

はじめに

2017/04/11時点のAmazon Linuxだと標準のRPM repositoryからインストールされるerlangのバージョンが古く(R14)、EPELからインストールできるRabbitMQのバージョンも古い(3.1.3)ので最新版のRabbitMQを入れてみたので備忘録として残しておきます。

なお、公式ではEC2ではOSはUbuntu使うのがオススメです、と書いてあるのでAmazon Linuxに固執する理由がないならUbuntu使った方が簡単に導入できると思います。(参考)

方針

RabbitMQ – Installing on RPM-based Linux (RHEL, CentOS, Fedora, openSUSE)にさまざまなアプローチが書いてありますので好きな方法を選択すると良いと思います。

今回はRabbitMQのメンテナが用意してくれているerlangのRPMビルドスクリプトを利用してerlangのRPMパッケージを作成、そしてRabbitMQが配布しているビルド済みのRabbitMQのRPMパッケージを使うことにしました。

Erlang

rabbitmq/erlang-rpm: Zero dependency Erlang RPM, just enough for running RabbitMQを手元に持ってきてmakeするだけでRPMパッケージが作成されます。
dockerのイメージをビルドするスクリプトも用意されているので環境に合わせてご利用ください。

上記以外の方法としてはErlang Solutionsのパッケージを使う方法も推奨されていますがこちらは試していません。

RabbitMQ

RabbitMQ – Installing on RPM-based Linux (RHEL, CentOS, Fedora, openSUSE)で配布されているRPMパッケージを利用している環境に合わせてダウンロードして署名キーと合わせてインストールするだけです。

rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc
yum install rabbitmq-server-3.6.9-1.noarch.rpm

RabbitMQのweb management GUI

RabbitMQはWebから利用できる管理用のGUIがあるのですが、3.3.0以降からlocalhost以外からのアクセスはデフォルトで拒否するようになっています。
そのため、rabbitmqctlコマンドを使ってadd_user, set_user_tags, set_permissionsする必要があります。

下記がサンプルになります。user、 passwordは環境に合わせて変更した方がよいと思います。

rabbitmqctl add_user test test
rabbitmqctl set_user_tags test administrator
rabbitmqctl set_permissions -p / test ".*" ".*" ".*"

参考

続きを読む

AWS Transit VPCソリューションを使って 手軽に マルチリージョン間 VPN環境を構築してみる

Transit VPC とは

AWS の VPC 間 VPN 接続を自動化するソリューションです。
高度なネットワークの知識がなくても、超カンタンに、世界中の リージョンにまたがる VPC を接続するネットワークを構築することができます。

概要


ある VPC を転送専用の VPN HUB(Transit VPC)として作成することで、他のVPCからのVPN接続を終端し、スター型のトポロジを自動作成します。
利用している AWSのアカウントに紐づいた VPC で VGW を作成すれば、HUBルーターに自動的に設定が投入され、VPNの接続が完了します。

予めテンプレートが用意されているので、ルーターの細かい設定を行う必要がありません。

また、高度な設定が必要な場合も、Cisco CSR1000V を利用しているので、Cisco IOS の機能は自由に利用することも可能です。

Adobe社では、大規模なネットワークを、AWS上の CSR1000V で構築しています。
https://blogs.cisco.com/enterprise/adobe-uses-cisco-and-aws-to-help-deliver-rich-digital-experiences

仕組み

  • AWS CloudFormation を使って、Transit VPC の CSR1000v のプロビジョニングが非常に簡単に行えるようになっています。

  1. VGW Poller という Lambda ファンクションが用意されており、Amazon CloudWatch を使って、Transit VPC に接続すべき VGW が存在するかを常に確認しています。
  2. VGWが存在する場合、VGW Poller が必要な設定を行い、設定情報を Amazon S3 bucket に格納します
  3. Cisco Configurator という名前の Lambda ファンクションが用意されており、格納した設定情報から、CSR1000v 用の設定を作成します
  4. Cisco Configurator が Transit VPC の CSR1000v へ SSH でログインし設定を流し込みます。
  5. VPN接続が完了します。

詳細については、下記、ご参照ください。
– AWS ソリューション – Transit VPC
https://aws.amazon.com/jp/blogs/news/aws-solution-transit-vpc/
– Transit Network VPC (Cisco CSR)
https://docs.aws.amazon.com/solutions/latest/cisco-based-transit-vpc/welcome.html

Transit VPC 構築方法

基本は、Wizard に従い、3(+1)ステップで設定が可能です。

事前準備 – CSR1000V用 Key Pair の作成

CSR1000V へログインする際に使う、Key Pair を EC2 で一つ作っておきましょう。
EC2 > Network & Security > Key Pairs から作成できます。名前はなんでもいいです。

.pem ファイルが手に入るので、後ほど、CSR1000V へログインする際にはこれを使います。

Step 1. Cisco CSR1000v ソフトウェア利用条件に同意

AWS マーケットプレイスの下記のページから、リージョンごとの値段が確認できます。

https://aws.amazon.com/marketplace/pp/B01IAFXXVO

  • For Region で 好きなリージョンを選択
  • Delivery Method で Transit Network VPC with the CSR 1000v を選択

その後 Continue

  • Manual Launch タブが選択されていること
  • Region / Deployment Options が先に設定したものとなっていること

上記を確認し、Accept Software Terms をクリックします。

Step 2. Transit VPC スタックの起動

下記のページより、Transit VPC 用の CloudFormation を起動することで、Transit VPC に必要な CSR1000v をセットアップすることができます。

http://docs.aws.amazon.com/ja_jp/solutions/latest/cisco-based-transit-vpc/step2.html

上記ページから Launch Solution をクリックします。
CloudFormation のページが立ち上がるので、まず、VPN HUB を 設置するリージョンになっているか確認します。
このソリューションは、Lambda を使うので、Transit VPC を設置できるのは、Lambda が使えるリージョンに限ります。東京は対応してます。
Lambda 対応リージョンは、こちらで確認できます。
https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/

正しいリージョンになっていたら、設定を進めます。

2-1. Select Template

テンプレートがすでに選択された状態になっていると思うので、特に設定の必要なし

Next をクリック

2-2. Specify Details

幾つかのパラメーターがありますが、最低限下記を変更すれば、動作します。

  • Specify Details

    • Stack name を設定します。
  • Parameters
    - Cisco CSR Configuration

    • SSH Key to access CSR で、事前準備で作成した key を選択します。
    • License Modelで、BYOL (Bring Your Own License) もしくは License Included を選択します。

CSR1000v のライセンスについて、Cisco から購入したものを使う場合は、BYOL を選択します。
ライセンス費用も利用料に含まれた利用形式が良ければ、License included version を選択します。
検証ライセンスがあるので、テストの場合は、BYOL で良いかと思います

入力が完了したら、 Next

2-3. Options

特に設定の必要なし Next をクリック

2-4. Review

  • 設定を確認して、一番下の acknowledge のチェックボックスをクリック

その後、Create で CSR1000V のインスタンス作成・セットアップが始まります

5分ほどすると、CSR1000V が 2インスタンス 立ち上がります。

事後設定(オプション)

起動した CSR1000V は デフォルトで、Lambda ファンクションからのログインのみを許可する設定になっているので、ssh で CLI にアクセスしたい場合は、Security Group の設定を変更します。

EC2 のダッシュボードから CSR1000V を選択し、Security Group の設定で SSH を許可します。
すべてのPCからSSHを受ける場合は、ソースアドレスとして 0.0.0.0/0 を指定します。

設定後、ssh でログインするには、事前準備で作成した キーペアで取得した .pem ファイルのパーミッションを変更します。

chmod 400 <キーペア名>.pem

これを使って、下記のコマンドで CSR1000V にログインできます

ssh -i <キーペア名>.pem <CSR1000V のパブリックIP>

ログインすれば、CSR1000v であることがわかると思います。

ip-XXX-XXX-XXX-XXX #sh ver
Cisco IOS XE Software, Version 16.03.01a
Cisco IOS Software [Denali], CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.3.1a, RELEASE SOFTWARE (fc4)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2016 by Cisco Systems, Inc.
Compiled Fri 30-Sep-16 02:53 by mcpre

<省略>

Step 3. スポーク VPC のタグ付け

上記、CSR1000V が立ち上がれば、あとは、Spoke VPC の VGW でタグを付けるだけで、CSR1000V への VPN 接続が完了します。

3-1. Spoke VPC の作成

新たに Spoke VPC を作成する場合は、下記の手順で作ります。

  • 好きなリージョンに、VPC を作成します。

    • VPC Dashboard > Virtual Private Cloud > Your VPC > Create VPC で作成します。
  • Virtual Private Gateway(VPG) を作成します。
    • VPC Dashboard > VPN Connection > Virtual Private Gateways > Create Virtual Private Gateway で作成します。
  • 作成した VPG を、先程作成した VPCにアタッチします。
    • VPC Dashboard > VPN Connection > Virtual Private Gateways > Attach to VPC  から、VPCへVGWをアタッチします。

3-2. VGW のタグ付け

  • 先程作成した VGW を選択し、下部の Tags タブを選択します。

    • Edit をクリックし Tag を追加します。

デフォルトの設定では、下記のタグを利用する設定になっていますので、下記タグを追加します
Key = transitvpc:spoke
Value = true

上記の設定が完了すると、VGWと Step2. で作成した、2台の CSR1000Vの間で自動的に VPN 接続が確立します。

http://docs.aws.amazon.com/ja_jp/solutions/latest/cisco-based-transit-vpc/step3.html

Step 4. 他の AWS アカウントからの接続設定 (オプション)

http://docs.aws.amazon.com/ja_jp/solutions/latest/cisco-based-transit-vpc/step4.html

まとめ

AWS の Transit VPC を使えば、世界中 にまたがる AWS の 各リージョンのVPCを簡単に VPN 接続できます。

また、VPN HUB ルーターは Cisco CSR1000v なので、企業内のシスコルーターと VPN 接続すれば、DC を AWS にして、世界中にまたがる VPN ネットワークを構築することができます。
ダイレクトコネクトとも連携可能です。

参考

On board AWS TransitVPC with Cisco CSR1000v (英語ですが、手順がわかりやすいです)

Cisco CSR 1000v: Securely Extend your Apps to the Cloud
https://www.slideshare.net/AmazonWebServices/cisco-csr-1000v-securely-extend-your-apps-to-the-cloud

続きを読む

Raspberry Pi 3 と DSUN-PIR を使って人感センサーを作る + 人感センサー検知状況を表示する簡易Webアプリケーションを作る

はじめに

最近、Raspberry Piを使い出したのですが、色々な用途に使えるので面白いですね!

今回はRaspberry Piとセンサーの勉強を兼ねて、Raspberry Pi 3 と DSUN-PIR(赤外線センサー)を使って人感センサーを作り、人感センサーの検知状況を表示する簡易Webアプリケーションを作ってみました。

今回使用した機材 及び 実行環境

今回は以下の機材を使用しました。
Raspberry Pi3 Model Bを使用しました。

Raspberry Pi スターターパック (Pi3用Standard)

Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Element14版, Blue)

Raspberry Piには以下の赤外線感知センサーを取り付けました。

PIRセンサーモジュール [DSUN-PIR]

人感センサーの検知状況を表示する簡易WebアプリケーションはAmazon EC2(Amazon Linux)のRuby + Sinatraで作りました。RubyやSinatraサーバのセットアップ手順は以下をご参照下さい。

Amazon LinuxにRuby Sinatra環境構築(rbenv + ruby-build + Ruby 2.3.1 + Sinatra 1.4.7インストール)

参考資料

以下の記事を参考にさせて頂きました。
とても参考になりました。ありがとうございました。

Raspberry PiのGPIO制御方法を確認する(GPIO制御編その1)

人感センサ A500BP (DSUN-PIR, SB00412A-1も) が安いだけでなく Raspberry Pi との相性もバッチリだったので、人感カメラが10分で出来てしまった話。

RaspberryPiで人感センサーを作る

Raspberry Pi 3 (Raspbian Jessie)の無線LANに固定IPアドレスを設定する

Raspberry Pi の初期設定

Raspberry Pi側のセットアップ手順

(1) Raspberry Piをセットアップします。

参考資料の記事を見ながら、Raspberry Piをセットアップします。

人感センサ A500BP (DSUN-PIR, SB00412A-1も) が安いだけでなく Raspberry Pi との相性もバッチリだったので、人感カメラが10分で出来てしまった話。

RaspberryPiで人感センサーを作る

Raspberry Pi 3 (Raspbian Jessie)の無線LANに固定IPアドレスを設定する

以下は任意ですが、Raspberry Piに無線LANでIPアドレスを自動付与するようにしておくと、Raspberry PiにLANケーブルを接続しなくても良くなるので便利です。

root@raspberrypi:~# wpa_passphrase 無線LANのSSID SSIDのパスフレーズ >> /etc/wpa_supplicant/wpa_supplicant.conf
root@raspberrypi:~# cat /etc/wpa_supplicant/wpa_supplicant.conf
country=GB
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="SSID"
    psk=パスフレーズが暗号化されて設定される
}
root@raspberrypi:~# 

(2) Raspberry PiのGPIO18に人感センサー(DSUN-PIR)を取り付けます。

Raspberry Piに人感センサー(DSUN-PIR)を取り付けます。

スクリーンショット 2017-04-02 23.17.25.png

スクリーンショット 2017-04-02 23.17.33.png

スクリーンショット 2017-04-03 1.25.56.png

スクリーンショット 2017-04-03 1.25.48.png

(3) Raspberry Piへsshログインします。

本記事では、例としてRaspberry Piに設定したIPアドレスを 198.51.100.10 と表記させて頂きます。

Raspberry Piへsshでログインします。piユーザでログインします。

MacBookProPC001:~ user$ ssh pi@198.51.100.10
pi@198.51.100.10's password: -> piユーザの初期パスワード raspberry を入力します。

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Mar 28 18:05:14 2017
pi@raspberrypi:~ $ 

(4) Raspberry PiのGPIO18を有効化します。

rootユーザにスイッチします。

pi@raspberrypi:~ $ sudo su - 
root@raspberrypi:~# 

Raspberry PiのGPIO18を有効化するスクリプトを作成します。

root@raspberrypi:~# mkdir /root/scripts
/root/scripts/start_gpio.sh
root@raspberrypi:~# vi /root/scripts/start_gpio.sh 
#!/bin/sh

GPIO="18"

echo $GPIO > /sys/class/gpio/export

ls -lrta /sys/class/gpio/
root@raspberrypi:~# chmod 755 /root/scripts/start_gpio.sh 
root@raspberrypi:~# 

スクリプトを実行し、Raspberry PiのGPIO18を有効化します。

root@raspberrypi:~# /root/scripts/start_gpio.sh 
total 0
drwxr-xr-x 50 root root    0 Jan  1  1970 ..
-rwxrwx---  1 root gpio 4096 Mar 28 18:05 unexport
lrwxrwxrwx  1 root gpio    0 Mar 28 18:05 gpiochip100 -> ../../devices/platform/soc/soc:virtgpio/gpio/gpiochip100
lrwxrwxrwx  1 root gpio    0 Mar 28 18:05 gpiochip0 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpiochip0
-rwxrwx---  1 root gpio 4096 Apr  2 13:56 export
drwxrwx---  2 root gpio    0 Apr  2 13:56 .
lrwxrwxrwx  1 root root    0 Apr  2 13:56 gpio18 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpio18
root@raspberrypi:~# 

(5) Raspberry PiのGPIO18に取り付けた人感センサー(DSUN-PIR)のテストを行います。

Raspberry PiのGPIO18に人感センサーを取り付けた場合、人感センサーに人が近くづくと /sys/class/gpio/gpio18/value の値が 0 から 1 へ変わります。

人感センサー周辺に人がいない場合、以下ファイルの値は 0 になります。

root@raspberrypi:~# cat /sys/class/gpio/gpio18/value 
0
root@raspberrypi:~# 

人感センサーに近づいてみます。

スクリーンショット 2017-04-02 23.14.50.png

すると、以下ファイルの値が 0 から 1 に変わります。

root@raspberrypi:~# cat /sys/class/gpio/gpio18/value 
1
root@raspberrypi:~# 

人感センサーから離れたら、以下ファイルの値が 1 から 0 に戻る事を確認します。

root@raspberrypi:~# cat /sys/class/gpio/gpio18/value 
0
root@raspberrypi:~# 

人感センサー検知状況表示用Webアプリケーションサーバのセットアップ手順

(6) 人感センサー検知情報用の簡易Webアプリケーションを作ります。

人感センサー検知情報表示用の簡易Webアプリケーションサーバ(Webサーバ)を作成します。

人感センサーは人が近づくと、Raspberry Piの/sys/class/gpio/gpio18/valueの値が変化しますので、この値をAPIサーバへ送信するようにします。

今回の記事では、WebサーバはRubyとSinatraで作ります。
RubyやSinatraのセットアップ手順は以下を参考にしてみて下さい。

Amazon LinuxにRuby Sinatra環境構築(rbenv + ruby-build + Ruby 2.3.1 + Sinatra 1.4.7インストール)

本記事では、例としてWebサーバを 198.51.100.20 と表記させて頂きます。
Webサーバへsshログインします。

MacBookProPC001:~ user$ ssh -i EC2インスタンスログイン用のSSH秘密鍵 ec2-user@198.51.100.20
Last login: Sun Apr  2 23:29:03 2017 from i121-115-95-232.s42.a013.ap.plala.or.jp

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.09-release-notes/
[ec2-user@example-ruby-sinatra-server ~]$ 

sinatraユーザを追加します。

[ec2-user@example-ruby-sinatra-server ~]$ sudo su - 
最終ログイン: 2017/04/02 (日) 23:30:13 JST日時 pts/0
[root@example-ruby-sinatra-server ~]# groupadd sinatra
[root@example-ruby-sinatra-server ~]# useradd sinatra -g sinatra -d /home/sinatra -s /bin/bash
[root@example-ruby-sinatra-server ~]# 
[root@example-ruby-sinatra-server ~]# su - sinatra
[sinatra@example-ruby-sinatra-server ~]$ 
[sinatra@example-ruby-sinatra-server ~]$ id
uid=501(sinatra) gid=501(sinatra) groups=501(sinatra)
[sinatra@example-ruby-sinatra-server ~]$ 
[sinatra@example-ruby-sinatra-server ~]$ /sbin/ifconfig eth0 | grep inet
          inet addr:198.51.100.20  Bcast:198.51.100.255  Mask:255.255.255.0
          inet6 addr: XXXX::XXX:XXXX:XXXX:XXXX/64 Scope:Link
[sinatra@example-ruby-sinatra-server ~]$ 

sinatraユーザに権限を付与します。

[root@example-ruby-sinatra-server ~]# echo "sinatra ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/sinatra
[root@example-ruby-sinatra-server ~]# chown root:root /etc/sudoers.d/sinatra 
[root@example-ruby-sinatra-server ~]# chmod 644 /etc/sudoers.d/sinatra 
[root@example-ruby-sinatra-server ~]# 
[sinatra@example-ruby-sinatra-server ~]$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
[sinatra@example-ruby-sinatra-server ~]$ 

(7) 人感センサー検知情報用の簡易Webアプリケーションを作ります。

まずWebアプリケーション作成用のディレクトリを作成します。

[sinatra@example-ruby-sinatra-server ~]$ ls -lrta /home/sinatra/
total 24
-rw-r--r-- 1 sinatra sinatra  124 Aug 16  2016 .bashrc
-rw-r--r-- 1 sinatra sinatra  193 Aug 16  2016 .bash_profile
-rw-r--r-- 1 sinatra sinatra   18 Aug 16  2016 .bash_logout
drwxr-xr-x 4 root    root    4096 Apr  2 23:31 ..
-rw------- 1 sinatra sinatra    8 Apr  2 23:31 .bash_history
drwx------ 2 sinatra sinatra 4096 Apr  2 23:31 .
[sinatra@example-ruby-sinatra-server ~]$ 

[sinatra@example-ruby-sinatra-server ~]$ mkdir /home/sinatra/example-pir-api
[sinatra@example-ruby-sinatra-server ~]$ 
[sinatra@example-ruby-sinatra-server ~]$ cd /home/sinatra/example-pir-api/
[sinatra@example-ruby-sinatra-server example-pir-api]$ pwd
/home/sinatra/example-pir-api
[sinatra@example-ruby-sinatra-server example-pir-api]$ 

Gemfileを作成します。

[sinatra@example-ruby-sinatra-server example-pir-api]$ ls -lrta /home/sinatra/example-pir-api/
total 8
drwx------ 3 sinatra sinatra 4096 Apr  2 23:37 ..
drwxrwxr-x 2 sinatra sinatra 4096 Apr  2 23:37 .
[sinatra@example-ruby-sinatra-server example-pir-api]$ 
[sinatra@example-ruby-sinatra-server example-pir-api]$ bundle init
Writing new Gemfile to /home/sinatra/example-pir-api/Gemfile
[sinatra@example-ruby-sinatra-server example-pir-api]$ 
[sinatra@example-ruby-sinatra-server example-pir-api]$ ls -lrta /home/sinatra/example-pir-api/Gemfile 
-rw-r--r-- 1 sinatra sinatra 75 Apr  2 23:37 /home/sinatra/example-pir-api/Gemfile
[sinatra@example-ruby-sinatra-server example-pir-api]$ 
[sinatra@example-ruby-sinatra-server example-pir-api]$ echo "gem 'sinatra'" >> /home/sinatra/example-pir-api/Gemfile
[sinatra@example-ruby-sinatra-server example-pir-api]$ echo "gem 'sinatra-contrib'" >> /home/sinatra/example-pir-api/Gemfile
[sinatra@example-ruby-sinatra-server example-pir-api]$ echo "gem 'json'"    >> /home/sinatra/example-pir-api/Gemfile
[sinatra@example-ruby-sinatra-server example-pir-api]$ 
[sinatra@example-ruby-sinatra-server example-pir-api]$ cat /home/sinatra/example-pir-api/Gemfile
# frozen_string_literal: true
source "https://rubygems.org"

# gem "rails"
gem 'sinatra'
gem 'sinatra-contrib'
gem 'json'
[sinatra@example-ruby-sinatra-server example-pir-api]$ 

Sinatraをインストールします。

[sinatra@example-ruby-sinatra-server example-pir-api]$ pwd
/home/sinatra/example-pir-api
[sinatra@example-ruby-sinatra-server example-pir-api]$ ls -lrta /home/sinatra/example-pir-api/
total 12
drwx------ 3 sinatra sinatra 4096 Apr  2 23:37 ..
drwxrwxr-x 2 sinatra sinatra 4096 Apr  2 23:37 .
-rw-r--r-- 1 sinatra sinatra  122 Apr  2 23:39 Gemfile
[sinatra@example-ruby-sinatra-server example-pir-api]$ 
[sinatra@example-ruby-sinatra-server example-pir-api]$ bundle install --path vendor/bundle
Fetching gem metadata from https://rubygems.org/..........
Fetching version metadata from https://rubygems.org/.
Resolving dependencies...
Installing backports 3.7.0
Installing json 2.0.3 with native extensions
Installing multi_json 1.12.1
Installing rack 1.6.5
Installing tilt 2.0.7
Using bundler 1.13.2
Installing rack-protection 1.5.3
Installing rack-test 0.6.3
Installing sinatra 1.4.8
Installing sinatra-contrib 1.4.7
Bundle complete! 3 Gemfile dependencies, 10 gems now installed.
Bundled gems are installed into ./vendor/bundle.
[sinatra@example-ruby-sinatra-server example-pir-api]$ 
[sinatra@example-ruby-sinatra-server example-pir-api]$ ls -lrta /home/sinatra/example-pir-api/
total 24
-rw-r--r-- 1 sinatra sinatra  122 Apr  2 23:39 Gemfile
drwxrwxr-x 2 sinatra sinatra 4096 Apr  2 23:39 .bundle
drwxrwxr-x 3 sinatra sinatra 4096 Apr  2 23:39 vendor
drwx------ 4 sinatra sinatra 4096 Apr  2 23:39 ..
-rw-rw-r-- 1 sinatra sinatra  568 Apr  2 23:39 Gemfile.lock
drwxrwxr-x 4 sinatra sinatra 4096 Apr  2 23:39 .
[sinatra@example-ruby-sinatra-server example-pir-api]$ 
[sinatra@example-ruby-sinatra-server example-pir-api]$ 

人感センサー検知状況表示用の簡易Webアプリケーションを作成します。

[sinatra@example-ruby-sinatra-server ~]$ vi /home/sinatra/example-pir-api/example-pir-api.rb 
/home/sinatra/example-pir-api/example-pir-api.rb
require 'sinatra'
require 'sinatra/reloader'
require 'json'

PIR_STATUS_FILE = "/tmp/example-pir-status.log"
PIR_STATUS_FILE.freeze

get '/' do

  if File.exist?(PIR_STATUS_FILE)

    status = File.read(PIR_STATUS_FILE, :encoding => Encoding::UTF_8)
    status = status.chomp

    if status == "1" then
      room_status = "[リビングに人がいます] " + status + ""
    else
      room_status = "[リビングに人はいません] " + status + ""
    end

  else

    room_status = "[リビングの人感センサー検知状況を表示できません]"

  end

  room_status

end

post '/put' do
  body = request.body.read

  File.open(PIR_STATUS_FILE, "w") do |f| 
    f.puts(body);
  end

  if body == ''
    status 400
  else
    body.to_json
  end
end

(8) Webサーバを起動します。

[sinatra@example-ruby-sinatra-server example-pir-api]$ sudo /usr/local/rbenv/shims/bundle exec ruby /home/sinatra/example-pir-api/example-pir-api.rb -o 0.0.0.0 -p 80 &
[1] 4965
[sinatra@example-ruby-sinatra-server example-pir-api]$ [2017-04-03 00:28:03] INFO  WEBrick 1.3.1
[2017-04-03 00:28:03] INFO  ruby 2.3.1 (2016-04-26) [x86_64-linux]
== Sinatra (v1.4.8) has taken the stage on 80 for development with backup from WEBrick
[2017-04-03 00:28:03] INFO  WEBrick::HTTPServer#start: pid=4966 port=80

 -> Enterキーを押します。
[sinatra@example-ruby-sinatra-server example-pir-api]$ ps awux | grep -v grep | grep ruby
root      4965  0.0  0.4 186148  4452 pts/2    S    00:28   0:00 sudo /usr/local/rbenv/shims/bundle exec ruby /home/sinatra/example-pir-api/example-pir-api.rb -o 0.0.0.0 -p 80
root      4966  1.7  2.7 360380 28236 pts/2    Sl   00:28   0:00 ruby /home/sinatra/example-pir-api/example-pir-api.rb -o 0.0.0.0 -p 80
[sinatra@example-ruby-sinatra-server example-pir-api]$ 

Raspberry Pi側の作業

(9) Raspberry Piで人感センサーが検知した情報をWebサーバへ定期的に送信するようにします。

人感センサー検知情報をWebサーバへ送信するスクリプトを作成します。
本記事では例としてWebサーバを 198.51.100.20 と表記しておりますので、198.51.100.20 を指定します。

root@raspberrypi:~# vi /root/scripts/put_gpio_status.sh 
/root/scripts/put_gpio_status.sh
#!/bin/sh

GPIO="18"
GPIO_VALUE="/sys/class/gpio/gpio$GPIO/value"
API="https://198.51.100.20/put"

SLEEP="2"

if [ ! -f $GPIO_VALUE ] ; then
  echo "$GPIO_VALUE not found."
  exit
fi

while :
do
  curl -H "Accept: text/plain" -X POST -d `cat $GPIO_VALUE` $API

  sleep $SLEEP
done

スクリプトを実行し、人感センサー検知情報をWebサーバへ定期的に送信するようにします。

root@raspberrypi:~# chmod 755 /root/scripts/put_gpio_status.sh
root@raspberrypi:~# 
root@raspberrypi:~# /root/scripts/put_gpio_status.sh &
[1] 1833
root@raspberrypi:~# 

動作確認

(10) Webブラウザを起動して、人感センサー検知情報表示用の簡易Webアプリケーションを表示してみます。

WebブラウザからWebサーバへアクセスしてみます。

 http://198.51.100.20/

人感センサーの周辺に人がいない場合は [リビングに人はいません] と表示されます。

スクリーンショット 2017-04-03 0.51.01.png

人感センサーに近づいてみます。

スクリーンショット 2017-04-03 1.01.45.png

すると、[リビングに人がいます] と表示が変わる事を確認します。

スクリーンショット 2017-04-03 0.54.05.png


Raspberry Piとセンサー類を組み合わせると、部屋の入室検知やそれに応じたアクションの自動化等、色々な事に活用出来そうですね!

以上になります。

続きを読む

S3にある大量のログデータをEMRを使って、簡単に集計したときのメモ

やりたいこと

S3にアップロードしてある大量のログデータを手軽に解析してみたい。
どこかにデータを移行することなく、簡単に集計したいので、今回はEMRを使って集計してみることにする。

手順

1. 前提

  • S3に以下のようなファイルがあるとして、集計作業を行なう

s3://aws-emr-sample-test/sample.csv

user_id,count
1,1
1,1
1,1
1,1
2,1
2,1
2,1
3,1
3,1
4,1

2. EMRの立ち上げ

  • サービスから、EMRを選択
  • クラスターの作成 を選択
  • 一般設定

クラスター名:お好きな名前を入力
起動モード:クラスター

  • ソフトウェア設定

ベンダー:Amazon
リリース:EMRの最新版を選択
アプリケーション:Core Hadoop: Hadoop 2.7.3 with Ganglia 3.7.2, Hive 2.1.1, Hue 3.11.0, Mahout 0.12.2, Pig 0.16.0, and Tez 0.8.4

  • ハードウェア構成(集計したいデータ量によって変えること)

インスタンスタイプ:m3.xlarge
インスタンス数:3個

  • クラスターの作成を選択し、ステータスが稼働中になることを確認する

余談

  • クラスターの起動時に、スポットインスタンスを使うと、通常の半額以下で買えることがあります。金額は、常に変動しておりますので、以下から確認してください。

https://aws.amazon.com/jp/ec2/spot/bid-advisor/

3. 集計

マスターサーバにSSHで接続する

接続すると、EMR環境下で立ち上がっているので、以下のような出力になります


       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|___|___|

https://aws.amazon.com/amazon-linux-ami/2016.09-release-notes/
19 package(s) needed for security, out of 42 available
Run "sudo yum update" to apply all updates.

EEEEEEEEEEEEEEEEEEEE MMMMMMMM           MMMMMMMM RRRRRRRRRRRRRRR
E::::::::::::::::::E M:::::::M         M:::::::M R::::::::::::::R
EE:::::EEEEEEEEE:::E M::::::::M       M::::::::M R:::::RRRRRR:::::R
  E::::E       EEEEE M:::::::::M     M:::::::::M RR::::R      R::::R
  E::::E             M::::::M:::M   M:::M::::::M   R:::R      R::::R
  E:::::EEEEEEEEEE   M:::::M M:::M M:::M M:::::M   R:::RRRRRR:::::R
  E::::::::::::::E   M:::::M  M:::M:::M  M:::::M   R:::::::::::RR
  E:::::EEEEEEEEEE   M:::::M   M:::::M   M:::::M   R:::RRRRRR::::R
  E::::E             M:::::M    M:::M    M:::::M   R:::R      R::::R
  E::::E       EEEEE M:::::M     MMM     M:::::M   R:::R      R::::R
EE:::::EEEEEEEE::::E M:::::M             M:::::M   R:::R      R::::R
E::::::::::::::::::E M:::::M             M:::::M RR::::R      R::::R
EEEEEEEEEEEEEEEEEEEE MMMMMMM             MMMMMMM RRRRRRR      RRRRRR

hiveを用いて集計をする

  • 集計については、hiveQLがインストールされているため、hiveを用いる

hiveは、hadoop上で動くDWH向けのソフトウェアで、主にhadoopが得意とするMapReduceの処理をSQLライクで実行することが可能です。

  • 集計を行なう

hiveを立ち上げる

$ hive

Logging initialized using configuration in file:/etc/hive/conf.dist/hive-log4j2.properties Async: false
hive>

集計DBの作成

--集計用のデータベースの作成
hive> CREATE DATABASE log;
OK
Time taken: 1.123 seconds

--対象データベースの選択
hive> use log;
OK
Time taken: 0.045 seconds
hive>

S3にあるログファイルをインポートする(以下の指定で、ディレクトリ以下のファイルをすべてインポートできる)

--S3からデータを読み込む
hive> DROP TABLE IF EXISTS log.test_table;
OK
Time taken: 2.545 seconds
hive> CREATE EXTERNAL TABLE IF NOT EXISTS log.test_table (
    >   user_id INT,
    >   count INT
    > )
    > ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY 'n'
    > LOCATION 's3://aws-emr-sample-test/';
OK
Time taken: 0.258 seconds
hive>

データが入ってるか、念のため、確認

--データがインポートされていることを確認
hive> SELECT user_id, count FROM log.test_table LIMIT 3;
OK
1       1
1       1
1       1
Time taken: 1.112 seconds, Fetched: 3 row(s)
hive>

集計する

--集計
hive> SELECT user_id, SUM(count) FROM log.test_table GROUP BY user_id;
Query ID = hadoop_20170331123614_c8493578-e1b9-48a9-8765-202649a8c9b1
Total jobs = 1
Launching Job 1 out of 1
Tez session was closed. Reopening...
Session re-established.


Status: Running (Executing on YARN cluster with App id application_1490962451243_0002)

----------------------------------------------------------------------------------------------
        VERTICES      MODE        STATUS  TOTAL  COMPLETED  RUNNING  PENDING  FAILED  KILLED
----------------------------------------------------------------------------------------------
Map 1 .......... container     SUCCEEDED      1          1        0        0       0       0
Reducer 2 ...... container     SUCCEEDED      1          1        0        0       0       0
----------------------------------------------------------------------------------------------
VERTICES: 02/02  [==========================>>] 100%  ELAPSED TIME: 11.28 s
----------------------------------------------------------------------------------------------
OK
1       4
2       3
3       2
4       1
Time taken: 19.344 seconds, Fetched: 5 row(s)
hive>

S3にあるログデータをどこかに移すことなく、簡単に集計できた!

まとめ

S3にアップロードしてあるログデータを簡単に速く集計かけたいときに、便利!

続きを読む