自作で大満足 ! AWS だけで理想の SLO 運用を実現した方法
Author : 岩本 隆史 (ENECHANGE株式会社)
概要
こちらが全体の構成図となります。

利用している主な AWS サービスや機能は下記の通りです。
- Amazon EventBridge スケジューラー (5 分おきに AWS Lambda 関数を呼び出す)
- AWS Lambda 関数 (イベントの集計やカスタムメトリクスの発行を担当する)
- Amazon Athena (Amazon S3 に出力される Application Load Balancer のアクセスログを集計する)
- Amazon CloudWatch カスタムメトリクス (単位時間ごとのエラー数と全イベント数を保存する)
- Amazon RDS (Athena のスキャン量を抑えるため、5 分ごとのエラー数と全イベント数を保存する)
- Amazon CloudWatch 複合アラーム (カスタムメトリクスを参照し、エラーバジェットのバーンレートが高ければ Amazon SNS トピックに通知する)
特に、CloudWatch カスタムメトリクスの設計にはこだわりました。私の理想とする SLO 運用の核となる部分です。
その点を中心に、以下の流れで解説します。
- Slomon で目指したゴール
- CloudWatch カスタムメトリクスの設計
- コストや社内展開で工夫した点
Slomon で目指したゴール
まず、Slomon では以下のゴールを設定しました。
- 書籍『サイトリライアビリティワークブック』で推奨されているアラート条件を忠実に実装すること (最重要)
- 監視にかかる費用をなるべく抑えること
- SLO の策定や変更ニーズに迅速に対応できる仕組みを整えること
最重要ゴールとした『サイトリライアビリティワークブック』で推奨されているアラート条件は、下記のものです (「5.2.6 複数ウィンドウ、複数バーンレートのアラート」)。
expr: (
job:slo_errors_per_request:ratio_rate1h{job="myjob"} > (14.4*0.001)
and
job:slo_errors_per_request:ratio_rate5m{job="myjob"} > (14.4*0.001)
)
or
(
job:slo_errors_per_request:ratio_rate6h{job="myjob"} > (6*0.001)
and
job:slo_errors_per_request:ratio_rate30m{job="myjob"} > (6*0.001)
)
severity: page
複数の時間枠やバーンレートを組み合わせることで、誤検知を減らす効果が期待できます。
このアラート条件を実装するため、Slomon では CloudWatch 複合アラームを活用することにしました。複合アラームを使うと、AND や OR などの条件で複数のアラームを組み合わせられます。
CloudWatch カスタムメトリクスの設計
ゴールが設定できたので、続いて CloudWatch カスタムメトリクスを設計することにしました。
メトリクスの設計には、どのようなクリティカルユーザージャーニーにどのような SLO を設定したいかが重要です。
結論として、以下のクリティカルユーザージャーニーと SLO を設定しました。
- クリティカルユーザージャーニー:電力使用量予測マイクロサービス (enechange-profiler) の POST /profile エンドポイント
- 複数の事業部で使われており、信頼性が特に重要
- アクセス数が多く、対応できれば自信を持って横展開できる
- SLO の期間:28 日間 (曜日の影響を抑えるため 4 週間とした)
- 可用性の SLO : 99.9% 以上 (過去の実績を参考にした)
- レイテンシーの SLO : 50% のリクエストが 0.06 秒以内、95% のリクエストが 0.08 秒以内 (同上)
SLO が設定できたので、いよいよカスタムメトリクスの設計です。Slomon では以下のように設計しました。
可用性
メトリクス名 | EnvironmentName | CriticalUserJourneyName | Category | TimeWindow |
---|---|---|---|---|
BadCount | prod-enechange-profiler | profile | Availability | 5m, 30m, 1h, 6h |
TotalCount | prod-enechange-profiler | profile | Availability | 5m, 30m, 1h, 6h |
レイテンシー
メトリクス名 | EnvironmentName | CriticalUserJourneyName | Category | Percentile | TimeWindow |
---|---|---|---|---|---|
BadCount | prod-enechange-profiler | profile | Latency | 50, 95 | 5m, 30m, 1h, 6h |
TotalCount | prod-enechange-profiler | profile | Latency | 50, 95 | 5m, 30m, 1h, 6h |
たとえば直近5分間の可用性に関するエラー数が 100 件だった場合は、下記のように発行します。
- メトリクス名 : BadCount
- 値 : 100
- ディメンション
- EnvironmentName (環境名) : prod-enechange-profiler
- CriticalUserJourneyName (クリティカルユーザージャーニー名) : profile
- Category (SLO のカテゴリ) : Availability
- TimeWindow (単位時間) : 5m
あとは、これらのメトリクスをもとに複合アラームを設定すれば OK です。実際には下記のようなアラームルールを設定しています (読みやすいように整形済み)。『サイトリライアビリティワークブック』の推奨するアラート条件と論理的に同じです。
(
ALARM(\"prod-enechange-profiler-slomon-profile-availability-2pct-1h\")
AND
ALARM(\"prod-enechange-profiler-slomon-profile-availability-2pct-5m\")
)
OR
(
ALARM(\"prod-enechange-profiler-slomon-profile-availability-5pct-6h\")
AND
ALARM(\"prod-enechange-profiler-slomon-profile-availability-5pct-30m\")
)
『サイトリライアビリティワークブック』の条件式に出てきた 14.4 は、30 日間のエラーバジェットの 2% を 1 時間で消費するバーンレートを示します (30 * 24 * 0.02 / 1 = 14.4)。同じく 6 は、エラーバジェットの 5% を 6 時間で消費するバーンレートです (30 * 24 * 0.05 / 6 = 6)。
これを参考に、私の設定したアラームルールでは 2pct 分のアラームの閾値を 1.344 としました。28 日間のエラーバジェットの 2% を 1 時間で消費するバーンレート 28 * 24 * 0.02 / 1 = 13.44 に対し、許容エラー率である 100 - 99.9 = 0.1 を掛けたものです。5pct 分の閾値も同様に計算し、0.56 としています。
この設定により、直近 1 時間および直近 5 分間のエラー率が 1.344% を超えたらアラートされるようになりました。直近 6 時間および直近 30 分間のエラー率が 0.56% を超えた場合も同様です。
このあたりの考え方については、Amazon CloudWatch Application Signalsのドキュメント が参考になります。
コストや社内展開で工夫した点
実装面での工夫として、コストや社内展開についても考慮しました。
コストについては、Athena のスキャン量や運用コストを抑えるために下記の工夫をしています。
- パーティション射影を使用して Athena で ALB アクセスログ用テーブルを作成する
- 集計したエラー数や全イベント数を RDS にも保存し、30 分・1 時間・6 時間の値は RDS で集計する
また、社内展開については Terraform モジュールを構築して進めやすくしました。それにより、下記のメリットが得られています。
- クリティカルユーザージャーニーの追加や SLO の変更に素早く対応できる
- Athenaの名前付きクエリを含めることで、過去の実績をすぐに集計できる
なお、Terraform のモジュールは下記のようなインターフェイスとしました。クリティカルユーザージャーニーの追加や SLO の変更が、critical_user_journeys の定義を変更するだけで済みます。
module "slomon" {
source = "..."
environment_name = "prod-enechange-profiler"
alb_access_logs_s3_url = "s3://********/AWSLogs/123456789012/elasticloadbalancing/ap-northeast-1/"
sns_topic_names_for_paging = ["incident-enechange-profiler"] # ページング用のSNSトピック名
critical_user_journeys = { # クリティカルユーザージャーニーの定義(複数可)
profile = { # CUJ名
http_method = "POST" # HTTPメソッド
path = "/profile/" # URLパス
slo = { # SLOの定義
availability_target = 99.9 # 可用性のターゲット
latency_p50_threshold = 0.06 # レイテンシのp50閾値
latency_p95_threshold = 0.08 # レイテンシのp95閾値
}
}
}
}
まとめ
このように必要なツールが AWS にそろっていたおかげで、SLO 運用ソリューションが自作できました。低コストかつ柔軟な SLO 運用が可能となり、現時点で 11 件のクリティカルユーザージャーニーを監視中です。
また自作には、機能改善や不具合調査がしやすいメリットもあると感じました。今後は、CloudFront のアクセスログにも対応していきたいと考えています。
以上、SLO 運用ソリューション「Slomon」についてご紹介しました。この記事が、SLO 運用を考えている方の参考になれば幸いです。
筆者プロフィール

岩本 隆史 (@iwamot)
ENECHANGE株式会社 VPoT兼CTO室マネージャー
2021 年 7 月、ENECHANGE株式会社に入社。インフラエンジニア兼 SRE を経て、2023 年 10 月より現職。2024 年 3 月からは、AWS Community Builder (Cloud Operations) としても活動中。
AWS を無料でお試しいただけます