続 カッコの付け方

AWSを始めとしたクラウドコンピューティング全般と、唯一神emacsにおける()の付け方についてだらだら書きます

Google Cloud Logging + Big Queryでアクセスログ解析 (リアルタイム風味) 前編

今更ビックデータ という言葉を使うとちょっと恥ずかしいぐらいの時代になりましたが、身近にあるビックデータ(になりうるもの)として、Apacheアクセスログ解析をやってみたいと思います。リアルタイムに解析できるのが良いですが、リアルタイム性を追求してしまうと、色々大掛かりになるので、そこまで頑張らなくてもできる(大半をGCPにおまかせ)ということで、リアルタイム風味 とします。

部品の説明

  • Google Cloud Logging
  • Big Query

この2つを使います。Big Query に直接流し込む fluent plugin もありますが、色々狙いがあってGoogle Cloud Logging + Big Query連携とします。

Google Cloud Logging

AWSのCloud Watch Logs に似ていますが、現状では Watch = 監視機能は持っていません。かわりにExport として GCS(gs) もしくは Big Query に出力します。
また、Cloud Loggingにデータを投げるには、 google-fluent を使います。「結局 fluentじゃねーか!」ですが、ちょっとカスタマイズされていて、普通のfluentと同じ設定だとまずいので、細かい話をあとで書きます。

Big Query

日本での知名度はイマイチですが、結構古くからあるサービスで、データ容量とクエリに対して課金となり、いかにもクラウドなサービスです。AWSのredshiftに似ていますが、ターゲットは別と言って良いと思います。
元々は、止まったデータ(過去ログとか)を解析するものでしたが、最近は動いているデータ(ストリームデータ)のインポートも容易になりました。この機能により、くどいですが リアルタイム風味です。

Google Cloud Logging へログインポート

インスタンスの準備

VMインスタンスからgoogle-fluentで投げ込みます。それには前提条件があります。

  • VMインスタンス起動時にのみ指定できる scope = AWSでいう EC2-IAM-Role を指定する必要がある。
    f:id:iga-ninja:20150429142352p:plain
  • プロジェクト単位でのAPI有効化
    f:id:iga-ninja:20150429142344p:plain

この状態でgoogle-fluentをインストールします。ドキュメントのとおりです。 $ curl -sSO "https://storage.googleapis.com/signals-agents/logging/google-fluentd-install.sh"

google-fluent の設定

インストールしただけでかなりの設定済みfluent.confファイルが仕込まれていますが、不要なものを取り除き、access-logの設定をします。ここで注意点と、今回の設計意図を述べます。

原則 fluentの format = none とする

通常のfluentであれば、fluent クライアント(ログの生産者)がログをjsonにパース、もしくは生の状態でログコレクタ(別サーバ)に投げつけてパースさせるかの違いはあれど。
どこかでパースしてjsonにする
のが普通です。しかしoutput先がCloud Logging なので、他のESなどに突っ込んでいたのと同じjsonにしても、Cloud Loggingには突っ込めません。厳密には Cloud Loggingに対して json化して突っ込むメリットはあるには有ります、がとにかく他のoutput plugin と同じようにパースしても使えないとだけ認識してください。

上記について、多分、並のエンジニアならこう思います

「パース出来ないならBig Queryに行った時もカラムにならないから使えねーじゃねーか!」

私もBig Queryの予備知識がなければ多分そう考えてます。しかしこう切り返します

「Big Query なんでカラムなんてどうでもいいんです!あんなものは飾りです、偉い人には..ry」

詳しくは後編で書きますが、Big Query はそもそもインデックスが無い、データ総なめ(Full Scan)のデザインになってます。カラムに高速化の意味は薄いです(少なくとも行ベースのRDBにおけるインデックスの重要性とはまるで違います、列ベースは列ベースで別の意味でのカラム分割メリットはありますが)よって、カラムなんてクエリで作ればいいんです。

もう少し大きく考えれば、ETLを何処でやるかです。Cloud Loggingと組む場合は、原則ETLもBigQueryの仕事となります。これにより、ログの生産者たるWebサーバは楽できる。Webサーバが楽した分、Big Queryが頑張ることになりますが、Big Queryは全然余裕でETLもこなしつつ集計もできます。このETLをfluentにやらせるのであれば、fluent の BigQuery プラグインを使うのが良いです。

能書きが長くなりましたが、設定ファイルです

centos用です。tag名が Cloud Logging上のログ名 -> Big Query上のテーブル名Prefixとなるので、ここをアプリごとに分割したい人は別名で指定することをオススメします。

<source>
  type tail
  format none
  path /var/log/httpd/access_log
  pos_file /var/tmp/fluentd.apache-access.pos
  read_from_head true
  tag apache-access
</source>

<source>
  type tail
  format none
  path /var/log/httpd/error_log
  pos_file /var/tmp/fluentd.apache-error.pos
  read_from_head true
  tag apache-error
</source>

sink設定 (Big QueryへのExport)

Export設定は、プロジェクトオーナー権限が必要ですが、Developers Console 上からもExport設定は出来ます。が、これをやってしまうとCloud Logging にたまっているデータを根こそぎBig Queryにぶち込むので嫌です。
特定のログのみBigQueryに入れるには、gcloudコマンドを使います。こちらもドキュメント通りですが
1. プロジェクトのBigQueryにユーザー追加
BQ側に適当なデータセットを作成し、
- Group by Email
- cloud-logs@google.com
- Can Edit
でユーザーを追加します。こんな感じです。

f:id:iga-ninja:20150429142357p:plain
2. gcloud コマンドを叩く

# cloud logging 上でのLog名を調べる
gcloud preview logging --project <project-id> logs list

# sink登録
gcloud preview logging --project <project-id> sinks create <sink名 適当でいい> \
bigquery.googleapis.com/projects/<project-number>/datasets/access_logs \
--log <cloud logging上のでLog名>

# sink 確認
gcloud preview logging --project <project-id> sinks list

ここまでの手順どうりに進めていたら、cloud logging上でのLog名は apache-accessになります。これで完了です。

まとめ

まだ前半しか終わってないですが。

  1. Google Cloud Loggingに入れるためには、fluent の format は原則 None
  2. sink を使わずにExportした場合、データ根こそぎ Big Query (or GCS)に飛ぶ。多分、嫌だとおもうので、gcloudコマンドでsink設定。
  3. Big Qeury の力を信じて、ログ生産者側でごちゃごちゃしない。ETLなど集計と同時にやればいい。

今、ドキュメントをみて気づいたのですが Cloud Logging -> Pub/Subがいけるようになったみたいです。夢が広がりんぐ。