Amazon Linux(2017.03)にdocker-composeでZabbix3.2をインストールするまで

Zabbixサーバーのインストールと起動

Zabbixは公式でdocker-composeの定義を用意してくれていますので、とっても簡単に起動までできます。

Amazon Linuxを立ち上げてSSHで接続したところから、下記のコマンドで起動できます。

sudo yum update -y
sudo yum install -y docker git

# Docker起動
sudo service docker start

# docker-composeのインストール
curl -L https://github.com/docker/compose/releases/download/1.13.0/docker-compose-`uname -s`-`uname -m` > /tmp/docker-compose
chmod 755 /tmp/docker-compose
sudo mv /tmp/docker-compose /usr/local/bin/

# zabbixのdocker-compose定義を取得
git clone --depth=1 https://github.com/zabbix/zabbix-docker.git

# zabbix起動
cd zabbix-docker
sudo /usr/local/bin/docker-compose -f docker-compose_v2_alpine_mysql_latest.yaml up -d

Webにアクセスするとログイン画面が表示されます。
初期状態では Admin/zabbix でログインできます。

初期状態でzabbix-server自体がホストとして登録されていますが、接続に失敗している状態になっています。
IPが127.0.0.1に設定されていますが、Dockerコンテナ内なのでDockerコンテナ内から接続可能なIPである必要があります。
sudo docker psなどでコンテナ名を確認し、コンテナ名をドメインとして登録することで接続できます。(Dockerネットワーク内はコンテナ名でIPを引けるため)

zabbix-agentのインストールと起動

RPMはRedHat7ではなく6用のものを使う必要があります。
7用のものを使うとsystemdが必要と言われてエラーになります。

インストールしてすぐに起動するとバインドアドレスが0.0.0.0/0になっているので油断しますが、設定ファイル(/etc/zabbix/zabbix_agentd.conf)を編集しないとローカルホスト以外からのアクセスはできないので注意が必要です。

sudo rpm -ivh http://repo.zabbix.com/zabbix/3.2/rhel/6/x86_64/zabbix-release-3.2-1.el6.noarch.rpm
sudo yum install zabbix-agent

# Server=127.0.0.1 の部分をZabbixサーバーのIPに変更する
sudo vim /etc/zabbix/zabbix_agentd.conf

sudo service zabbix-agent start

セキュリティグループ

下記のポートを開けるのを忘れないこと。
サーバー: 10051
エージェント: 10050

続きを読む

Mac OS Sierra でamazon awsのインスタンスにsshす

うまくできなくてめっちゃ詰まったので自分用として作成

前提(と用意するもの)

  • ES2のインスタンス
  • sshしたいインスタンスのキーペアと秘密鍵 hogehoge.pem

やり方

  • キーペアの秘密鍵 hogehoge.pem を ~/.ssh 以下に置く
  • ~/.ssh のパーミッションを700に、~/.ssh/* または hogehoge.pem のパーミッションを600に変更する
sudo chmod 700 ~/.ssh
sudo chmod 600 ~/.ssh/*
  • sudo vim ~/.ssh/configでコンフィグファイルを開いて、PubkeyAcceptedKeyTypes=+ssh-dssを追記

  • ssh接続する

    ssh -i /Users/username/.ssh/hogehoge.pem ec2-user@パブリックDNS

何が原因だったのか

  • Sierraにアップデータした時にsshのバージョンが上がって鍵がうまく使えなかったっぽい
  • 秘密鍵のある場所は700にしないといけないけど、秘密鍵自体は600じゃないと動かないっぽい(400がいいとか644がいいとか諸説ありだけど、私の環境では600じゃなきゃダメだった)

続きを読む

AWSでjupyter

これなーに

GPUが無いローカル環境でディープラーニングをやろうとすると、遅くてストレスマッハ。
一方GPUを簡単に使えるAWSでやろうとすると、IDEの無い状態(vimやemacs)でコードを書かないといけなくて辛い。
なので、AWS上でjupyterを使って多少楽にかけるようにしてみる。

jupyterのよさ

tabで補完できる。以上!
まぁseabornとかでグラフィカルに見えるとか、pandasで表がいい感じに見えるとかそういうのもある。他人に喋るとき楽。とか

やってみる

# jupyterインストール
pip install jupyter

# jupyterの設定ファイル等の生成
jupyter notebook --generate-config
  # rootユーザーでやると、それやめたほうがいいよって出る。別にいいやって場合は--allow-rootを追加でつける。

# ローカルからの接続設定
vi ~/.jupyter/jupyter_notebook_config.py

# 以下を追加
c.NotebookApp.ip ='*' # 接続元のIP制御
c.NotebookApp.port = 8888 # 接続元のポート制御

jupyter notebook --allow-root

あとは、AWSのセキュリティグループで接続元のグローバルIPとポート:8888を許可してあげれば、OK。

これでjypyter上でcaffeやkerasなどなどを好きに使って、GPU有りな形でコーディングできる。

続きを読む

〇FLAGの中の人に憧れてMastodon×AWSでモンストドン作ってみた

Mastodon立ち上げたらいい会社に入れると聞いて、邪な気持ちで。。。いや、Mastodonとモンストって相性よさそうだなぁと思いたち、少し乗り遅れた感をかもしだしながら、フルにAWSを使って規模拡大しても大丈夫な構成で作ってみた。

モンストドン (https://monstdn.com)

構成

monstdn.png

最小構成のざっくり料金($1=113円、1ヶ月30日計算)

サービス 単価 月額料金
ALB 1台 × $0.0243/1H + データ転送的なの  約2000円 + α
EC2 2台(t2.nano) × $0.008/1H + データ転送的なの 約1300円 + α
RDS 1台(db.t2.micro シングルAZ) $0.028/1H + データ転送的なの 約2300円 + α
ElasticCache 1台(cache.t2.micro) $0.026/1H + データ転送的なの 約2100円 + α
S3Bucket $0.025/GB + リクエスト数的なの + α
SES $0.10/1,000通あたり + データ転送的なの + α
合計     ( 約7700円 + α なので ) ざっくり1万ぐらい

※無料枠があるので1年目はもう少しやすくできそう

やったこと

  • AWSのアカウント作成
  • IAMの作成とアカウントの初期設定(二段階認証とか、パスワードポリシーとか)
  • Route53でドメインを買う
  • SESでメール設定と制限解除申請
  • ACMの取得(無料でHTTPS通信)
  • S3バケット作成(画像とかのアップロードファイルの配信用)
  • VPCとセキュリティグループの作成
  • SES、S3へアクセスする為のIAMユーザの作成
  • ElasticCacheでRedisの作成
  • RDSでPostgreSQLの作成
  • EC2でCentOSを使ってMastodonの構築(下に詳細)とイメージ(AMI)の作成
  • AutoScallingの設定
  • ALB(ApplicationLoadBalancer)の作成(ACMをつける)
  • Route53でHostZoneのレコード設定

CentOSでのMastdon構築(20170517現在)

sudo su -
yum -y update
yum -y install vim

localectl set-locale LANG=ja_JP.utf8
localectl set-keymap jp106
localectl status

timedatectl set-timezone Asia/Tokyo
timedatectl status

dd if=/dev/zero of=/mnt/swapfile bs=1M count=2560
mkswap /mnt/swapfile
swapon /mnt/swapfile
chmod 0644 /mnt/swapfile
echo "/mnt/swapfile                             swap                    swap    defaults                0 0" >> /etc/fstab
free

vim /etc/sysconfig/selinux
 SELINUX=enforcing
 ↓
 SELINUX=disabled

systemctl disable postfix
systemctl disable auditd.service

yum -y install libxml2-devel ImageMagick libxslt-devel git curl nodejs file
yum -y install epel-release
rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
yum -y install ffmpeg ffmpeg-devel

yum -y group install "Development tools"
curl -sL https://rpm.nodesource.com/setup_4.x | sudo bash -

yum -y install nodejs
npm -g install yarn

yum -y install postgresql postgresql-contrib postgresql-devel
yum install -y openssl-devel readline-devel

useradd mastodon
passwd mastodon
su - mastodon
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src && cd ~
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile && source ~/.bash_profile
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.4.1 && rbenv global $_ && rbenv rehash

# 確認
ruby -v

cd ~
git clone https://github.com/tootsuite/mastodon.git live
cd live
git checkout $(git tag | tail -n 1)

gem install bundler
bundle install --deployment --without development test
yarn install --pure-lockfile

cp .env.production.sample .env.production
sed -i "/^PAPERCLIP_SECRET=$/ s/$/`rake secret`/" .env.production
sed -i "/^SECRET_KEY_BASE=$/ s/$/`rake secret`/" .env.production
sed -i "/^OTP_SECRET=$/ s/$/`rake secret`/" .env.production

vim .env.production
#Redis,Postgresql,言語,SMTP,S3の設定

RAILS_ENV=production bundle exec rails db:setup
RAILS_ENV=production bundle exec rails assets:precompile

exit

cat << "_EOF_" > /etc/systemd/system/mastodon-web.service
[Unit]
Description=mastodon-web
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="PORT=3000"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_


cat << "_EOF_" > /etc/systemd/system/mastodon-sidekiq.service
[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=5"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_

cat << "_EOF_" > /etc/systemd/system/mastodon-streaming.service
[Unit]
Description=mastodon-streaming
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="NODE_ENV=production"
Environment="PORT=4000"
ExecStart=/usr/bin/npm run start
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_

systemctl enable mastodon-{web,sidekiq,streaming}
systemctl start mastodon-{web,sidekiq,streaming}

cat << "_EOF_" | crontab -
RAILS_ENV=production
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:daily > /dev/null
_EOF_

yum -y install nginx

cat << "_EOF_" > /etc/nginx/conf.d/mastodon.conf
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name {domainName};

  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;
}
_EOF_

systemctl enable nginx
systemctl start nginx

# ユーザ登録後 admin設定
RAILS_ENV=production bundle exec rails mastodon:make_admin USERNAME={UserName}

メモ

EC2のDiskはSSDで(swapで使う)
ロードバランサーはApplicationの方じゃないとwebSocketがうまくいかない
コミュニティベースのシステムだからCloudFrontはあまり必要性感じなかったので使わなかった
(日本向けだしS3のバケット東京リージョンにあるし、S3もかなり性能いいし)
もしCloudFrontを使うなら、websocketできないからS3の前に置く感じ
今回CloudFrontの利点があるとすれば”ドメイン”が自分の使えることぐらいかな
CentOSじゃなくてAmazonLinux使いたかったけど、ffmpeg入れるのにやたら時間かかったからやめた。一応動いたけど(純正AWSが。。。)
DockerはDeployまで楽そうだけど、効率よくなさそうだったのでやめた
AWSでDocker使うならECSでやってみたいけど、Mastodonはすんなりできるのかなー
セキュリティ的にはロードバランサーからの80番ポートしか受け付けないように制御してるから大丈夫かな。
sshでのログインは同じVPC内に踏み台サーバ立ててと。

最後に

ここまで読んで頂きありがとうございます。
技術的なことを投稿するのはこれが初めてですが、だれかのお役にたてれたら嬉しいです。
普段はPHPとAWS少しいじる程度なのでいい勉強になりました。
ほとんど公開されている文献をもとにプラモデル感覚で作りましたので、ご指摘等あればコメント頂ければと思います。
個人でのサイト運用となりますので、落ちたらごめんなさい。

続きを読む

Setup Rails on unicorn on nginx on AWS EC2 linux

How to install Unicorn

1.Modify Gemfile contents

$ sudo vim ~/(sampleapp)/Gemfile

Add gem 'unicorn'

2. Install unicorn at the Gemfile’s directory

$ bundle install

3. Check installation of unicorn

$ bundle show unicorn
/home/ec2-user/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/unicorn-5.3.0

4. Make “unicorn.rb” on /(sampleAppDirectory)/config and write following contents

unicorn.rb
  worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
  timeout 15
  preload_app true

  listen '/home/ec2-user/testApp/tmp/unicorn.sock' #{Railsアプリケーションのあるディレクトリ}/tmp/unicorn.sock
  pid    '/home/ec2-user/testApp/tmp/unicorn.pid' #{Railsアプリケーションのあるディレクトリ}/tmp/unicorn.pid

  before_fork do |server, worker|
    Signal.trap 'TERM' do
      puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
      Process.kill 'QUIT', Process.pid
    end

    defined?(ActiveRecord::Base) and
      ActiveRecord::Base.connection.disconnect!
  end

  after_fork do |server, worker|
    Signal.trap 'TERM' do
      puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
    end

    defined?(ActiveRecord::Base) and
      ActiveRecord::Base.establish_connection
  end

  stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
  stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])

5. Execute following code and create rake file at your app directory

$ rails g task unicorn 
Running via Spring preloader in process 13140
      create  lib/tasks/unicorn.rake

6. Start unicorn and check unicorn starting

$ bundle exec unicorn_rails -c config/unicorn.rb 

*↑production環境かdeployment環境は選べる。Unicorn commands一覧参照

$ ps -ef | grep unicorn
ec2-user 12631 11576  0 08:09 pts/1    00:00:00 vim unicorn.rb
ec2-user 13547 13151  0 08:37 pts/5    00:00:01 unicorn master -c config/unicorn.rb                                                                                            
ec2-user 13582 13547  0 08:37 pts/5    00:00:00 unicorn worker[0] -c config/unicorn.rb                                                                                         
ec2-user 13584 13547  0 08:37 pts/5    00:00:00 unicorn worker[1] -c config/unicorn.rb                                                                                         
ec2-user 13587 13547  0 08:37 pts/5    00:00:00 unicorn worker[2] -c config/unicorn.rb                                                                                         
ec2-user 14665 13960  0 08:51 pts/3    00:00:00 grep --color=auto unicorn

Modify the setting of Nginx

1. Modify nginx.conf to rails.cof

nginx/1.10.2時点ではnginx.conf($ nginx -tでconfigファイルを確認できる)。nginx.confに以下のように書き換える。

nginx.conf
# For mor# e information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user ec2-user;
worker_processes 1;

events {
    worker_connections 1024;
}

http {
#    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
#                     '$status $body_bytes_sent "$http_referer" '
#                      '"$http_user_agent" "$http_x_forwarded_for"';

#   access_log  /home/ec2-user/testApp/access.log  main;

#    sendfile            on;
#    tcp_nopush          on;
#    tcp_nodelay         on;
#    keepalive_timeout   65;
#    types_hash_max_size 2048;

#    include             /etc/nginx/mime.types;
#    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
#   include /etc/nginx/conf.d/*.conf;

#   index   index.html index.htm;

    upstream unicorn {
      server  unix:/home/ec2-user/testApp/tmp/unicorn.sock; #/home/{ユーザ名}/{Railsアプリケーション>名}/tmp/unicorn.sock
    }

    server {
        listen       xx; #HTTP = 80
        server_name  xxx.xxx.xxx.xxx; #Your server ip-address or domain name

        access_log  /var/log/access.log;
        error_log   /var/log/error.log;

        root    /home/ec2-user/testApp/public; #/home/{ユーザ名}/{Railsアプリケーション名}/public
#       index   index.html;
        client_max_body_size 4G; #100m;
        error_page  404              /404.html;
        error_page  500 502 503 504  /500.html;
        try_files   $uri/index.html $uri @unicorn;

        location @unicorn {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_pass http://unicorn;
                }

        }

2. Reload nginx

$ sudo service nginx restart

3. Access your server address!!!

ここからはunicornのnginxに対するpermission deniedが出た時の処理

2017/04/23 06:45:40 [crit] 29912#0: *1 open()
"/var/lib/nginx/tmp/proxy/1/00/0000000001" failed (13: Permission
denied) while reading upstream, client: (clientserver), server:
(my-server), request: "GET / HTTP/1.1", upstream:
"http://unix:/pathTo/tmp/unicorn.sock:/", host:
"(my-server)"

上記エラーではnginx, tmpにおけるアクセス権限がnginxのみしかないので、アクセス権を解放する(下記アクセスは777としているが修正する必要あり)

$ sudo chmod 777 nginx
$ sudo chmod 777 tmp

続きを読む

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を利用します。

ただ、途中です

続きを読む

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

続きを読む

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

続きを読む

JenkinsおじさんのためのAWS Batch

はじめに

この記事の対象者

主にこんな感じの人をターゲットにしています。

  • Jenkinsでジョブを管理している
  • AWSをcliで触るのは実は大変…。GUIでやりたい
  • Dockerはインストールはしているけれど、あんまり触ったことが無い

また、本記事執筆時点では、us-east(virginia)でのみ利用可能なので、VPCでの利用はあまり想定していません。 (VPNを繋げば出来ると思いますが…)
本来はAuto ScalingやSPOTインスタンスと組み合わせたりといろいろあるのですが、私的事情により、志は低く、過疎っているJenkinsサーバを廃止(サーバレス化)することを目標にしています。

対象のJenkinsジョブ

今回ターゲットにするのは、Jenkinsだと一般的と思われる以下の処理とします。

  • JDKがバージョン指定で入っている
  • バッチ処理の入ったリポジトリをgit cloneしてくる
  • シェルスクリプトからごにょごにょして、リポジトリの中身を実行する

PHPやRubyなど別言語の人は、Javaな部分は脳内で別言語に置き換えてみてください。

AWS Batchでの流れ

Jenkinsでごく一般的なこの処理をAWS Batchでやろうとした場合、以下のような流れが一番シンプルになるかなと思います。

  1. JDK等、必要な実行環境を準備したDockerfileを作成する
  2. Jenkinsでやっていたシェル相当のシェルスクリプトを作成する
  3. リポジトリにDockerfileとシェルスクリプトを追加する
  4. Amazon ECRに設定を作成する
  5. Dockerfileでビルドし、JDK及びバッチ処理のリポジトリの入ったコンテナを作成し、ECRにプッシュする
  6. AWS Batchの設定(IAM Role, Compute Environment, Job Definition等)を作成する
  7. AWS Batchを実行する

というわけで、ハンズオン的に進めて行きたいと思います。

作業手順

1. Dockerfileの作成

古風なエンジニアにはこちらの記事が一番わかりやすいんじゃないかと思います。

効率的に安全な Dockerfile を作るには

今回のケースだとJavaのバッチ(Hello.class)を動かしたいので

$ ls
Hello.class

$ vim Dockerfile

として、以下のようなDockerfileを作成します。

Dockerfile
FROM centos:6

RUN yum install -y java-1.7.0-openjdk java-1.7.0-openjdk-devel
ENV JAVA_HOME /usr/lib/jvm/java-openjdk
RUN mkdir /opt/batch-directory
COPY . /opt/batch-directory/
WORKDIR /opt/batch-directory

Javaは諸々の事情からOpenJDKにしていますが、Oracle Javaが必要な場合は、少し手間はかかりますが、Oracle Javaでもコンテナを作成することはできます。また、本来だとベースイメージはAmazonLinuxだったりJavaが入ったコンテナの方が良いと思いますが、保守的な方のために、敢えてCentOSにしました。(あんまり意味ないかな…)

2. シェルスクリプトの作成

Jenkinsにバッチを実行するためのシェルスクリプト(Jenkinsでコマンド欄に入れていたようなもの)を作ります。

$ ls
Dockefile
Hello.class

$ vim batch.sh

今回は解説用なので雑なものを用意しています。

batch.sh
#!/bin/bash

java -version
java Hello

3. Dockerfileとシェルスクリプトをリポジトリに追加

せっかく作成したので、これらのファイルをGitリポジトリに追加しましょう。(これはこの後の工程上の必須項目ではないので、一連がテストされてからでも大丈夫です)

4. Amazon ECRにリポジトリを作成する

Amazon EC2 Container Registry(ECR)にリポジトリを作成します。ここではリポジトリ名を入れるだけです。
Amazon EC2 Container Service.png

5. Dockerfileでビルド

先ほど付けた名前を使って、Docker buildをします。

$ docker build -t unagi/jenkins-ojisan .

6. コンテナをECRに登録する

タグ付けして、先ほど作成したECRに登録してあげます。

$ aws ecr get-login --region us-east-1

# これでdocker loginに必要なコマンドがでてくるので、実際はそれを使う
$ docker login -u AWS -p xxxxxx -e none https://xxxx.dkr.ecr.us-east-1.amazonaws.com
$ docker tag unagi/jenkins-ojisan:latest xxxx.ecr.us-east-1.amazonaws.com/unagi/jenkins-ojisan:latest
$ docker push xxxx.ecr.us-east-1.amazonaws.com/unagi/jenkins-ojisan:latest

7. AWS Batchの設定をつくる

Job definitionとCompute environmentを設定します。

こちらがJob definitionで、コンテナを起動するときの設定になります。環境変数を設定できるので、パラメータを渡したい場合は使う事ができます。
AWS Batch (1).png

S3アクセス等でIAM Roleを使いたい場合は、ここで定義するJob Roleで定義する必要があります。そしてさらに分かりにくいことに、ここに表示されるIAM Roleを作るためには、信頼するエンティティがAmazon EC2 Container Service Task Role(ecs-tasks.amazonaws.com)のIAM Roleを作る必要があります。IAM Role作成時に似たようなのが沢山あるので、非常に解りづらいところです。

そして、次の画面はCompute environmentです。
AWS Batch (2).png
こちらはあまり見所は無く、淡々と設定していきます。ここで出てくるRoleは、ECSで動作するために必要なもので、コンテナで使うモノではありません。なので、適当に作成します…。

8. AWS Batchの実行

Job definitionsからSubmit jobして実行します。実行時に先ほど設定した環境変数を変更しながらの実行等もできます。
ちなみにこれも凄く分かりにくいのですが、Job definitionを編集したい場合はCreate new versionです。新しいバージョンの定義が出来てしまうので、古い方は不要になった段階で削除してしまいましょう。

9. 実行ログの確認

CloudWatchのログから見ます。Submitしてから起動までは少し時間がかかるので、少し待たないとログ出力はされません。

あとがき

Jenkinsおじさん的には、Dockerが出てくるため取っつき辛い印象を持つのかなと思います。
美しくDockerを使う場合はさておき、バッチ処理をやるだけであれば、Dockerfileに書くのはバッチサーバを作るときのセットアップコマンドで、一回やってしまえばあまり難しくないです。

続きを読む

AWSのCentos7上にJPiereを立ち上げる

AWS上にJPiere(iDempiere)を構築する 忘却録

  • AWSインスタンスの作成
  • CentOS7の初期設定

AWS上にCentOS7 インスタンスを作成する

テスト的に作成するので、t2.small構成で作成しました。
セキュリティグループを作成する時に「全てのTCPトラフィックを許可する」「IPアドレス→My IP」として、緩いセキュリティながらもとりあえず安全な環境を作りました。

TeraTermでインスタンスに接続

インスタンス作成時のセキュリティキーを指定すればAWS上インスタンスに繋がります
単純なことですが、AWSインスタンスCentOS7 のデフォルトアカウント名は「centos」です。以前はEC2-userだったと思うので要注意です
私は、ログイン出来ずに多くの時間を費やしてしまいました

CentOS7の初期設定をザックリと

Update

$ sudo yum update

SELINUXの廃止

/etc/selinux/configに対して SELINUX=disabled
$ sudo yum install wget unzip vim

よく使うツールをインストール

$sudo yum install -y net-tools bind-utils NetworkManager-tui
$yum install bash-completion
$wget https://github.com/terralinux/systemd/raw/master/src/systemctl-bash-completion.sh -O /etc/bash_completion.d/systemctl-bash-completion.sh
$sudo localectl set-locale LANG=ja_JP.utf8
$sudo localectl set-keymap jp106
$sudo timedatectl set-timezone Asia/Tokyo

使わないサービスを停止

$sudosystemctl list-unit-files –type service | grep enabled
$sudo systemctl stop postfix
$sudo systemctl disable postfix

Javaをインストールします

今回はOpenJDK8を入れます
$sudo yum install java

Postgresql 9.4 をインストールします

JPiere4.1 はPostgresql9.4らしいので
$wget https://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-3.noarch.rpm
–2017-04-07 12:27:42– https://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-3.noarch.rpm
  rpmはhttps://yum.postgresql.org/repopackages.php ここから探す
$sudo rpm -ivh pgdg-centos94-9.4-3.noarch.rpm
$sudo yum -y install postgresql94-server postgresql94-devel postgresql94-contrib

初期化します

$sudo su
$su – postgres
-bash-4.2$ cd /var/lib/pgsql/9.4
-bash-4.2$ rm -rf data
-bash-4.2$ /usr/pgsql-9.4/bin initdb –encoding=UTF8 –no-locale –pgdata=/var/lib/pgsql/9.4/data

自動起動させるようにします

$sudo systemctl enable postgresql-9.4
$sudo systemctl start postgresql-9.4

postgresqlのVersion確認

$sudo su – postgres
psql -version
psql
postgres-# select version();
postgres-# q

Postgreユーザーのパスワード設定

 OSのpostgresアカウントとDBのpostgreアカウントがあるので双方パスワードの設定をします

postgres ユーザーのパスワード変更(Unix)

$ sudo passwd postgres

postgres ユーザーのパスワード変更(Postgresql)

$ su – postgres
-bash-4.2$ psql
psql (9.4.1)
Type “help” for help.

postgres=# password postgres
Enter new password: ********
Enter it again: ********
postgres=# q

postgresアクセス許可設定

pg_hba.conf編集

vim /var/lib/pgsql/9.4/data/pg_hba.conf
[…]
host all all 127.0.0.1/32 md5
host all postgres 0.0.0.0/0 md5 # add
[…]

postgresql.conf編集

vim /var/lib/pgsql/9.4/data/postgresql.conf
[…]
listen_addresses = ‘*’
[…]
port = 5432
[…]

postgresql再起動

$sudo systemctl restart postgresql-9.4

pgAdminⅢ のインストール

Postgresqlを管理するために Windows端末に pgAdminⅢをインストールしておく
インストール方法は割愛

pgAdminからの接続を試す

接続が出来ない場合、postgresqlの設定ファイルを再度確認してください
 F/Wの確認
 pg_hba.confの認証方法の確認

ログインロールの作成

名称:adempiere

DB作成

DB名称:idempiere
ここまでpgAdminで実施します

JPiereの入手とインストール

OSDNからJPiere関連ファイルを入手(ExpDat.dmpももらっておく)
$cd /usr/local/etc
$wget https://ja.osdn.net/dl/jpiere/ExpDat.dmp
$wget idempiereServer.gtk.linux.x86_64.zip
$sudo unzip idempiereServer.gtk.linux.x86_64.zip

データベースのリストア

idmepiere-server/data/seedディレクトリに移動します。
Adempiere_pg.jarファイルを解凍します。
$ sudo chmod a+rwx ../seed
$ jar xvf Adempiere_pg.jar
$ psql -d idempiere -U adempiere -f Adempiere_pg.dmp

もしくは ExpDat.dmpのリストア
iDempiereのデータベースのリストア
$ psql -d idempiere -U adempiere -f ExpDat.dmp

alternatives –config java
インストールされているJavaの確認と どのJavaを使うか?の選択

JPiereの初期設定と起動

$ cd /usr/local/etc/idempiere***/idempiere-server
$ sudo sh console-setup.sh
各設定値を入力します
DBはlocalhostで。
$ sudo sh idempiere-server.sh &
起動します
DBに関してのエラーが出た場合 私は
$ sudo sign-database-build.sh を実行して直りました

日本語の設定

$sudo yum -y install ibus-kkc vlgothic-*
$sudo localectl set-locale LANG=ja_JP.UTF-8

動作確認

http://サーバー名:8080/webui
でアクセスできます。

続きを読む