AWSにはmyApplicationというサービスがあります。以前からTerraformでmyApplicationをどのように構築するのがいいかと悩んでいましたが、納得感のあるパターンが決まったのでメモです。
myApplicationとは
myApplicationは、AWSリソースをアプリケーション単位でグループ化して、リソースの状態やコストを網羅的に把握できるようにするサービスです。特にリージョンを跨いでリソース表示できるのがAWSにおいて貴重な機能です。 無料ですし、タグでリソースを紐づけるだけで使えるので使い勝手もいいです。
myApplicationの画面は紐づけられているリソースやコストが表示されます。特にリソースは、東京リージョンで見ているのにGlobalとかも見えていますね。
myApplicationとAWSリソースの関係
AWSリソースを特定のmyApplicationに関連付けるためには、myApplicationのリソースIDをAWSリソースのタグに設定する必要があります。このmyApplicationのリソースIDは次のような形式で、ランダムな文字列が含まれています。
# myApplicationのリソースIDパターン arn:aws:resource-groups:{リージョン}:{アカウントID}:group/{myApplication名}/{ランダムな文字列} # 例 arn:aws:resource-groups:ap-northeast-1:123456789012:group/foo/km3hcsjf2h5izwou4jxqdvt7cz
AWSリソースのタグに「キーにawsApplication
、値にmyApplicationのリソースID」を設定するとそのリソースをmyApplicationに関連付けることができます。
awsApplication: <myApplicationのリソースID>
TerraformでmyApplicationを構築する
厄介なポイントはmyApplicationのリソースIDがランダムな文字列を含むため、myApplicationを作成した後にそのリソースIDを取得して、AWSリソースのタグに設定する必要がある点です。 Terraformで管理しやすい方法は2つ考えられます。
- myApplicationを作成するtfstateとAWSリソースを作成するtfstateを分ける
- myApplicationを作成してから
default_tags
にmyApplicationのリソースIDをハードコードで設定する - awscc_resourcegroups_tag_sync_taskを使って自動同期させる
myApplicationを作成するtfstateとAWSリソースを作成するtfstateを分ける
tfstateを分けることで、myApplicationのリソースIDを取得してからAWSリソースのタグに設定できるのでランダムなIDを意識せずに済みます。 例えば次のようにmyApplicationを作成するtfstateとAWSリソースを作成するtfstateを分けて、myApplicationのリソースIDを取得してからAWSリソースのタグに設定します。
resource "aws_servicecatalogappregistry_application" "main" { name = "foo" description = "Terraform managed." } outputs "my_application_id" { description = "myApplicationのリソースID" value = aws_servicecatalogappregistry_application.main.id }
利用側で、ステートからmyApplicationのリソースIDを取得して、AWSリソースのタグに設定します。
data "tfe_outputs" "foo" { organization = "my-org" workspace = "my-workspace" } provider "aws" { region = "ap-northeast-1" default_tags { tags = { awsApplication = data.tfe_outputs.foo.values.my_application_id # 他のタグ } } }
myApplicationを作成してからdefault_tags
にmyApplicationのリソースIDをハードコードで設定する
default_tags
にmyApplicationのリソースIDをハードコードで設定します。タグは影響度が低いので、myApplicationのリソースIDは割り切ってしまっていい判断です。
設定がシンプルかつ、やっていることが一目瞭然で管理しやすいのがメリットです。
一方で、もしmyApplicationを作り直すときは、myApplicationのリソースIDを手動で変更する必要があります。
provider "aws" { region = "ap-northeast-1" default_tags { tags = { awsApplication = "arn:aws:resource-groups:ap-northeast-1:123456789012:group/foo/km3hcsjf2h5izwou4jxqdvt7cz" # 他のタグ } } }
awscc_resourcegroups_tag_sync_taskを使って自動同期させる
AWSコンソールからmyApplicationを作成するときAutomatically add resources using tags
というオプションがあり、これで作ると指定したタグ
を持つAWSリソースに対してmyApplicationのタグを自動的に設定してくれます。仕組み的には、EventBridgeとIAM Roleを組み合わせています。
これと同じことをterraformで実現するのがawscc_resourcegroups_tag_sync_taskです。
残念ながらawsプロバイダーでは提供されておらず、awsccプロバイターを使う必要がありますが、人によってはこれも便利でしょう。ただし、TerraformリソースのデフォルトタグにmyApplicationのリソースIDを設定できないので、ignore_tags
を設定する必要があります。
# managedBy: terraformというタグを持つリソースをmyApplication fooに紐づける resource "awscc_resourcegroups_tag_sync_task" "main" { group = "foo" role_arn = "IAM RoleのARN" tag_key = "managedBy" tag_value = "terraform" } # デフォルトタグにawsApplicationを設定できないので、ignore_tagsを設定する provider "aws" { region = "ap-northeast-1" ignore_tags = { keys = ["awsApplication"] } }
まとめ
私はmyApplicationを作成してからdefault_tags
にmyApplicationのリソースIDをハードコードで設定する方法を主に使っています。
tfstateを参照する方法は、やりたいことに対して大げさすぎるんですよね。myApplicationを作るのは1回だけでしょうし、タグに紐づけたいだけなのでハードコードでも十分メンテできる判断です。
myApplicationのリソースIDからランダム文字列が消えれば扱いやすいのですが残念です。
参考
- myApplications とは AWS Console Home | AWS Management Console
- Getting started with myApplications for Terraform-managed applications | AWS Cloud Operations Blog
- [アップデート] myApplication でカスタムタグを使ったリソースの追加と、タグ同期機能によるリソースの自動追加が出来るようになりました | DevelopersIO
- Resource tag-sync tasks - AWS Service Catalog AppRegistry
- tfe_outputs | Data Sources | hashicorp/tfe | Terraform | Terraform Registry