Go to list of users who liked
Terraformで実現するNewRelic Dashboard as Code 〜マルチ環境対応の自動化実践〜
はじめに
近年、システム運用においてオブザーバビリティ(可観測性)の重要性がますます高まっています。複雑化するシステムの状態を把握し、迅速に問題を特定・解決するためには、効果的なモニタリングツールが不可欠です。NewRelicは、このオブザーバビリティを実現する強力なプラットフォームとして広く認知されており、システム全体の状態をリアルタイムで可視化し、迅速なトラブルシューティングやパフォーマンス改善を可能にします。
しかし、NewRelicのダッシュボードを手動で作成・管理することは、特に複数環境(開発、ステージング、本番など)を扱う場合、以下のような大きな課題をもたらします:
- 作業の非効率性: 環境ごとに同じ設定を繰り返す手間が発生
- 設定ミスのリスク: 人為的エラーによる環境間の設定の不一致
- 再利用性の欠如: 既存ダッシュボードの他環境への展開が困難
これらの課題を解決するために、「Dashboard as Code」というアプローチが注目されています。Terraformを活用してNewRelicのダッシュボードをコード化することで、次のようなメリットが得られます:
- 作業の効率化: コードによる一貫した設定の複数環境への適用
- エラー防止: 手動作業の排除による設定の再現性確保
- 拡張性の向上: 新規環境への迅速な展開
本記事では、Terraformを使用して開発環境でダッシュボードを調整し、その設定をステージング環境へ効率的に展開する手法を詳しく解説します。この方法により、オブザーバビリティの向上と運用作業の自動化を同時に実現できます。
システム構成
全体アーキテクチャ
以下に 全体アーキテクチャ構成図 を示します。このアーキテクチャは大きく 2つの層 に分かれています:
インフラストラクチャ層
この層では、AWS上にマルチ環境(DEV/STG) を構築します。各環境は以下の主要コンポーネントで構成されています:
- ECSクラスタ:コンテナ化されたアプリケーションの実行環境。
- VPCネットワーク:パブリックサブネットおよびプライベートサブネットによるネットワーク構成。
- AWS CodePipeline:CI/CDパイプラインの自動化を実現。
- AWS CodeBuild:アプリケーションのビルド環境。
- Amazon CloudWatch:ログ管理および監視のための基盤。
これらの環境は Terraform を用いてコードベースで定義され、完全に自動化された方法 で構築・管理されます。これにより、環境ごとの設定の一貫性と再現性が確保されます。
ダッシュボード層
インフラストラクチャ層で構築された基盤環境の情報を、Terraform show を活用して取得します(例:ECS、ALB、RDSのリソース情報)。その取得した情報を基に、Terraform を用いて NewRelicダッシュボード を自動生成します。
Terraformを使用することで、DEV環境で調整したダッシュボード設定を、STG環境 にそのまま展開できるため、作業の効率化と設定ミスの削減が実現されます。
マルチ環境ダッシュボード自動作成フロー
- ダッシュボードに必要な情報の整理
- 取得するリソースのメトリクスやログ、監視対象の項目を整理します(例:ECSのCPU・メモリ使用率、ALBのリクエスト数、RDSの接続数など)。
- サンプル環境(Dev環境)でのダッシュボード作成
- 手作業で Dev環境 のダッシュボードを作成し、必要なグラフやメトリクスを調整・整理します。
- Terraform Dashboardモジュールの作成
- Dev環境で作成したダッシュボードを基に、Terraformを用いて再利用可能な Dashboardモジュール を作成します。
- 全環境へのダッシュボード自動展開
- インフラストラクチャ層で構築された基盤情報(ECS、ALB、RDSなど)を Terraform show で取得し、その情報を利用して、DEV環境、STG環境 など複数環境のダッシュボードを自動生成します。
terraformディレクトリ構成
Terraformを使用したNewRelicダッシュボードの自動生成プロジェクトは、以下のような構造で組織化されています。
newrelic-dashboards/├── environments/│ ├── dev.tfvars # Dev環境用の変数定義ファイル│ ├── stg.tfvars # STG環境用の変数定義ファイル│└── modules/ ├── dashboard/ # ダッシュボードを管理するモジュール │ ├── main.tf # ダッシュボードリソースの定義 │ ├── outputs.tf # ダッシュボードの出力定義 │ └── variables.tf # モジュールの変数定義 │ ├── main.tf # 基盤情報取得のモジュール定義 ├── outputs.tf # 環境情報の出力定義 └── variables.tf # 環境全体の変数定義
この構造により、環境ごとの設定を分離しつつ、ダッシュボード生成ロジックを再利用可能なモジュールとして実装することができます。terraform apply -var-file=environments/dev.tfvarsのようなコマンドで、特定の環境用のダッシュボードを生成することが可能となります。
実装手順
事前準備
- AWSアカウント:申請済みであり、IAMユーザーが払い出されていること。
- GitHub環境:アクセス可能な環境を準備しておくこと。
- NewRelicアカウント:登録済みであること。
- NewRelicでのAWSインテグレーション設定:
- Amazon CloudWatch Metric StreamsまたはAPIポーリングの2つの方法があります。筆者は推奨されている Amazon CloudWatch Metric Streams を利用しています。
- 設定方法については、下記の記事をご参考ください。
AWSマルチ基盤環境構築
- GitHubで公開されているサンプルコードを利用します。
Terraformコードを修正してマルチ環境対応にします。
- 元のコードはマルチ環境向けに設計されていないため、リポジトリを2つのフォルダ(
dev-aws-ecs-cicd-terraform-master
とstg-aws-ecs-cicd-terraform-master
)にコピーします。 /dev-aws-ecs-cicd-terraform-master/terraform/terraform.tfvars
を以下のように修正します:aws_region="ap-northeast-1"stack="dev"fargate-task-service-role="dev-task-role"fargate-task-execution-role="dev-execution-role"aws_ecr="dev-petclinic"aws_profile="default"source_repo_name="dev-petclinic"source_repo_branch="master"image_repo_name="dev-petclinic"family="dev-family"
/stg-aws-ecs-cicd-terraform-master/terraform/terraform.tfvars
を以下のように修正します:aws_region="ap-northeast-1"stack="stg"fargate-task-service-role="stg-task-role"fargate-task-execution-role="stg-execution-role"aws_ecr="stg-petclinic"aws_profile="default"source_repo_name="stg-petclinic"source_repo_branch="master"image_repo_name="stg-petclinic"family="stg-family"
- 元のコードはマルチ環境向けに設計されていないため、リポジトリを2つのフォルダ(
それぞれのフォルダに移動し、
README.md
に記載されている手順に従い環境を構築します。
開発環境(Dev環境)でのダッシュボード設定
ダッシュボードのグラフ整理
グラフ名(リソース名) | 内容 | 目的 |
---|---|---|
Total Request Count (${var.alb_arn}) | ALBを通じたリクエスト数(AZごと)を表示 | トラフィック状況と負荷分散の状態を把握する |
HTTP Status Codes (${var.alb_arn}) | HTTPステータスコード(2XX、3XX、4XX、5XX)ごとの数を表示 | エラーレスポンスの発生状況を監視する |
ECS-CPU utilization (%) (${var.ecs_cluster_name}) | ECSクラスタのCPU使用率(平均、最小、最大、合計)を表示 | コンテナのCPUリソース使用状況を監視する |
ECS-Memory utilization (%) (${var.ecs_cluster_name}) | ECSクラスタのメモリ使用率(平均、最小、最大、合計)を表示 | メモリ不足やリソース過剰利用を確認する |
Database connections (${var.rds_instance_identifier}) | RDSデータベースへの接続数を表示 | データベースの負荷状況を把握する |
DB Throughput (bytes/s) (${var.rds_instance_identifier}) | RDSデータベースの読み取り・書き込みスループット(bytes/s)を表示 | データベースのパフォーマンスを監視する |
DB CPU utilization (${var.rds_instance_identifier}) | RDSデータベースのCPU使用率(平均、最小、最大)を表示 | データベース処理能力のボトルネックを監視する |
CodeBuild Failed Builds (${var.codebuild_project_name}) | CodeBuildプロジェクトのビルド失敗数を時間帯ごとに表示 | CI/CDパイプラインの問題を特定する |
実際のプロジェクトでは、APM(Application Performance Monitoring) 指標やECSタスク数、アプリケーションのレスポンス時間 など、さらに重要なメトリクスを追加する必要があります。ここでは指標の網羅性については議論しません。
Dev環境用サンプルダッシュボード作成
手作業でサンプル用ダッシュボードを作成します。
NewRelicが提供するグラフを活用し、0からクエリを作成する工数を削減できます。
例:DB CPU使用率のグラフダッシュボードのグラフを編集して、リソース名を特定します。
- ダッシュボード(sample)に移動し、グラフの右上[...] をクリックして[Edit] を選択します。
- クエリ内のDBインスタンスを特定する部分(
WHERE
句)をAWSリソース名に変更します。- 変更前:
SELECTmin(`aws.rds.CPUUtilization`),max(`aws.rds.CPUUtilization`),average(`aws.rds.CPUUtilization`)FROMMetricWHERE(entity.guid='NjI2NTg2M3xJTkZSQXxOQXwxMDIzMTI3ODkzMzM2ODE4NzU4')TIMESERIESAUTO
- 変更後:
SELECTmin(`aws.rds.CPUUtilization`),max(`aws.rds.CPUUtilization`),average(`aws.rds.CPUUtilization`)FROMMetricWHEREaws.rds.DBInstanceIdentifier='dev-petclinic'TIMESERIESAUTO
- 変更前:
- 変更理由:
- 今後Terraform化する際に、リソース名(
aws.rds.DBInstanceIdentifier
) は比較的に変換しやすいため、管理が容易になります。
- 今後Terraform化する際に、リソース名(
- ダッシュボード(sample)に移動し、グラフの右上[...] をクリックして[Edit] を選択します。
サンプルダッシュボードのJSON情報を取得
Terraformでダッシュボードをモジュール化
- 以下のパスに
main.tf
を作成します:/newrelic-dashboards/modules/dashboard/main.tf
- ダッシュボード定義をTerraformコードとして記述します。
terraform{required_providers{newrelic={source="newrelic/newrelic"version="~> 3.0"}}}resource"newrelic_one_dashboard""infrastructure_dashboard"{name="${var.environment} Infrastructure Dashboard"permissions="public_read_only"page{name="Load Balancer Metrics"widget_line{title="Total Request Count (${var.alb_arn})"row=1column=1width=3height=3nrql_query{query="SELECT sum(`aws.applicationelb.RequestCount.byAlb`) as 'Requests with AZ' FROM Metric WHERE `aws.applicationelb.LoadBalancer` ='${var.alb_arn}' AND aws.applicationelb.AvailabilityZone IS NOT NULL TIMESERIES auto SINCE 30 minutes ago UNTIL now"}}widget_line{title="HTTP Status Codes (${var.alb_arn})"row=1column=4width=3height=3nrql_query{query="FROM Metric SELECT sum(aws.applicationelb.HTTPCode_Target_2XX_Count) as '2XX', sum(aws.applicationelb.HTTPCode_Target_3XX_Count) as '3XX', sum(aws.applicationelb.HTTPCode_Target_4XX_Count) as '4XX', sum(aws.applicationelb.HTTPCode_Target_5XX_Count) as '5XX' WHERE aws.applicationelb.LoadBalancer='${var.alb_arn}' SINCE 30 minutes ago TIMESERIES"}}widget_line{title="ECS-CPU utilization (%) (${var.ecs_cluster_name})"row=1column=7width=3height=3nrql_query{query="SELECT average(`aws.ecs.CPUUtilization.byService`), min(`aws.ecs.CPUUtilization.byService`), max(`aws.ecs.CPUUtilization.byService`), sum(`aws.ecs.CPUUtilization.byService`) FROM Metric WHERE (aws.ecs.ClusterName='${var.ecs_cluster_name}') TIMESERIES AUTO"}}widget_line{title="ECS-Memory utilization (%) (${var.ecs_cluster_name})"row=1column=10width=3height=3nrql_query{query="SELECT average(`aws.ecs.MemoryUtilization.byService`), min(`aws.ecs.MemoryUtilization.byService`), max(`aws.ecs.MemoryUtilization.byService`), sum(`aws.ecs.MemoryUtilization.byService`) FROM Metric WHERE (aws.ecs.ClusterName='${var.ecs_cluster_name}') TIMESERIES AUTO"}}widget_line{title="Database connections (${var.rds_instance_identifier})"row=4column=1width=3height=3nrql_query{query="SELECT average(`aws.rds.DatabaseConnections`) as 'Connections' FROM Metric WHERE aws.rds.DBInstanceIdentifier = '${var.rds_instance_identifier}' TIMESERIES auto"}}widget_line{title="DB Throughput (bytes/s) (${var.rds_instance_identifier})"row=4column=4width=3height=3nrql_query{query="SELECT average(`aws.rds.ReadThroughput`) as 'Read', average(`aws.rds.WriteThroughput`) as 'Write' FROM Metric WHERE aws.rds.DBInstanceIdentifier = '${var.rds_instance_identifier}' TIMESERIES"}}widget_line{title="DB CPU utilization (${var.rds_instance_identifier})"row=4column=7width=3height=3nrql_query{query="SELECT min(`aws.rds.CPUUtilization`), max(`aws.rds.CPUUtilization`), average(`aws.rds.CPUUtilization`) FROM Metric WHERE aws.rds.DBInstanceIdentifier = '${var.rds_instance_identifier}' TIMESERIES AUTO"}}widget_line{title="CodeBuild Failed Builds (${var.codebuild_project_name})"row=4column=10width=3height=3nrql_query{query="SELECT average(`aws.codebuild.FailedBuilds`) FROM Metric FACET `aws.codebuild.ProjectName` WHERE `aws.codebuild.ProjectName` = '${var.codebuild_project_name}' SINCE 6 HOURS AGO TIMESERIES"}}}}
- 以下のパスに
環境変数ファイル(tfvars)を作成
newrelic-dashboards/environments/dev.tfvars
に環境情報を設定します:
environment="dev"alb_arn="app/dev-alb/52e8a82b796e3001"ecs_cluster_name="dev-Cluster"rds_instance_identifier="dev-petclinic"codebuild_project_name="codebuild-dev-petclinic-master"
補足:
上記のリソース情報は、インフラ基盤環境構築後にterraform show
を実行することで取得可能です。Terraformを実行してダッシュボードをデプロイ
- 以下のコマンドでDEV環境のダッシュボードをデプロイします:
terraform apply-var-file="environments/dev.tfvars"
本番ステージング環境(STG環境)への展開
今回の検証では、STG環境のダッシュボードはDEV環境と同じ内容 に設定します。そのため、STG環境への展開は非常に簡単です。
もしカスタマイズが必要な場合は、TerraformコードでSTG専用のカスタマイズを追加すれば対応可能です。
ただし、今回はマルチ環境への適用効率 を検証する目的で、カスタマイズ部分は割愛しています。
環境変数ファイル(tfvars)の作成
以下の環境情報を設定し、newrelic-dashboards/environments/stg.tfvars
を作成します:environment="stg"alb_arn="app/stg-alb/45a2fb743b4efc17"ecs_cluster_name="stg-Cluster"rds_instance_identifier="stg-petclinic"codebuild_project_name="codebuild-stg-petclinic-master"
Terraformを実行してダッシュボードをデプロイ
以下のコマンドを実行して、STG環境のダッシュボードをデプロイします:terraform apply-var-file="environments/stg.tfvars"
デプロイされたダッシュボードの確認
デプロイ後のダッシュボードは以下の通りです:- ダッシュボード名やリソース名はSTG環境 のものに置き換わっています。
実践のメリットと課題
実践のメリット
多環境への効率的な展開
- Terraformを活用することで、DEV環境で作成した設定をそのままSTGや本番環境に適用可能となり、作業の手間を大幅に削減できます。
- 再利用可能なモジュール化により、新たな環境の追加も容易です。
設定ミスの削減
- ダッシュボードをコード化することで、手動設定によるエラーや環境間の設定不一致を防ぐことができます。
将来の拡張性
- コードベースで管理することで、将来的にダッシュボード設定をCI/CDパイプラインに組み込み、自動化された運用が可能となります。
課題と注意点
コードの複雑性
- 多環境への適用時にカスタマイズが必要な場合、Terraformコードが複雑化する可能性があります。
- 特に、環境ごとに異なるリソース(例:メトリクスやカスタムグラフ)の柔軟な対応には、追加のスクリプトやモジュール設計が必要です。
キー管理のリスク
- NewRelicのAPIキーやアカウント情報が流出しないよう、十分な管理が必要です。
- Secret Manager や環境変数 を活用し、直接コードに書き込まない運用が推奨されます。
運用面での注意点
- 環境変数やリソース情報の管理方法を標準化する必要があります。
- ダッシュボード設定の変更管理プロセス(例:コードレビューやテスト)の確立が求められます。
まとめ
本記事では、Terraformを活用したNewRelic Dashboardの自動生成について詳しく解説しました。Dashboard as Codeというアプローチを採用することで、複数環境でのダッシュボード管理を効率化し、設定品質を向上できることを実証しました。
このアプローチを導入することで、システム監視の効率化 とオブザーバビリティの向上 を同時に達成することが可能となります。特に、多環境を管理する運用チームにとって、本手法は非常に有効なツールとなるでしょう。
今後の展望
CI/CDパイプラインとの統合
- GitHub Actions やJenkins を活用したダッシュボードの自動デプロイ基盤の構築
- プルリクエストベースのレビュー を導入し、コード変更の透明性を確保
- 継続的デリバリーによる、迅速かつ安全なデプロイの実現
自動化の更なる可能性
- アラート設定の自動化 により、異常検知の効率化および精度向上
- 再利用可能なカスタムダッシュボードテンプレート の整備
- チーム間で共有可能な、汎用性の高いモジュールの開発と展開
このように、TerraformとNewRelicを組み合わせることで、運用効率を大幅に向上させ、システムの安定性を高めることが期待できます。
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme