SRE実践の手引 ─ 信頼性をどう制御するか? から始める、現実的な指標と目標の設計と計測
SREの役割には、信頼性、SLIとSLO、エラーバジェット、トイル、ソフトウェアエンジニアリングといった複数のキーワードが存在するがゆえ、なかなかうまく実践できない、という声もあります。本稿では、難しく見られがちなSREの内実を、「信頼性の制御」というコンセプトを軸に整理し、小さく始める一歩を坪内佑樹(ゆううき)さんが解説します。
こんにちは。SREの研究者をやっているゆううき(@yuuk1t)です。
SRE(Site Reliability Engineering)は、従来のオペレーションエンジニア、システム管理者(sysadmin)と呼ばれる人々が担っていた技術領域の新しい形です。Googleによって提唱され、日本国内でも2015年ごろからWebコンテンツ事業者のコミュニティを中心に広く知られるようになりました。SREを学ぶために書籍やWeb記事を読んだものの、いざ実践しようとしたときに何から始めればよいか分からないという方は意外と多いのではないでしょうか。
本記事では、信頼性、SLIとSLO、エラーバジェット、トイル、ソフトウェアエンジニアリングといったSREにおける各種キーワードを、「信頼性の制御」というコンセプトを軸として整理した上で、これから本格的にSREを始めるための最初の一歩を紹介します。
SREとは何か? なぜ始めることが難しいのか?
SREが何であるかということは、SREが取り扱う話題が広範にわたることから、意外と説明が難しいのではないでしょうか。SREの原点とも言える書籍『SRE サイトリライアビリティエンジニアリング』{$annotation_1}(以降では「SRE本」とする)でも、「はじめに」の章には次のように書かれており、名前だけからSREが指す内容までは分からないと言えます。
それでは、サイトリライアビリティエンジニアリング(SRE)とはいったい何なのでしょうか。この名前が、その内容をはっきりとは表現できていないことは認めざるをえません。
これまで著者は、SREとはReliability、つまり信頼性を向上する技術であるという説明をしていたことがあります。サービスの信頼性は高いに越したことはないため、サービス提供者は当然信頼性をより高くしようとします。信頼性を高くするには、信頼性を損ねる要因であるヒューマンエラーやソフトウェアのエラーを防がなければなりません。
ヒューマンエラーを防ぐ最も手っ取り早い手段は、システムに変更を加えないことです。ソフトウェアのエラーについても、ソフトウェアの更新により予期せぬエラーが発生することがあるため、ソフトウェアを更新しないことで、エラーの発生を防げてしまいます。
しかし、ソフトウェアを更新しなければ脆弱性が残り、ソフトウェアの実行効率も向上せず、新しい機能も使えないという困った状態になります。加えて、システムを変更しないということは自動化もされないため、システム管理者は手作業に多くの時間を費やすことになります。その結果、長期的に見ると、気づかないうちにユーザーにも不便を強いることになり、別の新しいサービスに乗り換えられてしまうことにつながるでしょう。
そこで、信頼性とシステムに変更を加える速度を、長期的に両立することが必要となってきます。「SRE本」では、100%の信頼性を達成することは非現実的であり、目標として目指すものではなく、プロダクトが必要とする信頼性を達成すればよいとされています。
そこで、信頼性の目標値を設定し、目標を過剰達成せず、リスクを取って、変更速度を向上させていくという考え方が有効となります。したがって、SREとは信頼性を高める技術というよりは、むしろ信頼性を制御する技術と言えます。
どのような情報システムや組織に有効か?
SREにおける信頼性を制御する手法は、どのような情報システムに対しても有効であるというわけではありません。
前述のようにシステムを変更し続けることが前提となるため、パッケージソフトウェアのようにソフトウェアのライフサイクルが製品を納品して完了するものではなく、ユーザーが利用しながらも変更を続けていくような情報システムにSREはフォーカスしています。
また、100%の信頼性を目指さないことから、人命に直接関わるような100%の信頼性を求められる情報システムには向かず、エラーを許容可能なシステムに対して有効です。
例えば、Webサービスやクラウド・ホスティングサービスは、リリースした後にも継続的に開発を続けて運用することを前提としており、直接的に人命に関わることもあまりないため、SREが有効と言えます。
ただし、情報システムは広く利用されるほど、暗黙的に高い信頼性が求められ、自分たちが提供するシステムも100%の信頼性を提供しなければならないと思い込んでしまうことがあります。このような非常に高い信頼性を求めがちな傾向を踏まえて、限定的でもよいのでエラーを許容できないかと模索することが、変更速度の向上につながります。
また、このような情報システムの性質に加えて、エラーを許容することが前提となることから、サービスを開発する組織に失敗を許容する組織文化があることが、SREの実践には必要です。
システムを絶対に停止させてはいけないような圧力があったり、障害が発生するたびに再発防止のルールが増えたりする組織では、障害を恐れたり、障害発生後の事後処理が面倒になってしまって、変更速度がどんどん低下してしまいます。
SREがアプローチする問題意識は何か?
SREが有効なシステムにおいて、SREは具体的にどのような問題意識にアプローチするのでしょうか。筆者は次の3つが、SREがアプローチする主要な問題意識であると考えています。
- (a) 信頼性が、要求される水準に達していない
- (b) データセンターまたはクラウドサービスの利用料金が高い
- (c) サービス開発やサービスを支える基盤の変更速度が向上しない
(a)の問題意識はサービスの利用者から直接観測できるため、利用者から解決を要求されることも多いでしょう。(b)の問題意識についても、料金は定量的に観測しやすいため、費用削減が要求されやすい性質があります。したがって、一般に(a)と(b)は解決に向けてアプローチされやすく、それだけ解決の手段にもこれまで数多くの議論がなされています。
一方で(c)の問題意識は、変更速度が向上していないことにより、古いバージョンのソフトウェアや減価償却済みのハードウェアを使い続けていたり、単一障害点が残り続けていたり、新システムに部分的に移行できないままだったりするような状態で表出します。開発速度や変更速度の定量化が難しく、実際に開発や運用に携わるエンジニアにしか感じられないことから、なかなか解決に向けてアプローチしづらいものです。
ここでは、アプローチしづらい分、議論が少ない(c)の問題意識にフォーカスを当てることにします。
SREを実践するとはどういうことか?
(c)の問題意識を持つ要因として一般に挙げられるのが、手作業による日々のメンテナンスや、割り込みから始まるシステムアラートへの対応など、トイル(toil)と呼ばれる作業が大量に発生している状況です。
トイルを削減して変更速度を向上するには、オペレーションの自動化が必要となり、SREがソフトウェアエンジニアリングに注力する必要があります。オペレーションの自動化が進むと、システムの障害に素早く気づいたり、障害からすぐに復旧できるようになるため、結果的に信頼性を高めることにもつながります。「SRE本」ではSREの時間のうち、エンジニアリング作業に最低50%の時間を充てることを提案しています。
しかし、ソフトウェアエンジニアリングに時間を割り当てるといっても、現在目の前にあるトイルやその他の仕事が消えるわけではないため、すぐに実践することが難しいケースもあるでしょう。
また、ソフトウェアを自動化すると、ソフトウェア自体にバグがあったり、想定外の挙動をする可能性がでてきます。そのため、信頼性を低下させる恐れが生まれ、自動化に対して億劫になることもあり得ます。
そこで、トイルを削減するには、サービスにとって必要となる信頼性の指標と目標を明確に設定し、目標を下回らなければリスクを取ってよいとする仕組みをつくることが有効です。
SREの世界では、サービスの信頼性レベルの指標をSLI(Service Level Indicator)、指標に対する目標値をSLO(Service Level Objective)と呼びます。このSLIとSLOは、四半期などの一定期間ごとに設定するのが通例です。
SLIとSLOにより、信頼性の予算(バジェット)を期間内にどれだけ消費したかを計測しておき、予算の残量に応じて、どれだけリスクを取って変更してよいかを定量的に判断できます。このような仕組みを、SREの用語で「エラーバジェット」と呼びます。
このように信頼性を計測し、エラーバジェットにより信頼性を制御し、変更速度を向上できていれば、SREを実践していると言えるでしょう。
SREを始める難しさはどこにあるのか?
ここまでの話で、SREを実践することは一見すると簡単そうですが、一体どこに難しさがあるのでしょうか。SREを始める難しさとして、ここでは次の3点を挙げます。
- 計測可能なSLIの設計
- 適切なSLOの設定
- トイルまたは変更速度の計測
まず、計測可能なSLIの設計についてですが、Webや書籍で良いとされているSLIには、計測のための仕組みが追加で必要となり、これが難しい点です。
書籍『The Site Reliability Workbook』{$annotation_2}などで紹介されているSLIは、リクエスト駆動のシステムの場合、SLO期間内のリクエストの総数の中から特定の条件を満たしたリクエストの割合を計測する必要があります。特定の条件とは、例えばHTTPの200系の成功応答であることや、計測ウィンドウ内のHTTPリクエスト数の95パーセンタイルの応答時間が500ms以下であるといったものです。
この計測を実現するには、リクエストのログをなんらかのデータベースに保存し、解析するシステムが必要となります。したがって、信頼性を計測するには、ログ解析システムを構築する手間が増え、SREの実践を気軽に開始しづらくなります。
ただし、エムスリーの事例{$annotation_5}のように、もしすでにElasticsearchなどのデータストアにログを保存しているのであれば、リクエスト単位のSLIを設定するとよいでしょう。
次に、適切なSLOの設定についてです。SLOを大きくしすぎれば、予算が少なくなり、リスクを取れなくなります。逆にSLOを小さくしすぎると、ユーザーの体験を損なってしまいます。エラーバジェットが導入されていれば、予算があるだけリスクを取るため、SLOを過剰達成することは期待しないことになります。したがって、大きすぎず、小さすぎない値を設定しなければならない難しさがあります。
最後に、トイルの計測の難しさについてです。SRE実践の効果を測定をするために、トイルがどの程度削減されたか、つまり変更速度がどの程度向上したかを確認する必要があります。しかし、トイルはあらかじめ計画されたものではなく、割り込みにより発生するため、トイルにどの程度時間を割いたのかを直接計測することは難しいです。
また、タスク全体としてはトイルではなくても、部分的に繰り返し作業が含まれていたりするなど、トイルを内包していることもあります。タスク全体のうち、トイルに要した時間のみを計測することは難しいでしょう。
このように、SREを始める難しさの要因は、システム構築の手間はもちろん、エンジニアや単一チームだけではコントロールできない課題、タスク管理にまで及びます。
難しさを踏まえてSREを始める方法
「SRE本」やその類書では、SREの理想的なあり方や、先進的な取り組みについて書かれているため、最初からその理想を実現しようとするとハードルが高すぎて、なかなか前に進めなくなってしまいます。
そこで、まずSREの実践を始めるため、これまで筆者が実践してきた内容を紹介します。
1. SLIとして、時間単位の稼働率を採用する
リクエスト単位でSLIを設定することは、ログの収集・解析システムの構築が必要となり、その手間が発生する課題があることを述べました。リクエスト数は通常、手で数えられるほどの小さな数ではないため、計測の自動化が必須となります。
そこで、稼働時間と(稼働時間+停止時間)の比率による時間単位の稼働率を、SLIとして採用します。時間単位の稼働率であれば、停止時間のみを記録すればよく、システムの停止回数は一般に手動で対応可能であるため、計測しやすいという特徴があります。
時間単位の稼働率は、可用性の計算方法として従来から用いられてきたので、すでに計測しているのであれば、それを利用すればよいでしょう。
稼働率を計測する動機は、単なる実績の記録だけでなく、リスクを取るための予算が計測期間内にどれだけ残されているかを知ることです。したがって、システムが停止するたびに最新状況を更新していくワークフローを構築することが重要になります。
稼働率を記録していくワークフローの例は、次のようなものです。
- システム停止時の障害対応をした後に、Googleスプレッドシートのような表計算ツールに、停止時刻と復旧時刻、これらの差分である停止時間を入力します。障害対応の直後では後片付けで煩わしい場合は、日単位や週単位の定例会で入力時間を設けるとよいでしょう。
- 計測開始日から現在までの期間を対象に稼働率を計算し、同時に計測開始日から計測終了日までの期間を対象に稼働率を計算します。表計算ツールの式機能を使い、基本事項を入力すると自動で計算されるようにしておきます。
ただし、リクエスト単位の計測手法と比較すると、時間単位の稼働率計測には、精度に関するデメリットがあります。
まず、一部のリクエストのみに影響する部分的な信頼性の低下であっても、稼働率では稼働しているか停止しているかの2値でしか表現できません。したがって、部分的には稼働しているにもかかわらず、稼働率では全体が稼働しているか、もしくは全体が停止していることになります。リクエスト単位の計測であれば、部分的な信頼性の低下も割合で表現できます。
とはいえ、時間単位の稼働率計測であっても、部分的な稼働のうち特定のケースであれば、精度を上げることができます。システムの内部が複数のコンポーネントに分かれている場合は、コンポーネントごとの稼働率を計算することで、特定のコンポーネントのみ停止していることを表現できます。これにより、停止時間の長いコンポーネントに、システム全体の稼働率が引きづられることがなくなります。
2. SLOを、過去実績によって決定する
精度に課題はあるものの、最初のSLIとしては「時間単位の稼働率」が採用しやすいことを説明しました。
それでは、SLOはどのように決定すればよいのでしょうか。前述したように、ちょうどよいSLOを決定するのは難しい問題です。えいっと決めてみるのも手ですが、目標値というと、どうしても高い値を設定してしまいがちです。
そこで、過去にシステムが停止した情報を集め、稼働率の実績を期間ごとに計測し、その値を今後のSLOの上限値とします。
リクエスト単位の計測では、一定以上古い期間のログを保持していなかったり、計測に必要な情報をログに含めていなかったりして、過去の実績を計測できないことがあります。時間単位の稼働率であれば、チャットや社内wikiシステム、メールなどに何らかの対応ログであったり、ポストモーテムにシステム停止の記録が残っている可能性が高いため、実績値は比較的容易に計測可能です。
これらの実績値は、偶然障害が起きなかったり、逆に障害が重なったりして、期間によってとても高かったり低かったりするでしょう。ユーザーの体験を損ねない限り、リスクを取れるようにSLOは低い値を設定すべきなため、基本的には最も低い値に合わせることを推奨します。
少なくとも実績値を超えない程度になるべく低く設定し、ソフトウェアによる自動化やシステムに対する変更に対してリスクを取れるようにすることが望ましいでしょう。
3. アジャイル開発のベロシティから効果を測定する
トイルに要する時間を計測する難しさについては前述しました。そこで、考え方を変えて、トイルを直接計測するのではなく、トイル以外のエンジニアリングタスクをどれだけの速度で完了したかを計測します。
この計測を実現するには、エンジニアリングプロジェクトを計画し、速度(以降、アジャイル開発の用語であるベロシティと呼ぶ)を計測することが可能なアジャイル開発のプラクティスを適用できます。アジャイル開発では、タスクを洗い出し、タスクの規模を定量的に見積もり、2週間などのイテレーションを回す期間ごとにタスクをどれだけ完了させたかのベロシティを計測する手法が確立されています。
本来であれば、プロジェクトの計画からスタートするのですが、この文脈では、ベロシティを計測することが重要であるため、とりあえず現状のベロシティを計測してみましょう。具体的には、例えば次のようなステップを踏むことになります。
- イテレーションの単位となる計測期間を決定します。通常は2週間程度でしょう。
- イテレーションの開始前に、次のイテレーション内に完了させたいエンジニアリングタスクをGitHubのプロジェクトボードなどのカンバンに登録します。このタスクをバックログとよびます。
- バックログの規模を見積もります。規模の単位として、ここでは客観的に扱いやすい「時間」を採用します。例えば営業時間を8時間として、割り込みなしで6時間集中して完了できる程度の規模を1とします。
- タスクを完了すると、そのイテレーションで終了したタスクをDONEカラムに移動させます。
- イテレーション終了時に、DONEカラムのバックログの規模の和を計上したものが、そのイテレーションでのベロシティとなります。
このように計測したベロシティの変遷を基に、SLOを小さくしてリスクを取れるようにした結果、実際に成果が上がっているかを評価します。2~3カ月イテレーションを回しても、もしベロシティが向上していなければ、SLOが高すぎないかを見直してみてください。
また、計測結果ではなく、現場の肌感覚として改善されていないと感じるのであれば、調査など、プロダクション環境への変更以外のタスクの割合が大きい可能性があります。プロダクション環境への変更のリスクが大きすぎると、変更のリスクがどの程度かを調査したり、リスクを小さくするための検証に時間を割く必要があります。
その場合は、過去のバックログを見直し、プロダクション環境への変更に関わるバックログにのみラベルをつけ、ベロシティとしてはラベルをつけたバックログの速度のみを見るような工夫が有効でしょう。
SREにアジャイル開発を導入するメリットと試み
アジャイル開発を導入する本来の利点は、このようなベロシティの計測だけでなく、不確実性の高いプロジェクトであっても、徐々に確実性を高め、推進可能にすることにあります。この利点をうまく活用すると、それまで戦術的にタスクをこなすことに終始しがちだった従来の運用チームのあり方を、戦略的にプロジェクトを実行できるチームへと進化させることができます。
詳細については、書籍『アジャイルな見積りと計画づくり』{$annotation_3}を参考にしてください。
前述したように、SREではトイルを削減したり、システムの停止時間を短くしたりするため、ソフトウェアエンジニアリングに注力することになります。このため、ソフトウェア開発でよく用いられるアジャイル開発のようなプラクティスを適用する流れは、自然な成り行きと言えるでしょう。
関連する取り組みとして、スタディストの事例6では、同じようにカンバンを利用し、タスクを分類した上で全ての業務にポイントを付与し、作業時間割合を計測しています。
また、はてなのSREチームで、スクラム開発を実践している事例{$annotation_4}もあります。
SREを深めるための道標 ─ 変更リスクを低減する
ここまで、SREを小さく始める方法を紹介しました。ここからより良いSREを実践するには、プロダクション環境への変更のリスクをどれだけ低減できるかが、鍵になります。
同じ変更内容であっても、事前にリスクが小さいと分かるか、結果的に変更のリスクが小さければ、その分だけエラーバジェットの残量を気にせず、安心して変更を加え続けられます。
冒頭で、SREは信頼性を制御する技術であると述べました。リスクの低減とはすなわち、制御の幅を小さくすることに相当します。それにより、より緻密な制御が可能となります。
変更リスクの低減には、リスクの規模を知ることと、リスクの規模を小さくすることの、2つのステップがあります。これはすなわち、変更の影響範囲を知ることと、変更の影響範囲を小さくすることに言い換えられます。
さらに、変更の影響範囲は、いつからいつまでの影響かといった時間的範囲と、どの機能やどれだけのユーザーに影響するのかといった空間的範囲に分けられます。
こういった観点を次の表に分類し、それぞれにおいて有効な方法の例を挙げました。
影響範囲 | 時間的範囲 | 空間的範囲 |
---|---|---|
~の予測・確定 | - | リクエスト単位のSLI Observability |
~の低減 | アラーティング オンコール対応 Observability 回復オペレーションの自動化と高速化 |
分散システムの疎結合化(非同期化とキューイング、リトライ制御) |
変更の影響範囲を予測・確定する
まず、影響範囲の予測・確定についてです。そのうち時間的範囲の観点から、変更を加える前に予測する方法について、筆者には心当たりがありません。事後に確定するのであれば、前述した稼働率の計測で十分です。
一方、空間的範囲の予測については、時系列メトリック、ログ、トレース情報を継続的に収集し、システムの可観測性(Observability)を高めることで、変更内容に応じて、どこに影響がありそうかをある程度予測することが可能です。
蛇足ですが、著者の最新の論文7では、空間的範囲を予測するため、分散システム内のプロセス間のTCP/UDP通信の依存関係を継続的に追跡する手法を提案しています。
また、空間的範囲の確定については、すでに述べていますが、リクエスト単位のSLIを採用することで、時間単位の稼働率よりも小さな粒度で影響範囲を事後に確定できます。
変更の影響範囲を低減する
次に、影響範囲の低減についてです。時間的範囲において、影響を低減するということは、短時間で障害から復旧することを意味します。手動対応を要する障害から復旧するまでのプロセスは、一般に次のようなものになります
- アラーティングにより、SREがすぐに障害に気づく必要があります。
- オンコール体制を事前に整えて、SREがアラートを受け取り素早く対応を開始します。
- システムが高いObservabilityを持っていれば、SREが障害の原因に気づくまでの時間を短縮できます。
- 症状を抑えるか、原因を取り除くための回復オペレーションが自動化されていれば、復旧までの時間も短くなります。
一方、空間的範囲の影響の低減するということは、サービスの一部のユーザーや一部の機能のみに影響範囲を抑えるということです。SaaS(Software as a Service)などの外部システムに依存する場合は、呼び出しを非同期化したり、キューイングすることで、外部システムの信頼性低下に引きづられないようにすることができます。
また、事前に機能や役割ごとにシステムを分離して構成しておくことで、システムの一部に問題が発生しても、その影響を分離されたサブシステム内に留めることもできます。非常に複雑かつ大規模なシステムであれば、マイクロサービス構成をとることにより、システムを疎結合に分離できます。
障害発生後にポストモーテム(根本原因分析)を実施するときにも、単に原因を分析し予防に務めるだけでなく、このようにシステム変更時のリスクを評価することにより、次回の障害発生時に復旧時間を短くできます。
おわりに
本記事では、SREとは信頼性を制御する技術であると定義し、SREの実践を開始するための方法を紹介しました。特に、変更速度が低いという問題意識を持つケースに着目し、信頼性の低下を恐れず、リスクを取って変更できるようになることを主眼としました。
SREの実践においてハードルとして挙げた、SLIの計測が面倒であることや、SLOを過剰に高く設定してしまう傾向、およびトイルの計測の難しさについて、それぞれ、時間単位の稼働率のインクリメンタルな計測、過去履歴からのSLOの決定、およびアジャイル開発の導入により解決できることを解説しました。
最後に、SREを深めるための道標として、プロダクション環境への変更リスクを小さくするという観点で、各技術要素を簡単に紹介しました。
さらに深くSREを実践するにあたって、本文中に挙げた参考文献に加えて、国内であればSRE Lounge、海外であればSREconの資料を参照することをおすすめします。
参考文献
- 1: Betsy Beyer, et al. 編, 玉川竜司 訳, 澤田武男, et al. 監訳, SRE サイトリライアビリティエンジニアリング――Googleの信頼性を支えるエンジニアリングチーム, オライリー・ジャパン, 2017.
- 2: Niall Murphy, David Rensin, Betsy Beyer, Kent Kawahara, Stephen Thorne, The Site Reliability Workbook -- Practical Ways to Implement SRE, O'Reilly Media, 2018.
- 3: Mike Cohn 著, 安井 力, 角谷 信太郎 訳, アジャイルな見積りと計画づくり ~価値あるソフトウェアを育てる概念と技法~, マイナビ出版, 2009.
- 4: 菅井 祐太朗, SREチームにおけるスクラムの実践, DevLove関西 FearlessChange実践編, 2019, https://speakerdeck.com/hokkai7go/devlove-kansai-sre-scrum.
- 5: Shohei Takahashi, エムスリーはどのようにしてSREを始めたか, SRE Lounge #9, 2019, https://speakerdeck.com/tshohe/sre-lounge-number-9-emusurihadofalseyounisitesrewoshi-metaka.
- 6: 北野 勝久, NoOpsを実現するSREの存在意義と役割, NoOps Meetup #6, 2019, https://speakerdeck.com/katsuhisa91/class-sre-implements-noops.
- 7: 坪内 佑樹, 古川 雅大, 松本 亮介, Transtracer: 分散システムにおけるTCP/UDP通信の終端点の監視によるプロセス間依存関係の自動追跡, インターネットと運用技術シンポジウム論文集, 2019年12月. (to appear)