0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform勉強-第23回:CloudWatchエージェント, SSMパラメータストアでログを CloudWatch Logs に送信する

Posted at

作成した全てのコード

githubリポジトリ:"https://github.com/shu130/terraform-study23"

テーマ:

  • EC2 オートスケーリンググループでApacheを導入し、CloudWatchエージェントを利用してアクセスログとエラーログを CloudWatch Logs に送信する環境を構築
  • ASG (Auto Scaling Group) を使用して EC2 インスタンスをスケーリングし、Web サーバの冗長性を確保
  • SSMパラメータストア を活用してCloudWatch エージェントの設定を共有、複数インスタンスへの一貫した設定配布

ディレクトリ

.
├── provider.tf
├── vpc.tf
├── iam.tf
├── autoscaling.tf
├── cloudwatch.tf
├── ssm.tf
├── scripts
│   └── fetch_cloudwatch_config.sh
├── variables.tf
├── terraform.tfvars
└── outputs.tf

概要図

diagram02.png

コード作成と理解

1. IAM ロールとポリシーとインスタンスプロファイル

  • ASG用IAM ロールを作成
  • CloudWatch エージェントがCloudWatch Logs にログ送信できるように、CloudWatchAgentServerPolicy ポリシーを IAM ロールにアタッチ
  • EC2 インスタンスが SSM パラメータストアから設定情報を取得できるように、AmazonSSMReadOnlyAccess ポリシーもIAM ロールにアタッチ
  • 作成した IAM ロールを IAM インスタンスプロファイル として定義し、Auto Scaling Group (ASG) のインスタンスが起動時にこの IAM ロールを使用
./iam.tf
# ./iam.tf

# IAMロールを作成
resource "aws_iam_role" "cloudwatch_agent_role" {
  name = "CloudWatchAgentRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action    = "sts:AssumeRole"
      Effect    = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
  })
}

# IAMロールに2つのポリシーをアタッチ:
## 1.cloudwatch-Logsへのログ送信用
resource "aws_iam_role_policy_attachment" "cloudwatch_logs" {
  role       = aws_iam_role.cloudwatch_agent_role.name
  policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
}

## 2. SSMパラメータストア接続用
resource "aws_iam_role_policy_attachment" "ssm_access" {
  role       = aws_iam_role.cloudwatch_agent_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
}

# IAMロールをインスタンスプロファイルとして定義
resource "aws_iam_instance_profile" "cloudwatch_instance_profile" {
  name = "CloudWatchInstanceProfile"
  role = aws_iam_role.cloudwatch_agent_role.name
}

2. Auto Scaling Group(ASG)

  • IAM インスタンスプロファイルを通じて、ASG 内のすべての EC2 インスタンスが一貫して CloudWatch Logs へのアクセスと、SSM パラメータストアから設定を取得
  • EC2 インスタンスのスケールイン/スケールアウトを自動化
  • user_data スクリプトによりASG でインスタンスが起動する際に、Apache をインストールし、CloudWatch エージェントの設定ファイルを取得して、CloudWatch Logs にログを送信
./autoscaling.tf
#./autoscaling.tf

# 起動テンプレート作成
resource "aws_launch_template" "web_launch_template" {
  name_prefix = "${var.ec2_instance_name}-lt-"
  image_id      = var.ec2_ami
  instance_type = var.ec2_instance_type
  key_name      = var.ec2_key_pair
  
  # インスタンスプロファイルを適用
  iam_instance_profile {
    name = aws_iam_instance_profile.cloudwatch_instance_profile.name
  }

  network_interfaces {
    associate_public_ip_address = true
    security_groups = [aws_security_group.asg_sg.id]
  }

  # user_dataスクリプトを指定
  user_data = base64encode(templatefile("${path.module}/scripts/fetch_cloudwatch_config.sh", {}))

  tag_specifications {
    resource_type = "instance"
    tags = {
      Name = "${var.ec2_instance_name}"
    }
  }
}

# オートスケール設定
resource "aws_autoscaling_group" "web_asg" {
  desired_capacity    = 2
  max_size            = 4
  min_size            = 2
  vpc_zone_identifier = aws_subnet.public_subnets[*].id
  launch_template {
    id      = aws_launch_template.web_launch_template.id
    version = "$Latest"
  }

  tag {
    key   = "Name"
    value = "${var.ec2_instance_name}"
    propagate_at_launch = true
  }
}

user_dataスクリプト(fetch_cloudwatch_config.sh)について:

  • 初回起動時に自動実行
  • インスタンス起動時にApacheとCloudWatchエージェントをインストール
  • SSMパラメータストアからCloudWatchエージェントの設定を取得
  • 動的にインスタンスIDを取得して設定に反映
./scripts/fetch_cloudwatch_config.sh
# ./scripts/fetch_cloudwatch_config.sh

#!/bin/bash
# Apacheのインストールと起動
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd

# CloudWatchエージェントのインストール
yum install -y amazon-cloudwatch-agent
# jqのインストール
yum install -y jq

# SSMパラメータストアからCloudWatch設定情報を取得し、エージェント起動
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
aws ssm get-parameter --name "AmazonCloudWatch-ForwardProxy" --query "Parameter.Value" --output text --region "us-west-2" | \
  jq --arg id "$INSTANCE_ID" '.logs.logs_collected.files.collect_list[] |= (.log_stream_name = $id)' | \
  sudo tee /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json > /dev/null

/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
  -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

3. SSM パラメータストア

  • aws_ssm_parameter リソースで、CloudWatch エージェントの設定情報を保存
  • EC2インスタンスの起動スクリプト (fetch_cloudwatch_config.sh)によって、
    SSMから設定を取得し、jqでプレースホルダ {instance_id} を実際のインスタンスIDに置き換え
./ssm.tf
# CloudWatchエージェントの設定をSSMパラメータストアへ保存
resource "aws_ssm_parameter" "cloudwatch_config" {
  name  = "AmazonCloudWatch-ForwardProxy"
  type  = "String"
  value = jsonencode({
    logs = {
      logs_collected = {
        files = {
          collect_list = [
            {
              file_path        = "/var/log/messages"
              log_group_name   = "var-log-messages"
              log_stream_name  = "{instance_id}"
              timestamp_format = "%b %d %H:%M:%S"
            },
            {
              file_path        = "/var/log/httpd/access_log"
              log_group_name   = "HttpAccessLog"
              log_stream_name  = "{instance_id}"
              timestamp_format = "%b %d %H:%M:%S"
            },
            {
              file_path        = "/var/log/httpd/error_log"
              log_group_name   = "HttpErrorLog"
              log_stream_name  = "{instance_id}"
              timestamp_format = "%b %d %H:%M:%S"
            }
          ]
        }
      }
    }
  })
}

4. CloudWatch Logs

  • CloudWatch エージェントは、SSM から取得した設定に基づいてログを収集し、アクセスログとエラーログをCloudWatchロググループに送信
  • ASG のインスタンスごとに異なるログストリーム名を使用して、ログを管理
./cloudwatch.tf
# ./cloudwatch.tf

# CloudWatchエージェントのログ送信先:
## 1.アクセスロググループ
resource "aws_cloudwatch_log_group" "http_access_log" {
  name              = "HttpAccessLog"
  retention_in_days = 7
}

## 2. エラーロググループ
resource "aws_cloudwatch_log_group" "http_error_log" {
  name              = "HttpErrorLog"
  retention_in_days = 7
}

リソース作成後、動作確認にて問題なし

1. Apacheのアクセスログ

tail -f /var/log/httpd/access_log

2. Apacheのエラーログ確認

tail -f /var/log/httpd/error_log

3. Amazon CloudWatchコンソール

  • AWSコンソールにアクセス
  • 「CloudWatch」→「ロググループ」で、var-log-messagesHttpAccessLogHttpErrorLogの3つのロググループがある
  • 3つのグループでそれぞれのログストリームが作成されておりログ表示できた

4. CloudWatchエージェントのステータス

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
  • エージェントが正常に稼働

5. CloudWatchエージェントの設定ファイルの内容

cat /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
  • 設定ファイルが正しく取得されており、インスタンスIDが設定されている

6. CloudWatchエージェントのログ

cat /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log
  • エージェントの起動状況やエラーの詳細が出力

今回はここまでにしたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?