Instanaの設定をTerraformで管理する

この記事は、Instana Advent Calendarの12/24(日)の記載になります。

# はじめに

メリークリスマス🎅　クリスマス楽しめていますか？
InstanaとSantaは何か響きが似てますね。インスタナ、インスンタ、インサンタ、、、
と私に似て徐々に本来の寒さに戻りつつある冬の夜にこの記事を書いております。

ところで、InstanaのGithubリポジトリがあるのはご存知でしょうか？

https://github.com/instana

私は定期的にリポジトリのアクティビティを眺めて有用な情報がないかなとかをチェックするのですが、その中にTerraform Providerがあって、夏から秋にかけて一気に開発が進んでいる様子を観察してました。

そこで今回はこのTerraform Providerを触ってみたという記事になります。

:::note info
まだ公式ドキュメントにはないはず、、と思ったらすでにドキュメントにも案内されていました！

https://www.ibm.com/docs/en/instana-observability/current?topic=apis-terraform-integrations

:::

# InstanaでIaCできると嬉しいケース

まずInstana自体はAPM製品の中でも自動化が進んでおりエージェント側はほとんど設定が不要です。この点は非常に素晴らしいのですが、ユーザーの志向によりマニュアルで設定しないといけない項目がいくつかあります。

:::note info
Instanaではオートディスカバリ機能のおかげでエージェントが監視対象を自動的にディスカバリし事前に設定済みの監視項目を自動で有効にしてくれるため、通常エージェント側の設定は特殊な設定がある場合にそれを入れ込むくらいしか発生しません。このあたりはそもそも設定自動化をこちらで考えてなくて済むので非常に楽です。
:::

Instanaのアーキテクチャをご存知ない方に簡単に説明すると、他のAPMと同様にInstanaはエージェントとバックエンドそれぞれのソフトウェアが協調して動作をします。
- エージェントは監視対象に導入され、バックエンドにデータを送信します。
- バックエンド側では、送られてきたデータをもとにダッシュボードの設定やアラートの設定などデータを使ったアクションに関する設定を行った上で、ユーザーへビューやアクションの機能を提供します。

こうしたInstanaの構成を踏まえたときに、エージェント側、バックエンド側ではユーザーの志向つまり監視対象、アカウント、ポリシーなどの追加、削除に伴うInstanaへの反映作業というのが日々運用担当者のタスクとして発生します。以下は思いつく一例です。

- エージェントに関する運用業務
    - 監視対象の増減に伴う設定作業（インストール、アンインストール）
    - 監視対象の設定（DBテーブルへの認証設定など）に伴う設定作業
    - エージェントそのものに関する動作設定作業（ログのローテーションなど）

- バックエンドに関する運用業務
    - Webサイトの増減に伴う設定作業
    - モバイルアプリの増減に伴う設定作業
    - アプリケーションパースペクティブの増減に伴う設定作業
    - カスタムイベントの増減に伴う設定作業
    - アラートの増減に伴う設定作業
    - ユーザー改廃に伴う設定作業
    - APIトークン増減に伴う設定作業
    - メンテナンススケジュール追加に伴う設定作業
    - カスタムダッシュボード追加に伴う設定作業（SLI/SLO含む）
    - シンセティックテスト追加に伴う設定作業
    - etc...

こうした設定については規模が大きくなるにつれ手動での管理が大変になるため自動化してコードで設定を管理したいという欲求が自然と生まれてきます。

# Terraform Instana Provider
Instana Providerに関する情報はGitHubにリンクが記載があり、以下に詳細がありました。
2023/12/24現在の最新版は、v2.3.0となっています。

https://registry.terraform.io/providers/gessnerfl/instana/2.3.0

## できること

ドキュメントを読むと、このProviderはInstnaのWeb REST APIに対応とありますが、バックエンド向けのAPIのみに対応しているようです。
前述の通りエージェントを設定する場面は稀なので、大きな問題はありません。

2023/12/24現在時点でサポートしているリソース一覧は以下のとおりです。 [^1]
[^1]: https://registry.terraform.io/providers/gessnerfl/instana/latest/docs
 
> - Application Settings
>     - Application Configuration: instana_application_config
>     - Application Alert Configuration: instana_application_alert_config
>     - Global Application Alert Configuration: instana_global_application_alert_config
> - Event Settings
>     - Custom Event Specification: instana_custom_event_specification
>     - Alerting Channels: instana_alerting_channel
>     - Alerting Config: instana_alerting_config
> - Settings
>     - API Tokens: instana_api_token
>     - Groups: instana_rbac_group
> - SLI Settings
>     - SLI Config: instana_sli_config
> - Synthetic Settings
>     - Synthetic Test: instana_synthetic_test
> - Website Monitoring
>     - Website Monitoring Config: instana_website_monitoring_config
>     - Website Alert Config: instana_website_alert_config
>     - Custom Dashboard: instana_custom_dashboard

先程あげた想定業務のすべてをカバーしているわけではなさそうでしたが、それでもよく使う主要な設定項目についてはサポートしているようでした。

## 使ってみた

### Providerの指定

ドキュメントにある通りProviderを指定します。2023/12/24時点の最新版は2.3.0なのでそう指定します。

```terraform:provider.tf
terraform {
  required_providers {
    instana = {
      source = "gessnerfl/instana"
      version = "2.3.0"
    }
  }
}
```

### Resourceの指定

とりあえず簡単なリソースだけですが、以下の３つを試してみます。

- アプリケーションパースペクティブの設定
- アラートチャネルの設定
- カスタムイベントの定義

こちらガイドが用意されていなかったのでどこまでが対応できるのかなど細かい仕様などがわからかなったが、サンプルを見ながら簡単な設定はできそうでした。

```terraform:main.tf
provider "instana" {
  api_token = "<api-token>"    #予め作成したAPIトークン
  endpoint = "<unit>-<tenant>.instana.io"　　　#管理対象とするエンドポイント　
  tls_skip_verify     = false　　　
}

#アプリケーションパースペクティブの設定
resource "instana_application_config" "example" {
  label               = "Terrafomr Test"
  scope               = "INCLUDE_ALL_DOWNSTREAM"  
  boundary_scope      = "INBOUND"  
  tag_filter          = "agent.tag:stage EQUALS 'test' OR aws.ec2.tag:stage EQUALS 'test' OR call.tag:stage@na EQUALS 'test'"
}

#アラートチャネルの設定
resource "instana_alerting_channel" "example" {
  name = "Terraform Test"

  email {
    emails = [ "email1@example.com", "email2@example.com" ]
  }
}

#カスタムイベントの定義
resource "instana_custom_event_specification" "example" {
  name            = "Terraform Test"
  description     = "description"
  enabled         = true
  triggering      = true
  expiration_time = 60000
  entity_type     = "host"

  rules {  
    host_availability {
      severity         = "warning"
      offline_duration = 60000
      close_after      = 120000
      tag_filter       = "tag:my_tag EQUALS 'test'"
    }
  } 
}
```

### 実行

これでTerraformを実行してみます。

```bash
->> terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # instana_alerting_channel.example will be created
  + resource "instana_alerting_channel" "example" {
      + id   = (known after apply)
      + name = "Terraform Test"

      + email {
          + emails = [
              + "email1@example.com",
              + "email2@example.com",
            ]
        }
    }

  # instana_application_config.example will be created
  + resource "instana_application_config" "example" {
      + boundary_scope = "INBOUND"
      + id             = (known after apply)
      + label          = "Terrafomr Test"
      + scope          = "INCLUDE_ALL_DOWNSTREAM"
      + tag_filter     = "(agent.tag:'stage'@dest EQUALS 'test' OR aws.ec2.tag:'stage'@dest EQUALS 'test' OR call.tag:'stage'@na EQUALS 'test')"
    }

  # instana_custom_event_specification.example will be created
  + resource "instana_custom_event_specification" "example" {
      + description           = "description"
      + enabled               = true
      + entity_type           = "host"
      + expiration_time       = 60000
      + id                    = (known after apply)
      + name                  = "Terraform Test"
      + rule_logical_operator = "AND"
      + triggering            = true

      + rules {
          + host_availability {
              + close_after      = 120000
              + offline_duration = 60000
              + severity         = "warning"
              + tag_filter       = "tag:'my_tag'@dest EQUALS 'test'"
            }
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.
```
```bash
->> terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # instana_alerting_channel.example will be created
  + resource "instana_alerting_channel" "example" {
      + id   = (known after apply)
      + name = "Terraform Test"

      + email {
          + emails = [
              + "email1@example.com",
              + "email2@example.com",
            ]
        }
    }

  # instana_application_config.example will be created
  + resource "instana_application_config" "example" {
      + boundary_scope = "INBOUND"
      + id             = (known after apply)
      + label          = "Terrafomr Test"
      + scope          = "INCLUDE_ALL_DOWNSTREAM"
      + tag_filter     = "(agent.tag:'stage'@dest EQUALS 'test' OR aws.ec2.tag:'stage'@dest EQUALS 'test' OR call.tag:'stage'@na EQUALS 'test')"
    }

  # instana_custom_event_specification.example will be created
  + resource "instana_custom_event_specification" "example" {
      + description           = "description"
      + enabled               = true
      + entity_type           = "host"
      + expiration_time       = 60000
      + id                    = (known after apply)
      + name                  = "Terraform Test"
      + rule_logical_operator = "AND"
      + triggering            = true

      + rules {
          + host_availability {
              + close_after      = 120000
              + offline_duration = 60000
              + severity         = "warning"
              + tag_filter       = "tag:'my_tag'@dest EQUALS 'test'"
            }
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

instana_application_config.example: Creating...
instana_alerting_channel.example: Creating...
instana_custom_event_specification.example: Creating...
instana_application_config.example: Creation complete after 1s [id=cm3fbh4bsl1me5bn499g]
instana_alerting_channel.example: Creation complete after 1s [id=cm3fbh4bsl1me5bn4990]
instana_custom_event_specification.example: Creation complete after 1s [id=cm3fbh4bsl1me5bn49a0]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
```

どうやら無事設定がされたようです。
実際画面を見てみるといずれも設定が追加されているのがわかりました。

![スクリーンショット 0005-12-24 0.03.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586/4dee5809-4c48-eac0-3c11-c19b06ec0db2.png)

![スクリーンショット 0005-12-24 0.04.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586/fd880c25-308a-d87d-36d6-d817efc23c5d.png)

![スクリーンショット 0005-12-24 0.05.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586/c66e2665-2f22-dfe2-edce-d2a58020dca1.png)

ということで、全部はまだ試せていませんが、なんとなく動作イメージが掴めました。

### 感想・まとめ
- Instanaのバックエンドの設定変更はTerraformで一部の設定について行うことができます。
- 設定は簡単そうですが、tag_filterが必須のリソースになるなど、tagを予め検討をしておく必要がありそうです。 
- ただし、印象としてはまだガイドやリソースの仕様などの整備が整っておらずまだ正式な機能にはなっていない印象でした。今後ますます多くのリソースを開発してもらえることを期待します。