4
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?

More than 1 year has passed since last update.

【Terragrunt】ステージング環境が足りない?人数分用意すればいいじゃない

Posted at

概要

チーム開発を行なっている際、メンバーごとにAWS上で環境を用意したい時ありますよね。
環境なんていくつあっても困りませんからね〜。
みるく-milk.gif

今回!Terragrunt + GitHub Actionsでうまく複数メンバー分環境を立てるためのインフラを作成したので、それを説明しようと思います。

ご意見、アドバイスお待ちしています٩( ᐛ )و

環境

$ terragrunt -v
terragrunt version v0.46.2

$ terraform -v
Terraform v1.3.7

手法

技術選定

  • Terraform
  • Terragrunt

TerragruntはTerraformのラッパーです。
今回、採用した理由としては

  1. tfstate 間の依存関係定義が容易
  2. backendブロック中で環境変数にアクセスができる

の2点となります。

tfstate 間の依存関係定義が容易

環境を分けるとは言ったものの、完全に独立なリソースを作るわけではありません。
VPCやALB等、共通で参照するものもいくつかあります。
新しい環境はこれらの値(idやARN)に依存するわけですが、Terraformでtfstate 間で値を受け渡すには手間がかかります。
具体的にはtfstate1outputした値をtfstate2tfvarsにハードコード or 実行時に明示的に値を受け渡す必要があります。

一方Terragruntはdependency blockを使用することで、tfstate 間で簡単に値を共有することが可能です。

dependency "common" {
  config_path = "../common_resources"
}

メンバーの環境のtfstateはそれぞれ共通の依存関係があるため、この記述がすごくマッチしました。

backendブロック中で環境変数にアクセスができる

GitHub ActionsでのTerragrunt実行を想定しているため、tfstateファイルはlocalに保存しておくわけにはいきません。
また、ユーザー毎にtfstateを管理するキーも分ける必要があります。

Terraformでは、backendブロック内で直接環境変数を参照することができません。代わりに、-backend-configオプションを使用してterraform initの一部として引数を渡す必要があります。これは、各環境での手動の操作が必要となります。

  backend "s3" {
     bucket = "dummy-terraform"
     key    = "staging/terraform.tfstate"
     region = "ap-northeast-1"
  }
$ terraform init \
 -backend-config="bucket=real-terraform"\
 -backend-config="key=userA/terraform.tfstate"\
 -backend-config="region=us-east-1"

一方で、Terragruntでは、backendブロック内で直接環境変数を参照することが可能です。

remote_state {
  backend = "s3"
  config = {
    bucket         = "${get_env("STATE_BUCKET", 'hogehoge-terraform')}"
    key            = "${get_env("ENVIRONMENT", 'staging')}/terraform.tfstate"
    region         = "ap-northeast-1"
  }
}
$ export STATE_BUCKET=real-terraform
$ export ENVIRONMENT=userA
$ terragrunt init 

GitHub Actionsでシークレットから取得した環境変数として設定すれば、Terragruntがそれを読み取ってプロビジョニングしてくれます。

アーキテクチャ

とりあえず完成形です!

/common_resources
VPC, ALB, Route53, ECR等の共通で使用するある種の「箱」のようなリソースを作成します。
名称未設定ファイル.drawio (9).png

/user_resources
(localからでも可能ですが、)GitHub Actions上でworkflow_dispatchをトリガーとしこのリソースがプロビジョニングされます。
実行したGitHub Userの名前をキーとして以下のようなリソースを作成します。

名称未設定ファイル.drawio (10).png
ALBのリスナールールでホストヘッダーを見て、各ユーザー固有のFargateにリクエストを捌くようになっています。

初回デプロイ時は

  1. Route53にサブドメインの登録(<your github username>.<your domain>
  2. ALBリスナールールを追加
  3. ECSクラスタ、サービスの作成

が行われ、2回目以降はGitHubActionsでECRにpushされたImageを元にタスク定義を書き換えサービスを更新します。

結論

いかがでしょうか?
ユーザー毎に環境をGitHub Actionsで作成するためのアーキテクチャの一案です。
もっといい方法があるかもしれないですが、今の私ではこれが最適解でした😫
よければ参考にしてみて下さいっ💡

今後

すごい細かいですけど、Fargateは稼働時間でも利用料金が発生するため、ことステージング環境は夜間(業務時間外)は停止させたいですよね。
ECS on EC2であればASGで特定の時間コンテナインスタンスの数を0にすれば実現可能ですが、Fargateの場合どうすればいいのでしょうか・・・?

え…?夜間は業務時間外ではないですって?
す、すいませんでした🙇

4
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
4
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?