grafana をインストールし、データソースとして influxDB を追加する

OS: Amazon Linux 2(Centos 7 互換)

最新の grafana のバージョンを Download Grafana | Grafana Labs を参考にインストールする

$ wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.2.2-1.x86_64.rpm 
$ sudo yum localinstall grafana-5.2.2-1.x86_64.rpm

自動起動設定と起動方法は次の通り。

$ systemctl daemon-reload
$ systemctl enable grafana-server # 自動起動設定
$ systemctl start grafana-server 
$ systemctl status grafana-server
● grafana-server.service - Grafana instance
   Loaded: loaded (/usr/lib/systemd/system/grafana-server.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2018-08-25 00:37:35 UTC; 11h ago
...

grafana Web UI は 3000 port でアクセスできる。

http://localhost:3000 にアクセスし、認証を行う(初期ユーザ:パスワードは admin:admin)。 初回ログイン時にパスワードの変更を求められるので、変更を行う。

ダッシュボード上から「Add DataSource」をクリックし、InfluxDB で設定したユーザ・パスワードなどを入力していく f:id:kmikmy:20180825205534p:plain

ページ下部の「Save & Test」を押して、「DataSource is working」と出ればOK f:id:kmikmy:20180825205646p:plain

grafana でダッシュボードを作成し、ダッシュボードの中にパネルを作成する(左上の「+」からダッシュボードを作成し、「Add Panel」をクリックする)。

DataSource として InfluxDB を選択すると Influx QL を使って取得したデータを grafana 上に可視化することが可能。 f:id:kmikmy:20180825210904p:plain

InfluxDB の WebAPI エンドポイントに認証機能を追加してデータ取得まで行う

OS:Amazon Linux 2(Centos 7 互換) version: InfluxDB 1.6

InfluxDB 1.6 を install すると最初は、WebAPI エンドポイントが有効になっていない。 これを有効にするために設定ファイルを変更する必要がある。

/etc/influxdb/influxdb.conf

変更例

[http]
  # Determines whether HTTP endpoint is enabled.
  enabled = true

  # The bind address used by the HTTP service.
  bind-address = ":8086"

  # Determines whether user authentication is enabled over HTTP/HTTPS.
  auth-enabled = true

  # The default realm sent back when issuing a basic auth challenge.
  # realm = "InfluxDB"

  # Determines whether HTTP request logging is enabled.
  log-enabled = true
  ...

WebAPI エンドポイントを有効にするために [http] の項目で enabled = true にする。 バインドするポート番号 bind-address、認証機能を有効にするための auth-enabled = true , HTTP のリクエストのロギング有効化 log-enabled = true 等を設定する。 その他はお好きなように。(参考)Configuring InfluxDB OSS | InfluxData Documentation

設定を反映するために influxdb を再起動する

$ sudo systemctl restart influxdb

POST パラメータのq に influx QL を記述してエンドポイントを curl で叩く。認証機能を有効にして、admin ユーザが作られていない状況でエンドポイントを叩くと、最初に admin ユーザを作れと 403 Error になる。

$ curl -i -X POST http://localhost:8086/query --data-urlencode "q=SHOW USERS"
HTTP/1.1 403 Forbidden
Content-Type: application/json
Request-Id: d474184a-a854-11e8-8001-000000000000
X-Influxdb-Build: OSS
X-Influxdb-Error: error authorizing query: create admin user first or disable authentication
X-Influxdb-Version: 1.6.1
X-Request-Id: d474184a-a854-11e8-8001-000000000000
Date: Sat, 25 Aug 2018 10:51:32 GMT
Content-Length: 87

{"error":"error authorizing query: create admin user first or disable authentication"}

そのため、まずは admin ユーザを作成する(最初の admin ユーザの作成は認証しなくてもクエリが成功する)。

$ curl -X POST http://localhost:8086/query --data-urlencode "q=CREATE USER root WITH PASSWORD 'root' WITH ALL PRIVILEGES"

作成した admin ユーザの情報を用いて、エンドポイントを叩くことが可能になる。

$ curl -X POST http://localhost:8086/query -u root:root --data-urlencode "q=SHOW USERS"
{"results":[{"statement_id":0,"series":[{"columns":["user","admin"],"values":[["root",true]]}]}]}
$ 
$ curl -X POST http://localhost:8086/query?db=mydb -u root:root --data-urlencode 'q=SELECT * FROM cpu'
{"results":[{"statement_id":0,"series":[{"name":"cpu","columns":["time","host","region","value","value2"],"values":[["2018-08-25T03:12:37.911702475Z","serverA","us_west",0.64,null],["2018-08-25T03:13:44.479107406Z","serverB","us_east",0.1,null],["2018-08-25T03:14:13.822910528Z","serverB",null,0.1,null],["2018-08-25T03:34:49.405686775Z","serverB","us_east",0.1,"hoge"]]}]}]}

Amazon Linux 2 に InfluxDB を導入

InfluxDB とは

OSS の時系列データベース。センサーデータなどの時系列データを保存するデータストアとして使うことにした。

他のデータストアの候補としては OpenTSDB などがあったが、OpenTSDB はバックエンドに HBase を使うなど規模感がやろうとしていることに対して大きすぎるということで influxDB を選択した。

導入手順

環境:Amazon Linux2 (Centos 7.x 互換)

現在の stable 最新版 v1.6 を使う。 Installing InfluxDB OSS | InfluxData Documentation

まず、yum でインストールするために、influxdb の rpm 取得元として yumリポジトリの追加

$ cat <<EOF | sudo tee /etc/yum.repos.d/influxdb.repo
[influxdb]
name = InfluxDB Repository - RHEL 7
baseurl = https://repos.influxdata.com/rhel/7/\$basearch/stable # 公式では '7' ではなく、'$releasever' を指定しているが Amazon Linux 2 では '$releasever' が '2' になってしまうので '7' に変更する
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key
EOF

インストール&起動

$ sudo yum install influxdb
$ sudo service influxdb start
$ systemctl daemon-reload
$ systemctl enable influxdb # 自動起動を on に
influxdb.service is not a native service, redirecting to /sbin/chkconfig. # systemd サービスではないので、chkconfig にリダイレクトされる
Executing /sbin/chkconfig influxdb on

influxdb の設定ファイルは以下のパスに置かれている。とりあえずデフォルトのままでOK。

$ less /etc/influxdb/influxdb.conf

データ入力・出力

InfluxDB は API を使った入出力と CLI を使った入出力に対応している。 ここでは CLI(influx shell) を使ったデータの入力・出力を試す。 CLI では Influx QL という SQL に近いクエリ言語でデータの入出力を行う。

influx コマンドを利用して influxdb に接続する。precision は timestamp の表示形式を変更するオプション。指定がない場合は timestamp がエポック時間(例:1535166757911702475)で表示されるので rfc3339 形式を指定する。

データベースの作成、確認、利用の手順は mysql などと同じ流れ。

$ influx -precision rfc3339
Connected to http://localhost:8086 version 1.6.1
InfluxDB shell version: 1.6.1
> CREATE DATABASE mydb
> SHOW DATABASES
name: databases
name
----
_internal
mydb
> USE mydb
Using database performance_metrics
>

実際にデータを投入する前に、知っておかねばならない InfluxDB の用語を整理する。

  • measurement: 直訳で「測量」。InfluxDB では mysql などのテーブルに該当する概念を "measurement" と呼ぶ。measurement はスキーマレス。
  • tag: measurement の column。measurement の一レコードに複数の tag をつけることが可能。後述の field との違いとして tag には index が張られる。
  • field: measurement の column。measurement の一レコードに複数の field をつけることが可能。tag と違い、value には index が張られない。
  • series: measurement と tag の組み合わせ。1つの series に 1 つの value を設定するのがよいらしい(index を効かせるためでしょうか?)

mysql などのリレーショナルデータベースとの違いとしては measurement は予め作成しておく必要がなく、スキーマレス(column となる tag, field は任意のタイミングで追加可能)であるということ。

INSERT 構文は次のようになっている

INSERT <measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]
> INSERT cpu,host=serverA,region=us_west value=0.64
>

SELECT は通常の SQL がだいたい使えます。

> select "host", "region", "value" from "cpu"
name: cpu
time                           host    region  value
----                           ----    ------  -----
2018-08-25T03:12:37.911702475Z serverA us_west 0.64
> INSERT cpu,host=serverB,region=us_east value=0.10
> select "host", "region", "value" from "cpu"
name: cpu
time                           host    region  value
----                           ----    ------  -----
2018-08-25T03:12:37.911702475Z serverA us_west 0.64
2018-08-25T03:13:44.479107406Z serverB us_east 0.1
> INSERT cpu,host=serverB value=0.10
> select "host", "region", "value" from "cpu"
name: cpu
time                           host    region  value
----                           ----    ------  -----
2018-08-25T03:12:37.911702475Z serverA us_west 0.64
2018-08-25T03:13:44.479107406Z serverB us_east 0.1
2018-08-25T03:14:13.822910528Z serverB         0.1
> INSERT cpu,host=serverB,region=us_east value=0.10,value2="hoge"
> select * from "cpu"
name: cpu
time                           host    region  value value2
----                           ----    ------  ----- ------
2018-08-25T03:12:37.911702475Z serverA us_west 0.64
2018-08-25T03:13:44.479107406Z serverB us_east 0.1
2018-08-25T03:14:13.822910528Z serverB         0.1
2018-08-25T03:34:49.405686775Z serverB us_east 0.1   hoge

AWS EC2 料金体系(2018年7月)

まとめ

EC2 の代表的な料金体系は次の通り(2018/07/22 時点)

  1. オンデマンド/リザーブド/スポット 料金
  2. データ転送
  3. Amazon Elastic Block Store(EBS)
  4. Elastic IP アドレス
  5. Amazon CloudWatch
  6. Elastic Load Balancing(ELB)

参考:オンデマンドインスタンスの料金 - Amazon EC2 (仮想サーバー) | AWS

1. オンデマンド/リザーブド/スポット 料金

EC2 のインスタンスは「オンデマンド」「リザーブド」「スポット」などに分けられる。

必要なときに必要な分だけ使いたい場合は「オンデマンド」を選ぶ。一定期間の利用を考える場合は「リザーブド」、一定期間かつ特定の時間のみ稼働させるインスタンスは「スポット」を選ぶなど目的に応じて使い分ける。

オンデマンドとスポットは、時間単位(1時間未満は切り上げ)で課金される。 リザーブドは長期利用を目的としているため、前払い or 月単位で課金となる。 時間単価は安い順に リザーブド < スポット < オンデマンド となる。 長期利用を目的とする場合はリザーブドを選択するのが良さそう。 開発・テスト用サーバにはオンデマンドで立てて必要がなくなったらすぐ消すという運用が良さそう。 スポットはバッチサーバに使う。

インスタンスの料金はスペックによって異なるため詳細は省略。

オンデマンドインスタンスの料金 - Amazon EC2 (仮想サーバー) | AWS
料金 - Amazon EC2 スポットインスタンス - Amazon EC2 | AWS
EC2 インスタンス料金 – アマゾン ウェブ サービス (AWS)

2. データ転送

  • EC2 → インターネット(アウト): 1 GB/月 まで無料、0.12USD/GB 〜
  • インターネット → EC2(イン): 無料
  • EC2 → 異なるリージョンへのデータ転送: 0.09 USD/GB
  • Availability Zone1 ↔ Availability Zone2:異なる AZ(Availability Zone)間でのデータ転送はイン・アウトともに 0.01 USD/GB
  • パブリックアドレス or Elastic IPv4 アドレスを利用したデータ転送:0.01 USD/GB
  • 異なる VPCIPv6 アドレスを利用したデータ転送:0.01 USD/GB
  • 同じ AZ 間のデータ転送は 0.00 USD/GB

以上より、データ転送による料金を抑えるには次を守ると良さそう。

  • インターネットへの転送をなるべくしない
  • 利用するデータは同一 AZ のサーバ or RDS or S3 からひっぱる
  • 通信するサーバは同一 AZ におく(耐障害性の観点からは望ましくない)
  • 同一 AZ にあるサーバとの通信はプライベートアドレスを利用する

3. Amazon Elastic Block Store(EBS)

EBS はネットワークストレージの追加サービス。OS 上でマウントすることで追加領域として使うことができる。 GB 単位の月額料金が発生。

料金 - Amazon Elastic Block Store(ブロックストレージ)|AWS

4. Elastic IP(EIP)アドレス

1インスタンスあたり1 EIP まで無料。 追加の IP アドレス or 実行中のインスタンスと関連付けられていない Elastic IP アドレスあたり 0.005 USD/時間。

5. Amazon CloudWatch

EC2 のモニタリングサービス。メトリクス集計やアラーム機能などがある。 無料枠+α で使った分だけ従量課金。

料金 - Amazon CloudWatch | AWS

6. Elastic Load Balancing (ELB)

Elastic Load Balancing は、アプリケーションへのトラフィックを複数のインスタンスに負荷分散させるサービス。 以下の3つの種類がある。

  • Application Load Balancer
  • Network Load Balancer
  • Classic Load Balacer

料金体系はどれもロードバランサーの稼働時間あたりの料金+トラフィックによる従量課金。

料金 - Elastic Load Balancing | AWS

AWS EC2 チュートリアルのメモ

EC2 のドキュメントにあるチュートリアルをやった際のメモ Linux を実行する Amazon EC2 インスタンスのチュートリアル - Amazon Elastic Compute Cloud

Amaxon Extras Library について

MariaDB, php のインストールに amazon-linux-extras コマンドを使った。

$ sudo amazon-linux-extras install lamp-mariadb10.2-php7.2 php7.2

amazon-linux-extras コマンドによって「Amazon Extras repo」の追加とパッケージ(トピック)のインストールが行われる。 実際に、/etc/yum.repos.d を見ると repo ファイルが生成されていた。

$ ls /etc/yum.repos.d/amzn2-extras.repo
/etc/yum.repos.d/amzn2-extras.repo

amazon-linux-extras コマンドで、ruby, golang, emacs, memcached, nginx, postgres, redis, vim, emacs などをインストールすることができる模様。

$ sudo amazon-linux-extras list
  0  ansible2                        available  [ =2.4.2 ]
  1  emacs                           available  [ =25.3 ]
  2  memcached1.5                    available  [ =1.5.1 ]
  3  nginx1.12                       available  [ =1.12.2 ]
  4  postgresql9.6                   available  [ =9.6.6  =9.6.8 ]
...

参考: Amazon Linux - Amazon Elastic Compute Cloud

Fluentd (v1.0) Quickstart Guide をやってみた

docs.fluentd.org

公式サイトに従って、Quickstart Quide をやってみる。

fluentd のバージョンは v1.0 を使う。

Quickstart は以下の3ステップで構成される。

Step 1: Installing Fluentd
Step 2: Use Cases
Step 3: Learn More

Step 1: Installing Fluentd

Installing Fluentd Using Ruby Gem | Fluentd

install & setup

$ mkdir fluentd_quickstart # working directory の作成
$ cd fluentd_quickstart
$ gem install fluentd --no-ri no-rdoc # fluentd のインストール
$ fluentd --setup ./fluent # 設定ファイル(./fluent/fluent.conf )の生成

daemon 起動

# バックグラウンド で fluentd を起動
# -c 設定ファイルの指定
# -vv verbose
$ fluentd -c ./fluent/fluent.conf -vv & # バックグラウンド

動作確認

$ echo '{"json":"message"}' | fluent-cat debug.test
# 以下のメッセージが表示される
2018-02-26 14:32:19.831807000 +0900 debug.test: {"json":"message"}

daemon 終了

$ pkill -f fluentd # fluentd プロセスの kill

Step 2: Use Cases

実例を見る前に Step 1 で何がどうなってログが表示されたかわからないので設定ファイルの詳細を見てみる。

Configuration File Syntax | Fluentd

SlideShare による概要説明があった。

  1. 全ての Fluentd のイベントでは一つの入力に一つの tag が対応する
  2. Fluentd は tag が match するかどうかで出力先を判定
  3. match した出力にイベントが送られる
  4. Fluentd は複数の input、複数の output をサポートする
  5. Fluentd は受け取ったイベントを新しい tag を付けて、自分に再送信する(フィルタ機能)ことも可能

www.slideshare.net

続けて、設定ファイルは以下のディレクティブから構成されるとの説明。 これらのディレクティブについて見ていく。

1. source directives determine the input sources.
2. match directives determine the output destinations.
3. filter directives determine the event processing pipelines.
4. system directives set system wide configuration.
5. label directives group the output and filter for internal routing
6. @include directives include other files.

source

入力ソースを指定するディレクティブ。 @type に入力プラグインを指定する。 入力プラグインは in_xxxx と呼ばれる。 (出力プラグインは out_xxxx と呼ばれる)

なお、@ プレフィクス付きの項目はシステムの設定値、@ なしの項目は指定したプラグインの設定値を表す。

設定例 1. in_forward

設定例

## built-in TCP input
## $ echo <json> | fluent-cat <tag> 
<source>
  @type forward
  @id forward_input
</source>

type: forward の指定で、in_forward プラグインを利用する("in_" は不要)。 in_forward では TCP のエンドポイントで out_forward プラグイン(後述)が送信する形式の TCP パケットを待ち受ける。 Step.1 で利用した fluent-cat は out_forward 形式の TCP パケットを内部で構築して fluentd に送信しているということだ。

port 番号など、その他の設定値はこちらから。

forward Input Plugin | Fluentd

設定例 2. in_http

in_http プラグインでは HTTP でデータを待ち受ける。

設定例

# HTTP input
# http://localhost:8888/<tag>?json=<json>
<source>
  @type http
  @id http_input

  port 8888
</source>

動作確認

# 前提:Step.1 で fluentd が起動されていること
$ curl -X GET -d 'json={"message":"using in_http with GET"}' http://localhost:8888/debug.in_http
$ curl -X POST -d 'json={"message":"using in_http with POST"}' http://localhost:8888/debug.in_http
# stdout に GET, POST で送信したログが表示される
2018-02-26 16:09:38.238439000 +0900 debug.in_http: {"message":"using in_http with POST"}
2018-02-26 16:09:41.237832000 +0900 debug.in_http: {"message":"using in_http with GET"}

その他の設定値はこちらから。

HTTP Input Plugin | Fluentd

設定例 3. in_tail

in_tail はファイルの末尾からイベントを読み取る。 ファイルが追記されたらイベント発火とみなす。

tail Input Plugin | Fluentd

設定例

## File input
## read apache logs with tag=apache.access
#<source>
#  @type tail
#  format apache
#  path /var/log/httpd-access.log
#  tag apache.access
#</source>

format にログの形式を指定する。 標準で apache, syslog, nginx, json, csv などの形式に対応している

format による指定は古い設定方法になっており、v1.0 では parse プラグインとして 内で指定することが推奨されている。

Parser Plugin Overview | Fluentd

parse プラグインを指定した書き方は下記の通り。

## File input
## read apache logs with tag=apache.access
#<source>
#  @type tail
#  <parse>
#    @type apache
#  </parse>
#  path /var/log/httpd-access.log
#  tag apache.access
#</source>

in_tail プラグインの使用に際しては pos_file という設定値の指定が推奨されている。 fluetnd がファイルの何行目までを読んだかを pos_file に記録しており、fluentd が終了・再起動した際に pos_file がないとファイルの先頭から全てのイベントが再発火されてしまう。

source のまとめ

source では入力ソースを指定する。 source の中の3種類のタイプ(forward, http, tail)を紹介した。 その他の input plugin については下記のリンクから。

Input Plugin Overview | Fluentd

なお、入力プラグインは独自で作成することも可能。

match

match ではタグによって出力先を決定する。 @type に出力プラグインを指定する。 出力プラグインは out_xxxx と呼ばれる。

match で使う正規表現は以下のパターンがある。

* matches a single tag part.
** matches zero or more tag parts.
{X,Y,Z} matches X, Y, or Z, where X, Y, and Z are match patterns.

match には複数のパターンを組み合わせることも可能だし、複数のパターンを条件の OR として使うことも可能。

設定例 1. out_stdout

out_stdout はその名の通り stdout にイベントを出力する。 tag が debug.**(ゼロ個以上の任意のタグ列) にマッチすると、stdout にイベントを出力するようにする設定は次のようになる。

設定例

## match tag=debug.** and dump to console
<match debug.**>
  @type stdout
  @id stdout_output
</match>

設定例 2. out_forward

out_forward は TCP でログを送信する。 送信先は fluentd の in_forward が一般的(かな?)

設定例

# match tag=system.** and forward to another fluent server
<match system.**>
  @type forward
  @id forward_output

  <server>
    host 192.168.0.11
  </server>
  <secondary>
    <server>
      host 192.168.0.12
    </server>
  </secondary>
</match>

<server></server> で指定されたホストにデータを送る。もし、データの送信に失敗した場合は Secondary Output の設定が使われる。

Output Plugin Overview | Fluentd

match 順について

一つのイベントは最大一つにマッチする。 マッチ順は config ファイルの先頭から先に行われ、一度マッチした場合はその後の match ディレクティブをチェックすることはない。 イベントを複数の出力先に送りたい場合は out_copy プラグインを使うことを検討する。

out_copy では複数の出力先を指定することが可能。

copy Output Plugin | Fluentd

match まとめ

match は出力ソースを指定する。 match の中の2種類のタイプ(stdout, forward)を紹介した。 その他の output plugin については下記のリンクから。

Output Plugin Overview | Fluentd

入力プラグインと同様に出力プラグインも独自で作成することが可能。

filter

フィルタ処理を記載するディレクティブ。 filter は match と同じ syntax を持つが、filter はチェーンされる。

Input -> filter1 -> ... -> filterN -> output

設定例 1. record_transformer

record_transformer では、イベントに対して新たな key-value を追加したり、修正、削除ができる。

設定例

## Mutating event filter
## Add hostname and tag fields to apache.access tag events
#<filter apache.access>
#  @type record_transformer
#  <record>
#    hostname ${hostname}
#    tag ${tag}
#  </record>
#</filter>

record ディレクティブには追加/修正する key-value を記載する。 (上記例での tag フィールドの追加は不要な気がするが何か意味があるのだろうか・・・?)

上記例では利用していないが、remove_keys で削除する key の一覧を指定することもできる。

設定例 2. grep

その名の通り、特定のフィールドにある文字列が含まれたり含まれなかったりすることを条件にイベントの取捨選択ができる。

grep Filter Plugin | Fluentd の例

<filter foo.bar>
  @type grep
  <regexp>
    key message
    pattern cool
  </regexp>
  <regexp>
    key hostname
    pattern ^web\d+\.example\.com$
  </regexp>
  <exclude>
    key message
    pattern uncool
  </exclude>
</filter>

regexp ディレクティブでは、key に指定したフィールドが pattern で指定した正規表現にマッチしたイベントを後続に渡す。 exclude ディレクティブでは、key に指定したフィールドが pattern で指定した正規表現にマッチしたイベントは後続に渡さない。

regexp, exclude は上記例のように複合条件として一つの filter ディレクティブに記述できる。

filter まとめ

filter ができることは大きく次の3通り。

  1. 一つまたは複数のフィールドの値でイベントをフィルタ(grep)する
  2. 新しいフィールドを追加することによって、イベントを拡張する
  3. プライバシー保護やコンプライスのために、フィールドを削除したりマスクする。

Filter Plugin Overview | Fluentd

system

次のシステムの設定を設定できる。

- log_level
- suppress_repeated_stacktrace
- emit_error_log_interval
- suppress_config_dump
- without_source
- process_name

設定例

<system>
  # equal to -qq option
  log_level error
  # equal to --without-source option
  without_source
  # ...
</system>

label

label は内部のルーティングのために filter と output をグルーピングする。

設定例

<source>
  @type tail
  path /var/log/production.log
  tag system.log
</source>

<source>
  @type tail
  @label @STAGING
  path /var/log/staging.log
  tag system.log
</source>

<filter **>
  @type grep
  #...
</filter>
<match **>
  @type forward
  #...
</match>

<label @STAGING>
  <filter **>
    @type grep
    #...
  </filter>
  <match **>
    @type forward
    @id staging_forward_output
    <server>
      host 192.168.0.101
    </server>
  </match>
</label>

staging と本番環境で出力するログファイルを分ける時に、@STAGING でラベルされた in_tail による入力イベントは @STAGING 用の filter, match で処理が行われる。

使用用途としては、tag の prefix を使わずにイベントのフローを分離する時に役に立つ。

include

@include ディレクティブでは、外部の設定ファイルを読み込むことができる。 指定できるのは以下のパターン

  • ファイルパス
  • ファイルパス(glob パターン)
  • http URL

設定例

# absolute path
@include /path/to/config.conf

# glob match pattern
@include config.d/*.conf

# http
@include http://example.com/fluent.conf

設定ファイルの syntax チェック

設定ファイルの形式が誤っていると fluentd が起動できないので、起動前に dry-run で設定ファイルの形式に誤りがないかチェックすることができる。

$ fluentd --dry-run -c fluent.conf

Step 3: Learn More

Step 3 は Fluentd の詳細について学ぶステップになっている。 ここまでのステップで input/output/filter plugin についてはなんとなく理解できたので、残りの項目としては次のようなものがある。 この辺りは各自読んでもらいたい。

まとめ

Fluentd v1.0 の Quickstart guide をやりました。 Quickstart を通して、Fluentd で何ができるかがだいたいわかった気がします。 Fluentd を使うことによって簡単に・柔軟に・多目的なイベントが扱えるようになるという印象です。

VLDB 2017 の論文メモ

VLDB 2017 の論文メモ(編集中

Mostly-Optimistic Concurrency Control for Highly Contended Dynamic Workloads on a Thousand Cores

MOCC (Mostly-Optimistic Concurrency Control) という方式の CC (Concurrency Control = 並行性制御) についての論文。

MOCC は OCC と PCC のいいとこ取りをしたような CC。 通常は OCC のように振る舞うが、conflict 可能性が高いデータへの読み書きは PCC のように read/write ロックを獲得する。 conflict の可能性が高いというのは、これまでのトランザクションでアボート率が高い、またはリトライするトランザクション(最終的にアボートになったもの)で前に読み書きしていたデータのどちらかを指している。

PCC は global order でロックを獲得しないため本質的にデッドロックの可能性がある。 MOCC では conflict の可能性が高いデータに対しては PCC のように読み書きの前に read/write ロックを獲得するが、もし global order に違反した順番でロックを獲得しようとした場合、違反しているロックを解放(=キャンセル)して、該当のロックを獲得する。これにより global order でロックを獲得するというポリシーが保たれるためデッドロックが発生しない。ただし、違反してキャンセルしなければならないロックが多すぎる場合は、キャンセル処理自体が高コストなためロックの獲得を一か八か試みて獲得成功したら続行、獲得失敗(デッドロックの可能性があるという判断)したらアボートする。 獲得したロックを解放するというのは 2PL の原理に違反するため PCC では correctness が保証されない。しかし、MOCC では最終的にコミット可能かどうかを判断は最後の validation フェーズで行うため、途中でロックを解放しても correctness が保証される。

すなわち、MOCC は括りとしては OCC。トランザクションの途中でロックを獲得しているが、2PL と違ってロックの獲得によって correctness を保証しようとしているわけではなく、アボートを防ぐためにロックを獲得するのである。

MOCC を使った結果、read-only トランザクションにおいては OCC と同等の性能(MOCC によるオーバーヘッドがほぼない)。 write ありのトランザクションについては abort 率が改善されることにより、OCC よりも高い性能を示す。

(感想) MOCC は性能面においては最強の CC なように思う。 マイナス面としては理論的な理解の難さと実装の複雑さである。

以下、CC ってなんぞやという人のための補足

代表的な CC としては PCC と OCC がある。

PCC は比較的 traditional なデータベースシステムなどで用いられる。 PCC はデータを読み書きする前に read/write ロックの取得を試みて、ロックの競合がある状態ではそれ以上処理を進めない(ロックが獲得できるまで待機 or アボート)。代表的な PCC は 2PL (2-Phase Locking) 。

OCC はひとまずデータを読み書きしてみて(ここでの書き込み先はローカル変数)、最後に conflict があるかどうかをチェックし、conflict があればアボート、なければコミット(グローバルなデータに実際に書き込む)する。 OCC ではトランザクションの最後に write ロックを global order で獲得し、 read ロックは取得はしない。 read ロックを取得しない代わりに validation フェーズで conflict がないかチェックすることで correctness を保証する。

マルチコア、マルチソケットの環境においては、並行性制御は PCC(Pesimistic CC = 悲観的並行性制御)ではなく OCC (Optimistic CC = 楽観的並行性制御) が良いとされる。 PCC は read でもロックを獲得するためキャッシュの invalidation が発生し、read-only transaction で性能がスケールしない。

BlueCache: A Scalable Distributed Flash-based Key-value Store

PaxosStore: High-availability Storage Made Practical in WeChat

State Management in Apache Flink

Samza: Stateful Scalable Stream Processing at LinkedIn

An Empirical Evaluation of In-Memory Multi-Version Concurrency Control

Write-Behind Logging

永続ストレージ上のテーブル領域を更新してから、どこまでコミットしたかという情報をログに書いて永続化するという Write-Behind Logging(WBL)というロギング方式の提案。 Write-Ahead Logging(WAL)では、永続ストレージ上のテーブル領域に書き込む前に、変更内容を記載したログを永続化する。 論文で指摘されている WAL の欠点はログの書き込みとテーブル領域へのデータの書き込みが二重で発生する点。 WAL はシーケンシャルライトで一度に書き込めるので HDD の書き込み特性に適しているが NVM ではランダムライトがシーケンシャルライトと同等の性能を持つのでより効率的な方法が考えられる。

論文で前提とする DBMS は steal かつ MVCC である。 その前のトランザクションの変更が全て永続ストレージに記録されている最新のコミット済みトランザクションのコミット timestamp (cp) と 次のグループコミットの完了前はどのトランザクションにも割り当てられない commit timestamp cd (cp < cd) をログに記録する。 ∀ c < cp の commit timestamp c を持つトランザクションはコミット済みとみなすことができる。 一方、∀ c > cp ∧ c < cd の commit timestamp c を持つトランザクションは永続ストレージ上のテーブル領域に追記(Multi-version なので上書きはされない)されているが、コミット扱いとはみなされない。System Failer 後の restart recovery 後にその更新はなかったものとみなされる。

(感想とか疑問点) MVCC で過去のバージョンが参照できるから、直接 durable なテーブル領域にデータを追記して、後からログを書いてコミット確定する方式は PCMLogging[どこか] などいくつか提案されているうちの一つ。 ただ、いちばん大事な cp, cd の具体的な算出方法が書いていなくて非常にモヤモヤした。 cd は普通に(コミット直前で)計算されるコミットタイムスタンプのことかなと思ったけど、独特な言い回しがしっくりきていないので外れている気がする…。cp はまともに計算するのが大変だから、Silo というシステムでは epoch を使ってどこまでは少なくともコミットされているか(≒どこまでクライアントに結果を返してよいか)を管理していたりするんだけど、この論文では各ワーカー w の最小コミット済みトランザクションの timestamp を c_w とすると、cp = min(c_w) みたいな感じで計算しているのかなあ?これやるとワーカー数増えた時にしんどくなりそう。 「ロングトランザクションのケースだと cp が increment できないから、コミットタイムスタンプをログに記録する」みたいなことが書いてあって、この「コミットタイムスタンプ」って cd とはまた違うんだよね、きっと。自分の知識不足はおいといて、肝となる部分が説明されていない、論文中の具体例がない(あっても説明がなくてよく分からない)、で本当に大丈夫か?という論文でした。