一,引言
之前我們在使用 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
7,Azure Terraform(七)利用Azure DevOps 實現自動化部署基礎資源(補充)
8,Azure Terraform(八)利用Azure DevOps 實現Infra資源和.NET CORE Web 應用程序的持續集成、持續部署
二,正文
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
版權:轉載請在文章明顯位置注明作者及出處。如發現錯誤,歡迎批評指正。