しょ〜うぃん広場

おもにTech系なブログ、ときどき個人的なブログ

SRE本を読んだので概要をまとめてみた

2020年10月からSREになったので、そもそもSREとはどんな役割をもった職種なのか理解しないと行けないなと思って、Googleが出している Site Reliability Engineering (通称: SRE本) を読んでみた。

500ページもある厚い本なので、一人で読むのは途中で挫折しそうな感じがして、社内で輪読会を開いて読んでいくことにした。 毎週50ページぐらい読んでくるという少しハイペースで進めたが、2ヶ月半ぐらいかけて2020年末に無事全部読み終えることができた。 インフラは自分1人がメインで見ていて、サブで2人サポートしてくれるような体制なので、その3人+αで輪読会をして共通認識を得られたのはとても良かった。

2017年に出版された本だけれども、時代遅れな感じを受けることは全くなく、むしろ10年前からこんな運用してるGoogleすげーという感じで学ぶことばかりだった。 (Googleの自社自慢や社内話がところどころに散りばめられていて、Google SREの採用活動のために書かれた本 or 入社前のオンボーディング必読書として書かれた本なのでは?と思うことが多々あったが)

自分が読みながらまとめた概要を以下に書いていくので買おうか迷っている人はざっくり見てもらうと良いと思う。 全体を把握できるように丁寧に概要を書いたというよりは、自分がへぇ〜と思ったところをよく抽出しているので偏っている部分もあると思うがご了承頂きたい。

ちなみに、SREの役割・仕事内容についての理解を深めたいのであれば6章までの70ページぐらいを読めば十分であり、それ以降は自分の興味があるところだけかい摘んで読むのが効率が良い。 最初の70ページのためだけに5000円払うのでも価値がある内容である。

英語版は無料で公開されているので、英語ですらすら読める方はそちらをどうぞ。 (ちなみに社内輪読会でも普段技術書で英語を読み慣れているメンバーが英語版を読んでいたが、SRE本は技術書というよりは物語に近いので普段出てくる単語と傾向が違い大変だったと言っていた)

以下、章毎に概要。 (計2万字強あるのでまともに読むと大変だよ)

1章 イントロダクション

・昔は複雑なコンピューティングシステムを動作させるために、システム管理者(シスアド)を企業は雇ってきた。既存のソフトウェアコンポーネントを組み合わせてデプロイするような仕事。イベントに合わせて負荷対策をするのもシスアドの仕事。

・シスアド(運用, ops)は機能開発をするエンジニア(dev)とは異なるスキルセットが求められるので、devとopsという別のチームに分かれることになる。

・しかしそれが分けれていることで、コストがかかる。直接的なコストは複雑度や規模が上がるに従って、手作業で行っていてはそれに比例してチームを大きくしなければならないこと。間接的なコストはdevとopsで目標も使う言葉も異なることで、チームの間に溝が生まれてしまうこと。

・SREとはソフトウェアエンジニアに運用チームの設計を依頼したときに出来上がるもの。(従来は手作業で行っていた作業を自動化するもの)

GoogleのSREの5~6割は一般的なGoogleのソフトウェアエンジニア。残りの4~5割は、Googleの一般的なソフトウェアエンジニアのスキルを85~99%しか持っていないが、シスアドとしての特別な知識を持っている人。(代表的な2つの知識はUNIXシステムの内部とL1~L3レイヤのネットワーキングについて)

・そのハイブリッドなチームにしたことで、今までのシスアドが手作業でやっていたものを自動化することができ、多様性により勝利した。

・チケット、オンコール、手作業といった「運用」にかかる時間を最大50%として、それらを自動化することを目的としている。

・SREの責任範囲は「サービスの可用性、レイテンシ、パフォーマンス、効率性、変更管理、モニタリング、緊急対応、キャパシティプランニング」。この責任範囲は本番環境に限らず、開発環境やテスト環境も含まれる。

・コーディングスキルを使う時間を最低50%は確保するために、超過した場合にはバグとチケットを開発チームに戻すことをする。オンコールに開発者をアサインしたりもする。50%を確保できるようになったらそのアサインはまたSREに戻す。

・これをすることで、開発者にも自動化をすることのインセンティブが働くようになる。

Googleでは8~12時間のオンコールシフトの間に受け取るイベントは平均して最大2つ。それ以上あると振り返りができない。

・信頼性の目標として何%を目指せばよいのかは、以下を考えると良い。

・プロダクトの利用方法を踏まえて考えたとき、ユーザが満足する可用性のレベルはどの程度か
・プロダクトの可用性に満足できなかったユーザにとって、どのような代替策があるか
・可用性のレベルを変更したとして、ユーザのプロダクトの利用の仕方に何が起こるか。

・アラートはソフトウェアが解釈を行い、人間はアクションを行わなければならないときのみ通知を受け取るようにするべき。

・モニタリングの種類は以下の3つ。

・アラート: 人間が即座にアクションを起こして対応しなければいけないことが生じている、あるいは生じようとしていることを知らせる。
・チケット: 人間がアクションを起こさなければ修復できないが、数日かかったとしてもその結果障害が引き起こされることはないもの。
・ロギング: 人間が見る必要はないもの。何かが起きない限り誰かが読むことは想定されない。

・緊急対応に対して、手順書があると即興で行った場合に比べて3倍早く対応できることが知られている

・70%のサービス障害は動作中のシステムの変更によって引き起こされている。

2章 SREの観点から見た Googleのプロダクション環境

・以下用語整理。

・マシン: ハードウェアのことを指す。
・サーバー: サービスを実装しているソフトウェア (マシン上に構築)

・データセンターのマシンクラスタ内では頻繁にハードウェア障害が起きるので、それに影響を受けないように抽象化する必要がある。(Borg, k8s)

・Borgのジョブは再起動すればIPもportも変わるので、BNS(Borg Naming Service)で解決する

・利用できる平均のネットワーク帯域の最大化をソフトウェアで管理しているのがすごい

・ロックシステム(Chubby)とかモニタリングシステム(Borgmon)とか内製している。

Googleの全てのサービスはStubbyというRPCを使って通信する。OSS化されているのはgRPC。

・GSLB(Global Software-Load Balancer)のロードバランサーがリバースプロキシ、フロントエンドサーバ、バックエンドサーバへのリクエストをすべてバランシングしている。(しかも単純なアルゴリズムではなくて、負荷が低いサーバーへリクエストを流している)

・アクセスのピーク + 2 台のpodがあることが望ましい。

・1つはローリングアップデート用。

・1つは障害が起きた場合。(2つ同時に起きる確率は極端に低いと考えられる)

・Writeの頻度が少なければGlobal Replicaは有効。

3章 原則

・トイル: 日常的に繰り返される運用上の作業で、永続的な価値を生み出さず、サービスの成長に比例してスケールするもの。

・可用性を向上させるとコストは比例ではなく、指数的に増えていく。信頼性を担保しながら開発速度を上げていくバランスが大事。

・可用性のターゲットレベルを決める要素

・ユーザが期待するサービスのレベル
・ユーザが直接的に(サービスのステイクホルダーに対しての)収入につながっているか
・サービスは有料か、無料か
・市場に競合がある場合、強豪が提供しているサービスのレベル
・サービスはコンシューマ向けか、企業向けか (企業向けは高めに設定)
・サービスのフェーズ (成長フェーズなら低めに設定)

・G SuiteのSLAは99.9%。SLOは必然的にもっと高い。

・エラーバジェットの形成方法

・PdMがQのSLOを規定する。

・稼働時間を計測する

・SLOと実際の稼働時間の差分(余剰)がエラーバジェットとなり、残っているのであれば新しいリリースをpushできる。

・エラーバジェットを使い切ってしまったのであれば、リリースは停止して、システムの弾力性を増したり、パフォーマンス改善、テストの追加をしたりする。

4章 サービスレベル目標

・SLIは本当に計測したい値とは異なる代替の値を使わないと行けないこともある。例えば、レイテンシは本当はクライアントサイドのものを計測したいが難しいので、サーバーサイドのレイテンシを代わりの値として使う。

・よく使われるのは可用性で、処理に成功した正常なリクエストの数の比率で計測される。

・最初から厳し目のSLOを定義するよりは、緩めに定義していって達成できたらあげていくほうが良い。

5章 トイルの撲滅

・トイルとは、手動で行う運用作業のこと。

MTGやアラートの設定のクリーンアップなどはトイルではない、本番環境を動作させることに関連する作業で、繰り返し行われ、長期的な価値をもたないもの。

・トイルが多いと、キャリアの停滞やモラルの低下(不満の増大)などにつながる

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

・ホワイトボックスモニタリング: システムの内部によって公開されているメトリクスにもどつくモニタリング。

ブラックボックスモニタリング: ユーザが目にする外部の振る舞いテスト。

GoogleではSREチームの開発リソースの1割ぐらいをモニタリングシステムの構築とメンテナンスに使っている。

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

・4大シグナル (4つだけモニタリングできるとすればこれらを選ぶべき)

・レイテンシ
・トラフィック (リクエスト数)
・エラー (処理に失敗したエラーレート)
・サチュレーション (サービスの手一杯度。最も制約のあるサービスのメモリやCPUは十分か)

・モニタリングの仕組みは複雑にしすぎるとメンテナンスが難しくなるので、できるだけシンプルに保つように心がけること。

・無視されるアラートは本当に必要なのか考えるべき

・それほど重要ではないが気になるアラートはダッシュボードでモニタリングできるようにしておくと良いかもしれない。

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

・自動化のメリットは、時間が短縮されるだけではなくて、一貫性を保つことができることも上げられる。手作業によるオペレーションミスを防ぐことができる。

・自動化を進める上で、外部のベンダーに頼ってしまうとAPIが提供されていない場合があるので、できるだけ内製化を進めてきた。短期的にはコストになるが、長期的には資産(大きなメリット)になる。

・デプロイに関して言えば、PerlやChef,Puppetなどがある。全社は複雑な環境においてかゆいところまで手が届く。一方シンプルな構成であれば後者のほうが再利用しやすくエコシステムにも乗ることができる。

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

・リリースエンジニアの仕事

・理解が必要: ソースコード管理、コンパイラ、ビルド設定、自動ビルドツール、パッケージマネージャ、インストーラ

・スキルセット: 開発、設定管理、テストの統合、システム管理、カスタマーサポート

・リリースエンジニアはSWEと共にプロダクト開発を行いつつ、SREと共にリリースのステップを規定する。

カナリアテスト、ロールバックなどもリリースエンジニアとSREが共同で戦略を考え構築する。

・リリースエンジニアリングの4大要素

・セフルサービスモデル: リリースが完全に自動化されていて、人間が手を出すのは問題があったときのみ。
・高速性: できる限り早くロールアウトできる必要がある。1時間ごとにビルドを行って、そのうちリリースするものを選択するチームもあれば、テストが通れば毎回そのままリリースするチームもある。
・密封ビルド: 1ヶ月前のバージョンであればその当時の環境でビルドされた結果が得られること。
・ポリシーと手順の強制: リリースに関する作業は行って良い人が決まっている。

9章 単純さ

・SREはソフトウェアの信頼性を高めるための手続き、プラクティス、ツールを作成するために働く。それと同時にこの作業がアジリティに与える影響を最小限に抑える必要がある。

・コード1行1行を負債と捉えることができるので、定期的にデッドコードを削除したり、肥大化したコードを検出する仕組みをあらゆるレベルのテストに組み込むようにする。(小さなアプリケーションはバグりにくい)

・リリースも小さい(単純)な方が何が影響してデグレしたのか原因がつかみやすいし、APIも単純な方が(影響範囲が小さくて)バグりにくいし、修正も早く行える。

第三部 実践

サービスの信頼性の階層

基礎から順に

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

モニタリングがされていなければ。視界を閉ざされたまま飛行しているようなもの。

10章 時系列データからの実践的なアラート

・Borg(2005年)のモニタリングサービスとしてBorgmonが生まれた。

・Borgmonの設計思想は今のPrometheusにかなり近い。

・アラートのためにデータソースとして時系列データを使うというのはBorgmonから始まり、最近のOSSの監視ツールの標準になってきた。

・Bogrmonのログ収集の設計はDatadogのログ収集構成と似ている感じがする。

・各podにscraperがいて、クラスタ単位で集約して、グローバルBorgmonに飛ばす

・Borgmonで監視できるのはホワイトボックステスト(内部からの視点)だけなので、外部からの監視(ブラックボックステスト)もやる必要がある

・モニタリングのメンテナンスコストがサービスのサイズに比例しないように設計していくことが大事

11章 オンコール対応

・理想のレスポンスタイムは、時間に対する要求が厳しいサービスであれば5分、そうでないものは30分以内に対応するのが望ましい。

・オンコールチームは、プライマリとセカンダリのローテーションを用意して、プライマリが見過ごしたものはセカンダリが対応する。

・マネージャーはオンコールの量と質でメンバーのバランスを取る必要がある

・量: ローテーションの時間
・質: 対応したインシデントの数

・業務全体の50%以上はエンジニアリングに。オンコールは残りの時間の25%以上にならないようにする。

・つまり、プライマリとセカンダリで1人ずつ用意するためには最低8人のエンジニアが必要。

・根本原因の分析、改善、ポストモーテムの執筆、バグの修正までやると1件あたり平均6時間かかる。つまり12時間のシフトで2件の対応が限界。

・過負荷にならないためにはシフト中の発生数の中央値は0であるべき。

・時間外のオンコールには適切な補償を検討すべき。

・困難に直面した時、近年の研究の結果人間は反射的に行動する場合と理性的に慎重に行動する場合と2パターンに分かれることが分かっているが後者の行動をすべき。

・経験則に頼るのは良くない。4つの障害のうち最初の3つが外部サービスによる障害だったら、4つめも何も見ずに同じ障害だと考えてしまいがち。

・アラートはSLOを脅かす症状に対して行うべき。

12章 効果的なトラブルシューティング

・物事がうまくいく場合といのは、おかしくなる場合の中の特殊な例の一つ。

・問題があった場合には直接誰かに伝えるのではなく、皆が見える場所にチケットとして残しておく。それはあとから参照できるようにするため。

・問題を知っている少数のメンバーで対応して負荷が集中することになってしまう。

トラブルシューティングでは最初に根本原因を突き止めたくなるがその動きは良くない。重要なのは被害をそれ以上に広げないこと。

・システムがその環境下ができるだけうまく動作するようにすること。例えば、まだ生きているクラスタトラフィックを流す、一部のリクエストをドロップして負荷を下げるなど。

・場合によってはシステムをすべでダウンさせることも被害を広げないためには必要。

・否定的なデータは価値がある。(同時コネクション800以上にするとエラーが出たなど。)こういうものは積極的に外部に公開していくことで、他の人が同じ実験をしなくてもよくなる。

・特に意外だと思った結果ほど他の人にとっては価値のあるものになる

13章 緊急対応

・プロダクション環境のバックアップアクセスを持つ専用のセキュアルーム(パニックルーム)があり、必要に応じてそこに集まる。

Googleは社内システムにも自社サービスを使っているので、それが落ちると社内でもコミュニケーションが取れなくなる。

・自動処理のバグによって一気に全台に悪影響が広がってしまうこともある。オートメーションは停止でき、人間による手作業でも操作できるように設計しておく必要がある。

・インシデントを起こした人が一番状況が分かっているはずなので、その人に協力してもらうことは大事。

・同じことを二度と起こさないために、過去に何が壊れたのかをきちんと記録しておく。

・ポストモーテムで書いた改善点は確実に行うこと。

・大きな、むしろありそうもないような問いかけをしてみよう。主要なサーバーセンターが突然沈黙したら、だれかがDDoSを仕掛けてきたら…

14章 インシデント管理

・インシデントの状況をみたメンバー各々が、各自で思いついたアイデアを本番に適用していては何をして事態が改善した/悪化したのかわからない。きちんとコミュニケーションを取ることが必要。

・インシデント時はきちんと役割分担をして、他人の領域に踏み込んでしまわないことが大事。

・役割一覧

・インシデント指揮者: インシデントに対する高レベルな状況把握をする。事実上移譲していないすべての役割を担う。
・実行作業: システムを修正するのは実行作業チームのみ。
・コミュニケーション: ステークホルダーに対して定期的に最新情報を発行する。ドキュメントを正確かつ最新の状態に保つことまで受け持つ場合もある。
・計画者: 長期的な課題を扱うことで実行チームを支援する。バグの登録、夕食の発注、引き継ぎの調整など。

・インシデントが発生したときに集まる部屋があることが大事。遠隔チームであればIRC(Slack)を使うと記録が残って良い。

・複数人が同時に編集できるライブドキュメントがあるとよい。GoogleではGoogle Docsを使っている。

・付録Cにテンプレートがある

・ベストプラクティスまとめ P.173

15章 ポストモーテムの文化: 失敗からの学び

・ポストモーテムを書く目的は、インシデントがドキュメント化されること、影響を及ぼした根本原因が十分に理解されること、再発の可能性や影響を削減するための効果的な予防策が確実に導入されるようにすること。

・ポストモーテムを作成するかどうかは以下のような基準で判断される。

・ユーザに影響を及ぼしたダウンタイムが一定のしきい値を超えた場合
・データの損失が生じた場合
・オンコールエンジニアの介入が必要だった場合
・解決までの時間が一定のしきい値を超えた場合
・モニタリングの障害 (人手でインシデントが発見された場合)

・事前にポストモーテム作成の基準を明確にしておくと良い。

・ポストモーテムにおいて大事なことは、インシデントに関わりを持ったすべての人が知り得た情報をもとに善意でとった行動であるという前提で、人に対して批判をしないこと。

・ポストモーテムのテンプレート: 添付D

・ポストモーテムを書く文化を根付かせるために、過去のポストモーテムを振り返るポストモーテム読書会をやったり、過去のポストモーテムをロールプレイする不運の輪をやったりするとよい。(楽しい軽食と共に)

16章 サービスの障害の追跡

Googleにはサービス障害のログを残す Outalator という社内サービスがある。

・この四半期におけるアクション可能アラートと不可能アラートの比率を集計したり、メンバーごとの対応オンコール数の集計などができたりする。(アラートのエスカレーションの仕組みも入っていたりする)

・1つのインシデントが複数箇所に影響を及ぼす場合、それぞれのチームに独立してアラートが行くのは効率が悪いため、それらは1つの原因によって起きているというグルーピングをしたい。

・アラートが偽陽性の場合もあるので、ラベルを付与できるようになっている。

17章 信頼性のためのテスト

ユニットテスト: テスト駆動開発の概念を取り入れるために使う

結合テスト: コンポーネントが正しく動くことを確認する

システムテスト: デプロイされていないシステムに対してエンジニアが実行するテストとしては最大規模のもの。エンドツーエンドでテストする。

・スモークテスト: 単純で重要な挙動をエンジニアが確認する

・パフォーマンステスト

回帰テスト: 過去に起きたバグのテストケースたち

・本番環境に対するテスト

ブラックボックステスト

・設定テスト

・ストレステスト: データベースはどこまでいっぱいになると書き込みに失敗するか。

カナリアテスト

18章 SREによるソフトウェアエンジニアリング

GoogleのソフトウェアといえばGoogle MapやBigTableのようなものを思い浮かべるが、社内向けのツール(ソフトウェア)もたくさんある。とても複雑なProduction環境なので一般的なツールではカバーできないことが多く、自分たちで作る。

インテントベースのキャパシティプランニング。やりたいこと(サーバーをN台欲しい)を抽象化していくと、最後には99.999%の信頼性で動作させたいという要求になる。一般的には「XのリージョンでN+2の冗長性を確保したい」という粒度のインテントベースのプランニングをする(Googleの最低基準がここ)が、より洗練させたければ、可用性でしていできるようにするとよいだろう。

・Auxonはキャパシティプランニングの自動化ツール。インテントベースで要求ができる。例えば、「フロントエンドサーバはバックエンドサーバから50ms以内でなければならない」「大陸ごとにN+2でなければならない」という要求ができ、優先順位をつけられる。

・Auxonを作ったチームはもともとスプレッドシートでキャパシティプランニングを行っていたが、自動化の余地があると思って作った。最初はヒューリスティックなロジックだったが、そのロジック部分は後から入れ替え可能なように作られており、本番で稼働させながら改善をさせて、最終的に線形計画モデルを使ったものになった。

・いきなり完璧なツールができた!と社内に持っていくと上手く動かなかった時に信頼を失うことになるので、きちんと期待値の調整をして導入する必要がある。

Googleの社内ツールプロジェクトは、空いた時間で開発される草の根作業のままにしてもよいし、構造化されたプロセスを通して正式なプロジェクトにすることもできる。

19章 フロントエンドにおけるロードバランシング

・サービスによって、適切なロードバランシングのアルゴリズムが異なる。例えば検索サービスであればすぐに結果が欲しいのでレイテンシが小さいことが大事、動画のアップロードであれば、すぐに終わることは期待していなくて1度で成功して欲しいのでレイテンシを犠牲にしてもスループットが出せる利用率の低いリンクが適している。

・一番前段でバランシングするのはDNSのロードバランス。Aレコードを複数返すことでクライアントはそこから1つを選んでリクエストしてくれる。理論的にはSRVレコードを使ってレコードの重みや優先順位を付けられるが、まだHTTPには採用されていない。

・権威DNSサーバーが最適なロードバランシングをしても、ISPのネームサーバーはTTLの期限内であればその結果をキャッシュするので、多くのユーザはそちら(キャッシュ)を使ってしまう。(Googleは自前で大規模なDNSゾルバ群を持っているのでできる?)

・仮想IPアドレス(VIP)でのロードバランシング。VIPの実装で一番大事なのはネットワークロードバランサー

・L2でバランシングする、つまりパケット送信先MACアドレスのみを変更することにより、バックエンドはオリジナルの送信元と送信先IPを受け取れるので、バックエンドは直接オリジナルの送信元に送信できる(ダイレクトサーバーレスポンス, DSR)

・しかしこれには問題があり、すべてのバックエンドのマシンがお互いにデータリンク層(L2)で到達可能である必要がある。(Googleの場合にはネットワークがこれをサポートできなくなり、マシン数が単一のブロードキャストドメインに収まらなくなった)

・その解決策はP.239

20章 データセンターでのロードバランシング

・処理を行う個々のサーバーにリクエストをルーティングするためのアプリケーションレベルのポリシーを取り上げる。

・クライアントが、バックエンドの負荷状況を追えているとして、空いているバックエンドにリクエストを投げるロードバランスはうまくいかない。(説明がよくわからず P.244)

・クライアントから見ると、バックエンドは以下の3状態がある。

・健全: リクエストを処理している
・接続拒否: 起動中やシャットダウン中など
・レイムダック: リスニングしており処理もできるが、リクエストの送信をやめるように明示的に要求している

レイムダックのメリットは、グレースフルシャットダウンができること。

・クライアントとバックエンド間のヘルスチェックはクラスタのサイズがでかくなってくると一気にコストが高くなる。そこで20~100ぐらいのバックエンドのサブセットを用意することが多い。

・クライアントは使えるサブセットを使うか決まっている。

・1つのバックエンドにリクエストが集中しすぎて過負荷になると、別のバックエンドにつなぎに行くときにTCPのオーバーヘッドが発生する(通常は一度コネクションを張ったまま張りっぱなし)。 そのオーバーヘッドが原因でそのバックエンドも過負荷になってしまう。

・(こういうアルゴリズムを考えたがうまくいかなかった。という話が多い)

・ランダムに接続先のサブセットを選ぶのでは、負荷の偏りが大きい。

・決定的なサブセット選択のアルゴリズムを使うと300クライアント300バックエンドで、きれいに均等に分けることができる。

21章 過負荷への対応

Googleでは高負荷な状態では、検索対象のコーパスを減らしたり、完全に最新ではない可能性があるオーかるのコピー(キャッシュ)を使うことで負荷を減らして、1リクエストあたりの負荷を下げるようになっている

・バックエンドが過負荷のエラーを返すと、フロントエンドは自主規制をするようになっており、その上限をこえるリクエストはローカルで失敗させて、ネットワークに出ていかないようにする。

・リクエストの重要度を4段階に分けていて、上の2つはユーザに影響がでるのでその範囲では確実に処理ができるようにプロビジョニングしておく必要がある。

・重要度の低いものは過負荷な状態では拒否される

・その重要度はリクエストがいくつかのバックエンドサーバーを経由する場合でも伝搬される。

・エグゼキュータ平均負荷: プロセス中のアクティブなスレッド数を数えて、その値を指数関数的減衰で平滑化する。これによってファンアウトを持つリクエスト(短時間高負荷なもの)を受信するとスパイクが発生するが、平滑化によってほぼ飲み込むことができる、それが長時間になる場合には拒否をする。

・リトライは3回まで実行して、それでもだめならリクエスト元にエラーを返す。(データセンター全体が過負荷と判断する)

・リクエスト側にもリトライバジェットが設定されていて、全体のリクエストの10%がリクエストならOK。これはデータセンターにまだ余裕があれば10%以内に収まるという根拠で設定。

・過負荷に陥ったバックエンドはシャットダウンするというのはよく聞く考えだが、正しくなくきちんとロードバランサーがそこへのリクエストを遮断してあげるのが正しい選択。

22章 カスケード障害への対応

・カスケード障害とは、ポジティブフィードバックの結果として、時間と共に拡大していく障害のこと。

・1つのレプリカの負荷が高くなると、残りのレプリカの負荷も高まり、ドミノ式に全レプリカがダウンしてしまうやつのこと。

・CPUの高負荷やメモリの消費量増大で起きる影響まとめ P.276

・CPUの利用率が増えると、キャッシュヒット率も減ってCPU利用効率が下がる。

・処理するリクエスト数が増えるとメモリの消費量も増えてキャッシュヒット率が下がって更にバックエンドへのリクエストが増えたりする。

23章 クリティカルな状態の管理: 信頼性のための分散合意

・対障害性を高めるために通常は複数拠点にまたがってシステムを動作させるが、それらを正しく動作させるためには分散合意が必要。

・CAP定理とは、以下の3つの性質は同時に満たすことができないというもの。

・各ノードにあるデータの一貫したビュー
・各ノードのデータの可用性
・ネットワーク分断への耐性

・伝統的なACID(原始星、一貫性、独立性、永続性)から、次第に増えつつ得る分散データストアの特性BASE(高い可用性、厳密ではないステータス、結果整合性)に変わってきている。

・BASE特性をサポートするシステムの多くは、複数のマスターレプリケーションに依存していて、書き込みが並列で行われる。その衝突を回避するための仕組みを持っている。例えば、タイムスタンプが新しいものを優先するというようなシンプルなもの。それは "結果整合性" と呼ばれる。

・しかしこれは時として驚くような結果を及ぼすことがあって、クロックのゆらぎやネットワークの分断が起きたときに生じる

・複数のマシン間で時計が同期していることを保証するのは不可能

・結果整合性を持ったデータストアを扱うのは開発者にとっては難しく、エラーの起きやすい複雑な仕組みを構築してしまっていた。(これは本来データベースのレイヤで解決されるべき問題)

・うまく行かないアルゴリズムの例が3つ書かれている。(P.304)

・それらの問題を解決するプロトコルはいくつかあり、その一つがPaxosプロトコル

・分散合意アルゴリズムをうまく利用しているシステムの多くは、それらのアルゴリズムを実装しているZooKeeper、Consul、etcd といったサービスのクライアントとして動作している。

・SolrもバックエンドにZooKeeperを使っている

RMS (Replicated State Machine) は同一の処理の集合を同一順序で複数のプロセスで実行するシステム。

・分散処理のバリア(ロック, 他の処理が終わるまで待機)や、キューをRSMとして実装すればシステム全体を遥かに頑健なものにできる。

・分散合意のパフォーマンスについて、Googleでは一番大きなボトルネックは大陸をまたぐような場合のレイテンシで、リーダープロセスが別の大陸にあるとそこへの通信の往復(ラウンドトリップタイム)によりパフォーマンスが劣化してしまう。(アルゴリズム自体はボトルネックではないらしい)

・まとめ。分散システムを使うときにハートビートのようなアルゴリズムで手当たり次第に作るのは良くないよ。

24章 Cronによる分散定期スケジューリング

・cronの実行を小規模で行う場合と大規模で行う場合の違いについて。

・cronジョブには冪等性があるもの(GCのように何度実行しても大丈夫なもの)と、メール送信のように2回以上実行してはいけないものなどがある。(1度スキップされてよいものとそうでないものもある)

・二重起動してしまうよりも、スキップされる方がリカバリしやすい。そのため、問題があったときには「フェイルクローズ」状態になるように設計するのが大事。

Googleでは分散cronをしていて、Fast Paxosのプロトコルで分散cronを管理している、プライマリが途中で死んだ場合には、セカンダリがプライマリになってその処理を引き継いで途中から実行する。(このフェイルオーバーは1分以内に完了する)

・cronは大規模に実行すると実行時間の偏りでスパイクが起きやすいので、実行しても良い時間の範囲を指定できるようにした ( 0..23 のように)

25章 データ処理のパイプライン

ビッグデータを処理するための定期的なパイプラインに対する、信頼性とスケーラビリティに優れた代替案として、リーダー - フォロアーモデルの新たな見方を紹介。

・旧来のcronのような定期実行でデータを処理するやり方は データパイプライン と呼ばれる。

ビッグデータに対して、1つの出力が次の入力になってつながっていくものを マルチフェーズパイプライン と呼ぶ。(パイプラインの数を 深さ と呼ぶ。)

・深いパイプラインは深さ数十から数百になる。

26章 データの完全性: What You Read Is What You Wrote

・Q.データの完全性とは? A.データがユーザから利用可能であり続けること

・G Suiteを運用してきて24時間以上データにアクセスできないと信頼に大きく関わることが分かってきた。

・データが一部破損していてそれが復旧不可能であれば、そのユーザへの稼働時間はその間失われていることになる。

・データの完全性を極めて高くすることの秘密は、予防的な検出と素早い修復。

アーカイブは監査や法的証拠開示に基づいた過去データの取り出し、コンプライアンスを目的として長期に渡ってデータを安全に保管すること。これは短時間でリカバリできないといけないバックアップとは違う要求。

・データが長期間見えないのであれば、完全性が保たれていようと、そのデータは存在しないも同然

・障害におけるデータの可用性に対してSLOを定義して、それを満たせるかどうかを実践しておくことが大事。

・障害の種類は以下の組み合わせて24種類ある。

・根本原因: 6種類(P.365)
・範囲: 2種類 (広範囲、狭く直接的)
・レート: 2種類(ビッグバン、ゆっくり着実)

・ゆっくり進むデータの損失に対しては、特定の時間に戻ってデータを抽出してくる必要があり、ポイントインタイムリカバリと呼ばれる。

・ACIDやBASE特性をもつデータストアにこの機能をもたせるのは今日では幻想なので、自分たちでバックアップをとってやるしかない。(パフォーマンス的に無理)

レプリケーションはバックアップにはならない。

・リテンションとはデータのコピーを起こしておく期間のこと。徐々にデータが失われていったときに、その期間まではリストアすることができる。

・ユーザが操作を誤って削除してしまったときには自身でロールバックできれば障害にならない (Driveで30日後に完全に消えるみたいなやつ)

・し、サポートの負担をかなり減らすことができる

APIを提供する場合でも、ユーザからは見えないけど裏側で論理削除しておき、数日後に物理削除するような設計ができる。

・バックアップの期間はGoogleは30~90日(サービス毎に異なる)としている、それ以上取っておいてもデータの構造が変わっていたりと復元がかなり困難になることが多い。

・データサイズがTBからEB(エクサバイト)になると同じ戦略では通用しなくなるので注意

・インクリメンタルバックアップをとっておき、それを並列に実行できるようにシャーディングしておくことでリストアにかかる時間を1/Nにすることができる。

Googleで過去にあった大規模障害の例 2つ (GMailGoogle Music)

・テープからのデータ復元方法について、大規模な場合にはベンダーが用意しているロボットでの復元よりも、手作業でやるほうが数百倍早いことが練習で分かっていた

・複雑なシステムの場合には完全には理解しきれないバグを持っているものなので、どれほど経験を積んでいても障害を起こさないことは不可能に近い。そのため多重防御の実践は大事。(オンラインのバックアップとテープをオフラインバックアップとして持っておくことなど)

27章 大規模なプロダクトのローンチにおける信頼性

Googleではローンチ調整エンジニア(Launch Coordination Engineers, LCE)から構成される専用のチームを立ち上げて、ローンチを成功させるためにエンジニアリングチームに助言を行うようにした。

・ソフトウェアエンジニアやシステムエンジニアや、SRE出身の人がいる

・ローンチの定義は、アプリケーションに対して外部から目に見える変更を行う新しいコードがあること。

Googleでは週70回ローンチしている。

・ローンチ調整エンジニアの役割

・ローンチに関わる複数チームの連絡役
・タスクが滞りなく進んでいることを確認して、技術面からローンチを推進する
・門番の役割を果たし、ローンチが安全だという判断の承認を行う
・開発者に対してベストプラクティスやGoogleのサービスと統合する方法について教育するためにドキュメントやトレーニング用のリソースを準備する

Googleの場合LCEにするとほとんどのプロダクトのチームに関われるので社内全体がわかる!

4部 管理

・単独で働くSREは存在しないので、チームで働くことについて取り上げる。

・複雑で変化の早い環境における考え方を採用直後の数週間から数ヶ月のうちにトレーニングすることでベストプラクティスを学ぶ。これがないと習熟に数年かかることもある。

・SREの採用はGoogle全体の標準に照らし合わせてさえ候補者を見いだしにくいし、効率的に面接することは更に難しい。

28章 SREの成長を加速する方法: 新人からオンコール担当、そしてその先へ

・新しく入社したSREをどう成長させていくかという話。

・表28-1にSREの教育方法の推奨パターンとアンチパターンがある。

・図28-1に入社直後からタイムラインでどんな学習をしていくべきかが整理されている

・こういったものは時間経過に伴い古くなっていくが、意図的に古いものを1,2つ混ぜておいて、オンボーディング終了後にそれを改訂する課題を課す。

・オンコール担当ができるようになったら新人SREは卒業で、そこからは自らが継続的に学習をしていく必要がある

OJTでいきなり「みなと一緒にやってみよう!最初は大変だけどそのうち慣れれば早くできるようになるし、ツールもだんだんと分かってくるよ!」とするのはよくある一般的な新入社員への対応だが、これはベストではなく、より良い方法がある。

・それをしてしまうと以下のような疑問を抱いてしまう

・私はなんの作業をしているのだろう?
・私はどれだけ前進できているのだろう?

・学習の仕組みにはある程度の順序をもたせ、目の前の道筋がみえるようにする必要がある。

・P.416 にオンコール学習チェックリストがあり、オンコール担当になるまでに必要なものがまとめられている。これがあることで、自分のやっていることがどこに当てはまるものなのか、どれぐらい自分が理解できているのかを把握することができる。

・メンターがチェックリストに対する回答をチェックし、問題なければ次のステップに進む。

・ステップが進むに従って、触れるインフラの権限が増えていく。最初はすべてリードオンリーで徐々に書き込み権限が与えられていく。

・学習プログラムとプロジェクト(実際の仕事)の両方に関わるべきで、それにより目的と生産性の間隔を養うことができる。Googleのインフラを一通り理解するための初心者向けプロジェクトが渡される。

・プロジェクトの例:

・ユーザが使う機能に手を入れて、それを本番環境までリリースする。これにより開発者への共感が養われる。
・サービスで盲点になっているところにモニタリングを追加する。(同時に現状の課題認識もできる)
・まだ自動化されていない運用上の課題を自動化する

Googleでは今までの仕事の中で見たいことのないシステムにであうので、すぐれたリバースエンジニアリングのスキルを持っている必要がある。大規模な環境では検出が難しい異常が発生するので、手続き的よりは統計的に考える能力が必要になる。また、標準的な運用手順が破綻した場合には、完全に臨機応変に行動できなければならない。

・障害が発生したとき、取りうる選択肢は何百もあるなかで、それを選択するのか目の前に広がる決定木を効率よく刈り込んでいく必要がある。これは経験によってより高速にできるようになる。分析と比較をうまく行うことが大事。

・泥沼化する障害対応によくありがちなのは、未検証の推定を多く取り入れてしまうこと。そういうときは一度ズームアウトしてさまざまなアプローチを取ってみるということはSREが早い段階で学ぶべき教訓の一つ。

・サービスのトラフィックをすべて追いかけて、ユーザのクエリがたどる経路をたどっていく新人向けの課題がある、その構成図をシニアSREに見せるとシニアSREも知らない最近の変化を知ることができる。

・ポストモーテムはまだ入社していない新人が読むことを想定して書くと良いし、価値あるポストモーテムとは新人の教育にも使えるものである。

・ディザスターロールプレイング: 週1のMTGで犠牲者を1人選び、その人は過去に起きた障害の解決をしないといけない。犠牲者は起きた問題に対してどう行動するかを伝え、司会者はそれに対して実際に起きたことを伝える。

・過去に起きた忘れられていそうな障害や、近くリリース予定のものに関連して起きそうな障害を題材とするとよい

・サービスのここに損傷を与えた場合、どのメトリクスがどう変わるかを事前にチームで話し合う。それを実際にやってみて、予想通りにメトリクスが動いたかどうかを観察する。という学習方法をQ毎に実施している。(「検索クラスタを焼き払おう」という名前が付いている。謎)

・新人SREはシャドウオンコール担当として、シニアSREのオンコール対応を横で見守ることでどう対応しているのか学ぶことができる。次のステップは逆シャドウで、シニアに後ろに付いてもらってアドバイスを受けながら実際のオンコール担当をする。

29章 割り込みへの対処

・運用負荷には大きく3種類あり、ページ、チケット、運用業務に分類できる。

・ページは本番環境で非常事態が生じると発せられる。単純作業なものから思考が必要がものまであるが、期待されるレスポンスタイム(SLO)があり、分単位で設定されるものもある。ページの管理はプライマリオンコールエンジニアが対応する。

・チケットは顧客からの要望で、簡単なチケットであれば設定を変更して1回コードレビューを受ければ良いものもあるし、複雑なものは設計やキャパシティプランニングの変更などがある。チケットにもレスポンスタイム(SLO)が定められる事があり、単位は時間、日、週ぐらい。チケットの管理はプライマリオンコールエンジニアのスキマ時間に行ったり、セカンダリオンコールエンジニアが担当したり、オンコールエンジニア以外のエンジニアが担当したりとチームによって異なる。

・運用業務(トイル)は、コードやフラグのロールアウト、顧客からの単純な質問への回答が含まれる。管理方法はチケットと同様で様々。

・フロー状態(ゾーン)に入ることによって、生産性が増すだけではなく芸術的な創造性や科学的な創造性も増す。割り込みによってここからはじき出されないように、できるだけ長時間この状態にいれるようにすることが大事。

・フロー状態に到達するための最も明確な道筋の一つは、やり方がわかっているタスクを処理すること。

・プロジェクトとオンコールが共存する環境ではそのバランスが重要で、理想のバランスには個人差がある。

・オンコールのローテーションが長いと、根本解決をしようという判断をしにくく、同じ問題でうんざりさせられる人が続き、身動きが取れなくなってしまうことがある。チケットもオンコールと同様に引き継ぎを行って解決に時間がかかる問題にも取り組んでいく必要がある。

30章 SREの投入による運用過負荷からのリカバリ

GoogleのSREチームでは、プロジェクトと対処的な運用業務(デバッグトラブルシューティング、オンコール)に均等に時間を割り振ることが標準的なポリシーとなっているが、大量のチケットにより数ヶ月に渡ってバランスが崩れることがある。これが継続すると燃え尽き症候群になったり、スケールする仕組みを作れなくなる。

・解決のためには別のチームからSREを連れてくる。タスクをさばくだけではなく、プラクティスの改善に焦点を当てる。特に1章(プラクティス、哲学)や6章(モニタリング)の部分は重要。

・以下はチームにプラクティスを提供するコンサルティングとして参画する方へのアドバイス

・フェーズ1: サービスの学習と状況の把握

・スケール仕組みを作れているか、そういう思想になっているかが大事。そうでない場合を "運用モード" と呼ぶ。非常事態の数をへらすのではなくて、非常事態に素早く対応する方法に焦点を当ててしまうことによって運用モードに陥りやすくなる。(足りないなら単純に増やせばいいじゃん、自動化せずに。と考えてしまっている)

・フェーズ2: 状況の共有

・ポストモーテムを有効活用して、チームが学習していける基礎を作る。ポストモーテムがうまく書けないと誰かを非難してしまったり、次への教訓にならないポストモーテムが出来上がってしまう。

・フェーズ3: 変化の推進

・まずは基礎から固めていく。SLOがないならそれを定める。SLOが重要なのはそれによってサービス障害のインパクトを定量的に計ることができるようになるから。

コンサルタントがチームを離れた後でも、チームメンバーが彼ならどうコメントするだろうとうまく予想できるようになっている必要がある。うまいコメントの例は

・リリースを延期したのはテストに問題があったわけではありません。リリースに対して設定されたエラーバジェットが尽きてしまっているからです。

・SLOが厳しいので、リリースは問題なくロールバックできる必要があり、リカバリに要する平均時間は短くなければいけません。

・導く質問をすること。良い例と悪い例

・Good) TaskFailures アラートが頻繁に発生しているが、対応していません。これはSLOにどう影響していますか?
・Good) このターンアップの手順は相当複雑に見えます。新しいインスタンスを立ち上げるのになぜこれだけ多くの設定ファイルを更新しなければいけないのか理由は分かっていますか?
・Bad) これらの古くて停止したままのリソースたちは、どうしたんですか?
・Bad) どうしてFrobnitzerはこんなにたくさんのことをやっているんですか?

・最後にコンサルタントがチームを離れるときには、教えたことをチームが確実に実践するためのアクションアイテムを作ると良い。それを報告書としてまとめたものがポストバイタム(ポストモーテムの反意語)

31章 SREにおけるコミュニケーションとコラボレーション

・SREチームにも多様性があり、インフラチーム、サービスチーム、プロダクト横断なチームをもっている。たまには開発チームになることもある。

・開発チームとの関係は、SREチームと同規模の場合もあるし、何倍にも大きい規模の場合もある。

・プロダクションミーティング: SREチームが担当するサービスの状況について毎週30~60分で説明する。サービスの運用パフォーマンスの詳細について話し合い、それを設計や設定、実装と関連付けて考え、問題解決の方法を推奨するもの。設計上の判断をサービスのパフォーマンスと合わせて考えることは極めて強力なフィードバックループになる。

・遠隔で2チームの会議をする場合、人数が少ない方のチームのだれかにファシリテーターをやってもらうと、大人数のチームが自然と少人数のチームに耳を傾けることになって上手くいくことが多い。(科学的根拠はないけど経験的に)

・プロダクションミーティングのアジェンダ

・予定されている変更の確認

・メトリクス (最近の傾向、負荷の状態など)

・障害 (ポストモーテムが書かれる規模の障害について)

・ページされたイベント (ページのされ方は適切だったか、それはページされるべきだったのかの2点について)

・ページされなかったイベント (ページされるべきだったけどされなかったもの、ページすべきでないものの注意を引く必要があるもの)

・これまでのアクションアイテム (前回決めたアクションができているのか)

・既存サービスの大規模データマイグレーションは(Googleでも)よく発生する

32章 進化するSREのエンゲージメントモデル

・サービスが最初からSREのサポート対象になるわけではない。サービスを評価して、SREがサポートするに値するかどうかが判断される。

・SREが関わる最初のプロセスはPRR (Production Readiness Review)。プロダクション環境におけるサービスの信頼性を評価する。サポートを受けるにはこれが必要。

・SREのサポートが受けられない場合でも、ドキュメンテーションコンサルティングなどは提供されている。コンサルティングの場合にはSRE1,2人が数時間をかけてレビューしてフィードバックをする。

・基本的にはPRRをしたSREがそのサービスのサポート担当になる。最初は開発チームと一緒にインストラクションを行うが、この関係はその後に続くチーム関係の基盤となる。

・サービスの設計フェーズからSREが関わることでより理想の設計に近づけた形で開発をスタートすることができる。

・PRRは2~3Qぐらいかかることが多く、またレビューを希望しているサービスも多いので、レビュー対象のサービスの優先順位付けも厳密に行われることになった。

・SREの人数の増加がサービスの数の増加に追いついていない状態。SREを採用できてもトレーニングは通常よりも長い期間のトレーニングになる。

・その結果、ベストプラクティスをフレームワーク化していく方向に解決策を見出した。プロダクション環境で適切に動作するものをコードとして用意しておき、サービスはそれを利用するだけで、設計レベルからProduction Readyになる。

・SREのサポート言語はJavaC++、Go。

フレームワークを使うことで、PRRのレビューコストも下がるし、フレームワーク向けに作られたツールはSREがいなくてもすべて使用することができる。

5部 まとめ

33章 他の業界からの教訓

ライフセーバーを10年やっていた人が今GoogleでSREをやっている。信頼性という意味でこういうバックグラウンドは大事。

・障害への対策として、他の業界でもシミュレーションや実地訓練を主要な焦点としている。

・航空業界では実地訓練はできないのでリアルなシミュレータに実際のデータを流し込んでいる。

・ポストモーテムも業界によって呼び方は違うが、どこでも同じようなことは行っている。

・反復作業は自動化しようというのがソフトウェアエンジニアには根付いている文化であるが、業界によって例外もある。原子力海軍は自動化は行わず、手動で作業をしている。自動化やコンピュータはあまりにも高速すぎるので大規模で回復不可能なミスを犯すことを懸念している。原子炉を扱う場合にはタスクをすばやく終わらせるよりもゆっくりとした安定的なアプローチを取ることの方がはるかに重要。

Googleが扱っているのは、なにか問題があっても直接的に命に関わるようなことはない分野。それを意識してエラーバジェットのようなツールをイノベーションの文化や、計算下でリスクを犯すための資金として有効に使うべき。

34章 まとめ

Googleでは1000人を超えるSREが10箇所のサイトで働いている。

・100年前の飛行機が操縦士1人に対して、積み荷がいくつかしかなく、自分でメンテナンスも行っていた。それが現在はパイロット2人で6000マイルも飛行して乗客も百人単位で載せることができる。SREもこれを目指さないといけない。

・SREチームはできるだけコンパクトであるべきであり、高レベルでの抽象化とフェールセーフとしての多くのバックアップシステムと、考え抜かれたAPIが拠り所になる。同時に、日々の運用から得られるシステムに関する包括的な知識も併せ持つ必要がある。