はじめに
マルチアカウントで運用している環境で、同じメトリクスをいちいちスイッチロールしながら取得するのは面倒くさい。
CloudWatchダッシュボードを使えば、クロスアカウント設定でセレクタを切り替えながら確認することも可能だが、それも手間なので、一つのダッシュボードの画面で俯瞰できた方がいいよね!
ということで、やってみた。
なお、本記事は
- CloudWatchメトリクスを触ったことがある
- Terraformはある程度分かる
くらいの知識があることを前提としている。自分の書いた過去の記事でTerraform関連を読んで理解ができるのであれば、特に問題ないはずの難易度。
IAMロールを作成する
AWS公式のユーザーガイドに書かれているように、今回の対応をするには、集約する側のアカウントとされる側のアカウントにそれぞれ固定名のIAMロールが必要だ。
ためしにIAMロール名を変えて動かそうとしてみたが、Access Deniedになってしまった。
IAMポリシーはマネージドポリシーが用意されているので、以下のような固定名ロールを作れば良い。
################################################################################
# 集約する側のアカウント用 #
# 存在しない場合のみ作成 #
################################################################################
resource "aws_iam_role" "cloudwatch_monitoringaccount" {
name = "AWSServiceRoleForCloudWatchCrossAccount"
assume_role_policy = data.aws_iam_policy_document.cloudwatch_monitoringaccount_assume.json
}
data "aws_iam_policy_document" "cloudwatch_monitoringaccount_assume" {
statement {
effect = "Allow"
actions = [
"sts:AssumeRole",
]
principals {
type = "Service"
identifiers = [
"cloudwatch-crossaccount.amazonaws.com",
]
}
}
}
resource "aws_iam_role_policy_attachment" "cloudwatch_monitoringaccount" {
role = aws_iam_role.cloudwatch_monitoringaccount.name
policy_arn = "arn:aws:iam::aws:policy/aws-service-role/CloudWatch-CrossAccountAccess"
}
################################################################################
# 集約される側のアカウント用 #
# 存在しない場合のみ作成 #
################################################################################
resource "aws_iam_role" "cloudwatch_crossaccount" {
provider = aws.cross_account
name = "CloudWatch-CrossAccountSharingRole"
assume_role_policy = data.aws_iam_policy_document.cloudwatch_crossaccount_assume.json
}
data "aws_iam_policy_document" "cloudwatch_crossaccount_assume" {
statement {
effect = "Allow"
actions = [
"sts:AssumeRole",
]
principals {
type = "AWS"
identifiers = [
"arn:aws:iam::${data.aws_caller_identity.self.account_id}:root",
]
}
}
}
resource "aws_iam_role_policy_attachment" "cloudwatch_crossaccount1" {
provider = aws.cross_account
role = aws_iam_role.cloudwatch_crossaccount.name
policy_arn = "arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess"
}
resource "aws_iam_role_policy_attachment" "cloudwatch_crossaccount2" {
provider = aws.cross_account
role = aws_iam_role.cloudwatch_crossaccount.name
policy_arn = "arn:aws:iam::aws:policy/CloudWatchAutomaticDashboardsAccess"
}
Terraformプロバイダ設定
クロスアカウントで動かすので、Terraformプロバイダを複数設定する。
cross_account側の設定は、あらかじめaws configure --profile myenv
で設定しておくようにしよう。
shared_config_files
とshared_credentials_files
の位置は適宜変更すること。
provider "aws" {
region = "ap-northeast-1"
}
provider "aws" {
alias = "cross_account"
shared_config_files = ["/home/username/.aws/config"]
shared_credentials_files = ["/home/username/.aws/credentials"]
profile = "myenv"
region = "ap-northeast-1"
}
CloudWatchダッシュボードを作る
CloudWatchダッシュボードは、Terraformの公式ドキュメントを見てわかるとおり、ほとんどがCloudWatchのダッシュボードの構造体のJSONを書くだけだ。[AWS公式のユーザーガイド]を見つつ書いていこう。
今回はサンプルとしてElastic Load Balancing
のTargetGroupsPerRegion
で作ってみる。
なお、アカウントIDは直接書くと当然ながら危険なので、aws_caller_identity
データソースでProviderの設定から引っ張ってこよう。
同じ情報を並べて確認したいので、せっかくだからTerraformの構文でfor文を使って回して、jsonencodeで整形してあげると、コード量が減ってナイスな感じになる。
data "aws_caller_identity" "self" {}
data "aws_caller_identity" "cross_account" {
provider = "aws.cross_account"
}
locals {
accounts = [
{ graph_title = "MyAccount", account_id = data.aws_caller_identity.self.account_id },
{ graph_title = "CrossAccount", account_id = data.aws_caller_identity.cross_account.account_id },
]
}
resource "aws_cloudwatch_dashboard" "example" {
dashboard_name = "cloudwatch-dashboard-example"
dashboard_body = jsonencode({
widgets = [
for account in local.accounts :
{
type = "metric"
properties = {
title = account.graph_title
view = "timeSeries"
stacked = false
region = "ap-northeast-1"
stat = "Average"
period = 300
metrics = [
[
"AWS/Usage",
"ResourceCount",
"Type",
"Resource",
"Resource",
"TargetGroupsPerRegion",
"Service",
"Elastic Load Balancing",
"Class",
"None",
{
"accountId" = account.account_id
},
]
]
}
}
]
})
}
いざ、確認!
さて、ここまでできたら完成だ。terraform apply
してコンソールで見てみよう。
できた!
クロスアカウントのメトリクスは右上に「xa」のアイコンが表示され、クリックするとこのようにアカウントIDを確認することも可能だ。
これで、見やすいダッシュボードを作成することができるようになった!