Amazon EC2でAWSが提供するWindows AMIの検索方法 (AWS Tools for Windows PowerShell)

Get-EC2ImageByNameは日本語版が検索の対象になっていない。

AMIの名前

AWS提供のWindowsAMIの名前パターン

  • OSバージョン Windows_Server-2016, Windows_Server-2012-R2_RTM, …
  • 言語 Japanese, English, …
  • Full, Core, Nano
  • Base(SQLServerなし), SQL_2016_Standard, SQL_2016_Web, …
  • AMIのリリース年月日

検索条件

  • region = 検索するリージョン
  • owner = “amazon”
  • platform = “windows”
  • name = 先頭から末尾までのワイルドカード(?*)、大文字小文字を区別する(CaseSensitive)検索

名前で検索して最新の1件を取得する

Get-EC2Image `
    -Region ap-northeast-1 `
    -Owner amazon `
    -Filter `
        @{name="platform"; values="windows"}, `
        @{name="name"; values='Windows_Server-2016-Japanese-Full-Base-*'} `
    | sort CreationDate -Descending `
    | select name, imageid, Description -First 1

続きを読む

AWS CLIとAWS Tools for Windows PowerShellで既定のプロファイルを共有する

確認したVersion: AWS Tools for Windows PowerShell Version 3.3.86.0


  • Initialize-AWSDefaultsを使わない
  • %USERPROFILE%AppDataLocalAWSToolkitRegisteredAccounts.jsonがあったら削除する
  • %USERPROFILE%.awscredentials[default]のプロファイルを書く

.awscredentials

[default]
role_arn=arn:aws:iam::000000:role/aws-cross-account-role
source_profile=base
region=ap-northeast-1

[base]
aws_access_key=AAAAAA
aws_secret_access_key=AAAAAA
region=ap-northeast-1

AWS Tools for Windows PowerShell

毎回のセッションごとに読み込みが必要。
Set-AWSCredentialsではProfileNameは指定しないとcredentialsファイルを読んでくれない。
%USERPROFILE%AppDataLocalAWSToolkitRegisteredAccounts.jsonがあると.awscredentialsは指定しないと読み込まなくなる。Initialize-AWSDefaultsを実行するとRegisteredAccounts.jsonが作られてしまう。

Set-DefaultAWSRegion
Set-AWSCredentials -ProfileName default

$StoredAWSRegion
$StoredAWSCredentials

AWS CLI

%USERPROFILE%.awscredentials[default]を自動で読み込む。
AWS CLIのリファレンスにはregionは.awsconfigファイルに書けとあるけど、credentialsファイルに書いてあれば読み込まれる。

続きを読む

[AWS] 積年の夢の終焉…?:リージョン間VPN接続 (powered by VyOS 1.1.7)

プロローグ

[AWS] 積年の夢の実現:リージョン間VPN接続 (powered by SoftEther)
[AWS] 積年の夢の続き:リージョン間VPN接続 (powered by Windows Server 2012 R2)
と歩を進めてきた、三部作(勝手に後付け♪)のファイナルw VyOS編。

  • VyOSがSoftEther/Windowsより優れているのは、VPN Connection接続(下記【a】)もPeer-to-Peer接続(下記【b】)もMobileアプリからのL2TP/IPSec接続(下記【c】)も可能なこと(と思っている)。
    ⇒SoftEtherは【a】不可、Windowsはそりゃ頑張ればナンでもできるでしょうが。。
    OVERVIEW_20170516.jpg

  • 。。。と思っていたところ、VPN ConnectionでVyOS(Vyatta)用のconfigをDLできなくなった???一昔前はできたはず…(・・;)
    ⇒なんと、RegionによってVPNCがサポートしているルータが異なることを発見!!(VyOS(Vyatta)は、N.Virginiaにはあるが、N.Californiaにはない、といった具合)

  • 半面、VyOSのDisadvantageは、学習コストが(少なくともCCNAしか持っていないヲレには)高い、という点か。
    ※SoftEtherもWindowsも、自動化とか欲張らなければ、GUIでも設定可能

    • といいつつ、VyOSもLinuxベース(vbash?)なので、そこまではぢめまして感はなく。
    • 「configure~commit/save」は、Cisco IOSの「configure terminal」と似ていると感じたよ。
    • その後、VyOSも、接続するまでなら、そんなに敷居が高くない(低くはない)ことを識る(いわゆる「知らないから怖い」&「食わず嫌い」)

⇒いや、やはりVyOSの敷居は高かった。。。CentOS等と似て非なり。Cisco IOSと非なりて似る。

構成オプション、どん!

VyOSは、様々なインストール方法・様々なVPN接続方法がある(♬そしてワタシはツブされる…(@_@))

  • VyOSインストール方法
     【1】 AWSのAMIを利用してEC2インスタンスとして作成
     【2】 オンプレミスにVirtualBox上に仮想マシンとして作成
     【3】 VirtualBox上のDockerホストにてDockerコンテナとして作成【Dockerでルータをコンテナ化してみた】
     【4】 あらゆるDockerホストにてDockerコンテナとして動作
        ⇒ そしてマルチクラウドへ。。。(【VyOSを使ってSoftLayerとAWSをIPSecVPN接続】

  • VPN接続方法
     【a】 AWSのCustomer Gateway(CGW)/VPC Connection(VPNC)/Virtual Private Gateway(VGW)を利用 [//]
     【b】 VyOS同士の直接接続(Site-to-Site接続)[]
     【c】 Windows10やAndroidから接続(Point-to-Site接続) [/]

【1】AMIを利用してEC2インスタンスとして作成

  • VyOS AMIのビルトインユーザは、「ec2-user」でなく「vyos」
  • rootユーザにパスワードを設定。。。passwdコマンドではできない。。。!?【保留中】
  • ログインユーザ作成【保留中】
$ configure
# set system login user 《管理者ユーザ》 authentication plaintext-password 《管理者ユーザのパスワード》
# commit
# save
# exit
  • 「vyos」の公開鍵を、《管理者ユーザ》にコピー【保留中】
$ sudo cp /home/vyos/.ssh/authorized_keys /home/《管理者ユーザ名》/.ssh/
  • ビルトインユーザ「vyos」削除 ※「vyos」以外のユーザでログインし直した上で
    【保留中】VyOSサーバを再起動したら、作成した管理者ユーザでSSHログインできなくなった (・・;)
$ configure
# delete system login user vyos
# commit
# save
# exit
  • 2枚目のENI(Private側)にプライベートIPアドレスをアサイン

※EC2を作成するCloudFormationにおいて、Public側ENIをIndex0、Private側ENIをIndex1と指定済み
OR
※ENI 1枚挿しのEC2インスタンスを起動した後で、2枚目ENIを手動でAttach済み

$ configure
# set interfaces ethernet eth1 address '10.100.12.100/24'
# commit
# save
# exit
$ sudo ifconfig
《eth1にプライベートIPアドレス「10.100.12.100」が割り当たっていることを確認》 

※ifconfigやroute等のNW系コマンドはrootでのみ実行可能

【1】を使ってAWS上で【a】でツナぐずら

(韓国(KR)のVyOSサーバと、USのVGWをVPN Connectionで接続)

  • 【US】VyOSサーバ持つEIPを使って、CSGを作成

    • BGPのAS番号を「65000」と指定
  • 【US】VPCとVPNCを作成

    • VPCのRouteTableにおいて「Propagated=yes」
      ⇒KRへのルーティング情報が、VGW経由で、US側のRouteTableに動的に追加されるようになる!
  • 【US】VPNCから「VyOS用config」をDL・・・少なくとも「N.Virginia」なら可能

  • 【KR】「VyOS用config」の一部を手動で書き換え:

    • local-address

      • VyOSサーバのパブリック側プライベートIPアドレス(10.100.11.100)に書き換え
        NAT-Tを利用するため、EIPではなくてプライベートIPアドレスと理解)
    • BGPのアドバタイズ情報
      • 10.100.11.0/24, 10.100.12.0/24
      • このBGPアドバタイズが中々できずにハマる。。。「10.100.12.0/24」をVyOSが認識していないためと推理(後述)
  • 【KR】「VyOS用config」を投入!!

    • AWSからDLしたスクリプトを一部書き換え後に愚直に実行すると、BGPアドバタイズの行で「Already exists」のエラーが発生★ そりゃそうなので無視~
  • 【KR】BGPアドバタイズ情報の追加

$ configure
# set protocols static route 10.100.12.0/24 next-hop 10.100.12.1
# set protocols bgp 65000 network 10.100.12.0/24
# commit
# save
# exit

【とっても素敵な参考情報】BGPアドバタイズするネットワーク設定の追加

  • 【US】ルーティング情報の確認

    • VGWのTunnel(2本)がUpしていることを確認
    • KR側のVPCサブネットに関するルーティング情報が、BGPによって動的にUS側RouteTableに反映されていることを確認する。
  • 【KR】疎通確認
    ①KR側のVyOSサーバからUS側にPingを送って確認

vyos@VyOS-AMI:~$ ping 172.16.12.200 interface 10.100.11.100
PING 172.16.12.200 (172.16.12.200) from 10.100.11.100 : 56(84) bytes of data.
64 bytes from 172.16.12.200: icmp_req=1 ttl=254 time=196 ms
64 bytes from 172.16.12.200: icmp_req=2 ttl=254 time=196 ms
64 bytes from 172.16.12.200: icmp_req=3 ttl=254 time=196 ms
・・・

VyOS上の送信IF(Public側)を明示的に指定する必要がある模様

②KR側のプライベートEC2からUS側にPingを送って確認

ping 172.16.12.200
  • 【US】疎通確認

    • US側からKR側にPingを送って確認

【閑話休題】BGPアドバタイズでハマった考察

疎通できた後で振り返ってみれば単純なことだが、めっちゃハマったのは、BGPによる動的ルーティング情報交換

  1. VyOS EC2の2枚目のENIの(プライベート)IPアドレスが、いつの間にか外れていた…
    ⇒最初ifconfigで設定していたから、再起動中に消失?VyOS設定「set interfaces ethernet eth1 address~」なら永続的?

  2. VyOSサーバに対して、KR側プライベートサブネットへのStatic Routeが必要だった。
    ⇒これは…自力では思いつかない…
    【再掲】BGPアドバタイズするネットワーク設定の追加

  3. BGPのルーティング情報伝達(コンバージェンス?)に、設定投入~環境反映の間のタイムラグがある?
    ⇒KR側のVyOSへのBGP設定投入後、US側のVGWからRouteTableへの伝達に少し時間がかかることを知らず、設定ミスだと思いこんでいた…

【2】オンプレミスのVirtualBox上に仮想マシンとして作成

VyOSは、一般的にはISOファイルで提供されているのか(AWSならAMIで提供)。
ISOファイルをDLし、VirtualBoxの起動時の「Optical Device」として指定してあげると、VyOSのインストールプロセス開始☆
格闘中…)

【1】と【2】を【b】でツナぐもな

(オンプレミスのVirtualBox仮想マシンと、VyOS-EC2を、VyOS機能で直接通信)

【1】と【3】を【c】でツナぐだなも

(Windows10/Android端末と、VyOS-EC2を、IPSec/L2TPで通信)

エピローグ

AWSリージョン間接続について、SoftEther/Windows/VyOSをひととおりやってみた。
まだまだ試したいこと・課題はあるけど、ひとまずおなかいっぱい。

続きを読む

AWS S3 に手軽にファイルをアップロードする方法 (Cyberduck, Transmit or Coda 2.5)

concrete5 のサイトで、S3 にファイルマネージャー内のファイルを保存しています。

その際、concrete5 (ブラウザ + PHP) ではアップロードしきれない大容量ファイルをアップする必要があったので、メモとして残します。

Cyberduck や Transmit、 Coda 2.5 が良い

AWS CLI は、1端末につき1アクセスIDしか付与できませんので、複数アカウント管理している場合、切り替えが面倒です。

無料 (寄付型) ソフトで Mac & Windows 版がある Cyberduck や私が使っている、 Coda 2.5 や Transmit でも Amazon S3 を FTP のように扱える機能がついています。

各ソフト

設定のメモ

  • 接続設定を開く
  • Access ID を登録
  • シークレットキーを入力
  • アクセスできるバケットやフォルダを制限していたら、パスに
    • /[バケット名]/[フォルダ] などアクセスできる先のフォルダを入力する(そうじゃないと権限エラーで接続できない)
  • あとは FTP のようにファイルをやり取りする

参考記事

IAM アカウントを作成

AWS コンソールから IAM アカウントを作成します。

  • IAM ユーザーを作成
  • S3 の権限を付与
    • S3FullAccess ではなく、特定バケットや特定ディレクトリ内のみの権限をあげるようにしましょう。(後述)
  • アクセスキーと、シークレットキーを生成してダウンロード

AWS CLI も良い

AWS CLI を使ってコマンドラインから送る方法もありますが、それは、いろいろ先人の方が記事をかかれているので、検索されると良いかもです。

参考記事

以上

続きを読む

TeraTermから動的IPのEC2に簡単にSSHする方法

概要

WindowsからAWSのEC2インスタンスにSSH接続するには、TeraTermを使うことが多いと思われる。
接続するにはマクロが便利だが、マクロに書き込むIPアドレスが動的な場合には一工夫必要になる。
その一工夫を入れて、マクロ実行のみでSSH接続できるようにする。

前提条件

  • 接続先EC2は動的なパブリックIPを持つ。
  • EC2にはSSH認証でログインする。
  • AWS CLIはインストール済みである。
  • AWS CLIでEC2インスタンス情報を取得するためのプロファイルは設定済みである。
    • aws configure --profile プロファイル名 で設定できる。
  • EC2はNameで一意に特定できる。
    • ※別の方法でも一意に特定しても良い。

方法

EC2のパブリックIPを取得するバッチ

プロファイル名とインスタンス名を渡し、該当するインスタンスのパブリックIPをip_work.txtというテキストファイルに書き込む。
ここで --filters の中身を調整すれば、Name以外でインスタンスを指定することもできる。

get_ec2_ip.bat
cd /d %~dp0
aws --profile %1 ec2 describe-instances --filters "Name=tag:Name,Values=%2" --query "Reservations[*].Instances[*].PublicIpAddress" --output text>ip_work.txt

SSH接続するTeraTermマクロを作成

ssh_ec2.ttl
; 1. 動的IPアドレスを取得
; 1-1. バッチを実行し、テキストファイル(ip_work.txt)にIPを書き込む
;      ※バッチをパスの通っていない場所に置く場合はフルパスで指定する
exec 'cmd /c get_ec2_ip.bat プロファイル名 インスタンス名' 'hide' 1
; 1-2. ファイルからIPを取り出し変数にセット
;      (ファイルを仲介せず、コマンドの出力を直接受け取る方法を思い付かなかったので)
fileopen FH 'ip_work.txt' 0 0
filereadln FH HOST_ADDR
fileclose FH

; (2)ユーザ名/秘密鍵を設定
USER_NAME = 'ログインするユーザ名'
getenv 'HOME' KEY_FILE
strconcat KEY_FILE '\.ssh\秘密鍵ファイル(pem)'

; (3)コマンド組立て 
COMMAND = HOST_ADDR 
strconcat COMMAND ':22 /ssh /2 /auth=publickey /user=' 
strconcat COMMAND USER_NAME 
strconcat COMMAND ' /keyfile="' 
strconcat COMMAND KEY_FILE
; 設定ファイルを用意しているならここでセット
strconcat COMMAND '" /F=SETTING.INI' 

; (4)サーバへ接続 
connect COMMAND

; TeraTermのタイトルバーに任意の名前を記述しておくと分かりやすい
settitle 'タイトル名'

end

TeraTermマクロを実行

作成したマクロをttpmacro.exe(TeraTerm本体のディレクトリにインストールされているはず)で実行すれば良い。
私は次のように運用している。

  • 拡張子ttlのファイルをttpmacro.exeに関連付け
  • 接続先ごとにこのマクロを用意
  • 各マクロをコマンドランチャ(最近はAqulinaを使っている)に登録

続きを読む

AWSでMastodonインスタンスを作るまで。自分まとめ

だいたいネットのチュートリアル通り

http://webfood.info/mastodon-aws-tutorial/
だいたいこの通りにやると構築できます(終了)

とするのも寂しいので、自分の環境で再現できるように、手順と詰まりやすい所を残しておきますね。

1.VPCを作る Virtual Private Cloud

A. まず、AWSから借りるサーバーをひとまとめにする仮想イントラネット、VPCを作ります。

image.png

この時、CIDR ブロックは XX.0.0.0/16をお勧めします。
ウィザード通りで大丈夫かと
image.png

↓ここからはVPCでトラブった時の雑学 CIDR ブロックについて若干おさらい。

VPCってなんだっけ。情報の授業のおさらい

VPCはAWSの仮想イントラネットです。VPCはサブネットマスクを使って自身のネットワーク内に
あるサーバーや更なるサブネットのアドレスを割り当てます。

こんな感じ、0が自分のネットワーク内で使えるアドレス

XX.0.0.0.0/24のサブネットマスク
11111111.11111111.11111111.00000000
0の数が8つ
2^8 = 256 のIPを割り振る事ができる。

XX.0.0.0.0/16のサブネットマスク
11111111.11111111.00000000.00000000
0の数が8つ
2^16 = 65536 のIPを割り振る事ができる。
これが分かってないと時々サブネットが作れず詰みになったりします。

情報の授業終わり

パブリックサブネットを作る

外部からSSH接続できるように仮想ルーターを配置します。
VPCの作成ウィザードで作成されてると思いますが、作られてなかったら、

A’ VPCダッシュボードからインターネットゲートウェイインターネットゲートウェイの作成で仮想ルーターを作ります。

仮想ルーターが出来たら、VPCにアタッチで作成したVPCとルーターを繋ぎます。
これで仮想ネットワークがインターネットに接続されました。

ですが、まだルーターがあるだけです。どのサブネットを作り、ルーターと接続します。
B’ サブネットの作成をクリックして先ほど作ったVPCにサブネットを作ります。
サブネットに割り当てるCIDRはXX.0.0.0.0/24がおすすめ

そして作成したサブネットをチェックし、ルートテーブルタブをクリック。
現在のルートテーブルを編集し、サブネットとインターネットゲートウェイをつなぎます。
image.png

rtb-XXXXXXXをクリックして編集します。

image.png

ルートタブから別ルートの追加 送信先を0.0.0.0/0 ターゲットをigw-XXXXXX(先ほど作成したインターネットゲートウェイのID)
を指定します。
これで、このサブネットにある仮想コンピューターはすべてインターネットからアクセスできるようになりました。
↑ここまで、VPCでトラブるケース。

2.インスタンスを作る。

A. Mastodonを実行するインスタンスを作ります。
インスタンスの作成をクリック
image.png

GithubのREADMEがUbuntuを推奨しているのでOSはUbuntuを選択するのがいいと思います。
一応はAmazon Linuxでも動く模様。
インスタンス詳細は先ほど作成したVPCサブネットを選択

image.png

ストレージは8Gだとすぐいっぱいになるっぽい。
20GBだとそれなりー、との噂を聞いたかも(曖昧)

セキュリティグループの設定

B. SSH接続からインスタンスを操作するようにセキュリティグループを作ります。

image.png

マイIPを選択し、自分のコンピューターからSSHポートが繋がるようにします。

image.png

画面には移りませんがSSH接続するのに、RSA暗号を使います。
インスタンスを作成時にキーペアが作成されるので自分用の秘密鍵を大切に保管してください。(秘密鍵が漏れて、自分の仮想コンピューターで好き勝手されて、20万の請求が来たとかいう話も)
これを失くすとインスタンスに接続できません。必ず漏れないように大切に保管してください。

C. 外部から接続できるようにインスタンスにパブリックIPを設定します。
サービス > EC2インスタンス > Elastic IP
から新しいアドレスの割り当てでパブリックIPを取得します。
パブリックIPが取得出来たらアクション > IP の関連付けで先ほど作成したインスタンスにIPを割り当てます。

3インスタンスに接続する。

A. まず、自分はwindowsなのでSSHクライアントをダウンロードします。
Putty」でググってダウンロード
image.png

B. インストーラーをダウンロードしてウィザードに従ってインストールします。

C. Puttyをインストールしたら、ダウンロードした秘密鍵をPutty形式に変換します。
PuTTYgenを起動してLoadをクリック

先ほど保存した秘密鍵ファイルを選びます。

image.png

選択したらsave private keyを選択し、秘密鍵を保存します。

A. いよいよインスタンスに接続します。
Puttyを起動します。
左のタブから SSH > Auth からBrowseボタンを押して、先ほど保存した秘密鍵を選択
image.png

秘密鍵を読み込んだら、
sessionを選択
Host Nameubuntu@XX.XX.XX(インスタンスに割り当てたパブリックIP)を入力
ここまで言ったら接続設定を保存しましょう
Saved Sessions適当な名前を入れて接続設定を保存します。

image.png

接続設定を保存したら、Openをクリック

image.png

こういう系の画面が出たら成功です。
これでLinuxサーバーが操作が操作できます。

4.マストドンのセットアップ

ここからは完全に上述のテキスト通りです。

まず、メモリが足りないっぽいので、スワップファイルを作ります。

先ほどのコンソールにコマンドを打ち込みます。

$ sudo fallocate -l 4G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

パッケージを最新にします。

$ sudo apt-get update
$ sudo apt-get upgrade

途中grub関連(?)の更新が聞かれますが

keep the local version currently installed

を選択してください。(どっちでも大丈夫だとは思うけど念のため)

マストドンのビルドetcに必要なソフトを入れます

$ sudo apt-get install -y python3-pip unzip docker.io nginx
$ sudo pip3 install docker-compose

上のテキスト通り、nginxの設定ファイルを編集します。

$ sudo vim /etc/nginx/sites-enabled/default

元々機能してた部分は#でコメントアウトします。
XX.XX.XX.XXの部分はインスタンスのパブリックIP

置き換える内容は以下の通りで。

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

#server {
#  listen 80;
#  listen [::]:80;
#  server_name XX.XX.XX.XX;
#  return 301 https://$host$request_uri;
#}

server {
  listen 80;
  listen [::]:80;
  server_name XX.XX.XX.XX;
  #listen 443 ssl;
  #listen [::]:443 ssl;
  #server_name XX.XX.XX.XX;

  #ssl_protocols TLSv1.2;
  #ssl_ciphers EECDH+AESGCM:EECDH+AES;
  #ssl_ecdh_curve prime256v1;
  #ssl_prefer_server_ciphers on;
  #ssl_session_cache shared:SSL:10m;

  #ssl_certificate     /etc/letsencrypt/live/everydon.com/fullchain.pem;
  #ssl_certificate_key /etc/letsencrypt/live/everydon.com/privkey.pem;

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  #root /home/mastodon/live/public;
  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://localhost:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}

こんな感じになってるはず。
image.png

Nginxを再起動します。

$ sudo systemctl start nginx

これで、インスタンスのセキュリティグループをHTTPを任意のIPにすることでサーバーに接続できるはずです

Githubからマストドンのソースを持ってきます。

$ git clone https://github.com/tootsuite/mastodon

念のため、最新版を確認

$ cd mastodon
$ git tag -l
$ git checkout -b x.x.x refs/tags/vx.x.x(x.x.xは最新版のバージョン)

これでマストドンのソースがダウンロードされるはずです。

設定ファイルをコピーします。

$ cp .env.production.sample .env.production

設定ファイルの中でDBの永続化設定をします。

env.production
db:
  restart: always
  image: postgres:alpine
## Uncomment to enable DB persistance
  volumes:
    - ./postgres:/var/lib/postgresql/data

redis:
  restart: always
  image: redis:alpine
## Uncomment to enable REDIS persistance
  volumes:
    - ./redis:/data

dbとradisにある

  volumes:
    - ./nanntoka

の部分のコメントアウト(#)を外します

いよいよマストドンのビルドです
下記のコマンドを実行

$ sudo docker-compose build

5.マストドンの設定

マストドンが使うカギを生成します。
下記のコマンドを3回実行し、文字列をそれぞれどこかにコピーします。

$ sudo docker-compose run --rm web rake secret

こういう感じの文字列が出力されます。
3回コピーしてください。

4b804c1e71d14951a50cbc52f3b8a7ef9d1bf993e2774227cdf637102022f4a5af188aa4fa4c236b31e4ed6970469d1527e06097b678edfb0ed9e6d85c18d805

設定ファイルをもう一回いじります。

$ vim .env.production

ドメインの設定、後でもう一度設定し直します。

# Federation
LOCAL_DOMAIN=XX.XX.XX.XX
LOCAL_HTTPS=false

秘密鍵を入力します
=の先に3つの秘密鍵を入力

# Application secrets
# Generate each with the `rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
PAPERCLIP_SECRET=
SECRET_KEY_BASE=
OTP_SECRET=

日本語設定はパス

DBのマイグレーションをします。
マストドンが使うデータベースの初期設定ですね。

$ sudo docker-compose run --rm web rails db:migrate

マストドンが使う固定ファイルを生成します。

$ sudo docker-compose run --rm web rails assets:precompile

ここで、Nginxを再起動します。
マストドンはport3000とport4000で動きますが、
以降は80ポートに来たアクセスをNginxがport3000とport4000に割り振ります。

マストドンへのアクセスの玄関口になる訳ですね。

$ sudo systemctl stop nginx
$ sudo systemctl start nginx

マストドンを起動します

$ sudo docker-compose up -d

マストドンが起動しました。

http://XX.XX.XX.XX/

にアクセスするとマストドンのトップページに飛ぶはずです。

mastodon-top.png

6.連携ソフトの設定

マストドンが利用するメールサービスを設定します。
メールはAWSのメールサービスSESを利用します。

ただ、途中です

続きを読む

[AWS] 積年の夢の続き:リージョン間VPN接続 (powered by Windows Server 2012 R2)

はじめに

積年の夢の実現:リージョン間VPN接続 (Powered by SoftEther)
というポストで『SoftEtherによるAWSリージョン間VPN接続』に触れましたが、その同音異義版である、
Windowsサーバ仮想プライベートゲートウェイによるAWSリージョン間VPN接続』について、御本家AWS謹製の記事『Windows Server 2012 R2 のカスタマーゲートウェイとしての設定』を見かけ、飛びついて試してみました☆
(過去にこのアプローチをトライした当時はハマって断念…今正解を見るに、とても自力では辿り着けない世界… (・・;))
この記事に則して、AWS上の2つのリージョンを使って実装してみたところ、アッサリと疎通成功!!

以下、疎通に至ったまでの設定手順を備忘メモ φ(..)
(詳細記述は引用記事に任せることにして、全体の流れと画面コピーを中心に)

環境構成概要

@OVERVIEW.jpg
■SG側:VPC=172.16.0.0/16、プライベートIP=172.16.0.100、EIP=XXX.XXX.XXX.XXX
■US側:VPC=10.10.0.0/16、プライベートIP=10.10.12.200
を、IPSec-VPN接続。
※Virutal Private GWはUS側、WindowsサーバはSG(シンガポール)側、にしますよ。

構築手順

  1. [SG] Windows EC2インスタンスの作成・設定
  2. [US] カスタマーゲートウェイ(CGW)の作成
  3. [US] 仮想プライベートゲートウェイ(VGW)作成・RouteTableの設定
  4. [US] VPNコネクション(VPNC)の作成
  5. [SG] Windowsサーバの設定
  6. [SG] ルーティングおよびリモートアクセスサーバの設定・有効化(Windows)
  7. [SG] VPNトンネルの設定(Windows)
  8. [SG/US] 疎通確認

1. [SG] Windows EC2インスタンスの作成・設定

  • EC2にEIPを付与
  • EC2のSrc./Dest. Checkの無効化
  • Windowsアダプタの設定の更新
    ①デバイスマネージャ.jpg

※Windowsサーバ側からVPN通信を開始するみたい。Windows EC2側のSecurityGroupのInBoundは調整不要。

2. [US] カスタマーゲートウェイ(CGW)の作成

※CGW/VGW/VPNCの作成手順の詳細は、AWSサイトを参照
– SG側のWindows EC2のEIPを指定
②CGW.jpg

3. [US] 仮想プライベートゲートウェイ(VGW)作成・RouteTableの設定

  • VGWに紐づける、USからSGへのルーティング設定
    ③VGW-1.jpg

  • VGWのルート伝達を有効化
    ④VGW-2.jpg

4. [US] VPNコネクション(VPNC)の作成

  • 作成済みのCGWとVGWを紐づけるVPNCを作成
    ⑤VPNC.jpg

  • VPNC作成後に設定ファイルをDL
    ⇒IPSecの事前共有キー(Pre-Shared-Key)と、VGWのグローバルIPアドレス(2つ)をゲット。

5. [SG] Windowsサーバの設定

  • 役割(Roles)の追加:「ネットワーク ポリシーとアクセス サービス」&「リモートアクセス」
    ⑥役割.jpg

  • 役割サービスの設定:NPS
    ⑦NPS.jpg

  • 役割サービスの設定:RAS
    ⑧RAS.jpg

  • 役割サービスの設定:IIS (デフォルトのママでOK)
    ⑨IIS.jpg

6. [SG] リモートアクセスサーバの設定・有効化(Windows)

  • リモートアクセス設定①
    ⑩リモートアクセス設定①.jpg

  • リモートアクセス設定②
    ⑪リモートアクセス設定②.jpg

  • リモートアクセス設定③
    ⑫リモートアクセス設定③.jpg

  • リモートアクセス設定④
    ⑬リモートアクセス設定④.jpg

  • リモートアクセス設定⑤
    ⑭リモートアクセス設定⑤.jpg

7. [SG] VPNトンネルの設定(Windows)

※DLした設定ファイル中のnetshスクリプトをWindowsサーバ上で実行!

  • 設定ファイル内の設定項目の補足:

    • Local Tunnel Endpoint:SG側のWindowsサーバのEIP ※「XXX.XXX.XXX.XXX」に該当
    • Remote Tunnel Endpoint:US側のVGWが持つ(2つの)グローバルIPアドレス
       ※VPNC作成時に自動付与される
    • Endpoint 1:SG側のCIDR ※「172.16.0.0/16」に該当
    • Endpoint 2:US側のCIDR ※「10.10.0.0/16」に該当
  • ファイアウォールルールの追加設定
    ※Admin権限で起動したコマンドプロンプトにてnetshコマンドを実行

トンネル(正)用
netsh advfirewall consec add rule Name="VPN to AWS Tunnel 1" ^
Enable=Yes Profile=any Type=Static Mode=Tunnel ^
LocalTunnelEndpoint=172.16.0.100 ^
RemoteTunnelEndpoint=VGWのグローバルIPアドレス①》 ^
Endpoint1=172.16.0.0/24 ^
Endpoint2=10.10.0.0/16 ^
Protocol=Any Action=RequireInClearOut ^
Auth1=ComputerPSK Auth1PSK=《事前共有キー①》 ^
QMSecMethods=ESP:SHA1-AES128+60min+100000kb ^
ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2
トンネル(副)用
netsh advfirewall consec add rule Name="VPN to AWS Tunnel 2" ^
Enable=Yes Profile=any Type=Static Mode=Tunnel ^
LocalTunnelEndpoint=172.16.0.100 ^
RemoteTunnelEndpoint=VGWのグローバルIPアドレス②》 ^
Endpoint1=172.16.0.0/24 ^
Endpoint2=10.10.0.0/16 ^
Protocol=Any Action=RequireInClearOut ^
Auth1=ComputerPSK Auth1PSK=《事前共有キー②》 ^
QMSecMethods=ESP:SHA1-AES128+60min+100000kb ^
ExemptIPsecProtectedConnections=No ApplyAuthz=No QMPFS=dhgroup2
  • レジストリの追加設定
    ※Admin権限で起動したコマンドプロンプトにてコマンドを実行
reg add HKLM\System\CurrentControlSet\services\Tcpip\Parameters ^
/v EnableDeadGWDetect /t REG_DWORD /d 1

⇒Regeditで、下記画面のレジストリが追加されていることを確認:
⑮regedit.jpg

8. [SG/US] 疎通確認

SG側
C:\>ping 10.10.12.200

10.10.12.200  ping を送信しています 32 バイトのデータ:
要求がタイムアウトしました。
10.10.12.200 からの応答: バイト数 =32 時間 =176ms TTL=254
10.10.12.200 からの応答: バイト数 =32 時間 =176ms TTL=254
10.10.12.200 からの応答: バイト数 =32 時間 =176ms TTL=254

10.10.12.200  ping 統計:
    パケット数: 送信 = 4、受信 = 3、損失 = 1 (25% の損失)
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 176ms、最大 = 176ms、平均 = 176ms
US側
$ ping 172.16.0.100
PING 172.16.0.100 (172.16.0.100) 56(84) bytes of data.
64 bytes from 172.16.0.100: icmp_seq=1 ttl=128 time=176 ms
64 bytes from 172.16.0.100: icmp_seq=2 ttl=128 time=176 ms
64 bytes from 172.16.0.100: icmp_seq=3 ttl=128 time=176 ms
64 bytes from 172.16.0.100: icmp_seq=4 ttl=128 time=176 ms
^C
--- 172.16.0.100 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 176.363/176.461/176.549/0.076 ms

⇒反応があればOK!!

後記

  • いずれの方法がいいぜというよりは、リージョン間VPN接続スケーラビリティ管理をAWSに任せてラクしたいならVPN Connection、利用料を抑えるならSoftEther等で腹を括って自己責任、という使い分けでしょうか。
  • 今回の接続方法だとWindowsサーバ側[SG側]からVPNセッションを張る必要がある模様(US側から最初にPingを打つと疎通しない。SG側から疎通した後なら、US側からのPingも通るようになる)
    ⇒SG側からUS側に定期的にPingを打ってVPNセッションを維持する、とかでしょうか…?

  • VPNトンネルは、通信開始後Upになるのに少し時間がかかる。暫く通信していないとDownする。

  • VPNトンネルは可用性目的で2本張られるが、切り替え(フェールオーバ)はどうやって検証できるのだろうか…

  • 次は、VyOS/でやってみたひ。

続きを読む

IoTでペットヘルスケア[実装編:センサデータの取得~AWS IoT連携]

本記事で取り扱うこと

IoTでペットヘルスケア[構想編]
IoTでペットヘルスケア[実装編:センサデータの取得~AWS IoT連携] ←本記事(構想編の続編)です
IoTでペットヘルスケア[実装編:AWSサービス間の連携]←次回です

IoTでペットヘルスケア[構想編]で紹介したアーキテクチャのうち、下記の赤枠内の実装(センサデータの取得からAWS IoTへデータを取り込むまでの部分)について、順を追って説明します。手順は現時点(2017/5)のものであるため、時間が経過している場合には、より便利なものが出ている可能性もありますので最新の情報をご確認ください。

AWS Design_pets_healthcare_実装編01.png

Raspberry Pi 3の準備

利用機材

以下を準備します。

  • Raspberry Pi3 Model B
  • GrovePi+
  • Grove – PIR Motion Sensor
  • microSDカード(今回は16GB)
  • USB Micro B(給電用)
  • その他(セットアップ用)
    • HDMIケーブル
    • モニタ(HDMI対応)
    • USB接続マウス
    • USB接続キーボード
    • microSDカード・リーダライタ

その他以外を接続すると、以下のような状態になります。
raspberrypi.jpg

OSのインストール

RASPBIAN JESSIE WITH PIXELをインストールします。
シンプルにインストールするだけですが、以下のとおりです。

  1. RASPBIAN JESSIE WITH PIXELをダウンロード、解凍します。

    • 今回は以下のリリースを利用。

      • Version:April 2017
      • Release date:2017-04-10
      • Kernel version:4.4
  2. 解答したイメージファイルをmicroSDカードへDDで書き込む。

  3. microSDカードをRaspberry Piへ挿入、セットアップ用のその他機器を接続して給電用USBケーブルを接続する。

[オプション] 日本語環境を設定

初期インストール時は英語環境になっているため、必要であれば日本語環境化しましょう。

  1. OS起動後、MenuからRaspberry Pie Configurationをクリックします。

    • このあたりのメニューの名前はOSのバージョンで少しずつ変わっていますので、それらしいものをお探しください。
  2. Localisationのタブを選択し、以下を設定する。(※設定後、再起動を促されますが、Noを選択する)

    • Locale

      • Language: ja(Japanese)
      • Country: JP(Japan)
      • Character Set: UTF-8
    • Time zone
      • Area: Japan
    • Keyboard
      • Country: Japan
      • Variant: Japanese
  3. 日本語フォントをインストールする。
    • ログイン時のデフォルトユーザ(pi)でターミナルを開き、下記を実行します。
$ sudo apt-get install jfbterm

上記の手順を実行後、OSを再起動すれば日本語化されます。

[オプション] エディタのインストール

好みの問題かもしれませんが、初期のviは使いづらいためvimをインストールします。

$ sudo apt-get update
$ sudo apt-get install vim

[オプション] tmpのRAMDISK化

長期間の稼働を前提とするため、念のためにファイルI/Oが継続的に行われる部分についてはRAMDISK化しておきます。(そんなに大量に読み書きするわけではないため、気休め程度ですが。)

/etc/fstabに以下を追記し、再起動後に正常にマウントされていることを確認します。

tmpfs           /tmp            tmpfs   defaults,size=32m 0       0
tmpfs           /var/tmp        tmpfs   defaults,size=16m 0       0
tmpfs           /var/log        tmpfs   defaults,size=32m 0       0

ネットワーク接続

Raspberry Piをインターネットへ接続できるように設定します。
有線でも無線でも、お好きなほうでOKですが、設置場所を考えると無線のほうが取り回しが楽なのでいいかもしれません。GUIからも設定できるため、特に難しいことはないので説明は割愛します。

GrovePiのライブラリをインストール

GrovePiとセンサーを利用するためのライブラリを導入します。

  • GrovePiのライブラリをクローンしてインストール
$ mkdir /home/pi/grovepi
$ cd /home/pi/grovepi
$ sudo git clone https://github.com/DexterInd/GrovePi
$ cd /home/pi/grovepi/GrovePi/Script
$ sudo chmod +x install.sh
$ sudo ./install.sh

途中でインストールの継続を聞かれるのでY(Yes)を選択。

  • GrovePi+の接続確認。
    GrovePi+が接続されている状態で、以下のコマンドを実行します。
$ sudo i2cdetect -y 1

WS000004.JPG
上記のように04が見えていれば、正常にGrovepi+を認識できています。

PIR Motion Sensorのデータ取得

  • PIR Motion SensorをD8ポートに接続します。

接続ポートは他でもOKですが、次項のサンプルコードではD8前提となっています。

  • センサデータ取得のサンプルコード

0.5秒毎にセンサデータの取得(動きを検知)して、1分ごとの集計結果をファイルに出力するサンプルです。デーモン化する前提ですので、不要な部分はコメントアウトしてあります。動作確認時はコメントアウトを外してprint部分をすれば、0.5秒おきの検知結果を標準出力へ出します。
#長期間運用する場合は、デーモン化してしまうのでsyslogが溢れないようにコメントアウトしたままのほうが良いと思います。

grove_pir_motion_sensor_d.py
import os
import sys
import time
import grovepi
import datetime

def getMotionSensor():
    pir_sensor = 8
    motion=0
    grovepi.pinMode(pir_sensor,"INPUT")
    countPerMin = 0
    i = 0

    while True:
        try:
            if i >= 120:
                d = datetime.datetime.today()
                output = "{ " + "\"countPerMin\":" + str(countPerMin)    + ",\"timestamp\":\"" +d.strftime("%Y-%m-%dT%H:%M+09:00")+ "\" }"
                print output

                f = open('/tmp/motionDetected.json', 'w')
                f.write(output)
                f.close()                     

                i = 0
                countPerMin = 0
            else:
                i = i + 1

        # Sense motion, usually human, within the target range
            motion=grovepi.digitalRead(pir_sensor)
            if motion==0 or motion==1:  # check if reads were 0 or 1 it can be 255 also because of IO Errors so remove those values
                if motion==1:
                    countPerMin += 1
                    #print ('Motion Detected')
                    #print i
                #else:
                    #print ('-')
            time.sleep(.5)

        except IOError:
            print ("Error")

def fork():
        pid = os.fork()

        if pid > 0:
                f = open('/var/run/motionsensor.pid','w')
                f.write(str(pid)+"\n")
                f.close()
                sys.exit()

        if pid == 0:
                getMotionSensor()


if __name__=='__main__': 
    fork()   
  • テスト実行

    • ハードウェアのPinを読みに行くため、root権限での実行が必要です。
    • うまく動作すれば、/tmp/motionDetected.jsonへ以下のような内容が出力されます。
{ "countPerMin":0,"timestamp":"2017-05-05T14:47+09:00" }

こちらのセンサーは、もう少し短い間隔でデータを取得することも可能ですが、ネコ様がトイレに入って出てくるまでの動きを検知したいので、0.5秒おきに検知を行い、1分間(最大120回検知)の中でどのくらい動きがあったのかを返すためのデータ出力を行っています。最終的には、この検知回数を元に通知を行っていきます。

純粋にセンサーしかない場合はともかくとして、ラズパイやEdisonなどの処理能力があるものであれば、センサーの生データそのものよりも、少し加工して使いやすくしたものを作り出したほうがよいのでは、と思います。

データ取得スクリプトのデーモン化

データ取得のスクリプトをOS起動時やプロセス停止時に自動で起動するため、デーモン化します。
#最近はinit.dから変わっていますので、久しぶりに触る方はご注意ください。・・・一瞬、困ったのは私だけ?w

  • 上記のgrove_pir_motion_sensor_d.pyを/usr/local/libに配置します。
  • /etc/systemd/system に motionsensord.serviceを作成します。
motionsensord.service
[Unit]
Description=Pir Motion Sensor Daemon
[Service]
ExecStart=/usr/local/lib/grove_pir_motion_sensor_d.py
Restart=always
Type=forking
PIDFile=/var/run/motionsensor.pid
[Install]
WantedBy=multi-user.target
  • サービス設定を読み込み、手動でデーモンを起動して動作確認します。

設定のリロード、手動起動

$ sudo systemctl daemon-reload
$ sudo systemctl start motionsensord

デーモンのステータスやファイル出力を確認

$ sudo systemctl status motionsensord

出力結果の例
WS000005.JPG

  • 自動起動を有効にします。
$ sudo systemctl enable motionsensord

OS再起動後も動作していれば正常に設定できています。

AWS IoTの準備

1年ほど前と比較して、非常に簡単になっています。基本はAWS IoTに示されれる手順に沿って実行するだけです。
#この説明いらないのでは・・・と思いつつ、AWS IoT初学者の方もいらっしゃると思いますので、一通りの流れを紹介ということで。

デバイスの登録

Raspberry PiをAWSに接続するための設定を行います。

connect_01.jpg
AMCからAWS IoTのコンソールを開き、Connect のページを選択します。Configuring a deviceの”Get started”を選択します。

WS000008.JPG
接続までの流れ説明ページが表示されるので、”Get started”を選択します。

WS000009.JPG
環境に応じてSDKをセットアップするためのKitが準備されていますので、利用したいものを選択します。今回はRaspbianなのでLinux/OSXを選択します。また、AWS IoTへの部分を記述する際の言語も選択します。今回はNode.jsを利用します。最後に”Next”を選択します。

WS000010.JPG
AWS IoT上で管理するデバイスの名前を指定します。こちらは、管理者がどのデバイス(今回だとRaspberry Piのどのマシンなのか)が分かればよいため、任意の名前でOKです。指定後、”Next step”を選択
※どこかに設定した値と一致させなければならない、といったことはありません。

WS000011.JPG
接続用Kitのダウンロードを行います。内容を確認後、”Next step”を選択します。

ちなみに、ここまでの操作により、以下の手順が自動的に行われています。(1年前は個別に行う手順でしたので関係が分かりやすかったのですが、今は便利になった反面、何が行われているのか少々分かり難くなっています。)

  • デバイスがAWS IoTにデータを送る権限の定義(ポリシー作成)

    • A policy to send and receive messages の部分です
  • デバイスに配置する認証キーの作成
    • A certificate and private key の部分です。Kitに含めれます。
  • デバイスと認証キー、ポリシーの関連付け
    • 3つを関連付け、特定のデバイスに権利を持たせて認証し、AWS IoTのトピック(MQTTでつかうチャネルのようなもの)へPublish/Subscribeできる状態とします。

デバイスの設定

WS000012.JPG
ダウンロードしたファイルをデバイス(Raspberry Pi)へ転送し、示されている手順を実行します。
※こちらの画面は接続確認にそのまま利用しますので、開いたままにしておいてください。

start.shを実行すると、以下の処理が実行されます。

  • 証明書の確認
  • aws-iot-device-sdkをはじめ、各種モジュールのインストール
  • AWS IoTとの接続テスト
start.sh
start.sh
# stop script on error
set -e

# Check to see if root CA file exists, download if not
if [ ! -f ./root-CA.crt ]; then
  printf "\nDownloading AWS IoT Root CA certificate from Symantec...\n"
  curl https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem > root-CA.crt
fi

# install AWS Device SDK for NodeJS if not already installed
if [ ! -d ./node_modules ]; then
  printf "\nInstalling AWS SDK...\n"
  npm install aws-iot-device-sdk
fi

# run pub/sub sample app using certificates downloaded in package
printf "\nRuning pub/sub sample application...\n"
node node_modules/aws-iot-device-sdk/examples/device-example.js --host-name=av8pngo3zyi88.iot.ap-northeast-1.amazonaws.com --private-key=y_raspberrypi_01.private.key --client-certificate=y_raspberrypi_01.cert.pem --ca-certificate=root-CA.crtroot@raspberrypi:~/workspace/cat_healthcare/gitrepo/connect_device_package#

デバイスに接続し、start.shを実行すると、下記のようにconnectと表示されれば接続が成功しています。
WS000015.JPG

さきほどのAWS IoTの画面に戻ると、Step3の下に、デバイスからPublishされたメッセージが届いているのが分かります。これはstart.shから実行された接続確認用のコードから送られています。
WS000013.JPG

続いて、Step 4のテキストボックスに任意の文字列を入れ、Send messageを選択すると、デバイス(Raspberry Pi)側がSubscribeしているTopicにPublishすることができます。今回はテスト用に”test publish message AAAA”と送ってみました。すると、以下のようにデバイス側で受信することができています。
WS000014.JPG

以上でデバイス側の設定は完了です。

センサデータ取得の連携設定

取得したセンサーのデータを実際にAWS IoTへ送信します。

AWS IoTへのPublish

サンプルですので、べた書き部分が多いですが、以下のようなスクリプトを作成します。今回はconnect_device_packageを利用しやすくるため、同ディレクトリに配置してしまいます。

publish_data_pirmotion.js
var awsIot = require('aws-iot-device-sdk');
var fs = require('fs');

var clientId_suffix = 'MotionSensor01';
var deviceId = 'y_raspberrypi_01';
var sensor = 'motion_sensor';
var MQTT_clientID = deviceId + "_" + clientId_suffix;

var topicname = "topic/" + deviceId + "/sensor/" + sensor;

var device = awsIot.device({
    keyPath: 'y_raspberrypi_01.private.key',
    certPath: 'y_raspberrypi_01.cert.pem',
    caPath: 'root-CA.crt',
    clientId: MQTT_clientID,
    region: 'ap-northeast-1'
});


device.on('connect', function () {

    console.log('connect');
    setInterval(function () {

        var messageJson = JSON.parse(fs.readFileSync('/tmp/motionDetected.json', 'utf8'));
        messageJson.clientId = MQTT_clientID;
        messageJson.deviceId = deviceId;

        var message = JSON.stringify(messageJson);

        console.log("Publishing.. " + topicname);
        device.publish(topicname, message);
    }, 60000);
});

処理としては、モーションセンサのデータ取得結果(motionDetected.json)に対してdeviceIdやclientIdをデータとして含め、1分毎にAWS IoTへ送信しているだけになります。

注意点としては、MQTTの仕様として、同一のトピックに対して接続する際にclientIdごとにコネクションを確立しており、複数のデバイス間で重複していると、セッションの奪い合い(お互いに接続、接続断を繰り返してしまう)ことになります。そのため、一意になるようにclientIdを生成して上げる必要があります。今回はデバイスの名前にセンサーの名前を組み合わせて生成しました。

MQTTのトピック名についても、センサーの種類ごとに分けて生成していく想定になっています。センサーの種類を増やす際には、これらのスクリプトやトピックごと増やすアーキテクチャとなります。AWS IoT側からデータを利用する際は、このトピック名を対象として選択することになるため、複数種類のデータを取り扱う際には、十分に検討して設計が必要です。例えば、途中のパスによって値のグルーピングを行う等。

動作確認は、AWS IoTのテスト用コンソールを利用します。
WS000017.JPG
AWS Iotの”Test”ページを開き、トピック名を入力して”Subscribe to topic”を選択します。

すると、Subscriptionsの中に指定したトピック名が表示されますので、選択します。1分毎にデータを送っているため、成功していれば、以下のようにメッセージを受信(Subscribe)できます。
WS000019.JPG

以上でモーションセンサーで実際に取得したデータをAWS IoTへ連携することができるようになりました。

Publish用スクリプトのデーモン化

publish_data_pirmotion.jsもセンサデータ取得用のスクリプトと同様にデーモン化してしまいます。昔はnode.jsだとforeverなどを利用していた気がしますが、systemdの場合は、Pythonスクリプトと同様でOKです。

  • /etc/systemd/system に publish_motionData.serviceを作成します。
publish_motionData.service
[Unit]
Description=publish motion data
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/root/.nvm/versions/node/v6.1.0/bin/node  publish_data_pirmotion.js
WorkingDirectory=/root/workspace/cat_healthcare/gitrepo/connect_device_package
KillMode=process
Restart=always
[Install]
WantedBy=multi-user.target

#rootで作成しちゃっていますので、上記のような内容になっています。

  • サービス設定を読み込み、手動でデーモンを起動して動作確認します。

設定のリロード、手動起動

$ sudo systemctl daemon-reload
$ sudo systemctl start publish_motionData

デーモンのステータスやファイル出力を確認

$ sudo systemctl status publish_motionData
  • 自動起動を有効にします。
$ sudo systemctl enable publish_motionData 

OS再起動後もAWS IoTへデータが送られていることを確認できればOKです。

センサーの設置

Cat’s Restroomにセンサーを設置します。

我が家では、以下のように個室風のトイレが設置されています。
Cat'sRestroom_外観.jpg
少々わかりにくいのですが、上記の写真のようになっています。2つのカラーボックスを棚として開いている側を向き合わせて置き、片方の背板を出入り口用に切り取っています。中は市販のネコトイレ(すのこ式)です。
#ホワイトペレット最高!

その中に対して、以下のようにセンサーを設置しました。図は真横から見たときの断面図・・・絵心なさすぎてすいません。
RestroomSensor01.png

入り口の背板(上部)の内側にモーションセンサーを取り付け、トイレ内部の動きを検知するようにしています。配線は2つのカラーボックスの間から通して、ネコ様の出入りの邪魔にならないようにしています。また、トイレ内の上部を中心に検知する配置のため、トイレ掃除等を誤検知しにくく・・・もなっているはずです。
#誤検知については、AWS IoT側で受け取ったデータを処理する際に条件付け(しきい値判定など)を行うことでも回避しています。

この配置で、0.5秒に一回のセンサーデータ取得を行うと、ネコ様がトイレに入るとバッチリ検知ができるようになりました。

おわりに

今回、センサデータを取得してAWS IoTへデータ連携を行うところまでできるようになりました。次回はAWS IoT側で受け取ったデータを活用して召使いへ連携していく部分について記載したいと思います。

また、他にもセンサーはあるのですが、長くなりすぎるため別立てして拡張編でも書いたほうがよさそうです。

次回:IoTでペットヘルスケア[実装編:AWSサービス間の連携]
cat01.jpg

続きを読む

AWS Windows Server 2016でのJMeter環境構築(分散環境編)

この記事では、AWS ec2のWindows Server 2016に、JMeter3.2の環境構築をしました。また、CentOS7と組み合わせた分散環境を構築します。Windows側をマスターに、CentOS側をスレーブにします。リモートデストクップクライアントは、Microsoft Remote Desktop for Mac Beta version 8.2.31を利用しています。

1. Windows単独環境でのJMeter構築

単独環境での構築については、「AWS Windows Server 2016でのJMeter環境構築」を参考にしてください。

2. CentOSでのJMeter構築

ec2でのCentOS7の初期セットアップについては省略します。

必要なコンポーネントを追加します。

$ sudo yum update -y
$ sudo yum install wget -y
$ sudo yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel -y
$ sudo wget http://archive.apache.org/dist/jmeter/binaries/apache-jmeter-3.2.tgz -P /opt/

ダウンロードしたJMeter3.2をインストールします。

$ sudo tar zxvf /opt/apache-jmeter-3.2.tgz -C /opt/

自動起動を設定します。IPアドレスは環境に合わせて指定してください。

$ sudo vi /etc/rc.local
ファイル末尾に
/opt/apache-jmeter-3.2/bin/jmeter-server -Djava.rmi.server.hostname=172.31.27.62 &
を追加します。
$ sudo chmod +x /etc/rc.local

同時接続数を大きくしてもよいように、ファイルディスクリプタの最大数を拡張します。

$ sudo vi /usr/lib/systemd/system/rc-local.service
ファイル内の [Service] の配下に
LimitNOFILE=64000
を追加します。

再起動して動作確認します。

$ ps -ax | grep jmeter
  760 ?        S      0:00 /bin/sh /opt/apache-jmeter-3.2/bin/jmeter-server -Djava.rmi.server.hostname=172.31.27.62
  767 ?        S      0:00 /bin/sh /opt/apache-jmeter-3.2/bin/jmeter -Dserver_port=1099 -s -j jmeter-server.log -Djava.rmi.server.hostname=172.31.27.62
  905 ?        Sl     0:01 java -server -XX:+HeapDumpOnOutOfMemoryError -Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:G1ReservePercent=20 -Djava.security.egd=file:/dev/urandom -jar /opt/apache-jmeter-3.2/bin/ApacheJMeter.jar -Dserver_port=1099 -s -j jmeter-server.log -Djava.rmi.server.hostname=172.31.27.62
 9107 pts/0    R+     0:00 grep --color=auto jmeter
$ cat /proc/`pgrep java | head -1`/limits | grep 'open files'
Max open files            64000                64000                files     

同様の環境を計4セット構築します。

3. マスター設定

Windwosファイアウォールをオフにします。これをしないと、スレーブとうまく通信できません。

Windows側のJMeterのインストールフォルダ配下binにある、jmeter.propertiesを設定します。IPアドレスは環境に合わせてください。

jmeter.properties
remote_hosts=172.31.27.62,172.31.26.37,172.31.20.153,172.31.28.111

4. Jmeterの実行

JMeterを起動して、「AWS Windows Server 2016でのJMeter環境構築」で作成したテストシナリオを呼び出します。

スクリーンショット 2017-05-05 16.54.00.png

今度は、右上の緑矢印が2つ書かれているボタンをクリックします。
すると、4台分に相当する、約4000リクエスト/秒の性能が測定されていることがわかります。

スクリーンショット 2017-05-05 16.57.22.png

続きを読む