Site Reliability Engineering #10

第Ⅲ部 実践

サービスを成功裏に運用するには次の活動が必要になる。

  • モニタリングシステムの開発位
  • キャパシティプランニング
  • インシデント対応
  • サービス障害の根本原因が解決されていること

サービスの健全性はサービスの方向性をコントロールするまでに至る複数の段階に分類される。

https://landing.google.com/sre/sre-book/chapters/part3/#fig_part-practices_reliability-hierarchy

  1. モニタリング
  2. インシデント対応
  3. ポストモーテムと根本原因分析
  4. テスト
  5. キャパシティプランニング
  6. 開発 7. プロダクト

まずはサービスの動作を明らかにする、インシデントに対応して問題を深く理解する、再発防止・予防を行う。 キャパシティプランニング以降は再発防止・予防まで行えてコントロールできるようになる。

Site Reliability Engineering #9

9章 単純さ

そうして費用をいくらつぎ込んでも、信頼性だけは手に入らない。 信頼性は、極限まで単純さを追求することでしか手に入らないのだ。

--- C.A.R Hoare、チューリング賞記念講演にて

プロダクションソフトウェアシステムの大部分では、安定性とアジリティをバランス良く調整しなければならない。 SREは信頼性を高めるためにプロセス、プラクティス、ツールを駆使してアジリティの犠牲を最小限に信頼性を確保する。 高い信頼性で素早くロールアウトできることでプロダクション環境の変更が理解しやすくなり、バグの発見と修正が短くなる。 信頼性を高めるためには予想通りに作業の目標を完遂する「退屈」なことが望ましいことが述べられている。

「退屈」であるためには必要な複雑さと想定外の複雑さを区別することが必要である。 必要な複雑さとは問題の定義から取り外せない本質的なもの、想定外の複雑さとはエンジニアリングによって解決できるものとある。 例えばWebサーバでWebページを高速に返すために必要な複雑さと、JavaでWebサーバを書いた場合のガベージコレクションがパフォーマンスに与える想定外の複雑さがある。 SREは想定外の複雑さがあるシステムに対して、システムの差し戻しや自身が継続的に取り除く努力を行うことがある。

24H365Dの稼働が求められるWebサービスでは新しいコードがある程度の負債と言える。SREは肥大化していくソフトウェアに対して削除していくことで潜在的な障害やバグの可能性を減らす

理想としては追加するものがなくなったのではなく、取り除くものがなくなった状態であり、分かりやすい最小限のAPIが目指すものである。

サポート可能なシステムを作成するにはシステムのコンポーネント疎結合にして単純にする。 単純さは開発者のアジリティとシステムの安定性を同時に高めてくれる。 システムがより複雑になるとAPI間やバイナリ間の責任範囲の分離が重要となる。 うまく設計された分散システムはスコープが明確ではっきりとした目的を持ち協調動作します。

ソフトウェアを単純にして信頼性を高め、ゴミが散らばらないように環境を保つことによって、本当のエンジニアリングが前進できるようにしてる。

Site Reliability Engineering #8

8章 リリースエンジニアリング

リリースエンジニアはソフトウェアをビルドし、リリースするまでの全てに関わる。 リリースエンジニアのスキルセットとして開発、設定管理、テストの統合、システム管理、カスタマサポートといった複数の領域に関する深い理解が必要と述べられている。

Googleではリリースエンジニアを1つの職能として位置づけ、ソフトウェアエンジニアとプロダクト開発を共にしてソースコードのコミットからリリースまでのプロセスを確立する。

リリースエンジニアはリリースエンジニアリング領域のメトリクスをレポートするツールも開発し、Googleのデータ駆動を支えている。

リリースエンジニアリングのガイドとして4つの原理で表されるエンジニアリングとサービスの哲学を持つ。

  • セルフサービスモデル
    • プロダクト開発チームが自身のリリースプロセスをコントロールできるようにプロセス整備と自動化をする
  • 高速性
    • リリースを頻繁に行うことでバージョン間の変更を少なくする
  • 密封ビルド

    • 一貫性と再現性を担保するためビルドプロセスは自己完結し、ビルド環境以外のサービスに依存させない
  • ポリシーと手順の強制

    • コードベースの変更にはほぼ全てのコードレビューが求められる。また、リリースまでに複数のセキュリティとアクセス制御を設け、リリース手順を保護している。

継続的ビルドとデプロイメントはCI/CDについて触れている。 ビルドツールを整備し、特定のリビジョンのメインラインからブランチを作成しチェリーピックするブランチ戦略、継続的テストの導入、プロダクションへのソフトウェア配布をするパッケージ管理システムが提供されている。

以上で述べた各プロセスのサービスを使い、リリースプロセスのワークフローを提供するシステムがRapidになる。

landing.google.com

Rapidは並列実行可能なシステムでプロセスを担当する外部サービスと組み合わせて動作する。 デプロイメントの設定は独自のblueprintsファイルで行い、権限設定も行うことができる。 Rapidの目標はサービスのリスクプロファイルに適合させることで、リリース頻度と安定性のバランスを取ることにある。 例えばリリース頻度を高めたい場合は1時間ごとにビルドしてテストをパスしたものはプッシュされる。 インフラストラクチャの重要な部分の場合、マルチリージョンのインスタンスに並行して交互にロールアウトするなどである。

リリースエンジニアリングは初期の段階で優れたプラクティスやプロセスを適用しておく方がコストは節約できる。

Site Reliability Engineering #7

今回から要約をしていきます。

7章 Googleにおける自動化の進化

自動化によるメリットが述べられている。

  • 同じ手順を間違いなく行う一貫性
  • プラットフォーム化したときの間違いの集約とバグ修正コストの低さ
  • 人手を介さない高速な修復によるMTTRの削減
  • 時間の節約と、副次的な属人性の排除

Google SREはプロダクトやサービスが地球全体に及ぶ規模を持っており、限られた人員でサポートするには自動化は避けられない。

2章で述べられていたモノリシックなリポジトリで運用することで、他の組織のプロダクトやサービスにいつでもアクセスできる環境を整えている。 また、重要なコンポーネントAPI化もして自動化を阻害しうる要因を排除することが会社として移管している。 自動化のためにはベンダー製品であってもAPIを内製して推進をしている。

これらは「プロダクション環境下のプロダクトを所有する」というGoogle SREのミッションに基づいた行動になっている。

自動化に取り組むにあたって抽象度の高い自動化ツール(Puppet、Chef)やPOSIXレベルの抽象度の低いPerlとの使い分けが述べられている。 高レベルでは要点を押さえた簡潔な処理が書きやすいが、抽象化に漏れがあると構造的な失敗が繰り返され、一貫性が損なわれやすい。 例えばクラスタのバージョン更新にあたって上手くいく処理は書きやすいが、更新中に障害が起きたときに「どちらでもない状態」が生まれ人手を介することになる。 一方抽象度の低いツールは部品化され、再利用がしやすいメリットが述べられている。

自動化の進化はデータベースの例に取ると、SRE個人が所有するフェイルオーバーのスクリプトを実行する外部からメンテナンスする状態から、データベース自身がフェイルオーバーを備える内部でメンテンナンスする状態を辿ると延べらている。

自動化のユースケースでは本質的な問題に腰を据えることで、人手を極力排除した例が述べられている。

  • MySQLをサーバからBorgに載せ替えて自動フェイルオーバーを実現して、運用コストを95%下げた
  • 1週間で5つのBorgクラスタを立ち上げために、クラスタの初期状態からネットワーク構築、クラスタ利用者が登録した構築手順まで自動化する自律システム

自動化の勧めとしては時間で投資対効果で測るだけではなく、自律的な運用を設計段階で組み込むことで運用を省力化にすることが役立つと述べている。

Site Reliability Engineering #6

6章 分散システムのモニタリング

6.1 定義

  • モニタリング
    • システムに関するリアルタイム定量データの収集、処理、集計、表示を行うこと
  • ホワイトボックスモニタリング
    • システム内部のメトリクスでログ、JavaVM Profiling interfaceなど統計情報が得られるインプット
  • ブラックボックスモニタリング
    • ユーザが目にする外部の振る舞い
  • ダッシュボード
    • 主要メトリクスのサマリビュー
  • アラート
    • 人間に読まれることを意図した通知
    • チケット、メールアラート、ページに分類される
  • 根本原因
    • 修正されたら同一の事象が起きないと確信できる原因
  • ノードとマシン
  • プッシュ
    • サービス動作中のソフトウェア、設定への変更

6.2 モニタリングの必要性

システム自身が壊れた、壊れる予兆を次のモニタリングとアラートによって人間に通知ができる。

人間へページすれば貴重な時間を消費することになる。 効率的なアラートは人間が取り組む対象に絞られた室の高いシグナルに絞り、ノイズを低く抑える。

6.3 モニタリングにおける妥当な期待値の設定

GoogleのSREチームでは10人〜12人のメンバのうち、担当するサービスのモニタリングシステムの構築とメンテナンスに1人か2人を割り当てる。

重要なのはプロダクション環境での人間へのページ、切り分け、デバッギングに至るクリティカルパスをチーム全員でシンプルかつ包括的に保つこと。

6.4 症状と原因

モニタリングシステムは何が壊れたか、なぜ壊れたのかという2つの疑問に答えなければならない。

症状は観測された振る舞い、原因は振る舞いを起こしたメカニズムである。

6.5 ブラックボックスとホワイボックス

ブラックボックスは「現在、システムが正常に動作していない」という症状を扱う。 ホワイトボックスはログやHTTPエンドポイントといったシステム内部を調査する機能に依存する。

6.6 4大シグナル

6.7 テイルレイテンシに関する懸念(あるいはインスツルメンテーションとパフォーマンス)

レイテンシの傾向を判断するには算術平均よりも、ヒストグラムが優れている。 例えばリクエストの1%が低速の原因を占めることが起きうる。

6.8 適切な計測の粒度の選択

システムの様々な側面が粒度のレベルを変えて測定するべきである。 粒度を細かくしすぎると収集、保存、分析のコストが増大するため、バランスに注意する。

バランスを取るにはバケット化することで知りたい粒度にしながらコストを軽減できる。

  1. CPU使用率を毎秒記録する
  2. 記録した使用率を5%刻みのバケットに入れてインクリメントする
  3. 1分単位でバケットを集計する

6.9 可能な限りシンプルに、ただしやりすぎないこと

モニタリングシステムの設計はシンプルさに目を向ける。 モニタリングシステムが複雑になりすぎると、複雑でメンテンナンスが負担になりうる。

モニタリングの対象を選択するには次のガイドラインに沿って検討する。

  • 本当のインシデントを最も頻繁に捉えるルールは、可能な限りシンプルで予想しやすく信頼できるものであるべき
  • 四半期に1回未満のデータの収集、集計、アラートの設定は削除すべき – 収集されていてもダッシュボードに表示されない、アラートに使われていないシグナルは削除の候補である

6.10 原則の取りまとめ

モニタリングやアラートのルールを作成する際には以下の質問に沿って要否を判断する。

  • ユーザに近い将来含めて影響を及ぼす、ルールなしでは検出されないものか
  • アラートを放置しても影響がないものか
  • ユーザに悪影響が生じていいることを示しているか
  • アラートに対してアクションが取れるか、不要不急なものか
  • ページを受ける人が複数か、そうであるならば1人にできないか

6.11 長期間に渡るモニタリング

今日発生している一つ一つのページに人が対応するのは、明日のためのシステム改善にあてる時間がなくなる、というトレードオフの関係にある。 システムの長期的な展望を改善するために可用性なパフォーマンスの短期的な低下を受け入れることもある。

6.12 まとめ

メールアラートの価値は限定的でノイズになりやすい。代わりにダッシュボードでモニタリングすると良い。 長期的にはオンコールのローテーションとプロダクションを成功に導くため、達成可能な目標にターゲットを合わせてモニタリングシステムが素早い診断を確実に支援できることが必要である。