0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AzureリソースをTerraformのmodulesへ移動

Last updated at Posted at 2024-08-19

TerraformでセットアップされたAzureのリソースをTerraformモジュールに移動してみました。

普通にvariableをInputするようなところは割愛して、リソースによって何か特徴のあるところをいくつか例を紹介したいと思います。

Storage Account

main.tf

resource "azurerm_storage_account" "azfiles" {
  name                     = "${var.sa_name}"
.
.
.
}

resource "azurerm_storage_share" "share" {
  for_each = var.shares
  name                 = each.key
  storage_account_name = azurerm_storage_account.azfiles.name
  quota                = each.value
  depends_on = [
    azurerm_storage_account.azfiles
  ]  
}
variables.tf
variable "shares" {
  type = map(string)
}

Azure FileのShareを複数作る場合はvariableでMapを作りそこでKey,ValueでShareの名前とQuotaのサイズを設定します。Modulesでは以下のように設定します。

storageaccount.tf
module "storage" {
  source                      = "modules/sa/azfiles"
  sa_name                     = "${local.sa_name}"
.
.
.
  shares = { 
    share1 = 512
    share2 = 1024
  }  
}

これでQuotaが512GBのshare1と1024GBのshare2ができます。

Containers

Azure Blob Storageで複数のContainersをセットアップする場合は、VariablesでListを使用します。

main.tf
resource "azurerm_storage_account" "blob_nfs" {
  name                     = "${var.name}"
  resource_group_name      = "${var.resource_group_name}"
  .
  .
}

resource "azurerm_storage_container" "container" {
  for_each = toset(var.containers)
  name                  = each.value
  storage_account_name = azurerm_storage_account.blob_nfs.name
  container_access_type = "private"
}
variables.tf
variable "containers" {
  type    = list(string)
}

こんな感じでListのVariablesを設定して、Modulesでは以下のように呼び出します。

containers.tf
module "nfs" {
  source                      = "modules/modules/blob_nfs"
  name                        = "mystorage"
  .
  .
  containers                  = ["container1","container2"]
}

とするとmystoragecontainer1container2が作成されます。

Endpoint

リソースによってはPrivate Endpointが必要な場合もあります。

main.tf
resource "azurerm_private_endpoint" "endpoint" {
  count = var.pe_name == null ? 0 : 1

  name                = "${var.pe_name}"
  location            = "${var.location}"
  resource_group_name = "${var.resource_group_name}"
  .
  .
}

とするとpe_nameが存在する場合のだけ作成して、ない場合はendpointを作らないようにもできます。

WAF

main.tf
resource "azurerm_web_application_firewall_policy" "policy" {
  name                = "${var.policy_name}"
  resource_group_name      = "${var.resource_group_name}"
  location                 = "${var.location}"
.
.
.
    custom_rules { 
        name      = "${var.customrule_name}"
        priority  = var.customrule_priority
        rule_type = "${var.customrule_type}"

        dynamic match_conditions {
        for_each = var.match_conditions
            content {
                match_variables {
                    variable_name = "${match_conditions.value.variable_name}"
                    selector      = "${match_conditions.value.selector}"
                }

                operator           = "${match_conditions.value.operator}"
                negation_condition = false
                match_values       = ["${match_conditions.value.match_values}"]
            }
        }

        action = "${var.customrule_action}"
    }
  

custom_rules自身も複数ある場合もありますが、custom_rulesのなかのmatch_variables が複数ある場合の例です。dynamic match_conditionsとすることによってfor_eachをattributeで展開しています。
これはdynamicを使用してcontent{}の中でmatch_conditions.value.variable_nameなどとすることでVariableの値を取っています。

variables.tf
variable "match_conditions" {
  type = list(object({
    variable_name = string
    selector      = optional(string, "")
    operator      = string
    match_values  = string
  }))
}

Variable自体はこのように設定すればObjectのListとして利用できます。

  match_conditions = [
                     { 
                      variable_name = "RequestUri"
                      operator      = "Contains"
                      match_values  = "/test/abc"
                     },
                     { 
                      variable_name = "RemoteAddr"
                      operator      = "IPMatch"
                      match_values  = "123.45.67.89"
                     }

とかすると特定のIPアドレスから特定のPathへのアクセスを許可するルールができます。

また、WAFのルールで例外を設けるときなどvariableでlistの中にlistを作ります。

main.tf
  managed_rules {
    managed_rule_set {
      type    = "OWASP"
      version = "3.2"

      dynamic rule_group_override {
        for_each = var.rule_group_override
        content{
          rule_group_name   = "${rule_group_override.value.rule_group_name}"
          dynamic rule {
            for_each = rule_group_override.value.rule_ids
            content {
                id      = "${rule.value}"
                enabled = false
            }
          }
        }

      }
    }
  }
variables.tf
variable "rule_group_override" {
type = list(object({
  rule_group_name = string
  rule_ids      = list(string)
}))
}

モジュール側では以下のように設定すると、指定したWAFルールに例外が設定されます。

modules.tf
  rule_group_override = [
    {
       rule_group_name   = "REQUEST-920-PROTOCOL-ENFORCEMENT"
       rule_ids          = ["942260","942430"]
    },
    {
       rule_group_name   = "REQUEST-941-APPLICATION-ATTACK-XSS"
       rule_ids          = ["942110","942430"]
    }
]

その他

モジュールにしても、複数のtfファイルで管理することもできます。

modules
├── appgw
    ├── main.tf
    ├── variables.tf
    ├── region1.tf
    ├── region2.tf

例えば、異なるリージョンでの差分が多い場合、変数で対応するより別のファイルで設定することも可能です。

region1.tf
resource "azurerm_application_gateway" "region1" {
  count = var.location == "region1" ? 1 : 0
  name                = "${var.appgw_name}"
.
.
region2.tf
resource "azurerm_application_gateway" "region2" {
  count = var.location == "region2" ? 1 : 0
  name                = "${var.appgw_name}"
.
.
modules.tf
module "appgw" {
  source      = "modules/appgw"
  location    = "region1"
}

このようにすると、var.location変数がregion1の場合だけazurerm_application_gateway.region1が作成されるようにすることも可能です。ただし、このように条件を入れてリソースを作成するとazurerm_application_gateway.region1[0]と配列になって作成されます。
main.tfにはどちらのリージョンでも共通に作られるリソースを入れておくと、まとめて管理できます。

既存のリソースをモジュールに移動

すでにリソースをTerraformで作成している場合は、movedを使うと、Stateをモジュールに移動できます。

modules.tf
moved {
  from = azurerm_kubernetes_cluster.aks
  to   = module.aks_qa.azurerm_kubernetes_cluster.aks
}

まとめ

このようにmovedを使って既存のリソースをモジュールに移動できます。
この場合、リソース自体は何も変更行われず、Terraformのステートだけが、モジュールに移動します。

terraform state listとすると、リソースがモジュールに移動していることが確認できます。

terraform state list
module.storage.azurerm_storage_account.azfiles
module.nfs.azurerm_storage_account.blob_nfs
...
...
0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?