この記事の要点
- OpsWorksでfluentdをインストール・設定する方法
- IPアドレスを固定できない中、どうやって転送先のサーバを指定するか
- Ruby on Rails 4.2でfluentdにログを送るには
方針
- VPC使います。
- 手順はカスタムCookbookでコード化する
- 設定の使い分け
- カスタムJSON
- 環境によって変わる値(ステージングか、本番かなど)
- カスタムCoookbookの
opsworks/attributes/default.rb
- 決め打ちしたい設定値
- Appsの環境変数(Environment Variables)
- Railsアプリの設定、秘密情報など
- カスタムJSON
前提: カスタムCookbook
設定操作などをコード化するためにカスタムCookbookを使います。
カスタムCookbookの設定について
スタック設定でUse custom Chef cookbooks
をYes
にします。
リポジトリにGitHubを使う場合はssh://git@ssh.github.com:443/hoge/fuga.git
のようにします。普通外向きの22番ポートは開けないので443番ポートを使います。
また、カスタムCookbookは1つしか指定できないので、ほかのCookbookを使えるようにするために、Manage Berkshelf
をYes
にしておきます。
こうすることでBerksfileに記載したCookbookを使えるようになります。
OpsWorksでfluentdをインストールする
公式のCookbookを使います。
これを使うことで、fluentdのインストールだけでなく、設定もChefのレシピで書けるようになります。
サーバーとクライアント
fluentdでログを収集する場合、ログを集約するサーバーと、自ホスト内のログをとりまとめてサーバーに送るクライアント(?という表現でよいでしょうか)を用意するのが一般的かと思います。
OpsWorksでサーバーとクライアントそれぞれの設定を行うために、今回はレイヤーを使うことにしました。
具体的にはFluentd Server Layer
を用意し、そのレイヤーが設定されたインスタンスにはサーバー向けの設定、その他のインスタンスではクライアント向けの設定を行うようなレシピを書くことにしました。
BigQueryに蓄積する
fluent-plugin-bigqueryを使いました。
それとは別に
- APIの利用登録
- bqコマンドでデータセットの作成
- Google API ConsoleでGCEサービスアカウントJSONキーの取得
など行っておきます。
サーバーの指定
プライベートIPアドレスを固定できればそれで指定してやるのが楽ですが、OpsWorksでは指定できません。そこで、
- Route53のPrivate DNS機能をVPC内で名前解決できるようにする
- インスタンス起動時に自身のホスト名とプライベートIPアドレスをRoute53のAレコードに登録
とすることにしました。
こうすることでサーバーの指定をlog.stackname.yourdomain.local
のような形で設定に記述でき、プライベートIPアドレスが変化しても自動的に追従できます。
VPCでPrivate DNSを使うには以下の記事が参考になるので適当に設定します。
Route53編~Private DNS~ | ナレコムAWSレシピ
OpsWorksで起動時にRoute53のAレコードを設定するには、route53を使って自分で書くか、あるいはopsworks_route53などを使えば簡単です。
なお、インスタンスのIAM RoleにRoute 53の設定を触れる権限が必要です。(通常 aws-opsworks-ec2-role に AmazonRoute53DomainsFullAccess AmazonRoute53FullAccess あたりを設定すればとりあえず動くはずです。)
Ruby on Rails 4.2でfluentdにログを送る
act-fluent-logger-railsを使いました。
Railsからはローカルホストのfluentdにしかるべきタグを付けて送るだけです。
実装
カスタムJSON(Stack)
{
"fluentd_server":{
"gce_project_id": "BigQuery使うプロジェクトID",
"gce_service_json": "サービスアカウントJSONキーの内容",
"host":"log-server1.stackname.yourprivatedomain.local",
"port":24224
},
"opsworks_route53":{
"domainname":"yourprivatedomain.local",
"prepend_stack_name":true,
"zone_id":"XXXXXXXXXXXXX"
}
}
setup等のレシピ内で使用する設定で、opsworks/attributes/default.rb
に含められない内容をここで設定します。
カスタムCookbook
今回は
- Setup opsworks::setup
- Configure opsworks::configure
- Deploy opsworks::deploy
を使いました。
Berksfile
source 'https://supermarket.chef.io'
# (snip)
cookbook 'td-agent', '~> 2.2.0'
cookbook 'opsworks_route53', git: 'https://github.com/verdigris-cookbooks/opsworks-route53.git'
td-agent
およびopsworks_route53
クックブックを使うのでその指定を追加しました。
opsworks/metadata.rb
name 'opsworks'
maintainer 'Yuichi Takeuchi'
maintainer_email 'info@takeyu-web.com'
license 'All rights reserved'
description 'Installs/Configures base'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.1.0'
depends 'td-agent' # これと
depends 'opsworks_route53' # これ
dependsを指定してデフォルトのattributesを読み込むようにします。
opsworks/attributes/default.rb
default[:td_agent][:plugins] = [
'bigquery'
]
default[:td_agent][:includes] = true
fluent-plugin-bigquery
を使うのでその指定と、追加の設定を/etc/td-agent/conf.d
に置く設定を追加しました。この設定についてはこのへん。
opsworks/recipes/setup.rb
# (snip)
# fluentd server and client
include_recipe 'td-agent'
is_log_server = node[:opsworks][:instance][:layers].select { |layer| layer.match(/\Afluentd-server\z/) }.any?
if is_log_server
td_agent_match 'myapp' do
type 'bigquery'
tag 'myapp'
params(
method: 'insert',
auth_method: 'json_key',
json_key: '/etc/td-agent/service_account.json',
project: node[:fluentd_server][:gce_project_id],
dataset: 'myapp',
auto_create_table: true,
table: 'rails_%Y%m%d',
time_format: '%s',
time_field: 'time',
field_integer: 'time',
field_string: 'messages,ip,ua,uid'
)
end
file '/etc/td-agent/service_account.json' do
action :create
mode '0600'
owner 'td-agent'
group 'td-agent'
content node[:fluentd_server][:gce_service_json]
end
else
td_agent_match 'myapp' do
type 'forward'
tag 'myapp'
params(
method: 'insert',
flush_interval: '60s',
send_timeout: '60s',
heartbeat_type: 'udp',
heartbeat_interval: '1s',
server: [
{
host: node[:fluentd_server][:host],
port: node[:fluentd_server][:port]
}
],
secondary: [
{
type: 'file',
path: '/var/log/td-agent/forward-failed'
}
]
)
end
end
インスタンスセットアップ時にfluentdをインストールして、インスタンスがFluentd Serverレイヤーかどうかでそれぞれサーバ向けの設定とクライアント向けの設定ファイルを作ります。
opsworks/recipes/configure.rb
# (snip)
include_recipe 'opsworks_route53'
opsworks_route53::default
を実行するだけで、インスタンス名.スタック名.ドメイン名
(例 log-server1.stackname.yourprivatedomain.local
)をRoute53にAレコードを登録してくれます。便利。
opsworks/recipes/deploy.rb
# (snip)
node[:deploy].each do |application, deploy|
next unless deploy[:application_type] == 'rails'
template "#{deploy[:deploy_to]}/current/config/fluent-logger.yml" do
source 'fluent-logger.yml.erb'
action :create
mode '0660'
owner deploy[:user]
group deploy[:group]
variables(
rails_env: deploy[:rails_env]
)
end
end
Railsアプリのデプロイの際に、act-fluent-logger-railsの設定を置くことにしました。
opsworks/templates/default/fluent-logger.yml.erb
<%= @rails_env %>:
fluent_host: '127.0.0.1'
fluent_port: 24224
tag: 'myapp'
messages_type: 'string'