Fluentd&Kinesis&Lambdaによる柔軟で高可用性なログ収集基盤の構築


概要

Fluentdによるログ収集基盤を、Lambda&Kinesisを利用した形で構成を変更したので、その時のメモ。
先に一言で感想を述べるのであれば、巷の噂通り、Kinesis&Lambdaは素敵でした。

Fluentd Aggregatorが抱える問題点

ログデータをFluentdのForwarder & Aggregatorを経由し、S3とRedshiftに保存するような構成でしたが、Aggregatorは冗長化しづらくボトルネックとなっていました。

ログ収集に求める要件

ログ収集の構成を改善するにあたり、先に挙げた目の前の問題点を解決するのは勿論ですが、他にも様々な要件があり、大別すると以下4つ。

  • 信頼性: データをロスなく収集することができる。
  • 安定性: ログ量に関係なく安定的なパフォーマンスを維持できる。
  • 冗長性: 安全かつ簡単にスケーリングが可能
  • 汎用性: 複数ログを複数サービスに転送可能。

これらの要件を満たすことができる技術ということで、AWS Kinesis(&Lambda)の登場です。

AWS Kinesis & Lambdaとは?

AWS開発者ガイドから、それぞれの特徴と制限をざっくりと調べてみると以下の通り。

Kinesisの特徴と制限

Fluentdの場合は、PUSH型

  • 特徴
    1. 簡単管理: フルマネージド
    2. リアルタイム: ストリーミングタイプの継続処理
    3. 伸縮自在: シームレスにスループットやボリュームを変えることができる。
    4. インテグレーション(S3, Redshift, Dynamo)
    5. リアルタイム処理: KCL(Kinesis Client Library)を用いて容易にリアルタイムストリーミングデータの処理が実装可能。
    6. Low Cost: コスト効率が高い。
  • 制限
    1. 1レコードあたりの容量: 25KB
    2. 1シャードあたりの転送量: 1MB/秒、1000レコード/秒
    3. シャード数上限: 25シャード (申請すれば引き上げ可能らしい)
    4. ストリームの保持期間は24時間 (1週間まで延長可能)

Lambdaの特徴と制限

  • 特徴
    • コードを書くだけでいい(対応言語:Nodejs,Java,Python)
    • オートスケールする
    • インフラの管理が不要
    • メモリ容量: 128mb〜1.5GB
    • CPU: メモリ容量に対して変動
    • タイムアウトは15s〜300sで設定可能(デフォルト15s)
  • 制限
    • 同時実行可能数: 100/s

Kinesis&Lambdaのログデータの流れ

データの流れを図にしてみると以下の通り。

FluentdのAggregaterの場合は、単純にデータのルーティング処理でデータが通過していくだけという形(PUSH型)でしたが、Kinesisの場合は、データを保持し続け(デフォルト24時間)、それをLambdaが取りにいくという形(PULL型)になります。

従来のLog Aggregatorでは、例えばサーバー・ネットワークで問題が起きてログデータが欠損した場合、復旧は困難でしたが、そこをKinesisが担保してくれます。さらにLambda側で何か問題が起きた場合でも、Lambdaでは処理を再実行させることもできますし、処理を一旦停止しておくこともできます。 (素晴らしい・・)

KPLとKCLとは?

ログ収集でKinesisとLambdaを導入するにあたり、重要なライブラリがKPCとKCLです。簡単に言ってしまうと、データを送信する際に1レコードずつ送信するのではなく、1レコード内に複数レコード集約してまとめて送ってしまおう、というもので、スループットが劇的に向上します。
(ちなみにこれらを使わずにKinesisを利用することもできます。)

  • KPL(Kinesis Producer Library) : ログを集約する。
    • コア部分はC++で実装
    • プロトコルバッファ実装
    • リトライ、シャード数最適化、レコード集約、メトリクス送信
  • KCL(Kinesis Client Library) : 集約されたログを展開(Disaggregation)する。

それぞれのライブラリはgithubにてAWSから提供されています。

Kinesis&Lambdaを活用したログ収集構成

WEBアプリケーションのログデータをS3とRedshiftに保存しているのですが、KinesisとLambdaの導入により、以下のように構成を変更しました。

Fluentdの設定: Kinesis利用時の最適設定

Kinesisを導入にあたりFluentdの設定も見直しが必要になってきます。設定は、各々の環境や負荷状況により異なると思いますので、Fluentd・Kinesis・Lambdaの主要な設定項目を図にまとめてみました。
ログデータはこまめに送るよりは、なるべく一纏めに送るような設定にしたほうがパフォーマンスが良くなります。
実際に運用しながら微調整していくことが必要かなと思います。

設定例。

<match kinesis.**>
  type kinesis_producer
  region ap-northeast-1
  stream_name YOUR_KINESIS_NAME
  include_tag_key true

  buffer_type file
  buffer_chunk_limit 1m
  buffer_queue_limit 512
  buffer_path /var/log/td-agent/buffer/

  flush_interval 15s
  try_flush_interval 1
  queued_chunk_flush_interval 1
  num_threads 1
  detach_process 1
</match>

複数ログの取り扱いについて: Lambdaでのルーティング処理

ログの種類がアクセスログだけとか1種類だけならいいのですが、実際にサービスを運用すると様々な種類のログが出力され、必要なログもサービスに合わせて増えていくと思います。その度に、新しくKinesisとLambdaを構築するのは冗長的ではなく、手間がかかります。そのため、Kinesisには全てのログを流し込み、Lambdaでログを分類し、それぞれS3、Redshiftテーブルに放り込むというやり方ができます。

下記の図は、仮にログがaccess,photo,userと3種類あった場合のログデータの流れを表したものです。(Kinesis&Lambaの組み方は色々あると思いますので、あくまで一例として)

備考 (メモ)

ラムダ関数が失敗した場合はどうなるか?

Q: 関数がイベントの処理に失敗した場合はどうなりますか?

Amazon S3 バケット通知およびカスタムイベントに関しては、コードにエラーがある場合、サービスまたはリソースの上限を超えた場合、AWS Lambda は関数の実行を 3 回試行します。Amazon DynamoDB ストリームおよび Amazon Kinesis ストリームなどお客様に代わって AWS Lambda がポーリングする指定イベントソースに関しては、開発者のコードにエラーがある場合、Lambda はデータの有効期限が切れるまで実行を試行します。Amazon Kinesis および Amazon DynamoDB コンソール、AWS Lambda が関数に向けて生成した Amazon CloudWatch メトリクスを使用して進行状況をモニタリングできます。エラーまたは実行スロットリング率に基づいて、Amazon CloudWatch アラームを設定することもできます。

Kinesisと連携した際のLambdaの同時実行回数は?

Amazon Kinesis または DynamoDB のストリームを読み取る Lambda 関数の場合、Lambda ではストリームのシャードごとに関数が同時に実行されます。たとえば、Amazon Kinesis ストリームに 100 のシャードがある場合、関数の実行数はどの時点でも最大 100 件になります。関数は、(イベントソース定義内で設定したバッチサイズを上限として) レコード数に応じて呼び出され、1 秒に複数回、アクティブな各シャードからの読み取りを順次行います。たとえば、Amazon Kinesis ストリームに 10 のアクティブなシャードがあるとします。この場合、Lambda 関数の同時実行数は 10 件となります。

プロトコルバッファ(Protocol Buffer)とは?

Protocol Buffersのデザインの目的はシンプルさとパフォーマンスである。とりわけ、XMLより高速になるようデザインされている。Google は XML との比較で、3〜10倍小さく、20〜100倍高速であると主張している[2]。Google が挙げている例では、XML では 69 バイト以上の物が Protocol Buffers では 28 バイトであり、パースに 5〜10 マイクロ秒かかるのが、0.1〜0.2 マイクロ秒ですむとしている。

参考URL

・Amazon Kinesisの集約データをAWS Lambdaで処理する by AWS Solution Archtectブログ (2016/2)
http://aws.typepad.com/sajp/2016/02/process-amazon-kinesis-aggregated-data-with-aws-lambda.html

・秒間数万のログをいい感じにするアーキテクチャ (2016.6.3)
https://speakerdeck.com/kanny/miao-jian-shu-mo-falseroguwoiigan-zinisuruakitekutiya

・Kinesis Producer Library(KPL)とfluentdとLambdaを連携してKinesisのスループットを上げる (2016.6.5)
http://dev.classmethod.jp/cloud/aws/high-throughput-messaging-system-with-kinesis-kpl-fluentd-lambda/

・AWS Black Belt Tech シリーズ 2015 (2015.9.4)
http://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-tech-2015-amazon-kinesis

・AWS Black Belt Techシリーズ Amazon (2014.5.28)
http://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-tech-amazon-kinesis

・BufferedOutput pluginの代表的なoptionについて
http://qiita.com/tatsu-yam/items/bd7006e483f3b3c64309