第3回のオンライン輪読会に備えて読んだ内容を自分なりにまとめておく。
今回の記事はこちら。
[期待/予想する内容]
この記事の目次は次のとおりである。
- はじめに:真っ先にログに取り組む
- インストルメンテーションする理由
- 測定対象
- ドリルダウン
- インストルメント方法
- ログ記録によるインストルメンテーション
- Amazonのベストプラクティス
- ツール
- まとめ
「はじめに:真っ先にログに取り組む」……ログは大事。先日も、開発中のアプリケーションで不審な動作があったので、ログも読まずに適当にあたりをつけてコマンドを流したものの原因が想定と異なっており、全く状況が改善しないことがあったばかり。ログは大事。開発する時にキチンと記録するようにしておかないと、そもそもトラブルシューティングができない。ログは大事。
「インストルメンテーションする理由」……インストルメンテーションという見慣れない用語が出てきた。前節との関連でいうと、ログと何か関係があるのだろうか。ログが出るようにSystem.out.printlm()とかconsole.log()を埋め込むこと?理由はトラブルシューティングや監視のためなど様々あると思う。
「測定対象」……ログに記録するといっても、何を測定し、記録するべきか。難しい問題である。サーバーベースのアーキテクチャなら、メモリやCPUの使用率も重要だろうし、サーバーレスなアーキテクチャなら、各コンテナの実行時間とか同時起動数とかだろうか。このあたりは、前回の輪読会で読んだ内容と重なっている気がする。
「ドリルダウン」……AWS X-RayとかAppDynamicsとかで、システム間のリクエストの概要から詳細にどんどんクリックして進んでいける、みたいなやつかな。それと、分散システムを装備するってどういうことだろう?分散システムに、ドリルダウンできるような、測定対象のメトリクスを記録する機能をつけておくとか、そういうことかな。
「インストルメント方法」……で、そのメトリクスをログに記録するための実装方法、とかそういうことか。ここまで見て思ったけど、「装備する」と「インストルメント」って同義なのか?Musical instruments =楽器、みたいな。
タイトルの原題を見たら、同義のようだ。同じ意味なら特別な事情がない限りは同じ訳にして欲しいなあ……前回の翻訳もそうだけど、ABLの翻訳はちょっと残念な感じがある。
「ログ記録によるインストルメンテーション」……と思ってたら、ログ記録がタイトルに出てきた。ということは、ログ記録以外のインストルメント方法、実装方法もあるってことかな。あ、X-RayもAppDynamicsも専用のAPIにデータを突っ込む方法だから、ログ記録とはちょっと違うか。
「Amazonのベストプラクティス」……これは、ベストプラクティスがX-Rayに結実しました、とかそういう話……だと嬉しいなあ。前回の記事でも、負荷分散のベストプラクティスを取り入れて、ELBがClassicからALBへ進化したって話があったし。
[記事の要約]
次に、実際に記事を読んだ内容を箇条書きでまとめる。
はじめに:真っ先にログに取り組む
- ウェブサーバーで問題発生:ログを見て何が間違っているか確認すべき
- ログファイルにアクセスするツール:cat, sed, awk, grep
- 起動に失敗する構成(設定)、クラッシュする可能性がある場所、通信に失敗した箇所などがわかる
インストルメンテーションする理由
- システムの仕組みを学ぶため
- 顧客に提供しているエクスペリエンスを確認するため
- 特に、平均レイテンシだけでなく1件でも異常値がないかが重要
- 1つのサービスが相乗効果で他のサービスに影響することもある
- サービスの運用パフォーマンスに目標を設定するためには、インストルメントして可視性を確保する必要がある
測定対象
- システムの動作:可用性とレイテンシ
- システムをブラックボックスにしない:タスクの所要時間、特定のコードパスの実行速度、タスクのメタデータ、タスクの成否を明示的に記録する
- 分散システムの場合、システム間で共通のトレースIDを利用する(AWS X-Rayなどを利用)
ドリルダウン
- リクエスト率、エラー率、レイテンシなどのメトリックから、未加工のログにたどり着けるように
インストルメント方法
ログ記録によるインストルメンテーション
- 2種類のログ:リクエストデータとデバッグデータ
- 構造化されたリクエストログ:リクエストプロパティ、実行者、発生頻度、所要時間など
- 構造化されていないデバッグログ:エラーや警告。分析しやすくするため、リクエストログとは別のファイルに出力
Amazonのベストプラクティス:どう記録するか
- 作業単位ごとにログエントリは1つだけにする
- 長時間かかる作業では、複数のログエントリに分割して出力する
- バリデーション前にリクエストの詳細を記録する
- 動作中のアプリケーションのログレベルを変更する方法を用意する
- メトリック名を短く(例:Amazon Ion)
- サービスの最大スループットに耐えるログ書き込みディスクを用意する
- ディスクがいっぱいの時の動作をテストする
- クロックを同期する
- ログメトリックのゼロカウントを生成する
Amazonのベストプラクティス:何を記録するか
- 全ての依存サービスの可用性、レイテンシを記録する
- コールごと、リソースごと、ステータスコードごとなどの依存関係メトリックを分割する
- キューを利用する場合、キューの深さを記録する。キュー内の滞留時間も。
- エラー理由ごとのカウントを記録する(例:クライアントの問題かサーバーの問題か)
- 作業単位の重要なメタデータ(例:DynamoDBのテーブル名、一貫した読み取りかどうか)
- ログを暗号化し、アクセス制御して保護する
- プライバシーを保護するため、ペイロードをログに含めない
- トレースIDをログに記録する
- ステータスコードやリクエストサイズに応じたメトリックを作り、メトリック汚染を避ける(例:SmallRequestLatency、LargeRequestLatency)
Amazonのベストプラクティス:アプリケーションログ
- 本番環境ではinfo/debugレベルのログはオフにしてノイズを減らす
- エラーに対応するリクエストIDを含める
- ログを記録する頻度を制限し、大量のエラースパムを避ける
- 出力されない文字列のフォーマットを行わない
- 失敗したサービスコールからのリクエストIDをログに記録する
Amazonのベストプラクティス:高スループットサービス
- サンプリングしてログに記録する
- シリアル化とフラッシュを別スレッドに任せる
- ログローテーションを頻繁に行う
- 事前に圧縮されたログを書き込む
- ディスクではなくメモリに書き込む
- インメモリで集計する
- リソース使用率を監視しスケーリング限界を見極める
ツール
-
ローカルログ分析:jq、RecordStream
- 分散ログ分析:CloudWatch Logs Insights、AWS X-Ray、Amazon Athena
[予想のふりかえりなど]
コード上にログを埋め込むところから、AWS X-Rayが出てくるあたりまで、おおよそ事前に期待していた内容が書かれていた。
期待したとはいっても、特に詳細の部分についてはやはり自分はまだまだで、とても勉強になる部分が多かった。プライバシーを保護するために、ペイロードをログに含めないというのは自分も意識している部分ではあるが、例えば高スループットサービスのログ・ベストプラクティスで「事前に圧縮したログを書き込む」なんてのは想像もしていなかった。やはりアプリケーションの規模が違うと、見えている世界も全然違うんだな。
他にも、リクエストやレスポンスの種類に応じてメトリックを作り分ける手法とか、サービスコールのリクエストIDをログに含めるとか、基本的というか、AWSの作りを見ているとうっすら理解できる部分が詳しく文章化されていて、とても良かった。
今後の実務でのログやメトリックの実装の際にはぜひこの記事を参照したい。
そういう意味では、Amazon Ionというツールの存在を知ることができたのは大きな収穫だった。バイナリシリアル化のためのツールということくらいしか、今はまだ分からないが、輪読会初回で読んだように、シリアル化はバージョンアップの大きな障害となりうるので、きっと役に立つ気がする。
前回も書いたけど、翻訳がちょっと残念だ。この記事では、コードコメントとかそもそも翻訳されていない。せめて記事内で同一の英単語は同じ訳にして欲しい。タイトルでは「装備する」なのに、本文では「インストルメントする」では理解の妨げになる。
GitHubとかでOSSになってれば、一文ずつでもプルリクエスト送るんだけどなあ……。
[まとめ]
- 「The Amazon Builder's Library」の『運用の可視性を高めるために分散システムを装備する』を読んだ
- 分散システムを運用する上での、ログとメトリクスのHow/Whatについて詳細なベストプラクティスが書かれている(ぜひ再読して実務に生かしたい)
- ログのバイナリシリアル化のためのAmazon Ionというライブラリが良さそう
引き続きAmazon Builder's Library読んでいくぞ。