0
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?

TerraformでPagerDutyを構築する

Posted at

TerraformでPagerDutyを構築する

この記事では、Terraformを使ってPagerDutyの以下6つの要素を一括で定義するサンプルコードを示します。

  • オンコールユーザー登録 & 連絡手段設定
  • エスカレーションポリシー
  • オンコールスケジュール
  • メンテナンスウィンドウ
  • サービス本体
  • Datadogインテグレーション

目次

  1. variables_user.tf の解説

  2. variables_service.tf の解説

  3. main_user.tf の解説

  4. main_service.tf の解説

    1. 1) エスカレーションポリシー
    2. 2) オンコールスケジュール
    3. 3) メンテナンスウィンドウ
    4. 4) サービス本体
    5. 5) Datadogインテグレーション

variables_user.tf の解説

オンコール対象ユーザーを外部から指定できるように変数を定義します。

// variables_user.tf

variable "oncall_users" {
  description = "オンコールユーザーのリスト"
  type = list(object({
    name  = string  # 名前
    email = string  # メールアドレス
  }))
}
  • oncall_users:名前とメールアドレスを持つユーザーリストを想定

variables_service.tf の解説

サービス全般やメンテナンスウィンドウ、Datadog連携の設定を定義します。

// variables_service.tf

variable "service_name" {
  description = "PagerDuty サービス名"
  type        = string
}

variable "service_description" {
  description = "PagerDuty サービス説明"
  type        = string
}

variable "integration" {
  description = "有効化するインテグレーション"
  type        = object({ datadog = bool })
  default     = { datadog = true }
}

variable "vendors" {
  description = "ベンダー情報"
  type = object({
    datadog = object({
      id   = string  # Datadog ベンダーID
      name = string  # Datadog ベンダー名
    })
  })
}

variable "urgency" {
  description = "インシデントの緊急度(high または low)"
  type        = string
  default     = "high"
}

variable "maintenance_windows" {
  description = "メンテナンスウィンドウの設定リスト"
  type = list(object({
    start_time  = string  # ISO8601 形式
    end_time    = string  # ISO8601 形式
    description = string  # 説明
  }))
}
  • サービス名・説明、緊急度、メンテナンスウィンドウ、Datadog連携設定を外部化

main_user.tf の解説

variables_user.tf で受け取ったユーザー情報をもとに、PagerDuty上でユーザーと連絡手段を作成します。

// main_user.tf

resource "pagerduty_user" "main" {
  for_each = { for u in var.oncall_users : u.email => u }
  name     = each.value.name
  email    = each.value.email
  role     = "user"
}

resource "pagerduty_user_contact_method" "main" {
  for_each = pagerduty_user.main
  user_id  = each.value.id
  type     = "email_contact_method"
  address  = each.value.email
  label    = "Work"
}
  1. pagerduty_user

    • for_each で渡されたリスト分だけユーザーを作成
    • role = "user" で一般ユーザー権限を付与
  2. pagerduty_user_contact_method

    • 各ユーザーにメール連絡手段を登録

main_service.tf の解説

variables_service.tf の変数を活用し、エスカレーションからDatadog連携までを一気に定義します。

1) エスカレーションポリシー

// main_service.tf

resource "pagerduty_escalation_policy" "main" {
  name      = "${var.service_name} Escalation Policy"
  num_loops = 1

  rule {
    escalation_delay_in_minutes = 30
    target {
      type = "schedule"
      id   = pagerduty_schedule.main.id
    }
  }
}
  • num_loops:エスカレーション回数(ここでは1回)
  • rule:30分後にオンコールスケジュールへエスカレーション

2) オンコールスケジュール

// main_service.tf

resource "pagerduty_schedule" "main" {
  name        = "${var.service_name} Primary Schedule"
  description = "Primary on-call rotation"
  time_zone   = "Asia/Tokyo"

  # 平日日中レイヤー
  layer {
    name                         = "Workday Rotation"
    start                        = "2020-06-21T00:00:00+00:00"
    rotation_virtual_start       = "2020-06-21T07:00:00+00:00"
    rotation_turn_length_seconds = 86400
    users                        = [for u in values(pagerduty_user.main) : u.id]
    restriction {
      type              = "weekly_restriction"
      start_day_of_week = 1           # 月曜日
      start_time_of_day = "09:00:00"  # 09:00 〜
      duration_seconds  = 28800       # 8時間
    }
    # 他の平日制限も同様に追加
  }

  # 夜間レイヤー
  layer {
    name                         = "Nightshift Rotation"
    start                        = "2020-06-21T00:00:00+00:00"
    rotation_virtual_start       = "2020-06-21T07:00:00+00:00"
    rotation_turn_length_seconds = 86400
    users                        = [for u in values(pagerduty_user.main) : u.id]
    restriction {
      type              = "weekly_restriction"
      start_day_of_week = 1           # 月曜日
      start_time_of_day = "17:00:00"  # 17:00 〜
      duration_seconds  = 57600       # 翌09:00 まで
    }
    # 他の曜日も同様に追加
  }
}
  • layer:複数レイヤーで日中/夜間など細かくローテーション可
  • restriction:週◯曜◯時〜の時間制限を設定

3) メンテナンスウィンドウ

// main_service.tf

resource "pagerduty_maintenance_window" "main" {
  for_each    = { for idx, mw in var.maintenance_windows : idx => mw }
  start_time  = each.value.start_time
  end_time    = each.value.end_time
  description = each.value.description
  services    = [pagerduty_service.main.id]
}
  • start_timeend_time は ISO8601 フォーマット

4) サービス本体

// main_service.tf

resource "pagerduty_service" "main" {
  name                    = var.service_name
  description             = var.service_description
  escalation_policy       = pagerduty_escalation_policy.main.id
  alert_creation          = "create_alerts_and_incidents"
  acknowledgement_timeout = 7200

  incident_urgency_rule {
    type    = "constant"
    urgency = var.urgency
  }
}
  • acknowledgement_timeout:対応者のアクノレッジ猶予(秒)

5) Datadogインテグレーション

// main_service.tf

resource "pagerduty_service_integration" "main_datadog" {
  count   = var.integration.datadog ? 1 : 0
  name    = var.vendors.datadog.name
  vendor  = var.vendors.datadog.id
  service = pagerduty_service.main.id
}

resource "datadog_integration_pagerduty_service_object" "main" {
  count        = var.integration.datadog ? 1 : 0
  service_name = var.service_name
  service_key  = pagerduty_service_integration.main_datadog[0].integration_key
}
  • count = var.integration.datadog ? 1 : 0 で有効化制御

サンプルコードの参照

実際のTerraform構成例として、以下のリポジトリを参考にするとさらに理解が深まります。
GitHub

リポジトリには、今回ご紹介した「オンコールユーザー登録」「エスカレーションポリシー」「スケジュール」「メンテナンスウィンドウ」「サービス定義」「Datadog連携」が一通り動作するサンプルコードがまとまっています。

0
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
0
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?