4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NewRelicのService Levels機能でSLI/SLOをTerraform管理する

4
Posted at

はじめに

ゼロバンク・デザインファクトリー株式会社(ZDF)で、みんなの銀行におけるBaaSサービスのインフラ基盤の構築・運用を担当している斉木です。

みんなの銀行、BaaSサービスについては、以下をご覧ください。

SLI/SLO 運用について

今回は、BaaSサービスのインフラ基盤チームで実践しているSREプラクティスのうち、SLI/SLOの取り組みについて取り上げさせていただきます。

SLI/SLOの定義はSREの基本ですが、導入や運用に課題を抱えている企業も多いかと思います。設定したSLOを目指した運用・改善には、新機能構築以外の継続的な開発体制の確保が必要です。

成長期の企業や運用作業が肥大化した環境では、導入に向けたリソース確保に一定のハードルを感じます。運用における手動作業や定型作業(SREで言うトイル)が自動化され、継続的に解消され続ける文化・体制が重要です。

我々のチームでも同様の課題感を持ちつつ、新規構築・運用作業・トイルの削減を進める傍ら、SLI/SLOの導入に向けたPoCを進めておりました。

SLI/SLOは機能開発や改善が活発な環境では、一度設定しても継続的に更新が必要になります。GUI上で手動設定すると変更作業が煩雑になり、CI/CDの恩恵も受けられず、要件の更新速度に追従する際の足枷になります。

また、変更履歴が残らず、環境間の差異も生まれがちです。そこで私たちは、SLI/SLOをTerraformでコード管理することにしました。

本記事では、NewRelicの Service Level 機能をTerraformで管理する方法を紹介します。筆者のチームでは現在この構成をPoC段階で検証中です。試行錯誤の過程も含めてお伝えします。

なぜTerraformで管理するのか

  • 変更がコードレビューされる: SLO目標値の変更がGitLabのMerge Requestとして可視化されます
  • 環境間の一貫性: dev/stg/pseudo/prodで同じモジュールを使い、変数だけ差し替えられます

繰り返しになりますが、SLI/SLOは実際の計測値を確認しながら、継続的な改善が必要なものです。
都度NewRelicコンソールから変更していると、運用負荷が大きくオペレーションミスを誘発するため、Terraform資材として管理します。また、今後の拡張性としてCI/CD基盤の恩恵を受けることも考慮しています。

SLIの3分類

筆者のチームでは以下の3種類のSLIを定義し検討を進めています。

SLI 判定基準 用途
可用性 HTTP 5xx以外 = 成功 サービスが応答できているか
レイテンシ 応答時間が閾値以内 = 成功 ユーザー体験の品質
エラー率 HTTP 5xx = エラー 異常の割合

可用性SLIの成功イベントを「HTTP 5xx以外」としているのは、可用性が「システムが正常に応答できる状態にあるか」を測る指標であるためです。

4xx系レスポンスはサーバーがリクエストを正常に受信・処理した上で返すクライアント起因のエラーであり、システム自体は稼働しています。そのため、サーバー起因の障害を示す5xx系のみを失敗イベントとして扱っています。

この考え方はGoogle SRE Workbookでも採用されている一般的なプラクティスです。なお、408(タイムアウト)や429(レート制限)など一部の4xx系については、今後の運用データを踏まえて扱いを精査していく予定です。

それぞれをTerraformモジュール化し、API単位で呼び出す設計にしています。

Terraformの記述例

以下はすべて一例です。実際の運用ではサービス名やWHERE句、目標値などを環境や要件に合わせて変数化しています。

可用性SLO

resource "newrelic_service_level" "availability" {
  guid        = var.entity_guid
  name        = "${var.service_name} - Availability"
  description = "Availability SLO (target: ${var.target}%/${var.time_window_days}d)"

  events {
    account_id = var.account_id
    valid_events {
      from  = "Transaction"
      where = var.valid_where
    }
    good_events {
      from  = "Transaction"
      where = var.good_where  # 例: "appName = 'my-api' AND httpResponseCode < '500'"
    }
  }

  objective {
    target = var.target  # 例: 99.9
    time_window {
      rolling {
        count = var.time_window_days  # 例: 28
        unit  = "DAY"
      }
    }
  }
}

レイテンシSLO

可用性と構造はほぼ同じで、good_eventsの条件が異なります。

good_events {
  from  = "Transaction"
  where = "${var.valid_where} AND duration < ${var.latency_threshold_sec}"
  # duration は秒単位。100ms なら 0.1 と指定します
}

エラー率SLO

エラー率では good_events の代わりに bad_events を使います。

bad_events {
  from  = "Transaction"
  where = var.bad_where  # 例: "${var.valid_where} AND httpResponseCode >= '500'"
}

モジュール化のディレクトリ構成

modules/service_level/
├── availability/    # 可用性SLOモジュール
├── latency/         # レイテンシSLOモジュール
└── error_rate/      # エラー率SLOモジュール
environments/
├── dev/             # 開発環境(ベースライン測定用)
├── stg/
├── pseudo/
└── prod/

APIごとにモジュールを呼び出すだけで、SLO定義を追加できます。

# 以下は一例です。entity_guidやservice_name、目標値は環境・APIに応じて変数で管理します
module "accounts_api_latency" {
  source                = "../../modules/service_level/latency"
  entity_guid           = local.entity_guid.bff
  service_name          = "/accounts API"
  account_id            = local.newrelic_account_id
  target                = 95.0
  time_window_days      = 28
  latency_threshold_sec = 0.1  # 100ms
  valid_where           = "appName = 'my-api-bff' AND request.uri LIKE '/accounts%'"
}

APM Transactionに記録されないケース

認証トークン発行のように外部サービスで処理されるAPIは、主要マイクロサービスのAPMがなくTransactionを取得できません。このようなケースでは、CDNアクセスログなど別のデータソースや、経由するマイクロサービスのAPM TransactionをSLIに活用することを検討する必要があります。

valid_events {
  from  = "Log"  # カスタムログイベントを使用
  where = "logType = 'cdn_access' AND path = '/hoge/v1/fuga'"
}

NewRelicのService Level機能は Transaction 以外のイベントタイプもSLIのデータソースとして使えるため、計測対象に応じて柔軟に選択できます。

PoC段階での所感

  • 目標値は仮置きで始めてよい: まず計測基盤を作り、データで実態を把握してから調整するアプローチが有効です。GoogleのSREプラクティスでは28日間のローリングウィンドウが推奨されており、NewRelicのService Levelでもデフォルトが28日間です。少なくともこの期間のデータを蓄積してから目標値を見直すのが目安になります
  • APIごとに特性が異なる: 例えば、参照系はP95 < 100ms、決済系はP95 < 1000msなど、一律の目標は現実的ではありません。APIごとの特性やどのマイクロサービスを経由するか、それらのマイクロサービスがどんな処理をするかなどを確認して、適切な目標値を模索する必要があります
  • ダッシュボードもTerraform管理すると便利: newrelic_one_dashboard で環境ごとに同じ構成のSLOダッシュボードを自動生成できます

今回は、検証中のNewRelicのService Level機能をTerraformで管理する方法の一例を紹介させていただきました。

今後はError Budget Burn Rate Alertとの連携などを検討しつつ、本番環境への展開を進めていく予定です。

参考リンク


みんなの銀行、ゼロバンク・デザインファクトリーでは、一緒に働く仲間を募集しています!
より良い体験を届けられる銀行を、一緒に作りませんか?

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?