Azure Terraform(六)Common Module

Grant_Allen發表於2021-01-24

一,引言

  之前我們在使用 Terraform 構築一下 Azure 雲資源的時候,直接將所以需要建立的資源全面寫在 main.tf 這個檔案中,這樣寫主要是為了演示使用,但是在實際的 Terraform 程式碼的整個專案程式碼結構是需要封裝具體的 “Module”,這裡提到了 ”Module“ 也就是新的概念 “Common Module”。“Common Mudule” 其實對於開發來說,其實就是封裝的 ”類庫“,通過傳遞不同的引數,呼叫方法,來實現不同的返回值;同理,terraform 的 common moudle 也是一樣的。

 以下是 Terraform 專案結構

 

--------------------Azure Terraform 系列--------------------

1,Azure Terraform(一)入門簡介

2,Azure Terraform(二)語法詳解

3,Azure Terraform(三)部署 Web 應用程式

4,Azure Terraform(四)狀態檔案儲存

5,Azure Terraform(五)利用Azure DevOps 實現自動化部署基礎資源

6,Azure Terraform(六)Common Module

二,正文

1,Terraform 資源 Moudle 結構定義

按照資源劃分,將每種型別的資源劃分為單獨的 “Common Moudle”,比方 “資源組”,“流量管理配置”,“Web 應用程式”......

mian.tf:不是專案的入口,該檔案中包含了特定資源中的通用資原始檔。

resource "azurerm_traffic_manager_profile" "cnbate_traffic_manager_profile" {
  name                = var.traffic_manager_name
  resource_group_name = var.resource_group_name

  traffic_routing_method = var.traffic_routing_method

  dns_config {
    relative_name = var.relative_name
    ttl           = var.ttl
  }

  monitor_config {
    protocol                     = var.protocol
    port                         = var.port
    path                         = var.path
    interval_in_seconds          = var.interval_in_seconds
    timeout_in_seconds           = var.timeout_in_seconds
    tolerated_number_of_failures = var.tolerated_number_of_failures
  }

  tags = var.tags
}

resource "azurerm_traffic_manager_endpoint" "cnbate_traffic_manager_endpoint" {
  count               = var.enable_traffic_manager_endpoint && var.traffic_manager_endpoint_count > 0 ? var.traffic_manager_endpoint_count : 0
  name                = element(var.traffic_manager_endpoint_names, count.index)
  resource_group_name = var.resource_group_name
  profile_name        = azurerm_traffic_manager_profile.cnbate_traffic_manager_profile.name
  target_resource_id  = element(var.target_resource_ids, count.index)
  type                = var.traffic_manager_endpoint_type

  geo_mappings = element(var.geo_mappings, count.index)
}

outputs.tf :包含部署輸出變數的定義

################################ traffic manager profile ################################
output "traffic_manager_profile_name" {
  value = azurerm_traffic_manager_profile.cnbate_traffic_manager_profile.name
}

output "traffic_manager_profile_id" {
  value = azurerm_traffic_manager_profile.cnbate_traffic_manager_profile.id
}

################################ traffic manager profile ################################

output "azurerm_traffic_manager_endpoint_names" {
  value = azurerm_traffic_manager_endpoint.cnbate_traffic_manager_endpoint.*.name
}

output "azurerm_traffic_manager_endpoint_ids" {
  value = azurerm_traffic_manager_endpoint.cnbate_traffic_manager_endpoint.*.id
}

variables.tf:包含了當前資源所封裝的變數的定義

################################ traffic manager profile ################################
variable "traffic_manager_name" {
  type        = string
  description = "(required)The name of the traffic manager profile"
}

variable "resource_group_name" {
  type        = string
  description = "The Name which should be used for this Resource Group. Changing this forces a new Resource Group to be created."
}

variable "traffic_routing_method" {
  type        = string
  description = "(required) Specifies the algorithm used to route traffic"
}

variable "relative_name" {
  type        = string
  description = "(required) The relative domain name, this is combined with the domain name used by Traffic Manager to form the FQDN which is exported as documented below."
}

variable "ttl" {
  type        = number
  description = "(Required) The TTL value of the Profile used by Local DNS resolvers and clients"
}

variable "protocol" {
  type        = string
  default     = "http"
  description = " (required) The protocol used by the monitoring checks, supported values are HTTP, HTTPS and TCP."
}

variable "port" {
  type        = number
  default     = 80
  description = "(required) The port number used by the monitoring checks."
}

variable "path" {
  type        = string
  default     = "/"
  description = " (optional) The path used by the monitoring checks. Required when protocol is set to HTTP or HTTPS - cannot be set when protocol is set to TCP."
}

variable "interval_in_seconds" {
  type        = number
  default     = 30
  description = "(optional) The interval used to check the endpoint health from a Traffic Manager probing agent."
}

variable "timeout_in_seconds" {
  type        = number
  default     = 10
  description = "(optional) The amount of time the Traffic Manager probing agent should wait before considering that check a failure when a health check probe is sent to the endpoint. "
}

variable "tolerated_number_of_failures" {
  type        = string
  default     = 3
  description = "(optional) The number of failures a Traffic Manager probing agent tolerates before marking that endpoint as unhealthy. Valid values are between 0 and 9."
}

variable "tags" {
  type        = map(string)
  description = "(optional) A mapping of tags to assign to the resource."
}

################################ traffic manager endpoint ################################
variable "enable_traffic_manager_endpoint" {
  type        = bool
  default     = false
  description = "(required) whether to create traffic manager endpoint"
}

variable "traffic_manager_endpoint_count" {
  type        = number
  default     = 0
  description = "(required) number of create traffic manager endpoint"
}

variable "traffic_manager_endpoint_names" {
  type        = list(string)
  description = "(required) The name of the Traffic Manager endpoint."
}

variable "target_resource_ids" {
  type        = list(string)
  description = " (optional) The resource id of an Azure resource to target. This argument must be provided for an endpoint of type azureEndpoints or nestedEndpoints."
}

variable "traffic_manager_endpoint_type" {
  type        = string
  description = "(required) The Endpoint type, must be one of: 1:azureEndpoints,2:externalEndpoints,3:nestedEndpoints"
}

variable "geo_mappings" {
  type        = list(list(string))
  description = "(Optional) A list of Geographic Regions used to distribute traffic, such as WORLD, UK or DE. "
}

2,資源 Module 引用

將 terraform 專案所封裝的 common module 在一個主 mian.tf 進行引用的時候,使用 module

根據模組的位置以及使用該模組的位置,該 source 引數可能有所不同

module "cnbate_Web_app" {
  source                = "../module/web_app"
  app_service_locations = [local.location_eastAsia, local.location_southeastAsia]
  resource_group_name   = data.azurerm_resource_group.cnbate_resource_group.name

  enable                  = var.enable
  enable_app_service_plan = var.enable_app_service_plan
  app_service_plan_count  = var.app_service_plan_count
  app_service_plan_names  = var.app_service_plan_names
  app_service_plans       = var.app_service_plans

  enable_app_service = var.enable_app_service
  app_service_count  = var.app_service_count
  app_service_names  = var.app_service_names
  app_settings       = var.app_settings
}

如果模組之間由相互依賴引用,則通過 “module” 引用的方式來建立關係,同時 terraform apply 在執行部署計劃的時候,terraform 也會遵循這個依賴關係先後建立資源

module "cnbate_traffic_manager" {
  source                 = "../module/traffic_manager_profile"
  traffic_manager_name   = var.traffic_manager_name
  resource_group_name    = data.azurerm_resource_group.cnbate_resource_group.name
  traffic_routing_method = var.traffic_routing_method
  relative_name          = var.relative_name
  ttl                    = var.ttl
  tags                   = var.tags

  enable_traffic_manager_endpoint = var.enable_traffic_manager_endpoint
  traffic_manager_endpoint_count  = var.traffic_manager_endpoint_count
  traffic_manager_endpoint_names  = var.traffic_manager_endpoint_names
  target_resource_ids             = module.cnbate_Web_app.azurerm_app_service_ids
  traffic_manager_endpoint_type   = var.traffic_manager_endpoint_type
  geo_mappings                    = var.geo_mappings
}

注意,一旦依賴關係在 common module 階段發生改變的時候,就需要重新執行 terraform init 初始化操作,匯入的所有模組的配置

3,如何劃分 Terraform 資源模組

common module 的劃分和封裝沒有固定的標準,我們在劃分和封裝的時候要從多個角度去考慮問題

  1,專案太小,只有一個 web 應用程式,是否需要封裝?

  2,是否必須嚴格講每個 terraform resource 劃分成單獨的 common module?

  3,封裝的 common module 以及 module 引用是否滿足專案架構需求?

所以,劃分、封裝 common module 不是必須的。只要我們能夠清楚的看到實際專案的整體架構需求,是否使用模組化都是有利有弊的。大家要清楚的看到這一點。

完整程式碼請參考文章底部的 github 連結

三,結尾

參考資料:Terraform 官方azurerm 文件

Terraform_Cnbate_Traffic_Manager github:https://github.com/yunqian44/Terraform_Cnbate_Traffic_Manager

作者:Allen 

版權:轉載請在文章明顯位置註明作者及出處。如發現錯誤,歡迎批評指正。

相關文章