小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
在前面三篇实践部署操作中,我们熟悉了应用部署,资源组和虚拟网络创建部署。这一篇文章我们结合对Terraform相当重要的模块,部署一个相对而言比较复杂的基础设施,云计算实例。
一、构建复用模块
Terraform模块是编写高质量Terraform代码,提升代码复用性的重要手段,可以说,一个成熟的生产环境应该是由数个可信成熟的模块组装而成的。
Terraform模块最基础文件需提供:
- main.tf,用于资源定义,相互依赖
- variables.tf,用于申明变量,方便调用模块方使用自己的值
- outputs.tf,用于承接资源创建后,调用方关心的创建完成的内容,比如资源Id等
所以我们首先创建一个文件夹azure_machine_module,用于存放我们的模块,其目录结构如下图所示。
README.md文档用于描述该模块,方便使用者。
1.1资源组
资源组是用于保存 Azure 解决方案相关资源的容器。 资源组可以包含解决方案的所有资源,也可以只包含想要作为组来管理的资源。
#main.tf
#资源组
resource "azurerm_resource_group" "myterraformgroup" {
name = "myResourceGroup"
location = var.location
tags = {
environment = "Terraform Demo"
}
}
1.2网络部分
众所周知,对于Azure家的产品,创建计算实例(虚拟机)时,需要为其创建虚拟网络或者使用当前的虚拟网络。最佳实践上,每一组虚拟机都将会分配到虚拟网络的单独子网中,如下图所示。
所以我们对于网络通信这一部分,我们要提供网络接口、虚拟网络接口、子网。
#main.tf
#随机字符串
resource "random_string" "nic_prefix" {
length = 4
special = false
}
#虚拟网络接口
resource "azurerm_virtual_network" "myterraformnetwork" {
name = "myVnet"
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = azurerm_resource_group.myterraformgroup.name
tags = {
environment = "Terraform Demo"
}
}
# 子网
resource "azurerm_subnet" "myterraformsubnet" {
name = "mySubnet"
resource_group_name = azurerm_resource_group.myterraformgroup.name
virtual_network_name = azurerm_virtual_network.myterraformnetwork.name
address_prefixes = ["10.0.1.0/24"]
}
#网络接口
resource "azurerm_network_interface" "vm_nic" {
name = "${var.vm_name}-nic1"
location = var.location
resource_group_name = azurerm_resource_group.myterraformgroup.name
ip_configuration {
name = "${var.vm_name}_nic_${random_string.nic_prefix.result}"
subnet_id = azurerm_subnet.myterraformsubnet.id
private_ip_address_allocation = "Static"
private_ip_address = var.static_ip_address
}
tags = var.tags
}
由于时间关系,部分动态变量并没有抽出来,有时间再进行优化。
1.3虚拟机
为了部署虚拟机,我们需要用到资源组,网络,另外为了保障出入安全,还需要设置实例安全组。
#main.tf
#安全组
resource "azurerm_network_interface_security_group_association" "vm_nic_sg" {
network_interface_id = azurerm_network_interface.vm_nic.id
network_security_group_id = var.network_security_group_id
count = var.network_security_group_id == "" ? 0 : 1
}
#计算实例
resource "azurerm_virtual_machine" "windows_vm" {
name = var.vm_name
vm_size = var.vm_size
location = var.location
resource_group_name = azurerm_resource_group.myterraformgroup.name
tags = merge(var.tags, { activityName = "${var.activity_tag} " })
network_interface_ids = [
"${azurerm_network_interface.vm_nic.id}",
]
storage_image_reference {
publisher = var.publisher
offer = var.offer
sku = var.sku
version = "latest"
}
identity {
type = "SystemAssigned"
}
storage_os_disk {
name = "${var.vm_name}-os-disk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
admin_password = var.admin_password
admin_username = "azureuser"
computer_name = var.vm_name
}
os_profile_windows_config {
provision_vm_agent = true
}
delete_os_disk_on_termination = var.vm_os_disk_delete_flag
delete_data_disks_on_termination = var.vm_data_disk_delete_flag
}
1.4其它
还需要定义输入输出变量。
#outputs.tf文件输出任何我们想要传递回根用户以供重用的内容
output "vm_id" {
value = "${azurerm_virtual_machine.windows_vm.id}"
}
output "vm_name" {
value = "${azurerm_virtual_machine.windows_vm.name}"
}
output "vm_location" {
value = "${azurerm_virtual_machine.windows_vm.location}"
}
output "vm_resource_group_name" {
value = "${azurerm_virtual_machine.windows_vm.resource_group_name}"
}
# variables.tf文件定义了模块期望从根模块调用中定义的所有变量
# variable "resource_group_name" {
# }
variable "location" {
}
variable "sloc" {
}
variable "vm_size" {
default = "Standard_B1s"
}
# variable "vm_subnet_id" {
# }
variable "vm_name" {
}
variable "vm_os_disk_delete_flag" {
default = true
}
variable "vm_data_disk_delete_flag" {
default = true
}
variable "network_security_group_id" {
default = ""
}
variable "static_ip_address" {
}
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文件,使用子模块,提供详细参数,认证信息
module windows_desktop_vm_using_local_module {
source = "./azure_machine_module"
# resource_group_name = azurerm_resource_group.myterraformgroup.name
location = "eastus"
sloc = "uks"
# vm_subnet_id = module.azurerm_network_interface.vnet_subnets[0]
vm_name = "testCompute"
vm_size = var.desktop_vm_size
publisher = var.desktop_vm_image_publisher
offer = var.desktop_vm_image_offer
sku = var.desktop_vm_image_sku
static_ip_address = "10.0.1.15"
activity_tag = "Windows Desktop"
admin_password = "!@#qwe123"
}
provider "azurerm" {
features {}
subscription_id = "<yours>"
tenant_id = "<yours>"
client_id = "<yours>"
client_secret = "<yours>"
}
variables.tf,定义变量
# read in from the terraform.auto.tfvars file
variable "global_settings" {
}
variable "desktop_vm_image_publisher" {
}
variable "desktop_vm_image_offer" {
}
variable "desktop_vm_image_sku" {
}
variable "desktop_vm_image_version" {
}
variable "desktop_vm_size" {
}
terraform.auto.tfvars,实际参数
global_settings = {
#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
desktop_vm_image_publisher = "MicrosoftWindowsDesktop"
desktop_vm_image_offer = "Windows-10"
desktop_vm_image_sku = "20h1-pro"
desktop_vm_image_version = "latest"
desktop_vm_size = "Standard_B1s"
三、执行部署
terraform init 初始化环境
terraform plan 预览部署计划
terraform apply 执行部署
创建执行部署过程花费了六分钟左右的时间,等待时间确实有些久了。
检查Azure门户控制面板,确定资源创建成功。