My Note

自己理解のためのブログ

TerraformでMackerelのAWSインテグレーションを設定する

はじめに

前回の記事でMackerelの設定をterraformで行ったので、今回は "AWSインテグレーション" を設定します。 今回もTerraformの実行は 前回の記事と同様に terraform-cloudを利用していますので同様に設定します。

yhidetoshi.hatenablog.com

設定

  • AWSインテグレーションの方法は下記の公式記事にまとめられています。

mackerel.io

Terraformの構成

今回追加した部分は terraform/aws/awsリソース作成用のワークスペースを用意しました。 awsインテグレーションに必要となるIAMリソースを他の "org" からも参照するという想定で "org_a" 内で作らず workspaceを独立する形にしています。

├── README.md
└── terraform
    ├── aws
    │   ├── iam-aws-integration.tf
    │   ├── locals.tf
    │   ├── outputs.tf
    │   ├── providers.tf
    │   └── variables.tf
    ├── org_a
    │   ├── alerts.tf
    │   ├── integrations.tf
    │   ├── monitors.tf
    │   ├── notifications.tf
    │   ├── providers.tf
    │   ├── roles.tf
    │   ├── services.tf
    │   └── variables.tf
    └── org_b
        ├── providers.tf
        └── variables.tf

IAMロールの作成

  • terraform/aws/providers.tf
    • terraform-cloudを利用しない場合は backend "local" {}
terraform {
  required_version = ">=1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
  backend "remote" {
    hostname     = "app.terraform.io"
    organization = "my-org"

    workspaces {
      name = "mackerel-aws"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}
  • terraform/aws/variables.tf
    • この鍵情報は terraform-cloudの Variables にSensitiveで設定します。
variable "AWS_ACCESS_KEY" {
  type = string
}

variable "AWS_SECRET_KEY" {
  type = string
}
  • terraform/aws/iam-aws-integration.tf
    • AWSインテグレーションに必要な権限を付与する必要があるので下記のサイトを参考に適宜付与する
    • "identifiers" で指定しているアカウント番号は 217452466226 をセットするように指定されています。
resource "aws_iam_role" "mackerel_integration" {
  name               = "mackerel-aws-integration"
  assume_role_policy = data.aws_iam_policy_document.mackerel_integration_role.json
}

data "aws_iam_policy_document" "mackerel_integration_role" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::217452466226:root"]
    }
    condition {
      test     = "StringEquals"
      variable = "sts:ExternalId"
      values   = [local.aws_integration_iam_role_external_id_org_a]
    }
  }
}

resource "aws_iam_role_policy" "mackerel_integration" {
  name   = "mackerel-integration-policy"
  role   = aws_iam_role.mackerel_integration.id
  policy = data.aws_iam_policy_document.mackerel_integration.json
}

// ref: https://mackerel.io/ja/docs/entry/integrations/aws
data "aws_iam_policy_document" "mackerel_integration" {
  statement {
    actions = [
      "lambda:GetFunctionConfiguration",
      "lambda:List*",
      "budgets:ViewBudget",
      "cloudwatch:Get*",
      "cloudwatch:List*",
      "s3:ListAllMyBuckets",
      "s3:GetBucketLocation",
      "s3:GetBucketLogging",
      "s3:GetBucketTagging",
      "s3:GetEncryptionConfiguration",
      "s3:GetMetricsConfiguration"
    ]
    resources = ["*"]
  }
}

このtfファイルで作成されるIAMロールは以下の通りです。

  • 権限
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetMetricsConfiguration",
                "s3:GetEncryptionConfiguration",
                "s3:GetBucketTagging",
                "s3:GetBucketLogging",
                "s3:GetBucketLocation",
                "lambda:List*",
                "lambda:GetFunctionConfiguration",
                "cloudwatch:List*",
                "cloudwatch:Get*",
                "budgets:ViewBudget"
            ],
            "Resource": "*"
        }
    ]
}
  • 信頼関係
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::217452466226:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "${SET_IAM_ROLE_EXTERNAL_ID_FROM_MACKEREL_CONSOLE}"
        }
      }
    }
  ]
}
  • IAMロールに設定する external-id は Mackerelのコンソール画面で確認。

f:id:yhidetoshi:20220114112629p:plain

  • terraform/aws/locals.tf
    • Mackerelコンソールから確認した "external-id" をセット
locals {
  aws_integration_iam_role_external_id_org_a = "SET_IAM_ROLE_EXTERNAL_ID_FROM_MACKEREL_CONSOLE"
}
  • terraform/aws/outputs.tf
    • aws_integration_iam_role_arn は "org_a" で "iam-role-arn" が必要なので参照させる
    • aws_integration_iam_role_external_id_org_a は "org_a" で "external-id" が必要なので参照させる
output "aws_integration_iam_role_arn" {
  value = aws_iam_role.mackerel_integration.arn
}

output "aws_integration_iam_role_external_id_org_a" {
  value     = local.aws_integration_iam_role_external_id_org_a
  sensitive = true
}

Mackerelのインテグレーション設定

  • terraform/org_a/providers.tf
    • terraform-cloudを利用しない場合は backend "local" {}
terraform {
  required_version = ">=1.0"
  required_providers {
    mackerel = {
      source  = "mackerelio-labs/mackerel"
      version = "~> 0.0.8"
    }
  }
  backend "remote" {
    hostname     = "app.terraform.io"
    organization = "my-org"
    workspaces {
      name = "mackerel-org-a"
    }
  }
}

data "terraform_remote_state" "aws" {
  backend = "remote"

  config = {
    organization = "my-org"
    workspaces = {
      name = "mackerel-aws"
    }
  }
}
  • terraform/org_a/variables.tf
variable "MACKEREL_API_KEY" {
  type = string
}
resource "mackerel_aws_integration" "us_east_1" {
  name          = "us-east-1"
  memo          = "monitor for us-east-1"
  key           = ""
  secret_key    = ""
  role_arn      = data.terraform_remote_state.aws.outputs.aws_integration_iam_role_arn
  external_id   = data.terraform_remote_state.aws.outputs.aws_integration_iam_role_external_id_org_a
  region        = "us-east-1"
  included_tags = "" # ex) = "Name:hoge,Environment:dev"
  excluded_tags = ""

  ec2 {
    enable               = false
    role                 = "${mackerel_service.dev.name}: ${mackerel_role.web.name}"
    excluded_metrics     = []
    retire_automatically = true
  }

  lambda {
    enable = true
    role   = "${mackerel_service.aws.name}: ${mackerel_role.lambda.name}"
  }

  s3 {
    enable = false
    role   = "${mackerel_service.aws.name}: ${mackerel_role.s3.name}"
  }

  billing {
    enable = true
    role   = "${mackerel_service.aws.name}: ${mackerel_role.billing.name}"
  }
}


resource "mackerel_aws_integration" "ap_northeast_1" {
  name          = "ap-northeast-1"
  memo          = "monitor for ap-northeast-1"
  role_arn      = data.terraform_remote_state.aws.outputs.aws_integration_iam_role_arn
  external_id   = data.terraform_remote_state.aws.outputs.aws_integration_iam_role_external_id_org_a
  region        = "ap-northeast-1"
  included_tags = "" # ex) = "Name:hoge,Environment:dev"
  excluded_tags = ""

  ec2 {
    enable               = false
    role                 = "${mackerel_service.dev.name}: ${mackerel_role.web.name}"
    excluded_metrics     = []
    retire_automatically = true
  }
}

■ 結果

f:id:yhidetoshi:20220114121643p:plain

f:id:yhidetoshi:20220114120206p:plain

おわり

本記事では、TerraformでMackerelのAWSインテグレーションの設定を行いました。 AWSインテグレーションをすると意図せず多くのリソースを追加してしまい想定より多くの料金がかかる場合があるので注意が必要です。 タグで絞るなど工夫できます。今回は Mackerelのアンバサダプランを利用させていただいているので少額の課金も気にせず検証することができました。(感謝!)

また、以前にAWSインテグレーションにBillingの機能がなかった場合に、MackerelのサービスメトリクスにPostして監視する記事を書いたので よければ参照ください。

yhidetoshi.hatenablog.com