theme: condensed-night-purple
小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
在前面三篇实践部署操作中,我们熟悉了应用部署,资源组和虚拟网络创建部署。这一篇文章我们结合对Terraform相当重要的模块,部署一个相对而言比较复杂的基础设施,云计算实例。
一、构建复用模块
Terraform模块是编写高质量Terraform代码,提升代码复用性的重要手段,可以说,一个成熟的生产环境应该是由数个可信成熟的模块组装而成的。
Terraform模块最基础文件需提供:
- main.tf,用于资源定义,相互依赖
- variables.tf,用于申明变量,方便调用模块方使用自己的值
- outputs.tf,用于承接资源创建后,调用方关心的创建完成的内容,比如资源Id等
所以我们首先创建一个文件夹azuremachinemodule,用于存放我们的模块,其目录结构如下图所示。
README.md文档用于描述该模块,方便使用者。
1.1资源组
资源组是用于保存 Azure 解决方案相关资源的容器。 资源组可以包含解决方案的所有资源,也可以只包含想要作为组来管理的资源。
```yaml
main.tf
资源组
resource "azurermresourcegroup" "myterraformgroup" { name = "myResourceGroup" location = var.location tags = { environment = "Terraform Demo" } } ```
1.2网络部分
众所周知,对于Azure家的产品,创建计算实例(虚拟机)时,需要为其创建虚拟网络或者使用当前的虚拟网络。最佳实践上,每一组虚拟机都将会分配到虚拟网络的单独子网中,如下图所示。
所以我们对于网络通信这一部分,我们要提供网络接口、虚拟网络接口、子网。
```yaml
main.tf
随机字符串
resource "randomstring" "nicprefix" { length = 4 special = false }
虚拟网络接口
resource "azurermvirtualnetwork" "myterraformnetwork" { name = "myVnet" addressspace = ["10.0.0.0/16"] location = var.location resourcegroupname = azurermresource_group.myterraformgroup.name tags = { environment = "Terraform Demo" } }
子网
resource "azurermsubnet" "myterraformsubnet" { name = "mySubnet" resourcegroupname = azurermresourcegroup.myterraformgroup.name virtualnetworkname = azurermvirtualnetwork.myterraformnetwork.name addressprefixes = ["10.0.1.0/24"] }
网络接口
resource "azurermnetworkinterface" "vmnic" { name = "${var.vmname}-nic1" location = var.location resourcegroupname = azurermresourcegroup.myterraformgroup.name ipconfiguration { name = "${var.vmname}nic${randomstring.nicprefix.result}" subnetid = azurermsubnet.myterraformsubnet.id privateipaddressallocation = "Static" privateipaddress = var.staticip_address } tags = var.tags } ``` 由于时间关系,部分动态变量并没有抽出来,有时间再进行优化。
1.3虚拟机
为了部署虚拟机,我们需要用到资源组,网络,另外为了保障出入安全,还需要设置实例安全组。 ```yaml
main.tf
安全组
resource "azurermnetworkinterfacesecuritygroupassociation" "vmnicsg" { networkinterfaceid = azurermnetworkinterface.vmnic.id networksecuritygroupid = var.networksecuritygroupid count = var.networksecuritygroup_id == "" ? 0 : 1 }
计算实例
resource "azurermvirtualmachine" "windowsvm" { name = var.vmname vmsize = var.vmsize location = var.location resourcegroupname = azurermresourcegroup.myterraformgroup.name
tags = merge(var.tags, { activityName = "${var.activity_tag} " })
networkinterfaceids = [ "${azurermnetworkinterface.vm_nic.id}", ]
storageimagereference { publisher = var.publisher offer = var.offer sku = var.sku version = "latest" }
identity { type = "SystemAssigned" }
storageosdisk { name = "${var.vmname}-os-disk" caching = "ReadWrite" createoption = "FromImage" manageddisktype = "Standard_LRS" }
osprofile { adminpassword = var.adminpassword adminusername = "azureuser" computername = var.vmname }
osprofilewindowsconfig { provisionvm_agent = true }
deleteosdiskontermination = var.vmosdiskdeleteflag deletedatadisksontermination = var.vmdatadiskdeleteflag } ```
1.4其它
还需要定义输入输出变量。
```yaml
outputs.tf文件输出任何我们想要传递回根用户以供重用的内容
output "vmid" { value = "${azurermvirtualmachine.windowsvm.id}" }
output "vmname" { value = "${azurermvirtualmachine.windowsvm.name}" }
output "vmlocation" { value = "${azurermvirtualmachine.windowsvm.location}" }
output "vmresourcegroupname" { value = "${azurermvirtualmachine.windowsvm.resourcegroupname}" } ```
```yaml
variables.tf文件定义了模块期望从根模块调用中定义的所有变量
variable "resourcegroupname" {
}
variable "location" { }
variable "sloc" { }
variable "vmsize" { default = "StandardB1s" }
variable "vmsubnetid" {
}
variable "vm_name" { }
variable "vmosdiskdeleteflag" { default = true }
variable "vmdatadiskdeleteflag" { default = true }
variable "networksecuritygroup_id" { default = "" }
variable "staticipaddress" { }
variable "publisher" { }
variable "offer" { }
variable "sku" { }
variable "tags" { type = map description = "All mandatory tags to use on all assets"
default = { activityName = "AzureVMWindowsDemo" automation = "Terraform" costCenter1 = "A00000" dataClassification = "Demo" managedBy = "bt@bt.com" solutionOwner = "bt@bt.com" } }
variable "activity_tag" { }
variable "admin_password" { } ``` 到此为止,模块定义完成!
二、使用模块,构建业务
整个项目结构目录如下图所示。
main.tf文件,使用子模块,提供详细参数,认证信息
```yaml module windowsdesktopvmusinglocalmodule { source = "./azuremachinemodule" # resourcegroupname = azurermresource_group.myterraformgroup.name location = "eastus" sloc = "uks"
vmsubnetid = module.azurermnetworkinterface.vnet_subnets[0]
vmname = "testCompute" vmsize = var.desktopvmsize publisher = var.desktopvmimagepublisher offer = var.desktopvmimageoffer sku = var.desktopvmimagesku staticipaddress = "10.0.1.15" activitytag = "Windows Desktop" admin_password = "!@#qwe123" }
provider "azurerm" { features {} subscriptionid = "
" tenant
id = "
" client
id = "
" client
secret = "
" }
variables.tf,定义变量
yaml
read in from the terraform.auto.tfvars file
variable "globalsettings" { } variable "desktopvmimagepublisher" { } variable "desktopvmimageoffer" { } variable "desktopvmimagesku" { } variable "desktopvmimageversion" { } variable "desktopvmsize" { } terraform.auto.tfvars,实际参数
yaml globalsettings = {
#Set of tags tags = { applicationName = "Windows VM Demo" businessUnit = "Technical Solutions" costCenter = "MPN Sponsorship" DR = "NON-DR-ENABLED" deploymentType = "Terraform" environment = "Dev" owner = "Jack Roper" version = "0.1" }
}
Desktop VM variables
desktopvmimagepublisher = "MicrosoftWindowsDesktop" desktopvmimageoffer = "Windows-10" desktopvmimagesku = "20h1-pro" desktopvmimageversion = "latest" desktopvmsize = "Standard_B1s" ```
三、执行部署
terraform init 初始化环境
terraform plan 预览部署计划
terraform apply 执行部署
创建执行部署过程花费了六分钟左右的时间,等待时间确实有些久了。
检查Azure门户控制面板,确定资源创建成功。