• 用意するもの
  • RasberryPi3
  • fluentd
  • influxDB
  • Grafana
  • こんにちは, KMC2回生のwass80です。

    この記事はKMC Advent Calendar 2016 21日目の記事です.
    昨日の記事はtronくんの「Neutron 買ってみたのは いいけれど……」でした。記事タイトルが575ですね。
    明日の記事はbase64くんの「いい感じのメドレーを自動生成したい」です。自分がもやりたかったことやられたので, 後でいい感じコミットぜったいしたる。

    今回はRaspberryPi3 ModelBを買ったので, 使って部室の監視をしたいと思います。

    概略図

    いい感じ図

    Raspberryにつながった温度センサーの値をfluentdでinfluxDBに送りつける。
    grafanaでグラフを表示。

    用意するもの

    RasberryPi3はArduinoと違って, オス-メスのジャンプワイヤーが必要になるので注意しましょう。買い忘れました。

    RasberryPi3

    センサーをつなげて値を読み取りましょう。

    セットアップ

    Raspberry Pi 3を買ってMacを使ってWiFi接続とSSHの接続するまで

    SDカードにRaspbianを焼いてRasberryPi3に差し込みます。
    USBで電源を供給すれば起動します。HDMIで画面を見ます。
    初期パスワードはuser:pi/pass:raspberryです。速やかに変更しましょう。
    sshがデフォルトで無効になっているので有効化する必要があります。
    Wifiでつながると便利なのでその設定もします。

    温度センサー

    第39回「ラズベリーパイで温度・湿度・気圧をまとめて取得!AE-BME280でIC2通信」

    このセンサーにははんだ付けが必要です。 I²C方式シリアル通信をします。

    上の記事通りに接続したら, I²Cを有効化します。
    Github: SWITCHSCIENCE/BME280のコードを借りて(少し改変して)データを表示してみます。

    t, p, h = readData()  
    print("気温:%f\t大気圧:%f\t湿度:%f" % (t, p, h))  
    
    [email protected]:~ $ python bme280/bme280.py  
    気温:19.729584     大気圧:1005.779496   湿度:56.260745
    

    動いてそうです。

    このデータを10秒おきに次のfluentdに送りつけましょう。

    fluent/fluent-logger-python

    from fluent import sender  
    import time
    
    logger = sender.FluentSender('raspi', host='sharp')
    
    if __name__ == '__main__':  
            while True:
                    t, p, h = readData()
                    print("気温:%f\t大気圧:%f\t湿度:%f" % (t, p, h))
                    logger.emit('climate', {'temperature': t, 'pressure': p, 'humidity': h})
                    time.sleep(10)
    

    systemd用のunitファイルを書きましょう。

    #/etc/systemd/system/bme280.service
    [Unit]
    Description = bme280 climate sensor
    
    [Service]
    ExecStart = /home/pi/bme280/bme280.py  
    Restart = always  
    Type = simple
    
    [Install]
    WantedBy = multi-user.targe  
    
    $ sudo systemctl enable bme280
    $ sudo systemctl start bme280
    

    fluentd

    ログの受け渡しをするサービス。
    fluentdは Input → Filter → Output の経路でJSONのログ(event)を流します。

    例えば, 以下のことができます。

    • あるログファイルの書き込みを感知して(Input) 
    • それがErrorのログならば(Filter)
    • Slackへ通知する(Output)

    今回は以下の構成になります。

    • TCPでログを受け取る(Input)
    • そのすべてを(Filterなし)
    • influxDBに送りつける(Output)

    InputとFilterとOutputを結びつけるのは, ログに紐づくタグです。
    Inputでログにタグを付け, 対応するFilter, Outputが動きます。

    fluentdはすでに部室で動いていたので間借りします。

    fluentdはデフォルトでTCPで受け取る以下のForward Inputが動いています。

    #不要なコード
    <source>  
      type forward
      port 24224
      bind 0.0.0.0
    </source>  
    

    RaspberryPIからraspi.climateタグをつけてfluentdに送っています。

    #前述抜粋
    logger = sender.FluentSender('raspi', host='sharp') #sharpはfluentdのあるサーバ名  
    logger.emit('climate', {'temperature': t, 'pressure': p, 'humidity': h})  
    

    なので以下の設定を追加します。

    <match raspi.climate> #このタグであれば  
      @type copy #次のOutputそれぞれに受け渡す
      <store> #ファイルに保存
        @type file
        path /var/log/td-agent/raspi/climate.log
      </store>
      <store> #influxdbに送りつける
        @type influxdb
        host  192.168.220.31
        port  8086
        dbname climate
        user  root
        password  root
        use_ssl false
        time_precision s
      </store>
    </match>
    
    # matchは上からマッチし, マッチしたものがあればそれ以上マッチしない。
    <match raspi.**> #上にマッチしなければ, 別のファイルに保存。  
      @type file
      path /var/log/td-agent/raspi/raspi.log
    </match>  
    

    今回はinfluxDBに送るついでにファイルにも保存していますが, DBを真面目に運用するなら必要ないでしょう。

    influxDB

    field/tagキーに値を時系列で突っ込んで行くデータベース。

    Key Concepts

    「性別(∋男,女)」のように値の種類(=カーディナリティ)が少ないものはtagキー。
    「気温=実数」のようにカーディナリティが高いものはfieldキーに指定します。

    influxDBの準備にはdocker-composeを用いました。

    参考: nicolargo/docker-influxdb-grafana

    # docker-compose.yml
    version: '2'  
    services:  
      influxdb:
        image: influxdb:latest
        ports:
          - "8083:8083"
          - "8086:8086"
        env_file:
          - 'env.influxdb'
        volumes:
          - influxdb-storage:/var/lib/influxdb
      grafana:
        image: grafana/grafana:latest
        ports:
          - "13000:3000"
        links:
          - influxdb
        volumes:
          - grafana-storage:/var/lib/grafana
        environment:
          - GF_SERVER_ROOT_URL=%(protocol)s://example.jp/~wass80/app/grafana
          - GF_AUTH_ANONYMOUS_ENABLED=true
          - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    volumes:  
      influxdb-storage:
        driver: local
      grafana-storage:
        driver: local
    

    起動する。

    $ docker-compose up -d
    

    InfluxDB と fluentd を組み合わせを試してみた

    データベースを作ればデータを受け取る準備が完了します。
    influxDBのWebインターフェースはdeprecatedのようなので, 今回はCLIを用いました。

    $ docker ps
    CONTAINER ID        IMAGE                                COMMAND                  CREATED             STATUS              PORTS                                                                 NAMES  
    791734f2cf3a        grafana/grafana:latest               "/run.sh"                8 hours ago         Up 8 hours          0.0.0.0:13000->3000/tcp                                               dockerinfluxdbgrafana_grafana_1  
    d39bac4136e8        influxdb:latest                      "/entrypoint.sh influ"   8 hours ago         Up 8 hours          0.0.0.0:8083->8083/tcp, 0.0.0.0:8086->8086/tcp                        dockerinfluxdbgrafana_influxdb_1
    
    $ docker exec -it d39 influx
    Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring.  
    Connected to http://localhost:8086 version 1.1.1  
    InfluxDB shell version: 1.1.1  
    > CREATE DATABASE climate
    > SHOW databases
    name: databases  
    name  
    ----
    _internal  
    climate  
    
    #fluentdの設定 前述抜粋
      <store> #influxdbに送りつける
        @type influxdb
        host  192.168.220.31 # influxDBの動くサーバ
        port  8086
        dbname climate #データベース名
        user  root
        password  root
        use_ssl false
        time_precision s
      </store>
    

    これで{'temperature': t, 'pressure': p, 'humidity': h}というfleid:値がinfluxdbに流れます。

    Grafana

    influxDBの内容をめっちゃかっこよく表示してくれるいい子。

    先程のdocker-composeで一緒に起動していました。
    今回はBasic認証がすでにかかっているところで動かすため, Grafanaの認証を無効化しています。 リバースプロキシ用の設定を環境変数に追加しています。

    Grafana: Configuration

    # docker-compose.yml (前述抜粋)
      grafana:
        image: grafana/grafana:latest
        ports:
          - "13000:3000"
        links:
          - influxdb
        volumes:
          - grafana-storage:/var/lib/grafana
        environment:
          - GF_SERVER_ROOT_URL=%(protocol)s://example.jp/~wass80/app/grafana
          - GF_AUTH_ANONYMOUS_ENABLED=true
          - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    

    influxDBを登録しましょう。
    GUIで設定できます。

    あとはめっちゃいい感じGUIでグラフの設定をします。

    いいですね。

    できました。

    凡例の色付き横線を押すと色の変更と軸の左右の変更ができます。

    他にも色々センサーを買いましたが, RaspberryPIがアナログ入出力が出来ないことを知りませんでした。A-D変換を買ってきます。
    明日の記事をお楽しみに。