1. 導入: なぜSLO/SLIによる監視が重要なのか
Progateのようなプログラミング学習サービスは、ユーザーが学びたいと思ったときにいつでも利用できることが極めて重要です。もしサービスが不安定だったり、頻繁に障害が発生したりすれば、ユーザーの学習体験は損なわれ、サービスへの信頼も失われてしまいます。
DevOps・インフラエンジニアとして、私たちはサービスの安定稼働を保証する責任があります。しかし、ただ闇雲にサーバーのCPU使用率やメモリ使用量を監視しているだけでは、本当にユーザーに影響が出ている問題を見落としてしまったり、逆に重要度の低いアラートに疲弊してしまったりすることが少なくありません。
そこで注目されるのが、SRE(Site Reliability Engineering)のプラクティスであるSLO(Service Level Objective)に基づいた監視とアラート設定です。これは、サービスの信頼性をユーザー視点での数値目標として定義し、その目標達成度に基づいて監視・アラートを行うことで、効果的かつ効率的な運用を実現します。これにより、開発チームと運用チームが共通の目標を持ち、真に重要な課題に集中できるようになります。
2. 基礎知識: SLO、SLI、エラーバジェットとは?
SLOに基づいた監視を理解するために、まずは以下の基本用語を押さえておきましょう。
-
SLO (Service Level Objective – サービスレベル目標)
ユーザーが体感するサービスの品質に関する目標値です。例えば、「稼働率99.9%」「リクエストの99%は応答時間200ms以内」といった形で定義されます。これは内部的な目標であり、法的な拘束力はありません。 -
SLA (Service Level Agreement – サービスレベル合意)
SLOを基に、サービス提供者と顧客の間で交わされる、法的な拘束力を持つサービス品質に関する合意です。SLOが内部的な目標であるのに対し、SLAは外部顧客に対する約束となります。 -
SLI (Service Level Indicator – サービスレベル指標)
SLOを測定するための具体的な指標です。SLOを「稼働率99.9%」と定めた場合、SLIは「HTTPリクエストの成功率」や「サービスの稼働時間」などが該当します。また、「応答時間200ms以内」であれば、「99パーセンタイル応答時間」がSLIとなります。SLIは定量的に計測可能でなければなりません。 -
エラーバジェット (Error Budget)
SLOを満たすために「許容される障害の時間や回数」を指します。例えば、稼働率99.9%のSLOであれば、年間で約8.76時間のダウンタイムが許容されることになります。この8.76時間がエラーバジェットです。エラーバジェットを使い切るとSLO違反となり、通常は新機能開発を一時停止して信頼性向上にリソースを集中させるといった意思決定が行われます。
これらの概念を理解することで、単なるメトリクス監視から一歩進んだ、戦略的なサービス運用が可能になります。
3. 実装/解決策: SLOに基づいた監視・アラート設計
SLOに基づいた監視を実務に落とし込むための具体的な手順を見ていきましょう。
-
SLOの定義:
まず、あなたのサービスにおける「重要なユーザー体験」を特定します。Progateのような学習サービスであれば、「ログイン」「コースの開始」「動画の再生」「課題の提出」などが考えられます。それぞれの操作について、ユーザーが許容できる信頼性レベル(稼働率、レイテンシ、エラー率など)を数値で定義します。この際、現実的な目標設定が重要です。 -
SLIの選定と計測:
定義したSLOを測定するための具体的なSLIを選定します。「ログイン成功率」「動画再生時の応答時間」「課題提出時のエラー率」など、明確に測定できる指標を選びましょう。これらのSLIは、Prometheus、Grafana、Datadogなどの監視ツールを用いて継続的に計測します。アプリケーションログ、Webサーバーのアクセスログ、ロードバランサーのメトリクスなど、様々なデータソースを活用できます。 -
アラート設定:
エラーバジェットの概念に基づき、SLO違反が近づいていることを検知するアラートを設定します。例えば、「過去5分間のエラー率がX%を超えたら」「99パーセンタイル応答時間がYmsをZ分間超えたら」といったルールです。アラートの重要度(Severity)に応じて、通知先(PagerDuty、Slack、メール)を使い分け、本当に対応が必要なものだけが担当者に届くように調整します。 -
運用フローの確立:
アラート発生時の対応手順(Runbook)を整備します。誰が、いつ、どのように対応するのか、切り分けの初期手順、エスカレーション経路などを明確にしておおくことで、障害発生時の混乱を最小限に抑え、迅速な復旧を促します。また、障害発生後は必ず事後レビュー(Postmortem)を実施し、再発防止策を講じることが重要です。
4. サンプルプログラム: 簡易的なSLI計測とPrometheusアラートルール
ここでは、Pythonで簡単な外形監視を行うスクリプトと、PrometheusでSLIに基づいたアラートルールを設定する例を示します。
Pythonスクリプト(簡易的なサービスヘルスチェック)
このスクリプトは、指定されたURLにHTTPリクエストを送信し、応答時間とステータスコードを計測します。実運用では、この結果を時系列データベースに保存し、監視ツールで可視化・アラート設定を行います。
import requests
import time
import datetime
def check_service_health(url, timeout=5):
“””
指定されたURLのサービスヘルスをチェックし、応答時間とステータスコードを返します。
実運用では、取得したメトリクスをPrometheus ExporterやDatadog APIなどで送信します。
“””
start_time = time.monotonic() # リクエスト開始時刻を記録
try:
response = requests.get(url, timeout=timeout) # HTTP GETリクエストを送信
end_time = time.monotonic() # リクエスト終了時刻を記録
latency_ms = (end_time – start_time) 1000 # 応答時間をミリ秒で計算
status_code = response.status_code # HTTPステータスコードを取得
is_success = 200 <= status_code < 300 # 2xx系のステータスコードを成功と判断
print(f"[{datetime.datetime.now()}] URL: {url}, Status: {status_code}, Latency: {latency_ms:.2f}ms, Success: {is_success}")
return is_success, status_code, latency_ms
except requests.exceptions.RequestException as e:
end_time = time.monotonic()
latency_ms = (end_time - start_time) 1000
print(f"[{datetime.datetime.now()}] URL: {url}, Error: {e}, Latency: {latency_ms:.2f}ms, Success: False")
return False, None, latency_ms
if __name__ == "__main__":
# 監視対象のURLを指定してください (例: Progateのログインページなど)
target_url = "https://www.example.com/login"
print(f"--- サービスヘルスチェック開始: {target_url} ---")
# 複数回実行して傾向をシミュレーション
for i in range(5):
print(f"[{i+1}/5] Checking...")
success, status, latency = check_service_health(target_url)
time.sleep(2) # 2秒待機して次のチェックへ
print("\n--- 注意点 ---")
print("このスクリプトは非常に簡易的なものです。")
print("実運用では、より堅牢な監視ツール(Prometheus, Datadogなど)を使用し、")
print("定期的な実行、メトリクスの永続化、アラート通知機能などが必要です。")
print("エラーバジェットを考慮したアラートルール設定が重要になります。")
Prometheusのアラートルール例 (YAML形式)
この設定は、Prometheusのルールファイル(例: `alert.rules.yml`)に

コメント