🌏

AWSのIaCでTerraformを使う際の環境設定ベストプラクティス(AWSマルチアカウント対応)

2022/09/03に公開

はじめに

私が AWS を使って自社の Web サービス基盤を構築するにあたり、IaC に取り組むために Terraform を採用しました。
インフラの開発者が私だけで最初から Terraform を使った CICD 環境は用意するメリットがあまりなかったので、当面はローカル環境で Terraform コマンドを実行することにしました。
ローカル環境で Terraform を使う場合における最適な環境設定を考えてみたのでご紹介します。
私の構築する Web サービスの場合は環境ごとに別々の AWS アカウントを使用するマルチアカウント環境でしたが、マルチアカウント環境でない場合も参考になると思います。

AWS リソースを Terraform で管理する際の課題

AWS リソースを Terraform で管理する際の課題として以下の2つがありました。

課題 1:AWS の Credential 管理

Terraform で AWS リソースを作成する場合における AWS の Credential 使用方法について、以下の2つがよく知られています。

  • tfvars を使用する方法
  • 環境変数を使用する方法

しかし、上記の方法にはそれぞれ以下の課題があります。

tfvars を使用する方法における課題

terraform.tfvars というファイルに Credential を設定しておいて使用する方法です。
Git で管理する場合は.gitignore にこのファイルを追加することで Git の管理対象外とします。
この方法であれば AWS マルチアカウントの環境でも環境ごとに別々の tfvars ファイルを作成することで Credential も使い分けることができます。
しかし、この方法には以下の課題があります。

  1. .gitignore 頼り
    tfvars ファイルに AWS で最もセンシティブな情報である Credential の情報を記載するのはとても心臓に悪いです。
    特に Terraform で使用する権限は最も強い AdministratorAccess を使用するケースが多いため、万が一流出すると大変なことになります。
    .gitignore を誤って消してしまったり、内容を編集した際に tfvars の記載を消してしまう等のリスクを考慮するとかなり不安な運用になります。
  2. tfvars ファイルを Git 管理したい場合にできない
    tfvars ファイルは環境依存の Terraform 変数の値を環境ごとに指定する目的で使用するファイルのため、Credential を記載する目的以外でも使用することが多くあります。
    その際に Credential を記載しているという理由で Git にあげられないのはとても不便です。
  3. Credential を平文で保管しておくリスクがある
    tfvars ファイル自体を暗号化したりしない限りは、Credential をそのまま平文でローカル PC に保存することになります。
    PC が盗難にあった場合やウイルスに感染した場合に Credential が流出するリスクがあります。

環境変数を使用する方法における課題

ローカル PC 上の環境変数に Credential を指定して、Terraform 実行時に環境変数の値を読み込ませて使用する方法です。
Terraform の公式のチュートリアルでもこの方法を使用しています。
しかし、この方法にも以下の課題があります。

  1. 環境ごとに都度環境変数の変更が必要
    AWS マルチアカウントの環境の場合、環境ごとに使用する Credential を変える必要があります。環境を切り替えるたびに環境変数を設定し直すのはとても面倒ですし、
    Credential を参照するするためにどこか安全な場所で別途保管しておく必要があります。
  2. Credential を平文で保管しておくリスクがある
    tfvars を使用する場合と同様に Credential が流出するリスクがあります。

課題 2:Terraform バージョン管理

Terraform をチーム開発で使用する場合は、メンバーごとに使用する Terraform のバージョンの違いによって環境やコードに差分が出ないようにするため、使用する Terraform のバージョンをメンバー間で統一する必要があります。
また、Terraform を使用する複数のプロジェクトを 1 人で掛け持ちする場合には、プロジェクトごとに使用する Terraform のバージョンが異なるため、プロジェクトごとに使用する Terraform のバージョンを適宜切り替える必要があります。
上記の理由から使用する Terraform のバージョンを手軽に切り替えたり、複数人で簡単に統一できることが望ましいです。

aws-vault + Docker Compose

これらの課題を解決するのが今回紹介する aws-vault + Docker Compose を使用する方法です。
それぞれが上記の課題の解決策となっています。

  • AWS の Credential 管理の課題に対する解決策:aws-vault
  • Terraform のバージョン管理の課題に対する解決策:Docker Compose

これら 2 つを組み合わせて使用します。
それぞれの利点や設定方法などの詳細は以下の記事をご参照ください。
*記事:【aws-vault】AWS マルチアカウント環境での Credential 管理
*記事:Terraform をインストールする前に読んでほしい話

準備

aws-vault 設定

上記に記載したリンクの記事(【aws-vault】AWS マルチアカウント環境での Credential 管理)を参考に aws-vault の初期設定を実施します。
マルチアカウント環境の場合はアカウントごとにロールを切り替えられるようにしておきます。

Docker Compose を設定

次に上記に記載したリンクの記事(Terraform をインストールする前に読んでほしい話)を参考に Docker Desktop をインストールし、
docker-compose.yml を作成して Terraform を実行したいディレクトリに配置します。
一応ここにも docker-compose.yml の内容を載せておきます。(内容は上記の記事に記載しているものと同じです。)

docker-compose.yml
version: "3.7"

services:
  terraform:
    image: hashicorp/terraform:1.2.4
    volumes:
      - .:/infra
    working_dir: /infra
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
      - TF_CLI_ARGS_plan="--parallelism=20"
      - TF_CLI_ARGS_apply="--parallelism=20"
      - TF_CLI_ARGS_destroy="--parallelism=20"

これで準備は完了です。

使用方法

aws-vault exec で使用したい環境の Credential へ切り替えます。
・コマンド例

$ aws-vault exec env-dev
Enter MFA code for arn:aws:iam::000000000000:mfa/jumpuser:

認証が完了したら docker-compose.yml を配置したディレクトリに移動して、docker-compose コマンドを実行します。
・コマンド例

$ docker compose run --rm terraform validate
$ docker compose run --rm terraform plan
$ docker compose run --rm terraform apply
$ docker compose run --rm terraform destroy

以上です。とても簡単です。

仕組みの解説

上記の方法がどのように動作しているのか仕組みを解説します。
まず、aws-vault exec を実行して認証に成功するとサブブロセスに切り替わり、以下の環境変数が設定されます。

・環境変数例

- AWS_VAULT=env-dev
- AWS_DEFAULT_REGION=us-east-1
- AWS_REGION=us-east-1
- AWS_ACCESS_KEY_ID=%%%
- AWS_SECRET_ACCESS_KEY=%%%
- AWS_SESSION_TOKEN=%%%
- AWS_SECURITY_TOKEN=%%%
- AWS_SESSION_EXPIRATION=2022-09-02T01:45:13Z

これらの環境変数のうち以下の3つの Credential となる環境変数を Terraform コマンド実行時に Terraform が自動的に読み取って使用してくれます。

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_SESSION_TOKEN

Terraform のバージョンを適宜切り替えて使用するために Docker Compose を使用して Docker コンテナ内で Terraform コマンドを実行させています。
その際、docker-compose.yml の environment で必要なローカルの環境変数をコンテナ内の環境変数として渡してあげることで aws-vault exec で設定された環境変数の Credential を使用して Terraform コマンドを実行しています。

こうすることで AWS の環境やプロジェクトごとに簡単に Credential と Terraform バージョンを切り替えつつ Terraform が使えるようになります。

まとめ

今回は AWS の IaC で Terraform を使う際の環境設定における個人的ベストプラクティスとして aws-vault + Docker Compose を使用する方法をご紹介しました。
特に AWS マルチアカウント環境の場合や、Terraform のバージョンを複数使い分ける必要がある場合においてはとても便利な方法だと思います。
AWS マルチアカウントではない場合や、Terraform を個人で利用する場合においても、他の方法よりも総じてセキュリティや利便性が高いのでオススメです。

あくまで私が考えるベストプラクティスですが、どなたかの参考になれば嬉しいです。

Discussion