🎰

【Terraform】ECSスロットリング検知とSlackへの自動通知(AWS CloudWatchとChatbotの活用)ほぼ完成🙆‍♂

2024/04/25に公開

はじめに

本シリーズのご紹介

このシリーズでは、AWSとSlackを連携させる方法や、Terraformを用いた自動化技術の基本について詳しく解説します。今回は、いよいよ一通り実装していた目的のコードがほぼ完成します。100%完成ではない理由は動作確認をまだ行っていない点や適切な閾値を設定しきれていないためです。このあたりは別途完成次第、記事にまとめていきたいと思いますので乞うご期待ください。

要件定義&全体のアーキテクチャ

  • ECS
  • CloudWatch
  • AWS SNS
  • AWS Chatbot
  • AWS Systems Management
  • Slack

https://zenn.dev/take_tech/articles/04707c6594e3fb

サンプルコード導入&各種オブジェクトの解説
https://zenn.dev/take_tech/articles/5029460000a0ed

各種API取得&Terrafrom連携
https://zenn.dev/take_tech/articles/ac0704b50684da

Terraform上で、AWS Systems Managerを用いたセキュリティの強化
https://zenn.dev/take_tech/articles/4f728035d166b1

ECSスロットリングに対する適切なメトリクスの選定
https://zenn.dev/take_tech/articles/376ca4a3bd8bca

アーキティクチャ

今回やること

  • Terraformのスクリプト(主に変数やData Source)を修正する ⭕️こちら
  • コンテナの起動に失敗するようにスクリプトを更新する(ECSコンテナのタスクでPending状態を引き起こすリクエストを発生させる)
  • stg環境に対してTerraformによる変更を加える($ terraform apply
  • stgにコンテナをデプロイし、スロットリングを発生させる
  • Terraformのスクリプトを修正する(閾値を調整する)

結論:ほぼ完成したコード(閾値は今後調整)

variable.tf

variable "service" {
  default = "*************"
}

variable "environment" {
  default = "*************"
}

 .
 .
 .

このファイルでは、Terraformプロジェクト内で再利用される可能性がある変数を定義しています。ここで定義される変数には、プロジェクトや環境を横断して使われるserviceやenvironmentのような値が含まれます。これにより、異なる環境やサービスに対して同一のコードを柔軟に適用することが可能になります。

変数を利用することで、コードの変更が必要な場合においても、このファイルの値を更新するだけで済むため、管理が容易になり、エラーのリスクを減少させることができます。また、variable.tfに記載されていない変数は、通常、プロジェクト固有の設定や値であり、環境やサービスの変更に依存しないものです。

cloudwatch_alarm.tf

resource "aws_cloudwatch_metric_alarm" "ecs_throttling_alarm" {
  alarm_name          = "${var.service}-${var.environment}-ecs-throttling-alarm"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2 # 2回の評価でアラームを発生
  metric_name         = "PendingTaskCount"
  namespace           = "AWS/ECS"
  period              = 1 # 1分ごとに監視
  statistic           = "Average"
  threshold           = 5 # 5タスク以上がPending状態ならアラーム
  alarm_description   = "コードのバグによるコンテナの起動失敗が原因で、ECSのPendingTaskCountが設定された閾値を超えた場合にアラームが発生します"
  actions_enabled     = true
  alarm_actions       = [aws_sns_topic.ecs_throttling_notifications.arn]
  dimensions = {
    ClusterName = "${var.service}-${var.environment}"
    ServiceName = "${var.service}-${var.environment}-datadog-agent"
  }
}

このcloudwatch_alarm.tfファイルは、AWS CloudWatchを利用して特定のメトリクスに基づいたアラームを設定します。ここでは、ECSで管理されるコンテナのPendingTaskCountメトリクスを監視し、指定された閾値を超えた場合にアラームを発生させる設定を行います。アラームは、コンテナが想定通りに起動しない事象を検出するために用います。ただし、ここでの閾値の設定は仮であり今後の動作確認などで適切な値に修正していく予定です。

また、alarm_actionsはアラーム発生時に実行されるアクションを指定し、ここではAWS SNS(Simple Notification Service)を通じて通知が送られます。dimensionsパラメータを使って、どのECSクラスターやサービスに関連するアラームかを明確に指定しています。これにより、複数のサービスや環境間で発生するイベントを効果的に管理できます。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm#example-usage

sns_topic.tf

resource "aws_sns_topic" "ecs_throttling_notifications" {
  name = "${var.service}-${var.environment}-ecs-throttling-notifications"
}

このsns_topic.tfファイルでは、AWS SNSトピックを設定しています。このトピックは、特定のイベントが発生した際に通知を送信するために使用されます。ここで設定されているトピック(${var.service}-${var.environment}-ecs-throttling-notifications)は、ECSのタスクがスロットリングによりPending状態になることを検出したときにアラームがトリガーされると、関連するシステムに通知を送る目的で作成されています

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic#name
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription

db.tf

前章まではこちらでData Soruceを定義していたが今回の修正で削除することにしました。

# スクリプトを以下`chatbot_slack_config.tf`に遷移(見通しが良くなるため)
# その後、ファイルごと削除

chatbot_slack_config.tf

# データソース: AWS SSMからSlackの設定を取得
data "aws_ssm_parameter" "slack_channel_id" {
  name = "/${var.service}/${var.environment}/***********/slack-channel-id"
  type = "SecureString"
}

data "aws_ssm_parameter" "slack_workspace_id" {
  name = "/${var.service}/${var.environment}/***********/slack-workspace-id"
  type = "SecureString"
}

resource "awscc_chatbot_slack_channel_configuration" "ecs_throttling_alert_config" {
  configuration_name = "${var.service}-${var.environment}-ecs-throttling-alert-config"
  iam_role_arn       = awscc_iam_role.ecs_throttling_alert_role.arn
  slack_channel_id   = data.aws_ssm_parameter.slack_channel_id.value
  slack_workspace_id = data.aws_ssm_parameter.slack_workspace_id.value
  sns_topic_arns     = [aws_sns_topic.ecs_throttling_notifications.arn]
  guardrail_policies = ["arn:aws:iam::aws:policy/ReadOnlyAccess"]
}

resource "awscc_iam_role" "ecs_throttling_alert_role" {
  role_name = "${var.service}-${var.environment}-ecs-throttling-alert-role"
  assume_role_policy_document = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "chatbot.amazonaws.com"
        }
      },
    ]
  })
  managed_policy_arns = []
}

コードを上から説明していきます。
aws_ssm_parameter:
AWS Systems ManagerのParameter StoreからSlackのチャネルIDとワークスペースIDを取得します。これらのパラメータはSecureString型として保存されています。(SecureString型での保存が推奨されています。

https://engineering.mobalab.net/2021/03/25/handling-secrets-with-terraform/

awscc_chatbot_slack_channel_configuration:
このリソースを使用して、AWS Chatbotの設定を行い、Slackチャネルへの通知を設定します。ここで指定されるconfiguration_name、slack_channel_id、slack_workspace_idを通じて、特定のSlackチャンネルへの通知が可能となります。

awscc_iam_role:
AWS ChatbotがAWSのリソースと対話するために必要なIAMロールを定義しています。このロールは、ChatbotサービスがAWSリソースにアクセスするための権限を持っており、安全なアクセス制御を提供します。

https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/chatbot_slack_channel_configuration

db.tfvars 秘密情報のため.ignoreへ格納

# Terraform Slack Variables
export TF_VAR_slack_channel_id="**************"
export TF_VAR_slack_workspace_id="***************"

このファイルには、Terraformが実行される際に必要とされる環境変数が定義されています。具体的には、SlackのチャネルIDとワークスペースIDが含まれており、これらの値はTerraformの設定ファイルで利用されます。

また、環境変数としてTF_VARを使用することで、Terraformスクリプト内で自動的にこれらの値を引き継ぎ、セキュリティリスクを低減しながら設定を行うことが可能です。さらに、秘密情報を.ignoreファイルに格納することで、不用意な公開を避けるとともに、セキュリティを確保しています。これにより、開発環境やCI/CDパイプラインでの使用が安全に行えます。

まとめ

この記事では、Terraformを用いた設定の基本的な部分から、変数の定義、CloudWatchのアラーム設定、SNSトピックの作成、Slack通知の設定までをカバーしています。各リソースの設定方法と目的が説明されており、特にセキュリティに敏感な情報は.ignoreファイルで適切に管理されるように構成されています。

次の記事では、これらの設定が適切に機能しているかどうかを確認するための動作テスト方法について詳しく解説していく予定です。

最後に

ここまで読んでいただき誠にありがとうございました!
noteでも記事を執筆していますので、ぜひチェックしてみてください。
https://note.com/take_lifelog/n/n58df7ce7af6f

その他のZennの記事はこちら
https://zenn.dev/take_tech

今回の記事が良かったと思ったらぜひ「いいね」を押していただけると嬉しいです
大変励みになります💪

Discussion