基盤開発観点からみたはてなのAWS活用のこれまでとこれから
こんにちは、id:wtatsuru です。この記事は、はてなエンジニア Advent Calendar 2018 8日目の記事です。昨日は id:taketo957 による aws-cdkを用いた開発事例の紹介 - taketo957の日記 でした。
このエントリでは、はてなでAWSをどのように使ってきたかを、サービス基盤の開発・運用の観点から振り返ります。
黎明期
はてなで最初にAWSをプロダクションに投入したのは2011年、はてなブログβリリース時でした。当時は EC2 のみのオンプレミス側と同じ構成からスタートしています。
VPNを張って共通のネットワークに置き、監視やセットアップでもオンプレミス側となるべく共通のものを使う、という思想で構築・運用を開始しています。今で言う EC2 Classic のみ、アカウントもrootのみという古典的な時代ですが、ELB, VPC, RDS など徐々にリリースされていくクラウドサービスを検証・導入していきました。オンプレミス側ではSSDがバリバリ活躍し始めた頃ということもあり、I/O 性能が出ずに苦しむことも多かった頃です。
共通基盤構築と利用の拡大
その後、AWS利用のノウハウが溜まって基盤整備が進み、新規構築でクラウドを使うことも多くなってきました。はてなとしては、Mackerel のリリースなどサービスの幅が広がっていく時期でもありました。
- はてなで新しくWebサービスを作るときのインフラの作り方 - Hatena Developer Blog
- はてなのサーバプロビジョニングについて / Hatena Engineer Seminar #6 - Speaker Deck
多くのサービスへ利用を拡大していく中で、はてな全体で共通の基盤を使っているゆえの課題が出てきました。
例えば、IAMの権限をAWSサービス単位で広く取っている物が多いために、別のサービスリソースを触ってしまう危険性があり、コンソールを触る際の安全性が低い、などが挙げられます。1つのものを触るときに影響する範囲が大きく、基盤レイヤに何かを導入するときには既存の共通基盤や多様なサービス全体を見る必要があるため、基盤開発メンバ以外がさわりにくい状況が生まれており、改善の速度自体にも課題を感じていました。
費用管理上も、どのサービスがどれくらい使っているのかわかりにくい、という課題がありました。この点はタグベースの費用分類である程度解消しています。サーバ構築時に流れる chef recipe から動的にタグ付けするなどの運用により、サービス単位の利用料金を把握できる状態としています。
コスト配分タグの使用 - AWS 請求情報とコスト管理
アカウント分離
クラウド利用が進み、そのメリットを活かしたサービス開発が行われる時代が来ました。はてなでも、Mackerel の AWSマネージドサービスを使った時系列DBの構築や、はてなブログの独自ドメイン証明書基盤などが開発され、今後ますます広がっていくと予想されます。プロダクト単位で必要なサービスをいかにうまく使えるかがサービス開発の鍵になります。
- 時系列データベースという概念をクラウドの技で再構築する - ゆううきブログ
- AWSではてなブログの常時HTTPS配信をバーンとやる話 / The Epic of migration from HTTP to HTTPS on Hatena Blog with AWS - Speaker Deck
そんな中、基盤部分をある程度独立させてサービスレベルのスケーラビリティを高めて開発速度を上げることを目的として、AWSアカウント単位での分離を進めています。AWS Organizations や VPC Peering などアカウントを増やしやすい状況も後押ししています。
基盤開発観点では、開発者が触りやすいように社内構成のドキュメントの整備とガイドラインの策定を行いつつ、アカウントを増やしやすい仕組みや、社内の標準形を探る検証を行っています。今年のインターン成果もその一例です。
以前から続いているサービスも多いためまだ分離は一部のサービスのみですが、新規構築分では分離しながら、既存アカウントのマイグレーションも徐々に進めていく予定です。今年の re:Invent でもマルチアカウントを助けるサービスが次々発表されています。AWS Transit Gatewayでネットワーク構成は大きく変わりそうですし、AWS Resource Access Manager もかなりマイグレーションに役に立ちそうな予感がしています。目まぐるしくベストプラクティスが変わる状況ですが、うまくサービス開発をスケールさせることができる形を探っていきたいと考えています。
『思考する機械 コンピュータ』を読んだ
- 作者: ダニエルヒリス,W.Daniel Hillis,倉骨彰
- 出版社/メーカー: 草思社
- 発売日: 2014/06/03
- メディア: 文庫
- この商品を含むブログ (8件) を見る
コンピュータの原理的なところから、プログラミング、並列コンピュータなんかに関してまで、平易な言葉でわかりやすく、かつ本質をついた説明がなされていた。個別の論点に終始してしまいそうな内容が短く綺麗にまとめられていて感動した。例えば暗号に関して、情報量と絡めて「潜在的には一定の規則を持ちながら、表面的には不規則な数字列をある方法で用いる」とある。概念や考え方はなんとなくわかっていたものの、ここまですとんと腑に落ちる説明には初めて出会った。
一番印象に残ったのは、序章のこの部分である。
コンピュータの面白いところは、コンピュータが本質的にテクノロジーを超越しているということであり、私はその本質について語るためにこの本を書いている。
最初読んだタイミングでははっとさせられ、読み進めるに従ってじわじわ納得し感動を覚えた。この目的があるからこそ、全体像をわかりやすく描き出せているんだろう。
情報系の素養がある人間ならさらりと読めるし、そうでなくてもじっくり考えれば読めるようになっている。一通り見直すにはちょうどよかった。高校生の時にこの本に出会っていたら、進む道は少し違っただろうか、と考えさせられる本の1冊だった。
ISUCON5 本戦出場してきました
ISUCON5 本戦に、同僚の id:motemen id:ichirin2501 と一緒に 2nd Party Cookies として出場してきました。
結果は7位に終わり、トップの fujiwara 組に3倍近い差をつけられてしまう結果となってしまいました。
まず全体
今回の題材は、社長が作ったマイクロサービスアプリの改善。予選の凝ったDB設計とアプリからはがらっと変わって、DBは PostgreSQL に変わったもののそこは焦点からは外れ、外部APIコールの最適化がメインのテーマとなりました。
予選に続いてとてもいい問題で、ベンチマークもスムーズで非常に楽しめました。運営の皆様は大変だったと思いますが、ありがとうございました。
個人的には、初動や全体の方針はそこまで悪くなかったものの、インフラ担当としての開発支援や視野の広さ、実現に持っていく力という部分での差の大きさを痛感しました。
当日の動き
Slack ログを見ながら、自分の動きを中心に振り返ってみます。自分以外のやつはちょっと間違いあるかもしれません。
開始から初動
最初の作戦会議
1時間くらい観察したところで作戦会議。
- `/data` で外部APIを叩きに行くところが支配的。リソースぜんぜん使い切れてない。ここをキャッシュするとよさそう
- DB が PostgreSQL で驚いたが、データ量も小さく触らなくてもよさそう。 endpoints テーブルをハードコードする以上のことはあまり必要なさそう?
- APIも手元から叩けないし PostgreSQL そのままだと通らない(結局プラグインが必要とのことでした)で、手元環境作るのけっこうしんどいと判断。3台あるので実験用には別のものを使う
まずはやれるところを
やり残したこと、まずやるとよさそうなことの準備を進める。
- 外部APIの接続先とリクエスト時間をログに残して観察。キャッシュで50倍くらいまではいけそう、などと検討
- nginx で keepalive, static file 配信(実はミスってた)
- 1台なのでまずは Gazelle + Unix domain socket 化
- memcached を1台用意してキャッシュする
- zipcode も郵便番号と住所なんだしAPI叩かなくていい?じゃあDBに入れるか、という大きめの改善を by id:motemen さんがサッと入れてくれた。かっこいい
- そろそろCPUを使い切ってるので、3台使ってみる。PostgreSQL 外部から接続でちょっと手間取ったが、これ以降は PostgreSQL 全く触っていない。
キャッシュを入れた時点で14519で暫定1位、zipcode で18768、全台使って 33774。このへんで14時過ぎ、勢いづいてくる。
いったん作戦会議を挟む。
ゆきづまり
特別賞が10万点ってことは、そのへんまではいけるはず、もっと飛躍が必要ということでいろいろ考える。
- static file のアクセスが目立つので gzip 入れて etag / expires などで改善という話を id:ichirin2501 とする。そして効かなかったので戻す。config のちょっとしたミスで効いてなかったことがあとで判明。。
- JSON parser 負荷高い、という仮説のもと id:ichirin2501 が改善を始める
- nginx のCPU使用率が目立つ。クライアントの keep-alive はわりときいてる。worker 2, Starlet にして proxy-app 間を keep-alive をきかせてみる。
- API リクエストの並列化は優先度高いのでは、という相談をしてそちらは id:motemen さんに依頼。
- サーバ構成で DB と nginx は分けてみた
何だかスコアが伸びないし fail しまくる、nginx 499 出まくっている、という現象に悩まされる。並列リクエストの方は、再現性の微妙なエラーで行き詰まる (endpoints の1つが1コネクションしか受け付けない、ということだったのでそれもあったかもしれない)。さらに zipcode のデータを全部メモリに読み込んでいた結果、swap 発生で全台死にかける、など散々な状況。デバッグしにくいものを実機上でデバッグしていたりして、互いにロックしてしまったのがもったいなかった。
復活
いったん元に戻し、あらためて一つ一つ見ていく。
- static file の配信まわりでミスっていたのを id:ichirin2501 の指摘により修正。マジ感謝
- proxy-app 間の keepalive をやめることで 499 大幅減少。間のいろいろな改善が効いて 52097。3位くらいだったと思う
- nginx ミスがわかったので再びクライアント最適化系を入れる。sys 減らそうとネットワーク系も少しいじる。
記録残すの忘れてるが、16:30過ぎくらいに 76000 くらいまでいってた気がする。トップまであと5万よっしゃいくぞ、と盛り上がった。この時点でもまだサーバリソースは使い切れていなかった。
失速、敗北
- 70000こえたあたりで、fail が目立ち始めた。API の内容をキャッシュしすぎている、というようなエラー。
- よく出る Tenki API のキャッシュを切ってみるものの、スコアが1桁落ちる。
- 一度再起動試験を入れて無事に成功。しかしスコアは全く伸びず。。
- id:motemen id:ichirin2501 2人がかりのキャッシュ対策を見守りながら、最後の1時間でマージするちょっとした改善の準備をさっと行う
- API の傾向とレスポンスを観察。tenki の Last-Modified が3秒おきなのを把握。If-Modified-Since つけてもダメ、と思ってしまったが、何かミスがあったような気がしてならない。。
- 特定のAPIのみのキャッシュ期間の調整がうまくいかない。バグがあったのかもしれない
- しょうがないので static file 関連の最適化を外し、わざと遅くすることで fail を防ぐ。5-6万あたりで安定して通るようになった
最終スコアは 57,492。fail してもおかしくない状態だったし、悔いの残るスコアになってしまった。
反省点
具体的な反省点。
これから
2年前のISUCON3 よりは手ごたえがありましたが、もうひと伸びの必要性を感じました。上位は全て出題経験者だったし、ひとまず社内ISUCONなんかで出題経験を積みたいなーとなんとなく思っています。
あとは普段の仕事を真面目にがんばるだけですね。。要素技術についてはそんなに負けてないと思うので、幅を広げる・考察を深めるというあたりに注意してがんばっていきたいと思います。
ISUCON5 予選通過しました
ISUCON5 予選に参加し、無事に決勝に進むことができました。今年は、社内で id:motemen id:ichirin2501 と、 2nd Party Cookies というチームで出場しました。id:motemen がアプリ、id:ichirin2501 はアプリ / DBまわり、自分はインフラ全般を担当しました。結果は総合10位で決勝進出ですが、同じく社内若手エンジニアのチーム「はむちゃん」に負けてしまって悔しさいっぱいです。
やったこと
- 事前準備として、分析等の環境整備用セットアップスクリプト、nginx / slowlog の解析準備、ミドルウェアよくある設定復習、デプロイ雛形あたりまではやって臨む。
- 最初1時間とってた準備時間でサーバ構成を把握して、サーバ環境整備+最初のログ取得・解析。2台立てて1台はsandbox化。
- 普段あまり使っていない systemd でちょっと手間取る。
- ログの分析結果とサーバリソース・使用状況を見つつ作戦会議。
- リクエストに加えてベンチマーカーの特性も観察する。
- ヘッダにルーティング情報入れて、alp で URL ではなくそちらで分析できるようにしたのではかどる。
- あとは MySQL, nginx, Plack あたりのチューニングをちまちま。/etc/my.cnf がダミーとは..。
- 昼過ぎくらいで一通り終わったので、やり残しを消化しながらクエリを見たり再起動対策したり。このへん、細かめの施策で時間を潰してしまいがちだったかも。
- 最後に再起動試験と変更コストの大きな変更トライ、そしてベンチマークガチャ。
振り返る
予選は堅実にやろうと考えて、ある程度の事前準備はやる、使ったことないものはなるべく使わない・副作用のありそうなことは必要に応じて最低限、という原則で臨みました。最低限の役割は果たせたと思いますが、攻めが足りなかったことと、もっとやりたいけど知見が足りなくて手を出せていない部分が少し残ってしまった感じがあったので反省です。とくに、普段使わないけどISUCONでは必要になるノウハウあたりはもう少し手を動かしておこうかなと思っています。
冒頭にも書いた通り若手に負けて悔しいというのは本当に大きいのですが、ISUCON3以来の出場でチーム数見てびびってた身としては、決勝進出できて若干ほっとしている部分があります。少し自信戻ったし、優秀なチームメイト2人もいるので、ぜひ優勝狙っていきたいと思っています。
運営の皆様、この規模は本当に大変だと思います。ありがとうございました。手ごたえのある問題、快適なベンチマーカーもよかったです。決勝も期待しています。
こちらもどうぞ
アプリとクエリ改善の戦略などは motemen さんのエントリにまとまっています。
ISUCON5 予選通過したが若手に負けました #isucon - 詩と創作・思索のひろば
はてなにおけるサーバリソース可視化とMackerel
こんにちは。id:wtatsuru です。
この記事は はてなエンジニアアドベントカレンダー2014 の19日目です。昨日は、 id:hakobe932 による golangで書かれたSlack bot でエンジニアに話題提供しよう - はこべブログ ♨ でした。
今日は、Webサービスのシステム運用において不可欠なサーバリソース可視化の、はてなにおける運用の簡単な紹介をします。
はてなとサーバ管理ツールと可視化
サーバを運用する上で、日頃のサーバのリソース等の可視化と監視は必要不可欠なものです。その対象はCPU使用率やメモリ使用量などのOSレイヤから、ミドルウェアプロセス状況、レスポンスタイムまで多岐にわたります。このデータを蓄積しておくことで、システムの状態を正確に把握し、問題に対処することが可能となります。*1
はてなでは以前から、内製のサーバ管理ツールでサーバの管理を行っていました。サーバが作られると中央の管理ツールに登録され、その役割から必要な情報を自動で取得・可視化する仕組みを作っていました。
はてな社内のサーバ管理ツールに関しては、id:y_uuki による以下のスライドが詳しいです。
YAPC::Asia 2013ではてなのサーバ管理ツールの話のはなしをしました - ゆううきブログ
システムが大きくなるほど、可視化の仕組みが大きくなるほど、気軽に新しいグラフを組み込むのが難しい、という課題が出てきていました。GrowthForecast 等の簡単に投稿・可視化できるツールを導入していたものの、やはりマスタ情報と一元管理された場所で見える、というメリットは捨てがたいものです。
Mackerelを使った可視化
今年リリースされた Mackerel には、そんな可視化のノウハウも詰め込まれています。
Mackerel は標準のエージェントを入れるだけで基本的な情報は可視化されますが、さらに独自のカスタムメトリックを登録することが可能になっています。カスタムメトリック取得は、下記のようなSensu形式の出力をするコマンドを登録する形をとっています。
{metric name}\t{metric value}\t{epoch seconds}
これにより、スクリプトをさっと書いてとりあえず入れておき、必要であれば全体に展開する、などの柔軟な運用が可能となっています。
実際に使用している、「さっと書いた」プラグインはこのような感じになります。
- X240 Battery Plugin for Mackerel.io
- ThinkPad X240 のバッテリ残量計。ファイルを読んでいるだけの簡単なものです
- Theschwartz job count plugin for Mackerel
- TheSchwartz のジョブ数を拾ってくるもの。もうちょっと複雑です
カスタムメトリックについて、詳しくはヘルプを参照してください。
ホストのカスタムメトリックを投稿する - Mackerel ヘルプ
公式プラグイン集
ミドルウェアのメトリック可視化に公式プラグイン集を使う - Mackerel ヘルプ
公式プラグイン集には、はてなで実際に試用されているミドルウェアのプラグイン等が取り込まれています。ここでは、「グラフの出力と定義を同時に配布できる」というもうひとつの特徴が試用されています。
はてなでも、基本的に全サーバにMackerelを投入しさまざまなメトリックを収集しております。
MySQL のグラフなど、ユースケースによってもっとこういうのが欲しい!というものがありそうなので Issue, Pull Request お待ちしております。
プラグインの作り方に関しては、以下の記事がとてもわかりやすいです。
Mackerel プラグインを書いてみよう - インフラエンジニアway - Powered by HEARTBEATS
まとめ
以上、はてなでのサーバリソース可視化の運用の簡単な紹介でした。社内の運用にも Mackerel を使用しつつサービス運用・改善に取り組んでおります。
明日は id:sakahara さんです。よろしくお願いします!
*1:まあ単純にグラフが並んでいるとわくわくしますよね。
crontab の割り算と大きな数字
crontab にこんなのが書いてありました
*/120 * * * * $COMMANDS
書いた人は2時間おきに実行したかったんだと思いますが、まあうそっぽいですよね。
ちなみに crontab(5) には "steps" と書いてあります。
Ranges can include "steps", so "1-9/2" is the same as "1,3,5,7,9".
ISC cron 3.0 の entry.c を観察。
まず *
は最小から最大まで、と同じ意味。なるほど。
if (ch == '*') { /* '*' means "first-last" but can still be modified by /step */ num1 = low; num2 = high;
で、num1-num2/num3
の形式で記述されてると num3
を step として単純に num1
から num2
まで増やしてる。大きすぎる数字を入れると一発目しか実行されない。
/* range. set all elements from num1 to num2, stepping * by num3. (the step is a downward-compatible extension * proposed conceptually by bob@acornrc, syntactically * designed then implmented by paul vixie). */ for (i = num1; i <= num2; i += num3) if (EOF == set_element(bits, low, high, i)) return EOF;
結論
大きな数字を書いても意味がない
Twitterでのやりとり
@songmu さんの言う通りの結論でした。
@tatsuru アスタリスクって、そのレンジのエイリアスみたいなものだから、*/120は、分だと0-59/120 と同じなので、0分だけ動きそう。もしくは動かない。
— songmu (@songmu) 2014, 12月 17
新しい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