Ruby審議

Rubyに限らず色んなこと

Kibana + elasticsearch + fluent + fluent-agent-liteでNginxのログを集計して可視化するまで

はじめに

Kibana環境の構築 → NGNIXのログを集計 → 可視化のところまでの覚書 * Ruby on Rails 4.2 ← こいつのアクセスログを可視化 * NGINX (Latest) * Unicorn (Latest) * Mysql (Latest)

手順

ログ送信側

  • 1.NGINXのログ出力設定
  • 2.アクセスログを拾って集計サーバーへ転送(今回はローカルに転送)

ログ集計側

  • 1.転送されてきたログの受信
  • 2.ログをパースしてelasticsearchへ転送
  • 3.elasticsearchの設定
  • 4.kiabanを使ってelasticsearchのログを可視化

ローカル

  • 1.hostsに設定したserver nameを追記(ローカル)

ログ送信側の設定

1.NGINXのログ出力設定

  • NGINXのログの出力形式をLTSVにする
$ sudo vim /etc/nginx/nginx.conf

# 下記の設定を追記

http {
    ~~~~~~~省略~~~~~~~~~~

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    log_format ltsv   'host:$remote_addr\t'
                      'user:$remote_user\t'
                      'time:$time_iso8601\t'
                      'method:$request_method\t'
                      'uri:$request_uri\t'
                      'protocol:$server_protocol\t'
                      'status:$status\t'
                      'size:$body_bytes_sent\t'
                      'request_time:$request_time\t'
                      'upstream_response_time:$upstream_response_time\t'
                      'upstream_addr:$upstream_addr\t'
                      'referer:$http_referer\t'
                      'user_agent:$http_user_agent\t';


    access_log  /var/log/nginx/access.log  ltsv;

    ~~~~~~~省略~~~~~~~~~~

2.アクセスログを拾って集計サーバーへ転送

  • ログを転送するためにfluent-agent-liteをインストール
# 依存モジュールのインストール
$ sudo yum -y install perl-ExtUtils-MakeMaker
$ sudo yum -y install perl

# agent-liteのインストール
$ git clone https://github.com/tagomoris/fluent-agent-lite
$ git sudo ./fluent-agent-lite/bin/install.sh

# サービスの自動起動設定
$ sudo chkconfig fluent-agent-lite on
$ sudo chkconfig --list fluent-agent-lite
fluent-agent-lite   0:off   1:off   2:on    3:on    4:on    5:on    6:off
$ sudo /etc/init.d/fluent-agent-lite start
  • fluent-agent-liteの設定
$ sudo vim /etc/fluent-agent-lite.conf
# 設定ファイルの中身を編集

# fluentd tag prefix of all LOGS
TAG_PREFIX=""

# fluentd message log attribute name (default: message)
FIELD_NAME="message"

# LOGS: tag /path/to/log/file

# 可視化したログはここで拾い上げて転送してあげる
LOGS=$(cat <<"EOF"
nginx.access /var/log/nginx/access.log
EOF
)

# SERVERNAME[:PORTNUM]
# port number is optional (default: 24224)
PRIMARY_SERVER="127.0.0.1"

### or, PRIMARY SERVER LIST FILE of servers
# PRIMARY_SERVERS_LIST="/etc/fluent-agent.servers.primary"

# secondary server setting is optional...
# SECONDARY_SERVER="secondary.fluentd.local:24224"

# SECONDARY_SERVERS_LIST is available as like as PRIMARY_SERVERS_LIST

# max bytes to try read as one action from tail (default: 1MB)
# READ_BUFFER_SIZE=1048576

# PROCESS_NICE default: 0
  • 設定後は再起動
$ sudo /etc/init.d/fluent-agent-lite restart

ログ集計側の設定

1.転送されてきたログの受信

  • ログの受信やパースのためにtd-agentのインストール
# yumレポの追加
$ sudo vim /etc/yum.repos.d/td.repo

# 設定ファイル内
[treasuredata]
name=TreasureData
baseurl=http://packages.treasuredata.com/2/redhat/\$releasever/\$basearch
gpgcheck=1
gpgkey=http://packages.treasuredata.com/GPG-KEY-td-agent
# インストール & 起動設定
$ sudo yum -y install td-agent
$ sudo /etc/init.d/td-agent start
$ sudo chkconfig td-agent on
$ chkconfig --list td-agent
  • fluent用ログの出力場所を作成
$ sudo mkdir -m 755 /var/log/aggregated && sudo chown td-agent:td-agent /var/log/aggregated
$ sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-parser fluent-plugin-elasticsearch fluent-plugin-typecast fluent-plugin-file-alternative

ログの受信設定

# 24224で転送されてきたログを受け付け
$ sudo vim /etc/td-agent/td-agent.conf
<source>
  type forward
  port 24224
</source>

<match **>
  type file
  path /var/log/aggregated/unmatched/unmatched
</match>

2.ログをパースしてelasticsearchへ転送

  • elasticsearchへの転送設定
$ sudo vim /etc/td-agent/td-agent.conf

# 設定情報を追記
~~~~~~~~~~~~~~~~ 省略~~~~~~~~~~~~~~~~~~~~~~
# Elascticsearch用のパース
<match nginx.access.**>
  type copy
  <store>
    type parser
    format ltsv
    add_prefix parsed
    key_name message
  </store>

  <store>
    type stdout
  </store>
</match>

# パースしたデータのキャスト
<match parsed.nginx.access.**>
  type typecast
  item_types request_time:string, upstream_response_time:string
  tag         casted.nginx.access
</match>

# パースキャスト済みのデータをElascticsearchに転送
<match casted.nginx.access>
  type_name nginx
  type elasticsearch
  include_tag_key true
  tag_key @log_name
  host localhost
  port 9200
  logstash_format true
  flush_interval 10s
  buffer_type file
  buffer_path /var/log/td-agent/buffer/casted.nginx.access.buffer
</match>
~~~~~~~~~~~~~~~~ 省略~~~~~~~~~~~~~~~~~~~~~~
  • 再起動
$ sudo /etc/init.d/td-agent restart
  • elasticsearchのインストール
# 依存モジュールのインストール

$ sudo yum -y install java-1.7.0-openjdk
  • yumレポの追加
[elasticsearch-2.x]
name=Elasticsearch repository for 2.x packages
baseurl=http://packages.elastic.co/elasticsearch/2.x/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

3.elasticsearchの設定

$ sudo yum -y install elasticsearch

# 起動設定

$ sudo /etc/init.d/elasticsearch start
$ sudo chkconfig elasticsearch on
$ chkconfig --list elasticsearch
elasticsearch   0:off   1:off   2:on    3:on    4:on    5:on    6:off
$ sudo vim /etc/elasticsearch/elasticsearch.yml

# 設定ファイル内
http.cors.allow-origin: "/.*/"
http.cors.enabled: true
network.host: 0.0.0.0

# 設定後に再起動
$ sudo /etc/init.d/elasticsearch restart

4.kiabanを使ってelasticsearchのログを可視化

  • 可視化のためにkibanaのインストール
# zipファイルの取得
$ wget https://download.elastic.co/kibana/kibana/kibana-4.3.1-linux-x64.tar.gz

# 解凍
$ tar xvfz kibana-4.3.1-linux-x64.tar.gz
$ mv -n kibana-4.3.1-linux-x64 kibana
$ sudo vim /etc/init.d/kibana


#!/bin/bash
# chkconfig: 2345 85 15
# description: ログ可視化サービス

export NAME=kibana
export LOG_DIR=/var/log/${NAME}
export PID=/var/run/${NAME}.pid
export LOG=${LOG_DIR}/${NAME}.log

test -d $LOG_DIR || mkdir $LOG_DIR

case $1 in
  'start' )
    $0 status >/dev/null 2>&1 && echo "${NAME} is already running." && exit 1
    nohup /home/vagrant/${NAME}/bin/${NAME} 0<&- &> $LOG &
    echo $! > $PID
    ;;
  'stop' )
    $0 status >/dev/null 2>&1 || echo "${NAME} is not running." || exit 1
    test -f $PID && cat $PID | xargs kill -s SIGKILL && rm $PID
    ;;
  'restart' )
    $0 stop
    sleep 1
    $0 start
    ;;
  'status' )
    test -f $PID || echo "${NAME} not running." || exit 1
    PID=`cat $PID`
    kill -s 0 $PID >/dev/null 2>&1 && echo "${NAME} is running." && exit 0
    echo "${NAME} not running."
    exit 1
    ;;
  *)
    echo "Usage: $0 start|stop|restart|status"
    ;;
esac


# 設定の変更
$ sudo chmod 755 /etc/init.d/kibana & sudo chown root:root /etc/init.d/kibana
# 起動設定
$ sudo /etc/init.d/kibana start
$ sudo /etc/init.d/kibana status
kibana is running.
$ sudo chkconfig kibana on
$ chkconfig --list kibana
kibana          0:off   1:off   2:on    3:on    4:on    5:on    6:off
# kibana用のルートをNginxに通す
$ sudo vim /etc/nginx/conf.d/kibana.conf
server {
  listen 80;
  root        /home/vagrant/kibana/;
  server_name kibana.local;
  index index.html;

  location / {
    proxy_pass http://localhost:5601;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

# 再起動
$ sudo /etc/init.d/nginx restart
  • kibanaの設定変更
$ vim kibana/config/kibana.yml

# 下記を追記
elasticsearch.url: "http://localhost:9200"
host: "localhost"

# kibanaを再起動
$ sudo /etc/init.d/kibana restart

ローカルの設定

1.hostsに設定したserver nameを追記(ローカル)

$ sudo vim /etc/hosts

# 仮想環境のipを指定
192.168.33.10 kibana.local 

最後に

下記にアクセスすると見れている! http://kibana.local

Aws::SQS::Errors::SignatureDoesNotMatch: Signature expired: 20160304T025839Z is now earlier than 20160304T030120Z (20160304T031620Z - 15 min.)

デプロイ時に突然エラー あれ?と思ったらサーバーの時間がずれていることが原因だった。。

日本時間にサーバーを修正

chefレシピをベタッと

execute "/etc/localtime" do
  command "cp -p /usr/share/zoneinfo/Japan /etc/localtime"
end

package "ntp"
service "ntpd" do
  action [:enable, :start]
  supports :start => true, :status => true, :restart => true, :reload => true
end

template "/etc/ntp.conf" do
  source "ntp.conf.erb"
  owner "root"
  group "root"
  mode 0644
  notifies :restart, "service[ntpd]"
end

ntp.conf

# server 0.centos.pool.ntp.org iburst
# server 1.centos.pool.ntp.org iburst
# server 2.centos.pool.ntp.org iburst
# server 3.centos.pool.ntp.org iburst

server -4 ntp.nict.jp
server -4 ntp1.jst.mfeed.ad.jp
server -4 ntp2.jst.mfeed.ad.jp
server -4 ntp3.jst.mfeed.ad.jp

HTTPの教科書を読んだ

教科書というだけあって懇々とHTTPのみのことに関して漏れ無く解説してくれる。

HTTPヘッダ

カテゴリ  フィールド名   説明  
一般ヘッダ Cache-Control  キャッシング動作の指定  
一般ヘッダ Connection コネクションの管理
一般ヘッダ Date メッセージ生成の日時
一般ヘッダ Pragma メッセージディレクティブ
一般ヘッダ Trailer メッセージのおわりにあるヘッダーの一覧
一般ヘッダ  Transfer-Encoding   メッセージボディの転送コーディング形式の指定 
一般ヘッダ  Upgrade   他のプロトコルへのアップグレード 
一般ヘッダ Via プロキシサーバーに関する情報
一般ヘッダ Warning エラー通知
リクエストヘッダ Accept 処理できるメディア・タイプ
リクエストヘッダ Accept-Charset 文字セットの優先度
リクエストヘッダ Accept-Encoding コンテンツエンコーディング
リクエストヘッダ Accept-Language 言語の優先度
リクエストヘッダ Authorization Web認証のための情報
リクエストヘッダ Expect サーバーに対しての特定動作の期待
リクエストヘッダ From ユーザーのメールアドレス
リクエストヘッダ Host 要求されたリソースのホスト
リクエストヘッダ If-Match エンティティタグの比較
リクエストヘッダ If-Modified-Since リソースの更新時間の比較
リクエストヘッダ If-None-Match エンティティタグの比較
リクエストヘッダ If-Range リソースが変更されていない場合にエンティティのバイト範囲の要求を送信
リクエストヘッダ If-Unmodified-Slice リソースの更新時間の比較
リクエストヘッダ Max-forwards 最大転送ポップ数
リクエストヘッダ Proxy-Authorization プロキシサーバーのクライアント認証のための情報
リクエストヘッダ Range エンティティのバイト範囲の要求
リクエストヘッダ Referer リクエスト中のURIの取得元
リクエストヘッダ TE 転送エンコーディングの優先度
リクエストヘッダ User-Agent HTTPクライアントの実装情報
レスポンスヘッダ Accept-Range バイト範囲の要求が受け入れ可能かどうか
レスポンスヘッダ Age リソースの推定経過時間
レスポンスヘッダ Etag リソース特定のための情報
レスポンスヘッダ Location クライアントを指定したURIにリダイレクト
レスポンスヘッダ Proxy-Authenticate プロキシサーバーのクライアント認証情報
レスポンスヘッダ Retry-After リクエスト再試行のタイミング要求
レスポンスヘッダ Server HTTPサーバーの実装情報
レスポンスヘッダ Vary プロキシサーバーに対してのキャッシュの管理情報
レスポンスヘッダ WWW-Authenticate サーバーのクライアント認証情報
エンティティヘッダ Allow リソースがサポートするHTTPメソッド
エンティティヘッダ Content-Encoding エンティティボディに適用されるコンテンツエンコーディング
エンティティヘッダ Content-Language エンティティの自然言語
エンティティヘッダ Content-Length エンティティボディサイズ
エンティティヘッダ Content-Location リソースに対応する代替URI
エンティティヘッダ Content-MD5 エンティティボディのメッセージダイジェスト
エンティティヘッダ Content-Range エンティティボディの範囲の位置
エンティティヘッダ Content-Type エンティティボディのメディア・タイプ
エンティティヘッダ Expires エンティティボディの有効期限
エンティティヘッダ Last-Modifed リソースの最終更新時間

【Rails】enviromentsの読み込みを設定をinitializersファイルロード後にする方法

はじめに

enviromentsの設定でinitializers内で拡張したメソッドを 使おうとすると通常の読み込み順では使えない

config内の読み込み順

"environment.rb",
"application.rb",
"boot.rb",
"environments/*",
"initializers/*",
"routes.rb"

解決法

after_initializeというメソッドで意図した順番で 読み込んでくれることができる

Rails.application.configure do
  config.after_initialize do
    # ここに設定を記述
  end

end

S3で静的Webサイトホスティングからデプロイまで覚書

今回の流れ

1.S3でバケットの作成

AWSの管理画面からS3のバケットを作成します。

バケット名:

独自のドメインを設定する場合はドメイン名とバケット名を合わせてください。

リージョン:

東京がいいかな?

2.バケットのホスティング設定

プロパティメニューから作成したバケットの「静的ウェブサイトホスティング」を 選択。

有効化しインデントとエラードキュメントを設定

3.IAMの作成

IAMでユーザーを新規作成後に「アクセスキーID」と「シークレットアクセスキー」が 発行されるのでメモをしておいてください。

作成したユーザーの「ポリシーのアタッチ」から「AmazonS3FullAccess」を 選択

4.ページをデプロイ

デプロイには「s3cmd」を使用します。

インストール済みなことを確認

$ which s3cmd
/usr/local/bin/s3cmd

デプロイしたいルート・ディレクトリで設定ファイルを作成します。

s3cmd -c ./.s3cfg --configure
Access Key: アクセスキー
Secret Key: シークレットキー
Encryption password:
Path to GPG program: None
Use HTTPS protocol: True
HTTP Proxy server name:
HTTP Proxy server port: 0

これで./s3cfgという設定ファイルができあがる

$ ls -la
total 48
drwxr-xr-x  10 hoge-user  staff   340  2 19 10:19 .
drwxr-xr-x  60 hoge-user  staff  2040  2 18 18:48 ..
-rw-r--r--@  1 hoge-user  staff  6148  2 14 16:54 .DS_Store
-rw-------   1 hoge-user  staff  1781  2 19 10:19 .s3cfg
-rwxrwxrwx   1 hoge-user  staff    79  2 19 09:42 deploy.sh
drwxr-xr-x   8 hoge-user  staff   272  2 16 00:18 dist
-rw-r--r--   1 hoge-user  staff  1532  2 16 00:50 gulpfile.js
drwxr-xr-x   7 hoge-user  staff   238  2 14 16:24 node_modules
-rw-r--r--   1 hoge-user  staff   402  2 14 16:24 package.json
drwxr-xr-x   9 hoge-user  staff   306  2 16 00:19 src

これでいよいよデプロイ

デプロイしたいディレクトリとデプロイ先のバケット名を指定してあげる

s3cmd -c .s3cfg -P --follow-symlinks sync ./ディレクトリを指定/ s3://バケット名を指定/

コマンドが長いのでスクリプトにしてもいいと思います

$ cat deploy.sh
#!/bin/sh
s3cmd -c .s3cfg -P --follow-symlinks sync ./ディレクトリを指定/ s3://バケット名を指定/

5.独自ドメインを設定 DNSレコードにCNAMEでS3のエンドポイントを指定してあげればOKです!

簡単でいいですね!

ELBにSSL証明書を設定する方法

今回の流れ

  • 1.秘密鍵の作成
  • 2.証明書署名要求の作成
  • 3.証明書の取得
  • 4.中間証明書の取得
  • 5.ELBに設置

1.秘密鍵の作成 && 証明書署名要求の作成

鍵の作成にはopensslを使用するのでインストール済みか確認してください

$ which openssl
/usr/local/bin/openssl
openssl genrsa -out 『任意の名前を設定』.pem 2048 -sha256
  • 2.CSRの作成
openssl req -new -sha256 -key 『任意の名前を設定』.pem -out 『任意の名前を設定』.jp.csr
  • CSRで入力する情報
項目
コモンネーム【Common Name】    例:)hoge.com
組織名【Organization】         例:)Hoge.Inc.
部門名【Organizational Unit】  例:)Web Development Devision
市区町村郡名【Locality】       例:)Shibuya-ku
都道府県名【State or Province】例:)Tokyo
国名【Country】                例:)JP

下記は任意で設定

メールアドレス【E-Mail address】 例:)hoge@hoge.com

パスフレーズ【Challenge password】 設定するとWEBサーバーの自動起動に支障をきたします。

3.証明書の取得

こちらは証明書購入元の指示にしたがってください。CSRが必要になります

4.中間証明書の取得

こちらも証明書購入元から取得

5.ELBに設置

ロードバランサーはすでに立ち上げ済みとします。 Configure Security Settingsで今まで作成したものをそれぞれを設定すればすぐに完了です

証明書名:*             → 任意で設定
プライベートキー:*     → 秘密鍵を登録
パブリックキー証明書:* → 証明書
証明書チェーン:      → 中間証明書

簡単でいいですね!