Python
fluentd
docker
GoogleCloudPlatform
bigquery

fluentdとGoogleのBigQueryを連携させるのに1日以上時間を溶かした話

fluentdとGoogleのBigqueryを連携させたい!

この記事は、前回の記事

Docker&Ubuntu初心者がfluentdを使ってみた
の続きとなります。
目標は、PythonのWebフレームワークのflaskからFluentd経由でBigQueryにアクセスログ等を格納することです。
今回は1日以上時間を溶かす結果となりましたが多くの知見が得られましたので、皆さんのお役に立てば幸いです。

BigQueryとは

Google Cloud Platform(以下GCP)が提供するビッグデータ解析サービスです。普通数TB(テラバイト)もあるような大きなデータセットは、SQLのクエリを実行してもあまりにもデータが大きすぎて結果が返ってこないということもあります。でもBigQueryを使えば数秒で結果が返ってきます。流石すぎますGoogle様。

alt

Dockerfile

今回もDockerのUbuntuイメージでやっていきます。私が調べた限り、GCPはPython 2.7系に依存しているため、インストールしておきます。
またfluentdのBigQuery用プラグインもインストールします。バージョンが最新のものをgithubから引っぱってきます。

FROM ubuntu:xenial

RUN apt-get update && apt-get -y upgrade
RUN apt-get install sudo
RUN apt-get install -y curl
RUN apt-get install -y  vim
RUN apt-get install -y git
#デフォルトで24224を使うのでポートを空けておく
EXPOSE 24224

# fluentd(td-agent)のインストール
RUN curl -L https://toolbelt.treasuredata.com/sh/install-ubuntu-xenial-td-agent3.sh | sh

# python2.7
RUN apt-get -y install python2.7
RUN apt install -y python-pip python-dev

# GCPのダウンロード
RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz

# パッケージのダウンロード
RUN mkdir -p /usr/local/gcloud \
  && tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \
  && /usr/local/gcloud/google-cloud-sdk/install.sh

# パスを通す
ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin

# fluentd-plugin-bigqueryのインストール
RUN /opt/td-agent/embedded/bin/fluent-gem install --no-document specific_install
RUN /opt/td-agent/embedded/bin/fluent-gem specific_install https://github.com/kaizenplatform/fluent-plugin-bigquery.git

dockerをbuildしたのちに、コンテナを起動する時に

$ docker run --name test1 -it -p 24224:24224 ubuntu:td-bq /bin/bash

などで、ポートを空けてあげることに注意してください。
コンテナに入った時に、

$ bq

と打ってみてください。

not foundにならなければOKです。
Dockerfileを書く段階で、パスを通す必要がありそうです。

GCPの設定

GCPでプロジェクトを作る過程は、他に詳しい記事がたくさんあるので割愛します。
コンテナ上で、ログインするには

# gcloud auth login

と打つと、Enter verification codeと出るので指定のURLに飛んでポチポチしたのちに表示される認証コードをコピペします。
これで、GCPへのログインが完了しました。

続いて、BigQueryでデータセットとテーブルを作っていきましょう

# bq mk -t your-project-id:your_dataset

これでデータセットが作られました。
続いてテーブルスキーマを決定しておきます。スキーマの指定には、リスト形式で指定する方法とJSON形式で指定する方法がありますが今回はJSON形式で保存します。


[
 { "name":"usr",
   "type": "STRING"
  },
  {
    "name": "country",
    "type": "STRING"
  }

]

この単純なjsonファイルをschema.jsonという名前にして
/etc/td-agent の下に置きましょう。

# bq mk -t your-project-id:your_dataset.your_table /etc/td-agent/schema.json

GCPのBigQueryのページに飛んでもらうと、テーブルができたことを確認できたと思います。
また、後々使用するので
Google Developer Consoleからサービスアカウントを作成します。
発行が完了すると、画面上にクライアントID、メールアドレス、フィンガープリントが表示され、鍵ファイルがダウンロードされるはずなので保存して置きます

  

td-agent.confの設定

ここで一日溶かしました。かなり複雑ですね。/etc/td-agent にあるtd-agent.confに、諸々の設定を書いていきます。

td-agent.conf
<match testing.logs>
  @type bigquery_insert

  auth_method json_key
  json_key {
      "private_key":"-----BEGIN PRIVATE KEY-----\n ... -----END PRIVATE KEY-----\n",
      "client_email":"XXX@XXXXXXXX.gserviceaccount.com"
  }

  project yourt-project-id
  dataset your-dataset
  table your-table
  schema_path /etc/td-agent/schema.json
</match>

上のようなものを、td-agent.confに付け加えてあげてください。
一応中身の説明をすると、auth_methodにjson_keyを指定してあげて
private_keyとclient_emailは先ほどGCPのサービスアカウントの取得時に得られた鍵ファイルから、書いてあげます。
typeのところでは bigqueryのpluginの設定をしているみたいです。またschema_pathは先ほど使ったjsonファイルのパスを指定してあげます。

また各種権限を付与するために、rootユーザにUSERをしてします。
/etc/init.d の下にある td-agentの中身を

TD_AGENT_USER=root

にしてあげてください。

これで設定は終了です。
td-agentの起動をします

root# /etc/init.d/td-agent start

td-agentが起動しました。

root# echo '{"usr": "yutaro", "country":"japan"}' | /opt/td-agent/embedded/bin/fluent-cat testing.logs

私の場合、これでBigQueryに値が無事格納されました!
エラーが出る場合は、/var/log/td-agent の下に td-agent.logというファイルに
エラーログが出力されるのでこちらを適宜見ながら、修正できるといいと思います。

またpythonファイルから実行するには

$ pip install fluent-logger

としてあげて、/usr/local/bin/python/ に

test.py
from fluent import sender
from fluent import event

# params -> *(tag, host, port)
sender.setup('testing', host='localhost', port=24224)
event.Event('logs', {
    'usr': 'yutaro',
    'country': 'japan'
    })

という test.pyを作っておいて

$ python test.py

で、BigQueryに値が格納されます。
Webアプリでのアクセスログ等も、このようにしてあげれFluentd経由でBigQueryに格納できると思います。
間違いや訂正等ありましたら気軽にご連絡ください。