この記事は New Relic 使ってみた情報をシェアしよう! by New Relic Advent Calendar 2024シリーズ1 6 日目の記事です。
現在、 SRE として参画しているプロジェクトで New Relic を導入して 1 年が経ちました。New Relic が導入されたのは私が参画する以前ではあるのですが、以前にも別のプロジェクトで APM の機能を利用したことがあったのである程度の機能については把握していました。
現在のプロジェクトでも、 APM の機能を利用して Web アプリケーションのパフォーマンスを継続的に計測しています。主にはアプリケーションのデプロイのイベントを APM のデプロイメントとして記録して、記録の前後でのリクエストの傾向やパフォーマンスメトリクスを比較することでサービスの信頼性指標について評価したり、キャパシティプランニングを行っています。
ドキュメントのサンプルにあるように、以下のように curl でコマンドを実行することでデプロイメントとして記録できます。
curl -X POST "https://api.newrelic.com/v2/applications/$APP_ID/deployments.json" \
-H "X-Api-Key:$API_KEY" \
-i \
-H "Content-Type: application/json" \
-d \
'{
"deployment": {
"revision": "REVISION",
"changelog": "Added: /v2/deployments.rb, Removed: None",
"description": "Added a deployments resource to the v2 API",
"user": "datanerd@example.com",
"timestamp": "2019-10-08T00:15:36Z"
}
}'
アプリケーションのデプロイが終わったタイミングでデプロイメントを作成してデプロイイベントを記録するのが一般的です。その際は、上記のようなリクエストをデプロイ処理の後に発行するだけです。
デプロイメントを作成すると、 APM の Summary ページでは以下のようグラフ中に破線として記録されます。
私たちのプロジェクトでは、アプリケーションのデプロイのイベントをデプロイメントとして記録するだけでなく、サービスに係るインフラの変更もデプロイメントとして記録しています。
具体的にはリソースのスケールアップやスケールアウトといったイベントをデプロイメントとして記録しています。
サービスでは新機能の実装や施策の実施に応じて、リクエストの傾向が変わるため、事前にリソースのスケールアップやスケールアウトを行っています。そのため、 1 台当たりのアプリケーションサーバーに対する負荷も変化するため、パフォーマンスを追跡しやすくするために、デプロイメントとしてインフラの作業を記録しています。
現状のデプロイメント作成の問題点
プロジェクトでは AWS を利用しており、現在は AWS CloudFormation によって Amazon EC2 Auto Scaling リソースを作成して、サーバーを管理してます。
スケールアップやスケールアウトの際は、AWS CloudFormation のスタックを更新して、作業を行っています。作業した後にデプロイメントの作成を行っていますが、 CloudFormation のスタック更新は、マネジメントコンソール上から変更セットを作成後に変更内容をレビューし変更セットを実行して行っています。このワークフローの問題として、 New Relic のデプロイメントの記録が一連の作業から抜け漏れることがありました。また、繰り返しの作業の一部となり Toil になっていました。
Terraform からのデプロイメントの作成
プロジェクトには OS の更新やインスタンスタイプの見直しといったロードマップがあり、その際の IaC の改善として AWS CloudFormation から HCP Terraform への移行を考えています。Terraform にインフラのコード管理が移ることで、リソースの変更をトリガに New Relic のデプロイメントの記録を自動化できないかと考えて、試してみました。
結論から述べると、以下のように Terraform のコードを記述することで、 Amazon EC2 Auto Scaling リソースに対して変更が発生した場合に New Relic にデプロイメントを記録することができました。
resource "aws_autoscaling_group" "app" {
desired_capacity = 10
max_size = 10
min_size = 10
vpc_zone_identifier = [var.subnet_id]
launch_configuration = aws_launch_configuration.app.id
}
resource "null_resource" "record_deployment" {
triggers = {
capacity = aws_autoscaling_group.app.desired_capacity
}
provisioner "local-exec" {
command = <<EOT
curl -X POST "https://api.newrelic.com/v2/applications/$APP_ID/deployments.json" \
-H "X-Api-Key:$API_KEY" \
-i \
-H "Content-Type: application/json" \
-d \
'{
"deployment": {
"revision": "REVISION",
"changelog": "Added: /v2/deployments.rb, Removed: None",
"description": "Added a deployments resource to the v2 API",
"user": "datanerd@example.com",
"timestamp": "2019-10-08T00:15:36Z"
}
}'
EOT
}
}
triggers
の値に aws_autoscaling_group.app.desired_capacity
を指定することで、Amazon EC2 AutoScaling Group の Desired Capacity に変更があったときに、 New Relic のデプロイメントを記録できます。
ほかにも aws_launch_configuration.instance_type
を指定したり、 aws_autoscaling_group.app.user_data_base64
を指定することで、各種インフラの変更作業を起点に追跡できそうです。
プロジェクトでは AWS CloudFormation から Terraform への移行作業を行っており、試行段階ですが、これによって確実に繰り返しの手作業を減らせることが確認できました。
NRQL の COMPARE WITH
句と組み合わせることで記録されたデプロイメントの前後の比較もより活用していきたいと思います!