Glide Note

glidenote's blog

Serverspec本を読んで、先鋭化されつつあるWeb系インフラエンジニアを知る

Serverspec

Serverspecを執筆されたmizzyさんからご恵贈頂きました。ありがとうございます。

本書の詳細な紹介はあんちぽさんのブログと、mizzyさんが出演したRebuildがオススメです。

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

以前サーバ/インフラ徹底攻略を本ブログで紹介したあとに、 書内のある特集を執筆担当された方と話していて、

Web系インフラエンジニアがどんどん先鋭化されつつあって、この本の内容を理解出来る人ってどれくらいいるんだろうね

という事を仰っていたのが非常に印象的であった。

先鋭化という言葉を聞いて、昨今のWebインフラエンジニア界隈の技術を思い起こすと、 Serverspecの登場以前、以後でその先鋭化具合が顕著になったと個人的に思っている。

サーバのテスト標準ツールとなったServerspec

ServerspecはWeb系インフラエンジニアに待望されていたものであり、 その登場により現在のサーバ構築において

  1. PuppetやChefなどでインフラのコードを書く
  2. 適用する
  3. Serverspecでテストを実行する

という一連の作業がスタンダードになった。

サーバ構築の一連の作業において一番面倒な確認作業をコードに出来ることで、 自動化、属人性の排除、CIはもちろん、何が設定されていて、何が動いているのかなどインフラの透明性を高める事が可能になった。

またserverspec/serverspecのcontributorsを見ると、 Web系インフラエンジニアが非常に多いことから分かるように、作者のmizzyさんを中心に、 Web系インフラエンジニアが自分たちで使うためにPRを送り、それが取り込まれ機能拡張され進化したツールだと思っている。

Kaizen Platform, Inc.でのServerspec利用

私の現在勤めるKaizen Platform, Inc.においても、技術顧問であり本書の前書きを担当した伊藤直也さんによって Serverspecは導入され、インフラエンジニアのyoshiakisudo、@m_doiによりChef + Serverspec + GitHub + CircleCI + Docker を組み合わせる形に進化し、

  1. Chefのレシピを書く。Serverspecのテストを書く
  2. GitHubにPushする
  3. GitHubへのPushを契機にCircleCI上に新規にDockerコンテナを立て、Chefを適用
  4. DockerコンテナにServerspecを流してテストを実行する

というサイクルを1日に十数回まわして、インフラの継続的な改善を行っている。

サーバへのChef適用

余談であるが、サーバへのChef適用は@m_doiのより昨年夏からChatOps化されており、

チャット(Slack)上からhubot経由でGitHub上にデプロイ用PRを作成

作成されたPRのmerge

mergeを契機にCircleCI経由でサーバにChefを適用

というようになっていて、手元やサーバからコマンドラインを操作して実行することはない。

これが可能なのもServerspecにより、インフラコードのテストが行われているためであり、Serverspecの功績は非常に大きい。

Serverspec本を読むことは、Serverspecという強力な武器を手にして、飛躍的に進化し続けているWeb系インフラエンジニアを知るために 最も有用な手段である。

最近1週間くらいずっとAmazonでベストセラー1位になっているので、もう既にみんな読んでいると思いますが傑作です。

本書内で拙作の

を紹介して頂いて、期せずしてオライリー本デビューをさせていただきました。ありがとうございます

監視アーキテクチャ(Sensu,Pingdom,Mackerel,StatusPage.io,PagerDuty)についてまとめてみる(2014年12月版)

Sensu Advent Calendarに便乗して、Kaizen Platform, Inc.の2014年12月現在の監視アーキテクチャの話をちょっとしてみようと思う。

モニタリング領域

サービスを監視している領域

Pingdom

  • Pingdom - Website Monitoring
  • 外部ネットワークからのサービスの死活監視。アメリカ、ヨーロッパ、アジアなどの拠点からサービスの死活監視が出来るため、特定の地域からアクセス出来ない場合なのが検知出来る。
  • 後述するstatuspage.ioとの連携で、障害を検知すると、サービスのステータス状況が自動で変わるようになっている

Sensu

  • Sensu | The open source monitoring framework.
  • 監視フレームワーク
  • サーバを内部ネットワークから監視するために利用
  • サーバのプロセス監視、サーバ間の疎通監視、エラー監視など一般的な監視はSensuが担当
  • 自作の監視プラグインなども利用して監視

Mackerel

Incident Management領域

アラート通知先や障害情報の自動更新を管理している領域

StatusPage.io

  • StatusPage.io - Hosted Status Pages for Your Company
  • サービスのステータスを外部に公開、障害情報の公開に利用。 Kaizen Platform Inc Status
  • Pingdomと連携しているので、サービスに障害があった場合は自動でお知らせが出る。
  • Twitter連携しているので障害情報を公開すると、Twitterアカウントにもお知らせが出せる。

PagerDuty

  • Incident Management System for IT Monitoring Tools | PagerDuty
  • アラートのハンドリングに利用
  • 各監視サービスのアラートは全てPagerDutyに集約
  • アラートの通知先をSMS、電話、スマホアプリ、チャットなどに設定出来る。
  • 通知スケジュールも細かく設定出来るので、日替わりでエスカレーション先のエンジニアを切り替えている
  • スマホアプリの出来が良い。

Infomation / Escalation領域

お知らせ、エスカレーション領域

Twitter

  • 前述のstatuspage.ioと連携。
  • statuspage.io上で障害情報を掲載するとTwitterにも投稿されるので、障害情報の更新において二度手間が無い。

Slack

  • Slack: Be less busy
  • 各種アラートがPagerDuty経由でSlackに通知される
  • Slackに逐一通知されるんので、アラートの履歴や対応状況などが一目で分かるようになっている

電話、SMS、メール、アプリへのPush通知など

  • PagerDutyが通知をハンドリングしてくれるので、「最初はSMSにアラートを送って、反応が無ければ○○分後電話する」など通知設定をして運用している。
  • 監視担当の人がその日都合が悪かったりした場合など、通知先の変更が簡単にできる。

その他

  • Mackerelの部分には、Datadogも検証。非常に素晴らしいサービスだった。
  • 現時点ではDatadogの方が高機能なんですが、MackerelがDatadogの超えてくれるのを期待してMackerelを採用

なぜ複数のサービスを組み合わせて監視しているかは技術顧問の伊藤直也さんのスライドを見ると分かるかと思います。

来年にはガラッと変わっているかもしれないけど、各コンポーネントがAPIで疎結合化されているのでアーキテクチャの変更も容易。

些細な障害、兆候も検知して見逃さないように、いろいろと試行錯誤を繰り返している。

ncコマンドでファイル転送するときにpvコマンドで進捗を表示する

ファイルを送受信するときに暗号化する必要が無い場合は 高速なのでncコマンドを多用しているんですが、進捗表示の方法を毎回忘れてググっているので自分用にメモ。

送信側

3000ポートを転送に使う場合。

1
pv hogemoge.zip | nc -l 3000

受信側

1
nc foobar.com 3000 | pv > hogemoge.zip

ファイル転送中は下記みたいな感じで転送済みデータサイズ、転送速度、残り時間、プログレスバーなど進捗が確認出来る

簡易的な回線速度の測定にも使えるので、大変便利。

参考

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などを用いてスクリプトを動かす必要があり。

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

参考