Terraformでモジュール化する

Terraformでモジュール化する

Working on new project on Crumble’s Office in Prishtina, Kosovo.
Photo by Fatos Bytyqi / Unsplash

最近勉強中のTerraform(v0.13.2)の、モジュール化についてブログを書きます。
AWSのリソースにポリシーを適用したIAMロールをアタッチする場合には以下のような要素を定義する必要があります

・IAM role
・IAM Policy
・IAM Policy document
・信頼ポリシー
・IAM Policy attachment

IAM Roleの定義のように、毎回似たような記述を繰り返すのは大変なので、共通化できる部分をモジュール化すると便利です。

モジュール化前

module化する前のコードです
ファイル名は任意で、好きな名前を設定可能です。
また、リソースごとにファイルを分けるなどしてもOKです。

# iam_role
resource "aws_iam_role" "example" {
    name        = "ezample"
    assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}

# iam_policy
resource "aws_iam_policy" "example" {
    name    = "example"
    policy  = data.aws_iam_policy_document.allow_describe_regions.json
}

# policy_doc_ec2_assume_role
data "aws_iam_policy_document" "ec2_assume_role" {
    statement {
        actions = ["sts:AssumeRole"]

        principals {
            type        = "Service"
            identifiers = ["ec2.amazonaws.com"]
        }
    }
}

# policy_doc_allow_describe_regions
data "aws_iam_policy_document" "allow_describe_regions" {
    statement {
        effect    = "Allow"
        actions   = ["ec2:DescribeRegions"]#リージョン一覧を取得する
        resources = ["*"]
    }
}

# iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "example" {
    role       = aws_iam_role.example.name
    policy_arn = aws_iam_policy.example.arn
}

IAMロールを定義するたびにこの全てを記述するのは大変です

モジュール化後

モジュール化したいファイルは以下のようなディレクトリ構成にします
iam_roleというディレクトリを作成します。

┝main.tf #moduleを利用するファイル
└iam_role/
└iam_role.tf #moduleを定義するファイル

iam_role/iam_role.tfはこのように記述します

variable "name" {}
variable "policy" {}
variable "identifier" {}

resource "aws_iam_role" "default" {
    name = var.name
    assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

data "aws_iam_policy_document" "assume_role" {
    statement {
        actions = ["sts:AssumeRole"]

        principals {
            type        = "Service"
            identifiers = [var.identifier]
        }
    }
}

resource "aws_iam_policy" "default" {
    name   = var.name
    policy = var.policy
}

resource "aws_iam_role_policy_attachment" "default" {
    role       = aws_iam_role.default.name
    policy_arn = aws_iam_policy.default.arn
}

output "iam_role_arn" {
    value = aws_iam_role.default.arn
}

output "iam_role_name" {
    value = aws_iam_role.default.name
}

1-3行目
後から代入したい値はvariableで変数として宣言して初期値は空欄にしておきます

moduleを利用するmain.tfはこのように記述します

module "describe_region_for_ec2" {
    source     = "./iam_role"
    name       = "describe-region-for-ec2"
    identifier = "ec2.amazonaws.com"
    policy     = data.aws_iam_policy_document.allow_describe_regions.json
}

data "aws_iam_policy_document" "allow_describe_regions" {
    statement {
        effect    = "Allow"
        actions   = ["ec2:DescribeRegions"]#リージョン一覧を取得する
        resources = ["*"]
    }
}

1行目
moduleと宣言します
2行目~
sourceでmoduleがどこのディレクトリにあるかを指定し、変数に代入したい値を定義していきます

このように、何度も利用する部分は切り出して、モジュール化すると便利です

参考文献:
野村友規 実践Terraform AWSにおけるシステム設計とベストプラクティス