今更ビックデータ という言葉を使うとちょっと恥ずかしいぐらいの時代になりましたが、身近にあるビックデータ(になりうるもの)として、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で投げ込みます。それには前提条件があります。
この状態で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
でユーザーを追加します。こんな感じです。
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になります。これで完了です。
まとめ
まだ前半しか終わってないですが。
- Google Cloud Loggingに入れるためには、fluent の format は原則
None
- sink を使わずにExportした場合、データ根こそぎ Big Query (or GCS)に飛ぶ。多分、嫌だとおもうので、gcloudコマンドでsink設定。
- Big Qeury の力を信じて、ログ生産者側でごちゃごちゃしない。ETLなど集計と同時にやればいい。
今、ドキュメントをみて気づいたのですが Cloud Logging -> Pub/Subがいけるようになったみたいです。夢が広がりんぐ。