ENECHANGE Developer Blog

ENECHANGE開発者ブログ

【AWS ECS】タグによるコスト管理とタグ伝播

ENECHANGE所属のエンジニア id:tetsushi_fukabori こと深堀です。
私事ですがこの記事が公開される頃には育児休業に入っています。
育児休業制度は2022年10月から制度が変わっているのですが、どのような影響があるかをフワッとしか理解していないので何かやらかしをしないか心配です。

ikumen-project.mhlw.go.jp

この記事が公開される頃には既にやらかしているかも知れませんね(恐怖)。


今回は「既存アプリケーション基盤のコンテナ化プロジェクト」でリリース後に気がついたコスト管理の設定にミスと対処について紹介します。
コスト管理は大事なので事前に確認しておきたいですね。しておけばよかったです。

以前の記事で説明したチーム構成とも関連する話です。

背景

ENECHANGEでは様々な事業者、ユーザーに提供するプロダクトを開発・運用しています。
これらのプロダクトはそれぞれ個別に収益の計画があるため、コストも個別に計測する必要があります。

このため、当然ですがクラウドインフラのコストもそれぞれに分けて集計ができなければいけません。
今回のコンテナ化プロジェクトで構築したインフラのコストも適切にプロダクトに帰属する形で計測をする必要があります。

やりたいこと

ENECHANGEではAWSのコスト配分タグとして Serviceタグ を設定しているため、今回のプロジェクトでも構築したコンテナ環境のランニングコストを特定の Serviceタグ で集計したいです。
各プロダクトが利用しているAWSリソースには個別の Serviceタグ を設定していて、プロダクトが利用しているインフラの全てのコストは同一の Serviceタグ で集計できることが現在の運用の前提になっています。

課題

課題というか、発生してしまったトラブルの経緯です。

クラウドリソースのterraform管理とタグ付け設定

ENCHANGEのクラウドインフラはインフラチームによりterraformで管理されています。
ディレクトリの階層構造はいろいろなパターンがありますが、基本的には以下のような構成になっています。

product-name
├── environment
│   ├── common
│   │   └── main.tf
│   ├── production
│   │   └── main.tf
│   └── staging
│       └── main.tf
└── network
    └── main.tf

プロダクト配下にいくつかディレクトリがあり、その中に環境別または環境共通のディレクトリが切られ、 main.tf ファイルがディレクトリごとに存在します。

terraformのAWS ProviderにはDefault Tagsという機能があります。

www.hashicorp.com

弊社の管理では main.tf に記載している provider ブロック内で以下のような default_tags を指定しています。

provider "aws" {
  region = "ap-northeast-1"

  default_tags {
    tags = {
      Service     = "product-name"
      Environment = "production"
      Description = "Managed by Terraform"
    }
  }
}

Environment タグは環境共通のリソースだと設定しません。)
このように設定することで main.tf 内で作成した全てのリソースに Serviceタグ がつけられ、これによってコストが計測できます。
環境の情報や「このリソースがterraform管理されていること」も一括でタグ管理できています。

コンテナ環境の稼働開始とコストの推移

これでコスト管理は万全、ということでワクワクでリリースしました。
1週間後には現行環境であるAWS Elastic Beanstalk環境の停止がありましたので、そのタイミングでコストも確認し、ECSのコストが乗っていることを確認しました。

ECSのコストが乗っていなかった(確認時点は9/28、画像はサービスタグで絞り込んだ状態)

乗ってません。

ECSのタスク定義にもサービスにも Serviceタグ を指定しているのに一体なぜ…?!

ECSタスクのタグ付けとコスト管理

実はECSタスクのコストはECSのタスクにタグが付いていないとタグで集計できません。

何を当たり前のことを…という感じの文章ですが、言い換えるとECSのサービスやタスク定義にタグが付いているだけではタグで集計ができないのです。
該当するドキュメントはこちらです。

docs.aws.amazon.com

ではタスク自体にタグを付けるにはどうしたら良いでしょうか?
タグはスケールイン・スケールアウトで動的に増減するため、何らかの方法で動的に起動したタスクにタグが乗ってもらわないと困ります。

やったこと

タスク自体へのタグ設定方法

AWSもそんなことは当然考えに織り込んでいて、タグの伝播という機能を使ってタスク定義またはサービスについているものと同じタグをタスクに設定可能です。

docs.aws.amazon.com

docs.aws.amazon.com

タスク作成時にタグの伝播を指定可能

ECSサービスの作成時かタスクの実行時に設定が可能な機能で、terraformでもECSサービスの設定としてコード管理ができます

registry.terraform.io

これを使ってタスクにタグを設定しましょう。

Serviceタグ の管理問題

ここで立ち止まって考えると、タグの伝播のもととなるリソースは2つから選択可能でした。

  • タスク定義
  • サービス

別の記事でも紹介しましたが、タスク定義はアプリチームが管理しています。
ということはアプリチームによって Serviceタグ が変更されてもインフラチームが検知する仕組みはありません。

また、アプリチームが設定した Serviceタグ と、インフラチームで設定している Serviceタグ が相違した場合集計上の面倒が生じます。
これはコスト管理上不都合です。

ではサービスから伝播しよう…とすると、1つ困ったことがあります。
他の全リソースに共通で設定している「このリソースがterraform管理されていることを示すタグ」がタスクに設定されてしまうのです。
タスク自体はterraformで管理はできず、またタスク定義自体もterraformでは管理しないことを決定したので、これは明確に嘘のタグになってしまいます。

最終的な設定

ECSのサービスの設定として「タスクにサービスのタグを伝播する」こととしました。
嘘のタグが付くことになりますが誤ったコストタグがついてしまうことに比べて影響が小さいと判断し、サービスと同じタグを伝播して設定しました。

まとめ

ECSのタスクのコスト管理にタグを付けるため、APIにしか無いタグ伝播の設定を使ってサービスと同じタグを設定するようにしたことで、タグによるコスト管理ができるようになりました。
タスク定義とサービスのどちらからタグを伝播するかで一長一短ありましたが、管理上の都合からより望ましい方式をチームで協議し選択しました。
コスト管理のタグ設定の管理(ややこしいですね)がインフラチームのGitHubリポジトリで管理されているため、チームの責任分界として管理可能な範囲内からタグを伝播することで、責任範囲と一致した管理を行うことができるようになりました。

コストがとれてめでたしめでたし(金額は上昇)