wtatsuruの技術方面のブログ

はてなスタッフ id:wtatsuru です。日常ブログはこちら https://tatsuru.hatenablog.com/

新しいReserved Instance

AWSの新Reserved Instanceの話です。

Amazon Web Services ブログ: 【AWS発表】EC2のリザーブドインスタンスモデルがシンプルに
購入オプションを見ると、Heavy Usage がなくなって焦ったのでがんばって追いつきました。こちらの記事がたいへん参考になりました。

Amazon EC2のリザーブドインスタンスで重度の購入オプション拡充&軽度/中度の廃止 | cloudpack技術情報サイト

どうなったのか

三行で

  • 従来の "Heavy Utilization" のみに集約された
  • 初期費用の払い方で、最初に一括・半分払って残りは月々・初期費用無し月額のみ、の3つのオプションあり。真ん中が従来のと同じ
  • インスタンス起動の有無に関わらず料金は同じ

感想

基本Heavyで買って、AutoScale な部分をどうするか、〜〜〜、これは人間が考えるものではない!!!という議論をしていましたが、過去のものとなりました。使う分だけ買いましょう。
リソース確保のためだけに light っていうやり方ができなくなりました(最近はそんなに困らなくなったんでしょうか)。料金面では、頑張らなくて良くなった分、頑張っていたよりは高くなることもあるかもしれませんね。

おまけ

こういうので表にしました https://gist.github.com/tatsuru/fd048d331135b00b30b0

multilog が作るディレクトリのパーミッション

ここで固定されてる。
https://github.com/daemontools/daemontools/blob/master/src/multilog.c#L312
damontools-toaster で堅いこと言うなよ、というパッチを当てたりする。よい子は真似してはいけない。

diff -Naur ./src/multilog.c ../daemontools-0.76/src/multilog.c
--- ./src/multilog.c    2014-09-16 15:52:28.654130526 +0000
+++ ../daemontools-0.76/src/multilog.c  2014-09-16 15:51:25.779141973 +0000
@@ -309,7 +309,7 @@
   if (fchdir(fdstartdir) == -1)
     strerr_die2sys(111,FATAL,"unable to switch to starting directory: ");
 
-  mkdir(d->dir,0700);
+  mkdir(d->dir,0755);
   d->fddir = open_read(d->dir);
   if ((d->fddir == -1) || (fchdir(d->fddir) == -1))
     strerr_die4sys(111,FATAL,"unable to open directory ",d->dir,": ");

Docker Index Trusted Build してみた

Docker Index の Trusted Build ってやつをやってみた。
tatsuru/ikachan Repository | Docker Index
やり方はこの辺に書いてある通り Docker Index Help Documentation and Support | Docker Index

  • まずは適当にリポジトリを作る tatsuru/docker-images · GitHub
    • Dockerfile 1枚のリポジトリが並ぶのは嫌だったので、ikachan/ 以下に Dockerfile と README を置く。
  • Trusted Build のページから適当に Build 追加。Github の hook が作られる。
  • 自動ビルドされるので、 build statusのページ を眺めるだけ
    • Build Queue ってのがあって、自分の場合は20分くらい時間がかかった。CI的に使うには向いてなさそう。
  • ビルドされたら Transfer Queue に入って転送される。これはすぐに終わった。

repository information には README.md と Dockerfile がうまいこと結合されたやつが入ってた。
公開用のビルドは全部これでやると、たしかに安心できる。もうちょっと速くなればなぁ。

ikachan docker image

Ikachan が動く docker image 作った。
tatsuru/ikachan Repository | Docker Index
ikachan 動かしたいことがたまにあるけど、モジュールが入らなかったりして面倒だったので公開 docker コンテナにしてさくっと動かすようにした。何かツールを動かしたい時も、一式全部 docker コンテナにしておくと何も考えなくてよくなっていいな。
docker push が耐えられないほど遅くて、しかもたまにこけるので、よく使うやつじゃないとやる気がでない。

JAWS DAYS 2014 発表してきました

JAWS DAYS 2014
ちょっと前の話になりますが、JAWS DAYS 初参加・初発表してきました。発表については会社の方のレポートが詳しいのでそちらでどうぞ。
【イベント登壇レポート】JAWS DAYS 2014で、Miiverseの取り組みを弊社エンジニア渡辺が任天堂と共同で発表しました - Hatena Developer Blog
Jaws Days 2014 Miiverse // Speaker Deck

参加者としての感想をいくつか。

いろいろやりがいがある環境なのでどんどん改善していきたいと思います

よくサンプルにあるやつ

require 'aws-sdk'
ec2 = AWS::EC2.new(
  :access_key_id => ACCESS_KEY,
  :secret_access_key => SECRET_KEY,
  :ec2_endpoint => 'ec2.ap-northeast-1.amazonaws.com'
)

IAM role を設定したインスタンスだと、ACCESS_KEY, SECRET_KEY は自動で取得してくれて便利

ec2 = AWS::EC2.new

途中でリージョン変えるのは適当にこういう感じで

ec2 = ec2.regions[region]
ec2.instances.filter('instance-state-name', 'running')

client を使うとAPIだいたいそのまま叩けていいんだけど、この方法だと region 設定できないので注意する。そのまま多々気に入ってるだけみたい

ec2 = AWS::EC2.new
client1 = ec2.client  # これは us-east-1
client2 = ec2.regions['ap-northeast-1'].client # これも us-east-1
client3 = AWS::EC2.new(:ec2_endpoint => 'ec2.ap-northeast-1.amazonaws.com').client #ちゃんと設定すると ap-northeast-1 を向く

Regions and Endpoints - Amazon Web Services

Docker コンテナにアプリケーションを立てて Graphite でいい感じに可視化するまで

このときにやった可視化部分の話。急いで作ったのでいろいろ雑な部分が多い。
開発合宿でDockerとMesosを使っていい感じにリソース提供とデプロイするやつを作ってた - wtatsuru's blog

はじめに

元のやつから内部情報を削ったサンプルを置いておきます。適当にサーバ名など修正すれば使えるかもしれません。
https://github.com/tatsuru/docker-sample-app
全体の仕組みについてはここの図がわかりやすいと思います
Docker + Mesos + Marathon + Graphite + Fluentd + Sensuを組み合わせたデプロイ管理ツールの話 - ゆううきブログ

やりたいこと

  • 目的はアプリケーションの現状を俯瞰できるダッシュボードを作ること。
  • それぞれのDockerコンテナは短命なので、下記の情報をうまく集約してやる必要がある。
  • レイテンシとHTTPレスポンスの健全性。全体のログを集める必要がある。
  • CPUやメモリ使用率の推移。コンテナごと・アプリケーションのバージョンごとに見たい。

Graphite

Graphite - Scalable Realtime Graphing - Graphite
可視化は最初 Growthforecast あたりでやるつもりでいたけど、メンバーの一人から以下のような発言が出たため Graphite を使うことに。

2013-12-14 18:04:30     y_uuki  RRDtoolグラフみたくない

Graphite のドキュメントはこっちが最新らしいので注意。
Graphite Documentation — Graphite 0.9.10 documentation
グラフは '.' 区切りの階層構造で表現されていて、こういう感じで送りつけるだけでよく気軽に使える。

PORT=2003
SERVER=graphite.your.org
echo "local.random.diceroll 4 `date +%s`" | nc -q0 ${SERVER} ${PORT}

これで Graphite の "local.random.diceroll" に入る。

書式が Sensu plugin の形と同じ(!)なので、Sensu 側で送るのも簡単

  "handlers": {
    "graphite": {
      "type": "tcp",
      "socket": {
        "host": "graphite.example.com",
        "port": 2003
      },
      "mutator": "only_check_output"
    }
  }

Sensu で送って可視化

  • 全部 fluentd でやろうとすると、メトリクスまわりが面倒になってきた
  • Sensu Plugin だと標準出力に数字を出すだけで入れられてお手軽。メトリクスはまずこれで集めてみる
コンテナ単位の負荷を親からとる

集計は Fluentd

Graphite で描く

適切に名前空間を分けておけば Graphite のグラフを並べてdashboardを作れます(本物は見せられないのでスクショと xslate のテンプレートだけ。。)
こういう名前空間にしてみた

  • Sampleapp.{accesslog,errorlog} 以下にアプリ全体のアクセスログ・エラーログの集計結果
  • Sampleapp.sampleapp-$version.$container 以下に各コンテナから集計したメトリクス
  • docker.$dockerhost.sampleapp-$version.$container.{memory,cpu}.stat. 以下に docker ホストから集計したメトリクス
  • Graphite の glob だったり各種記法が便利
  • (whisperだと?)ファイルシステム上のファイルにそのままマッピングされるので、この調子でガンガン作るとそのうち破綻するかも
全体のdashboard

f:id:wtatsuru:20131222121938p:plain

  <p>
    <img src="http://graphite.example.com/render?width=350&from=-1hours&until=now&height=250&areaMode=stacked&target=[% ucfirst(service.name) %].accesslog.counts.app.*xx_count&title=Accesses" alt="accesses" />
    <img src="http://graphite.example.com/render?width=350&from=-1hours&until=now&height=250&areaMode=stacked&target=[% ucfirst(service.name) %].accesslog.gauges.app.access_*xx_percentage&yMax=100&title=HTTP%20Status%20Code" alt="http status code"/>
    <img src="http://graphite.example.com/render/?width=350&height=250&target=[% ucfirst(service.name) %].errorlog.gauges.count&lineMode=connected&from=-1hours&title=Errors&hideLegend=true" alt="errors"/>
  </p>
  <p>
    <img src="http://graphite.example.com/render?width=350&from=-1hours&until=now&height=250&areaMode=stacked&target=[% ucfirst(service.name) %].accesslog.gauges.app.access_0-100msec_percentage&target=[% ucfirst(service.name) %].accesslog.gauges.app.access_100-200msec_percentage&target=[% ucfirst(service.name) %].accesslog.gauges.app.access_200-500msec_percentage&target=[% ucfirst(service.name) %].accesslog.gauges.app.access_500msec-1sec_percentage&target=[% ucfirst(service.name) %].accesslog.gauges.app.access_1sec_over_percentage&yMax=100&title=Latency" alt="latency"/>
    <img src="http://graphite.example.com/render/?width=350&height=250&lineMode=connected&from=-1hours&target=[% ucfirst(service.name) %].[% service.name %]-*.*.load_avg.five&drawNullAsZero=true&hideLegend=true&title=Loadavg5" />
    <img src="http://graphite.example.com/render/?width=350&height=250&from=-1hours&target=docker.*.[% service.name %]-*.*.memory.stat.total_rss&drawNullAsZero=true&title=Memory%20Usage(RSS)" alt="memory usage" />
  </p>
各バージョンごとに

f:id:wtatsuru:20131222121945p:plain

    <img src="http://graphite.example.com/render/?width=400&height=200&from=-1hours&target=scale(derivative(docker.*.[% service.name %]-[% deploy_version.id %].*.cpuacct.stat.user)%2C0.01)&drawNullAsZero=true&title=CPU%20Usage" />
    <img src="http://graphite.example.com/render/?width=400&height=200&from=-1hours&target=docker.*.[% service.name %]-[% deploy_version.id %].*.memory.stat.total_rss&drawNullAsZero=true&title=Memory%20Usage" />

まとめ

  • docker で立てたアプリを sensu, fluentd から graphite に送っていい感じに可視化するやつを作ってみた
  • Dockerコンテナを作って壊す環境だと、中央で適切にクライアント管理しないとすぐに破綻しそう
    • Sensu Plugin でメトリクスを送るのは便利だが、クライアント一覧は破綻した
    • Graphite も、* でいけるうちはいいが、ここも数が増えるとつらくなりそう
      • 分散の仕組みもあるし、ベンチマークは同僚がやってたので期待してます
  • 集約する処理が入ると Fluentd で集めてさくっと処理するのが便利だった
  • Fluentd, Sensu 2つも動かしたくはないので、どちらかに一本化したい
    • 監視までやるなら Sensu でさくっとやると便利そう
    • sensu plugin の出力を fluentd/graphite にいい感じに渡す仕組みを作ればよさそう?
  • Graphite の記法が便利で楽しい
    • あくまで glob なので、GROUP BY 的なものなど機能不足は否めない。dashboard側でテンプレートから生成するなどの工夫は必要そう
はてなで一緒に働きませんか?