fluentd + AWS PrivateLinkでAWSのログ収集をサービス化する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

大栗です。

PrivateLinkはサービス独自のVPCエンドポイントを構築できるので、マイクロサービスなどを提供しやすくなります。マイクロサービスでは機能要件を基本に論じられることが多いですが、非機能要件でもサービス化できると思いログ収集をPrivateLinkでサービス化してみました。

概要

図のような構成を考えてみます。右のVPCにAggregatorとなるfluentdをPrimaryとSecondaryとしてMulti-AZに構築します。それぞれをPrivateLinkで各VPCと接続します。

Forwarder側のポイント

PrivateLinkではアカウントをまたがってサービスを提供できるのでアカウントIDやVPC IDをAggregatorに知らせるべきです。fluent-plugin-ec2-metadataを使ってレコードに追加することを検討しましょう。

また、PrivateLinkはAZ毎のエンドポイントに名前が付きます。ログの集約を目的としている場合は分散させたくないのでforward先をリージョンのエンドポイントではなくAZのエンドポイントを使用してActive-Standbyの構成にしましょう。

Aggregator側のポイント

ログの処理方法によりNLBのクロスゾーン負荷分散を有効にするかを検討しましょう。処理能力の向上を求める場合はクロスゾーン負荷分散を有効にして、集約を行う時にはクロスゾーン負荷分散を無効にしてAZ毎にAggregatorインスタンスを配置しましょう。

今回は集約を目的とするのでクロスゾーン負荷分散を無効にしてActive-Standbyの構成にします。

やってみる

以下の順に設定します。

  • Aggregatorの設定
  • PrivateLinkの設定
  • Forwarderの設定

前提として以下の環境で行います。

  • リージョン:東京
  • OS:Amazon Linux 2 LTS Candidate
  • fluentd: v1.0系(td-agent3を使用)

Aggregatorの構築

こちらに従ってAmazon Linux 2にtd-agentをインストールします。

$ curl -L https://toolbelt.treasuredata.com/sh/install-amazon2-td-agent3.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   851  100   851    0     0    851      0  0:00:01 --:--:--  0:00:01  1658
==============================
 td-agent Installation Script
==============================
・
・
・
完了しました!

Installation completed. Happy Logging!

td-agentの設定ファイルを編集します。ここでは普通にforwardで受けます。タグはblog.<ログ名>.<アカウントID>.<VPC-ID>の形式を前提とします。

####
## Output descriptions:
##

<match blog.**>
  @type file
  path /var/log/blog/file/var-log-${tag[1]}-${tag[2]}-${tag[3]}
  flush_interval 10s
  time_slice_format %Y%m%d
  time_slice_wait 10m
  time_format %Y%m%dT%H%M%S%z
  <format>
    @type ltsv
  </format>
  <buffer tag>
    @type file
    path /var/log/blog/buf/var-log.buf
    timekey 1m
    timekey_use_utc true
    timekey_wait 10
  </buffer>
</match>

####
## Source descriptions:
##

<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

ログの出力先も作成しておきます。

$ sudo mkdir /var/log/blog
$ sudo chown td-agent:td-agent /var/log/blog

td-agentを自動起動にして開始します。

$ sudo systemctl enable td-agent.service
Created symlink from /etc/systemd/system/multi-user.target.wants/td-agent.service to /usr/lib/systemd/system/td-agent.service.
$ sudo systemctl start td-agent.service

別AZにもう1台td-agentのAggregatorを構築します。これで外部からログを受け付けられます。

PrivateLinkの設定

NLBを設定してPrivateLinkを設定します。

まずはNLBを設定します。以下の内容を元に設定してください。ポイントはポートを24224にする事と2台のAggregatorをターゲットグループに入れることです。

AWS PrivateLinkで異なるAWSアカウント間の重複するVPCレンジ間で通信してみる(その1:NLB作成) #reInvent

NLBを設定してしばらくするとターゲットのAggregatorがhealthyになります。

次にAggregatorのNLBをエンドポイントサービスとして登録します。

エンドポイントサービスの作成をクリックします。

前項で作成したNLBを選択して登録します。

ここで作成したサービスのサービス名をメモしておきます。

次にエンドポイントを作成します。複数アカウントがある場合は、Forwarderがあるアカウントで操作してください。

エンドポイントの作成をクリックします。

サービスカテゴリでサービスを名前で検索を選択して、サービス名を入力し検証ボタンをクリックして検証します。

『サービス名が見つかりました。』となったら、接続先のVPCとエンドポイントを作成するサブネットを選択します。それとエンドポイントに設定するセキュリティグループを選択します。「プライベート DNS 名を有効にする」については「サービスでサポートされていません」と表示されますが気にしないでください1

エンドポイントのサービスの画面から作成したエンドポイントの接続リクエストを承諾します。しばらく経つと利用可能になります。

これでForwarder側からAggregatorにアクセスできるようになりました。

Forwarderの設定

最期にForwarderの設定を行います。

エンドポイントのDNS名を確認すると3個表示されています。これはリージョン単位のエンドポイントと各AZのエンドポイントとなります。

No. DNS名 備考
1 <エンドポイントID>-<ランダムな英数字>.<エンドポイントサービスID>.<リージョンID>.vpce.amazonaws.com リージョンのエンドポイント。
2 <エンドポイントID>-<ランダムな英数字>-<AZコード>.<エンドポイントサービスID>.<リージョンコード>.vpce.amazonaws.com 各AZのエンドポイント。エンドポイントで有効にしたAZ毎に作成される。

Forwarder側のEC2(Amazon Linux 2)でtd-agentをインストールします。

$ curl -L https://toolbelt.treasuredata.com/sh/install-amazon2-td-agent3.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   851  100   851    0     0    851      0  0:00:01 --:--:--  0:00:01  1658
==============================
 td-agent Installation Script
==============================
・
・
・
完了しました!

Installation completed. Happy Logging!

AWSの情報を取得するためにfluent-plugin-ec2-metadataもインストールします。

$ sudo /sbin/td-agent-gem install fluent-plugin-ec2-metadata
Fetching: aws-sdk-ec2-1.1.0.gem (100%)
Successfully installed aws-sdk-ec2-1.1.0
Fetching: fluent-plugin-ec2-metadata-0.1.2.gem (100%)
Successfully installed fluent-plugin-ec2-metadata-0.1.2
Parsing documentation for aws-sdk-ec2-1.1.0
Installing ri documentation for aws-sdk-ec2-1.1.0
Parsing documentation for fluent-plugin-ec2-metadata-0.1.2
Installing ri documentation for fluent-plugin-ec2-metadata-0.1.2
Done installing documentation for aws-sdk-ec2, fluent-plugin-ec2-metadata after 9 seconds
2 gems installed

td-agentの設定ファイルを編集します。ここでは/var/log/messagesの内容を送信します。ここで送信先を1aをPrimaryにして1cをstandbyにしています。

<source>
  @type tail
  path /var/log/messages
  pos_file /var/log/link/var-log-messages.pos
  tag blog_source.message
  format syslog
</source>

<match blog_source.*>
  @type ec2_metadata
  output_tag blog.${tag_parts[1]}.${account_id}.${vpc_id}
  <record>
    account_id         ${account_id}
    vpc_id             ${vpc_id}
    availability_zone  ${availability_zone}
    instance_id        ${instance_id}
    private_ip         ${private_ip}
  </record>
</match>

<match blog.**>
  @type forward
  send_timeout 60s
  recover_wait 10s
  heartbeat_interval 3s
  phi_threshold 5
  hard_timeout 60s
  flush_interval 10s
  <buffer tag>
    @type file
    timekey 1m
    path /var/log/link/buf/var-log-${tag[1]}-${tag[2]}-${tag[3]}.buf
    timekey_use_utc true
    timekey_wait 10
  </buffer>
  <server>
    name PrivateLink-1
    host vpce-00000000000000000-xxxxxxxx-ap-northeast-1a.vpce-svc-99999999999999999.ap-northeast-1.vpce.amazonaws.com
    port 24224
    weight 60
  </server>
  <server>
    name PrivateLink-2
    host vpce-00000000000000000-xxxxxxxx-ap-northeast-1c.vpce-svc-99999999999999999.ap-northeast-1.vpce.amazonaws.com
    port 24224
    weight 60
    standby
  </server>
</match>

td-agentを起動してログを送信します。

$ sudo systemctl enable td-agent.service
Created symlink from /etc/systemd/system/multi-user.target.wants/td-agent.service to /usr/lib/systemd/system/td-agent.service.
$ sudo systemctl start td-agent.service

動作をみる

Aggregatorの1aのインスタンスを確認すると、以下のように出力されます。

# ls -al /var/log/blog/file/
合計 12
drwxr-xr-x 2 td-agent td-agent  171  4月 25 10:21 .
drwxr-xr-x 4 td-agent td-agent   29  4月 19 06:18 ..
-rw-r--r-- 1 td-agent td-agent  228  4月 25 10:17 var-log-message-111111111111-vpc-aaaaaaaa_0.log
-rw-r--r-- 1 td-agent td-agent  717  4月 25 10:18 var-log-message-111111111111-vpc-aaaaaaaa_1.log
-rw-r--r-- 1 td-agent td-agent 1779  4月 25 10:21 var-log-message-111111111111-vpc-aaaaaaaa_2.log

ログを見ると、以下のように/var/log/messageの内容が出力されています。

host:ip-10-0-100-117	ident:dhclient	pid:2950	message:XMT: Solicit on eth0, interval 114660ms.	account_id:111111111111	vpc_id:vpc-aaaaaaaa	availability_zone:ap-northeast-1a	instance_id:i-12345678901234567	private_ip:10.0.100.117

ここで、1a側のtd-agentを停止してみます。

# sudo systemctl stop td-agent.service

するとForwarder側のtd-agentのログに以下のように出力があり、Standbyに切り替わった事が分かります。

2018-04-25 10:34:04 +0000 [warn]: #0 detached forwarding server 'PrivateLink-1' host="vpce-00000000000000000-xxxxxxxx-ap-northeast-1a.vpce-svc-99999999999999999.ap-northeast-1.vpce.amazonaws.com" port=24224 phi=6.068021942130376 phi_threshold=5
2018-04-25 10:34:04 +0000 [warn]: #0 using standby node vpce-00000000000000000-xxxxxxxx-ap-northeast-1c.vpce-svc-99999999999999999.ap-northeast-1.vpce.amazonaws.com:24224 weight=60

Aggregatorの1cのインスタンスでログを確認すると、以下のようにログが出力されます。

$ ls -al /var/log/blog/file/
合計 4
drwxr-xr-x 2 td-agent td-agent  61  4月 25 10:35 .
drwxr-xr-x 4 td-agent td-agent  29  4月 23 11:08 ..
-rw-r--r-- 1 td-agent td-agent 228  4月 25 10:35 var-log-message-111111111111-vpc-aaaaaaaa_0.log

さいごに

PrivateLinkはマイクロサービスの基盤として利用する事が多いと思いますが、今回はログのプラットフォームを提供してみました。ネットワークのCIDR重複などを考えなくて良いので、複数の組織のまたがる環境では有用だと思います。同様に監視などもサービス化できそうです。

PrivateLinkでネットワークを分離することで柔軟にシステムを構築できますね。


  1. プライベート DNSはAWS のサービスと AWS Marketplace のパートナーサービスの場合に有効化できます。