Glide Note

glidenote's blog

CloudFrontのログをfluent-plugin-bigqueryを利用してBigQueryに入れるようにした

TL;DR

  • Amazon CloudFrontのアクセスログをBigQueryに入れるようにした
  • BigQueryへのデータ投入には社内の他プロジェクトでも利用していて実績があり、KAIZENがメンテナになっているfluent-plugin-bigqueryを利用

背景

ここ2ヶ月くらい、あらゆるログをBigQueryに集約しつつあって、今回はAmazon CloudFrontのアクセスログについて作業をした。

Amazon CloudFrontのアクセスログには以下のような特徴がある。

  • Amazon CloudFrontのアクセスログは数時間〜1日程度遅れでS3のBucketに追加される。時系列はバラバラ
  • CloudFrontのアクセスログがtsv形式。
  • ベストエフォート型で全てのログがS3に収容される保証は無い
  • gzで圧縮されてS3に追加される(BigQueryに入れるにはgz形式から展開する必要がある)
  • ログファイルの数が非常に多い。作業していた環境でだいたい1日に15,000個くらいgzファイルがあって、全部をダウンロードするのに160分くらいかかる

という感じ。

仕組みの詳細

データの流れ

  1. CloudFrontのログが自動でS3に追加される
  2. batchサーバからs3cmd syncでcronで定期的にs3からログファイル(gz形式)をローカルに持ってくる
  3. batchサーバで、取得したログファイルをzcat ${FILE} >> /var/log/cloudfront/access.log で連結する
  4. batchサーバのFluentdでin_tailを用い/var/log/cloudfront/access.logを読み込む
  5. fluent-plugin-bigqueryを用いてBigQueryにデータを投入する(日付毎にデータ投入先のテーブルを分ける)

こんな感じでBigQueryにデータが入っている

先日発表されたS3 Event Notificasionsを検証中なので、問題が無ければ、Amazon SQSを利用した処理に切り替え予定。

この方式を採用した理由

  • 私がFluentdの運用に慣れていた。
  • KAIZENがメンテナをしているfluent-plugin-bigqueryを利用したかった
  • BigQueryへのデータ投入部分を自前で実装しなくて良い
  • BigQueryへのデータ投入周りのエラーハンドリング、再送処理をfluent-plugin-bigqueryに任すことが出来る
  • logrotateを利用して、ログの世代管理が出来る。Fluentdがログ切り替えを検知出来る。(nginxのログなど他のアクセスログと同じような感じで扱える)
  • Fluentdを利用しているので、スケールが容易
  • /var/log/cloudfront/access.log-YYYYMMDD.gzというように日別でログが分かれているので、障害やトラブル発生時のリカバリーも簡単になっている。(障害が発生した日の15,000個とかのログをS3から持ってきて云々… みたいな面倒な処理が必要ない)

その他

  • CloudFrontのログがS3に追加されるのが遅い場合1日程度かかるので、翌日のテーブルにデータが入ってしまう。BigQueryからデータを取り出すときに工夫が必要
  • BigQueryにデータ投入先のテーブルが存在しないと死ぬので、別でテーブル作成の仕組みと監視をしておく必要あり。
  • データサイズが大きい場合、テーブルを適切に分割していないとBigQuery破産に。
  • テーブルの自動作成、監視にはbigqueryを利用

該当部分のtd-agent.confの設定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<source> 
  type         tail 
  path         /var/log/cloudfront/access.log
  pos_file     /var/log/td-agent/cloudfront-access-log.pos
  tag          extracted.cflog

  format       tsv
  keys         day,time,x_edge_location,sc_bytes,c_ip,cs_method,cs_Host,cs_uri_stem,sc_status,cs_Referer,cs_User_Agent,cs_uri_query,cs_Cookie,x_edge_result_type,x_edge_request_id,x_host_header,cs_protocol,cs_bytes,time_take
</source>

<match extracted.cflog>
  type                        bigquery

  buffer_type                 file
  buffer_path                 /var/log/td-agent/cf.bq.*.buffer

  method                      insert

  auth_method                 private_key
  email                       ''
  private_key_path            ''

  buffer_chunk_limit          768k
  buffer_queue_limit          5000
  flush_interval              1
  try_flush_interval          0.05 
  num_threads                 10 
  queued_chunk_flush_interval 0.01

  project                     ''
  dataset                     ''
  table                       %Y%m%d

  fetch_schema                true
</match>

BigQueryにログを集約したことで集計も調査も非常に簡単になって、本当にBigQuery素晴らしい。

S3 Event NotificasionsをAmazon SQSで受け取る

最近やっている仕事で先日発表されたS3 Event Notificationsが利用出来そうな感じがしたのでちょっと調査。 S3にファイルがアップされたらAmazon SQSで通知を受け取るようにしてみた。

S3 => SNS => SQS への通知は解説しているサイトが結構あるんですが、S3 => SQS への通知設定の 情報が見当たらなかったので、動くようになるまで、いろいろと試行錯誤を繰り返した。 特にSQSのPermission設定が恐ろしく分かりにくくに2日くらいハマったので、自分用にメモしておく。

S3 Bucketの作成

S3でBucketを作成。既存Bucketを利用する場合はここはSKIP。 今回は検証用にglidenote-sqs-testという名前でBucketを作成

SQSの設定

S3のイベント通知を受け取るQueueを作成する

Queue名をsqs-testをして作成。

Add a Permissionをクリックして通知の受信元を設定する。

下記のように設定して、Add Conditionを選択

  • Valueにはarn:aws:s3:::{S3のBucket名}を設定

Actions部分はSendMessageだけ選択して、Add Permission を選択

こんな感じの設定になっていることを確認

S3 Event Notificationsの設定

S3のイベント通知をSQSに送るように設定。下記の例ではPUTPOSTイベントのみSQSに通知するように設定

正しく設定が出来ると下記のようになる。SQSのパーミッション設定が上手くてきていないとエラーになる。

実際にS3 EventをSQSで受け取る

下記のようなrubyのスクリプトを用意してSQSでイベントを受信してみる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'aws-sdk'

AWS.config(
  :access_key_id     => 'your_access_key_id',
  :secret_access_key => 'your_secret_access_key',
  :sss_endpoint      => 'sqs.ap-northeast-1.amazonaws.com'
)

url = 'https://sqs.ap-northeast-1.amazonaws.com/xxxxxxxxxxxx/sqs-test'

sqs = AWS::SQS.new

while true
  receive = sqs.queues[url].receive_message()
  if receive
    puts receive.body
    receive.delete
    sleep 1
  end
  puts "Waiting"
  sleep 1
end

するとほぼリアルタイムで下記のような感じでイベントを受信出来る

1
{"Records":[{"eventVersion":"2.0","eventSource":"aws:s3","awsRegion":"ap-northeast-1","eventTime":"2014-11-20T06:16:39.474Z","eventName":"ObjectCreated:Put","userIdentity":{"principalId":"AWLW0VGTI46AA"},"requestParameters":{"sourceIPAddress":"10.115.144.24"},"responseElements":{"x-amz-request-id":"E1C0A0C1F42CAA54","x-amz-id-2":"0p2FzYuEkiyaZn/n33XJLYjE3cmePkiqEFF5NMYy+c1PSGTNfmUf+Msou4Mejnr0"},"s3":{"s3SchemaVersion":"1.0","configurationId":"S3TestNotification","bucket":{"name":"glidenote-sqs-test","ownerIdentity":{"principalId":"AWLW0VGTI46AA"},"arn":"arn:aws:s3:::glidenote-sqs-test"},"object":{"key":"shindel.png","size":794485,"eTag":"b52627268c0e9071be00c5a38fdbc912"}}}]}

リアルタイムでS3のイベントを受信するにはSQSと常時通信しているために Supervisordなどを用いてスクリプトを動かす必要があり。

これでリアルタイムな処理に対応が出来るようになった。ちょっと現在やってるタスクに適用出来るかしばらく検証してみる。

参考

サーバ/インフラ徹底攻略を読んでインフラエンジニアの高齢化問題について考える

サーバ/インフラ徹底攻略 (WEB+DB PRESS plus)

本書の「テスト駆動インフラ&CI最前線」を執筆されたmizzyさんからご恵贈頂きました。ありがとうございます。

事前に断っておくと私がここで記載している「インフラエンジニア」はITインフラエンジニアの話です。

本書の詳細なレビューは他の方にお任せするとして、内容を読むと

  • サーバプロビジョニング
  • Vagrant
  • Serverspec
  • インフラCI
  • AWS
  • GitHub
  • Docker
  • nginx
  • メンテナンス、運用の話

が主なTopicsになる。

これらは今のインフラエンジニアにとって必須の知識、スキルになってきていて、その他にも 従来から必要だったOSレイヤー、ミドルウェアレイヤー、LAMP、ログ収集の定番Fluentdなど インフラエンジニアに要求されるスキルセットの範囲が広く、しかも深くなっていると個人的には思っている。 もはや運用だけでやっていればいい時代は終わっていて、必要なものは自分で作るためにコードを書ける必要もある。

守備範囲が広く、そして深いので覚えることが尽きず、インフラエンジニアは非常に面白い職種のはずなんですが、 それがあまり伝わっていないのか、 若い人が非常に少ない職種。 私自身、6年前にインフラエンジニア(当時はサーバエンジニアという名前だった)になるまで どんな職種だかよく理解していなかったので、イメージがしにくい職種なのは確かだと思う。

WEB系企業各社インフラエンジニアの採用には非常に苦労しているようで、 このままだと5年後、10年後にはさらに高齢化が進むのは必至なのと、今現役バリバリの優秀なエンジニアから 知見を引き継ぐ若い優秀な人材が減っていってしまうので、今から若いインフラエンジニアを養成する必要があると思う。

本書は2014年のインフラエンジニアに求められている知識やスキルが1冊に良くまとまっているし、 インフラエンジニアの魅力も伝わると思うので、インフラエンジニアを理解したい人や インフラエンジニアを目指している人には非常に良書である。

新卒エンジニアには研修などで是非読んで欲しい本。

2014/10/31時点でAmazonでベストセラー1位になっているので、サーバ/インフラ徹底攻略を読んで、 若いインフラエンジニアが増えてくれることを期待している。

今インフラは楽しいぞ!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
目次

巻頭企画
[入門]コードによるインフラ構築
サーバ構成管理の自動化を実現するる……伊藤 直也
第1章 ChefとVagrantによるインフラのコード化
設定の一元管理で作業を省力化する
第2章 Serverspecによるテスト駆動インフラ構築
設定変更の反映を確実なものにする

特集1
Amazon Web Services最新活用
レイヤ別比較,構築の定石,構成管理の自動化る
第1章 Amazon Web Servicesレイヤ別比較
各サービスの特徴を理解し,うまく使い分ける……片山 暁雄,平山 毅
第2章 EC2とVPCによるシステム構築
セキュアで可用性を高めたインフラの作り方……舟崎 健治,吉荒 祐一
第3章 RDSによるデータベースの活用
作成,デプロイ,バックアップ……今井 雄太,八木橋 徹平
第4章 CloudFormationによる構築の自動化
テンプレートの作成からミドルウェア構築設定まで……安川 健太

特集2
テスト駆動インフラ&CI最前線
Infrastructure as Codeがもたらすワークフローの刷新る……宮下 剛輔
第1章 インフラのテストとその重要性
「インフラのコード化」による開発手法の応用
第2章 テスト駆動インフラの実践
VirtualBox,Vagrant,Puppet,Serverspecによるテスト自動化
第3章 インフラCIの実践
GitHub,Wercker,DigitalOceanによる継続的テスト
第4章 インフラの継続的改善の実践
GitHub Flowをベースとしたワークフロー変革

特集3
実践Immutable Infrastructure
使い捨てサーバによる運用の変革る……田中 慎司
第1章 Immutable Infrastructureとは何か
不変なサーバ,Blue-green Deploymentとそれらの利点
第2章 Immutable Infrastructureで利用するツール/サービス
比較・整理と,システム全体での組み合わせ
第3章 コンテナ型仮想化とクラウドによる実践
Docker+HAProxy,Amazon EC2+ELB
第4章 クラスタ管理ツールによる実践
Apache Mesosでリソース管理の自動化

特集4
[詳解]nginx
設定の柔軟性と優れたスケーラビリティ
第1章 nginxの世界へようこそ
アーキテクチャ,用途,メリット,デメリット……久保 達彦
第2章 はじめてのnginx
インストール,起動と終了,基本設定……道井 俊介
第3章 一般的なWebサーバの構築
バーチャルホスト,アクセス制御,SSL通信,基本認証……飯田 祐基
第4章 実践的なWebアプリケーションサーバの構築
Unicorn/RailsやPHP-FPMと連携させる……道井 俊介
第5章 大規模コンテンツ配信システムの構築
キャッシュ,ロードバランシングを活用する……飯田 祐基
第6章 拡張モジュールのしくみと作り方
nginxを自由にカスタマイズするための基礎知識……久保 達彦

特集5
メンテナンス本格入門
緊急対応,計画停止,メンテフリー化
第1章 メンテナンスとは
種類と手法を整理する……桑野 章弘
第2章 計画メンテナンスの流れ
事前準備,作業のチェック,振り返り……松浦 隼人
第3章 緊急メンテナンスの流れ
普段から備えるべきこと,障害時の対応……松浦 隼人
第4章 メンテフリーへのアプローチ【インフラ編】
省力運用を実現するインフラ,データベース設計と障害検知……松浦 隼人,中村 俊之
第5章 メンテフリーへのアプローチ【アプリケーション編】
ダウンタイムを減らすリリース手法とアプリケーション設計……福永 亘,中村 俊之,松浦 隼人
第6章 ガールフレンド(仮)とアメーバピグの事例
現場でどう実践し,どう障害を切り抜けたか……福永 亘,杉山 仁則

一般記事
Dockerで軽量な仮想環境
Linuxコンテナでインフラを瞬時に構築する……伊藤 直也

参考

ChatOpsでOSのセキュリティアップデートを自動化出来るようにした

先日@naoya_itoさんが自身のブログ(インフラの継続的デリバリー)KAIZEN platform Inc.のインフラについて書いていたやつの続編的な内容。

TL;DR

  • Chat(Slack) + Hubot + CircleCI + GitHub を用いてセキュリティアップデートを自動化した
  • GitHubのPull Requestを契機にセキュリティアップデートを実行できるようにした
  • CircleCIが大変便利。インフラ系の作業を自動化するのに非常に合っている気がする

背景

KAIZEN platform Inc.では、

  1. ネットワーク脆弱性スキャン
  2. アプリケーション脆弱性スキャン
  3. セキュリティアップデートの定期実行

の3つをセキュリティ系タスクとして継続的にやっていこうという話になり、今回は私が担当した、「セキュリティアップデートの定期実行」の話。

RHEL系OSにはyumの自動更新機能がありますが、これが稼働していて意図せずミドルウェアがバージョンアップして、 過去にみんな痛い目に遭遇した経験があるので、これは利用せずにアップデートの内容を事前に確認したいという事情もあります。

仕組みの詳細

全体の流れ

  1. 定期的にHubot自身が、Chat(Slack)上からHubotにSecurity Checkを指示する(今回はキャプチャを取るために私が召喚してます)
  2. Hubot経由でCircleCIのAPIを叩いて、Security Update用リポジトリ上にチェック用ブランチを作成して、GitHubにPush
  3. GitHubへのPushを検知して、CircleCIが検証環境であるQA環境のサーバに対して、sshしてyum --secuity check-updateを実行
  4. セキュリティ更新があれば、下記のようなデプロイ用ブランチへのPull Requestを作ってインフラメンバーにmentionを送る。無ければそのまま終了。
  5. インフラメンバーがPull Request内容を確認して、問題が無ければMerge。
  6. デプロイ用ブランチへのMergeを契機に対象サーバについてyum --security -y updateがかかり、セキュリティアップデートがかかる
  7. アップデート後にCircleCI経由でSlack上のHubotを召還
  8. Hubot経由でe2eテストが自動で走り、セキュリティアップデートによって、アプリケーションに不具合が発生していないかテストされる
  9. e2eテストに問題が無ければ、Production環境のサーバ向けに2-8の手順を繰り返す
  10. 最終的には下記のように、どのサービス、どのステージでセキュリティアップデートが完了したかが通知される
  11. 寿司を食う

この一連の流れが各ロール(web,log,proxy,batch等々)のサーバ数十台に対して一斉に自動で走ってくれて、 進捗報告もChat(Slack)に都度通知されるようになっている。

人の手を介するのは5のセキュリティアップデート内容のレビューとMergeボタンを押す部分だけ。

naoyaさんのブログから画像を拝借すると、セキュリティアップデートの適用もMergeボタンに集約された感じ。

これにより

  • 定期的なセキュリティアップデートのチェックを自動化
  • セキュリティアップデートをPull Requestでレビュー可能に
  • CircleCI経由で実行することで、CircleCI上に作業ログの保存

が出来るようになった。

CircleCIについて

CircleCIには

  • ssh鍵やTOKENがセキュアに渡すことが出来る
  • 実行ログが残せる
  • Chat系アプリと簡単に連携できる
  • UIが直感的で分かりやすい
  • CircleCI自体にssh出来るので、デバッグが簡単に出来る

という特徴があるので、インフラ系の作業を自動化するのには非常に合っていると思う。(某OSSなCIツールで同じ事をやろうとすると、そこまで行くのにいろいろと設定が必要でyak shavingな感じが…)

私が担当した以外のセキュリティ系タスクも自動化がされているし、 Chefの適用、セキュリティスキャンなどChatOpsの範囲が広がってきて、最近はサーバにほとんど入らなくなってきているので もっと頑張れば寿司だけ食っていれば良い世界が来るかもしれない。

Slackのチャンネル移動をキーボードで簡単に出来るようKarabinerのprivate.xmlを書いた

仕事でSlackを使っているんですが、 キーボードショートカットがあんまり使いやすくなくて、 特にチャンネル移動が致命的に使いにくくてストレスフルなので、、Karabiner(旧keyremap2makbook)のprivate.xmlを書いた。 (Slackのメニューにチャンネル移動の項目がないので、Macの環境設定からキーバインドの設定が出来ないのでKarabinerで実現してます)

今までWeechatというIRCクライアントを使っていたので、そのキーバインドに合わせた。 具体的には

  • Ctrl + Nで次のチャンネル or DMに移動
  • Ctrl + Pで前のチャンネル or DMに移動
  • Alt + Aで未読チャンネル or DMに移動

導入方法

~/Library/Application\ Support/Karabiner/private.xml に下記のように設定を追加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0"?>
<root>

    <appdef>
        <appname>SLACK</appname>
        <equal>com.tinyspeck.slackmacgap</equal>
    </appdef>
    <item>
        <name>For Slack CTRL+N=move next channel, CTRL+P=move previous channel, ALT+A=move unread channel</name>
        <identifier>private.app_slack_move_channel_with_ctrln_ctrlp</identifier>
        <only>SLACK</only>
        <autogen>__KeyToKey__ KeyCode::N, ModifierFlag::CONTROL_L, KeyCode::CURSOR_DOWN, ModifierFlag::OPTION_L</autogen>
        <autogen>__KeyToKey__ KeyCode::P, ModifierFlag::CONTROL_L, KeyCode::CURSOR_UP, ModifierFlag::OPTION_L</autogen>
        <autogen>__KeyToKey__ KeyCode::A, ModifierFlag::OPTION_L, KeyCode::CURSOR_DOWN, ModifierFlag::OPTION_L, ModifierFlag::SHIFT_L</autogen>
    </item>

</root>

これでKarabinerの設定画面からReloadXMLをして、設定にチェックを入れれば動くようになる。

これでホームポジションから動かずにSlackがだいたい操作できるようになって快適になった。