TerraformでPagerDuty設定入門 その１

# PagerDutyの設定はコードで行おう

PagerDuty Advent Calendarの7日目！ 今回はPagerDutyをTerraformで設定する方法について解説します。

TerraformはInfrastructure as Codeを実現するための代表的なツールです。AWSやAzureなどのクラウド環境をTerraformで構築しているという方も多いでしょう。

一方で、これまでクラウドのIaCに挑戦してこなかった方や、最近エンジニアとしてデビューした方からすると、まだ馴染みがないという人もいるかもしれません。本シリーズでは、そういった方に向けて一から説明したいと思います。

今回は、そもそも何故Terraformで書く必要があるのか、その理由を解説します。

## PagerDutyをコードで設定する目的

Infrastructure as Code(以下IaC)はその名の通り、インフラをコードで記述する手法のことをいいます。ここでいうインフラとは、AWSやAzureといったパブリッククラウドだけでなく、VMwareのようなプライベートクラウドもそうですし、PagerDutyやNew Relic、CloudflareのようなSaaSまで、幅広く指しています。

PagerDutyを利用する場合、さまざまな設定をPagerDutyのUIから行いますよね。

Serviceを追加したい場合はService DirectoryからNew Serviceをポチっとすると設定画面が出てくるので、必要な項目を入れていくわけです。

![CleanShot 2024-12-08 at 00.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17840/c131dec1-9a13-4138-defc-a6a9de7d8f43.png)
![CleanShot 2024-12-08 at 00.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17840/0ff2ae96-06d0-1ebc-46dc-57dac3be03e7.png)

ユーザーを追加したければ、UsersからAdd Usersすると追加ができますね。
![CleanShot 2024-12-08 at 00.14.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17840/10b2365a-a735-7971-0856-38a3423602cd.png)

こういった操作を、 **PagerDutyのUIではなく、コードを書くことによって行うのがIaC**です。

Terraformの場合、次のようなコードをテキストエディタで書きます。

```terraform
## Web appという名前のServiceを作成
resource "pagerduty_service" "web" {
  name                    = "Web app"
  auto_resolve_timeout    = 14400
  acknowledgement_timeout = 600
  escalation_policy       = pagerduty_escalation_policy.engineering.id
  alert_creation          = "create_alerts_and_incidents"

  auto_pause_notifications_parameters {
    enabled = true
    timeout = 300
  }
}

## Engineeringという名前のエスカレーションポリシーを作成
resource "pagerduty_escalation_policy" "engineering" {
  name      = "Engineering"
  num_loops = 2

  rule {
    escalation_delay_in_minutes = 10

    target {
      type = "user_reference"
      id   = pagerduty_user.jacopen.id
    }
  }
}

## jacopenという名前のユーザーを作成
resource "pagerduty_user" "jacopen" {
  name  = "jacopen"
  email = "jacopen@example.com"
}
```

書き終わったら、terraformコマンドを実行するとPagerDuty側に設定が行われます。

![CleanShot 2024-12-08 at 00.28.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17840/9cb43da5-7462-53a0-8392-7ecbff64921f.png)

さて、ここでひとつ疑問点が生まれますね。UIで設定すれば終わるものを、何故コードを書いて設定する必要があるのでしょうか。

それは、次のようなメリットがあるからです。

### ミスを減らせる

人間はミスをする生き物です。ユーザーの追加ひとつをとっても、ミスする余地は多分にあります。

`jacopen@example.com` をユーザーに追加するつもりだったのに、 `jacpen@example.com` とtypoして設定しまうなんてこと、普通に起きそうですよね。

コードにすることでtypoが防げるわけではないですが、そこにテキストで設定内容が残るので、ミスに気づきやすくなります。「設定したつもりが追加し忘れていた」というミスも防ぎやすくなります。

```terraform
resource "pagerduty_user" "jacopen" {
  name  = "jacopen"
  email = "jacpen@example.com" # ミスっている
}
```

「ユーザーの追加を忘れていた」
「エスカレーションポリシーへの追加を忘れていた」
「Serviceに間違ったエスカレーションポリシーが設定されていた」
「Service Dependencyの設定が間違っていた」

などなど、よく起きそうな各種ミスを、コード化によって防いでいきましょう。

### 使い回せる

利用が多岐に渡ると、同じような設定を行うことが増えてきます。似たような設定をするために、毎回UIを開いてポチポチするのは効率がよくありません。

コードにすることで、必要なものをコピーして複製するといった作業が容易になります

```terraform
resource "pagerduty_service" "web" {
  name                    = "Web app"
  auto_resolve_timeout    = 14400
  acknowledgement_timeout = 600
  escalation_policy       = pagerduty_escalation_policy.engineering.id
  alert_creation          = "create_alerts_and_incidents"

  auto_pause_notifications_parameters {
    enabled = true
    timeout = 300
  }
}

# 上のコードをコピペして一部を書き換え
resource "pagerduty_service" "backend" {
  name                    = "Backend"
  auto_resolve_timeout    = 14400
  acknowledgement_timeout = 600
  escalation_policy       = pagerduty_escalation_policy.engineering.id
  alert_creation          = "create_alerts_and_incidents"

  auto_pause_notifications_parameters {
    enabled = true
    timeout = 300
  }
}
```

また、Terraformのループ記法を活用することで、コードの記述量を減らしながら大量の設定を流し込むといったことも可能になります。

```terraform
## ユーザ名とメールアドレスをまとめて記述
locals {
  users = [
    { name = "jacopen", email = "jacopen@example.com" },
    { name = "yusuke", email = "yusuke@example.com" },
    { name = "kazuki", email = "kazuki@example.com" },
  ]
}

## for_eachで上記のリストをループさせて複数リソースを作成
resource "pagerduty_user" "user" {
  for_each = { for u in local.users : u.name => u }
  name  = each.value.name
  email = each.value.email
}
```

### 記録が残る
UIで設定する欠点として、いつ誰がどのような変更を行ったのか後から知ることが難しいという点が挙げられます。たとえば何か変な設定が入っているので消したい･･･となっても、その設定をいつ誰がどのような意図で入れたのか分からないので、消していいものか判断が付かないなんてこともよくあります。

IaCの場合、書いたコードをGitで管理することによって、いつ誰がどのような変更を行ったのか辿ることが容易になります。

![CleanShot 2024-12-08 at 01.36.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17840/862c2b8f-cf39-4aa9-1ff2-3539c8e56b28.png)

### チームワークができる
IaCがその威力を最も発揮するのは、チームで作業を行うときです。

GitHubやGitLabを活用することで、Terraformを実行する前にチームメンバーにレビューしてもらうことが可能になります。

![CleanShot 2024-12-08 at 01.51.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17840/328b0de5-d933-a843-cd0f-97b25662d4b5.png)

チームワークという観点では、一覧性の向上も見逃せないポイントです。後からチームに参加したメンバーがいるとして、そのメンバーがPagerDutyの設定周りを把握しておきたいという場合、UIからさまざまな画面に散らばっている設定を確認していく必要があります。それはなかなか骨の折れる作業ですよね。

PagerDutyに関する設定はすべてTerraformのコードに記載されている状態にしておけば、コードを上から下まで眺めることで全体像を把握することができます。

## PagerDutyでIaCする際に取り得る手段

ここまで、Terraformを例にIaCを行う方法を説明しました。

https://www.terraform.io/

TerraformはIaCにおいてデファクトスタンダードなツールであり、PagerDutyの設定に関してもおそらく利用ユーザーが最も多いと考えられます。Terraformを抑えておけば、特に困ることはないでしょう。

Terraformの記述は、HashiCorp Configuration Language(HCL)という独自言語を利用します。インフラの記述に特化した言語で、利用に若干のクセはあるものの、使い始めると比較的短期間に習得することができます。

PagerDutyが中心になって開発しているProviderがあり、これを利用することでさまざまな設定を行うことができます。
https://registry.terraform.io/providers/PagerDuty/pagerduty/

設定可能なリソースは次のとおり。結構広くカバーしています。

- pagerduty_addon
- pagerduty_alert_grouping_setting
- pagerduty_automation_actions_action
- pagerduty_automation_actions_action_service_association
- pagerduty_automation_actions_action_team_association
- pagerduty_automation_actions_runner
- pagerduty_automation_actions_runner_team_association
- pagerduty_business_service
- pagerduty_business_service_subscriber
- pagerduty_escalation_policy
- pagerduty_event_orchestration
- pagerduty_event_orchestration_global
- pagerduty_event_orchestration_global_cache_variable
- pagerduty_event_orchestration_integration
- pagerduty_event_orchestration_router
- pagerduty_event_orchestration_service
- pagerduty_event_orchestration_service_cache_variable
- pagerduty_event_orchestration_unrouted
- pagerduty_event_rule
- pagerduty_extension
- pagerduty_extension_servicenow
- pagerduty_incident_custom_field
- pagerduty_incident_custom_field_option
- pagerduty_incident_workflow
- pagerduty_incident_workflow_trigger
- pagerduty_jira_cloud_account_mapping_rule
- pagerduty_maintenance_window
- pagerduty_response_play
- pagerduty_ruleset
- pagerduty_ruleset_rule
- pagerduty_schedule
- pagerduty_service

### Pulumi

Terraformさえ覚えておけば特に困ることはないと思いますが、他の仕組みも知っておきたいという人もいるでしょう。特にHCLは難しくないとはいえ、その独特なクセを嫌がる人もいます。そこで取り得る選択肢が、Pulumiです。

https://www.pulumi.com/

PulumiはTypeScriptやGo、Pythonといった一般的な言語を使って記述が可能なIaCツールで、PagerDuty Providerも提供されています。慣れ親しんだ言語で記述をしたいという人には選択肢のひとつとなるかもしれません。

本シリーズでは解説しませんが、また機会があれば解説してみたいと思います。

### Ansible
IaCという文脈でよく取り上げられるツールであるAnsibleですが、PagerDutyの設定においてはあまり利用されていません。

一応ユーザーやアラートを設定出来るモジュールが提供されているものの、カバー範囲もせまく、あえてこれを利用するメリットが見当たらないのが現状です。

https://docs.ansible.com/ansible/latest/collections/community/general/pagerduty_user_module.html

## まとめ

今回はPagerDutyでIaCを行うメリットについて解説しました。

次回からは、実際にTerraformのコードでPagerDutyを設定していく例を解説していきます。