Terraform(全稱:Hashicorp Terraform )是一種開源工具,用于預配和管理雲基礎結構。 它将基礎結構編入描述雲資源拓撲的配置檔案中。 這些資源包括虛拟機、存儲帳戶和網絡接口等。
本文介紹在Windows系統中,如何安裝Terraform,并且根據Azure的示例模闆建立,在中國區建立一個虛拟機(VM)的入門級教程。
安裝Terraform
Terraform的Windows版本為一個.exe檔案,下載下傳後把放置在自定義的檔案夾中,最後配置号系統的PATH即可。
- 下載下傳Terraform(https://www.terraform.io/downloads.html),根據情況選擇Windows 32-bit版 或 64-bit版
- 解壓檔案,複制到目标檔案夾中,如:C:\LBWorkSpace\tool
- 配置系統PATH路徑
- 打開CMD,使用Terraform --version測試
準備建立VM的Terraform模闆
準備Terraform模闆,參考Azure的官方文檔:使用 Terraform 在 Azure 中建立帶有基礎結構的 Linux VM。可以一步一步的編寫模闆,也可全部COPY至本地,并命名為:terraform_azure.tf(名字可以随便改動,檔案字尾名tf不可變)。
1 # Configure the Microsoft Azure Provider
2 provider "azurerm" {
3 # The "feature" block is required for AzureRM provider 2.x.
4 # If you're using version 1.x, the "features" block is not allowed.
5 version = "~>2.0"
6 features {}
7 }
8
9 # Create a resource group if it doesn't exist
10 resource "azurerm_resource_group" "myterraformgroup" {
11 name = "myResourceGroup"
12 location = "chinaeast"
13
14 tags = {
15 environment = "Terraform Demo"
16 }
17 }
18
19 # Create virtual network
20 resource "azurerm_virtual_network" "myterraformnetwork" {
21 name = "myVnet"
22 address_space = ["10.0.0.0/16"]
23 location = "chinaeast"
24 resource_group_name = azurerm_resource_group.myterraformgroup.name
25
26 tags = {
27 environment = "Terraform Demo"
28 }
29 }
30
31 # Create subnet
32 resource "azurerm_subnet" "myterraformsubnet" {
33 name = "mySubnet"
34 resource_group_name = azurerm_resource_group.myterraformgroup.name
35 virtual_network_name = azurerm_virtual_network.myterraformnetwork.name
36 address_prefixes = ["10.0.1.0/24"]
37 }
38
39 # Create public IPs
40 resource "azurerm_public_ip" "myterraformpublicip" {
41 name = "myPublicIP"
42 location = "chinaeast"
43 resource_group_name = azurerm_resource_group.myterraformgroup.name
44 allocation_method = "Dynamic"
45
46 tags = {
47 environment = "Terraform Demo"
48 }
49 }
50
51 # Create Network Security Group and rule
52 resource "azurerm_network_security_group" "myterraformnsg" {
53 name = "myNetworkSecurityGroup"
54 location = "chinaeast"
55 resource_group_name = azurerm_resource_group.myterraformgroup.name
56
57 security_rule {
58 name = "SSH"
59 priority = 1001
60 direction = "Inbound"
61 access = "Allow"
62 protocol = "Tcp"
63 source_port_range = "*"
64 destination_port_range = "22"
65 source_address_prefix = "*"
66 destination_address_prefix = "*"
67 }
68
69 tags = {
70 environment = "Terraform Demo"
71 }
72 }
73
74 # Create network interface
75 resource "azurerm_network_interface" "myterraformnic" {
76 name = "myNIC"
77 location = "chinaeast"
78 resource_group_name = azurerm_resource_group.myterraformgroup.name
79
80 ip_configuration {
81 name = "myNicConfiguration"
82 subnet_id = azurerm_subnet.myterraformsubnet.id
83 private_ip_address_allocation = "Dynamic"
84 public_ip_address_id = azurerm_public_ip.myterraformpublicip.id
85 }
86
87 tags = {
88 environment = "Terraform Demo"
89 }
90 }
91
92 # Connect the security group to the network interface
93 resource "azurerm_network_interface_security_group_association" "example" {
94 network_interface_id = azurerm_network_interface.myterraformnic.id
95 network_security_group_id = azurerm_network_security_group.myterraformnsg.id
96 }
97
98 # Generate random text for a unique storage account name
99 resource "random_id" "randomId" {
100 keepers = {
101 # Generate a new ID only when a new resource group is defined
102 resource_group = azurerm_resource_group.myterraformgroup.name
103 }
104
105 byte_length = 8
106 }
107
108 # Create storage account for boot diagnostics
109 resource "azurerm_storage_account" "mystorageaccount" {
110 name = "diag${random_id.randomId.hex}"
111 resource_group_name = azurerm_resource_group.myterraformgroup.name
112 location = "chinaeast"
113 account_tier = "Standard"
114 account_replication_type = "LRS"
115
116 tags = {
117 environment = "Terraform Demo"
118 }
119 }
120
121 # Create (and display) an SSH key
122 resource "tls_private_key" "example_ssh" {
123 algorithm = "RSA"
124 rsa_bits = 4096
125 }
126 #output "tls_private_key" { value = tls_private_key.example_ssh.private_key_pem }
127
128 # Create virtual machine
129 resource "azurerm_linux_virtual_machine" "myterraformvm" {
130 name = "myVM"
131 location = "chinaeast"
132 resource_group_name = azurerm_resource_group.myterraformgroup.name
133 network_interface_ids = [azurerm_network_interface.myterraformnic.id]
134 size = "Standard_DS1_v2"
135
136 os_disk {
137 name = "myOsDisk"
138 caching = "ReadWrite"
139 storage_account_type = "Premium_LRS"
140 }
141
142 source_image_reference {
143 publisher = "Canonical"
144 offer = "UbuntuServer"
145 sku = "18.04-LTS"
146 version = "latest"
147 }
148
149 computer_name = "myvm"
150 admin_username = "azureuser"
151 disable_password_authentication = true
152
153 admin_ssh_key {
154 username = "azureuser"
155 public_key = tls_private_key.example_ssh.public_key_openssh
156 }
157
158 boot_diagnostics {
159 storage_account_uri = azurerm_storage_account.mystorageaccount.primary_blob_endpoint
160 }
161
162 tags = {
163 environment = "Terraform Demo"
164 }
165 }
View Code
完成 Terraform 腳本:https://docs.microsoft.com/zh-cn/azure/developer/terraform/create-linux-virtual-machine-with-infrastructure#complete-terraform-script
登入到中國區Azure
本文使用Visual Studio Code工具來展示指令及Terraform腳本,也可以直接使用PowerShell視窗。
一:打開VS Code,使用 az cloud set --name AzureChinaCloud 設定登入環境為China Azure。
二:使用 az login 登入
三:如有多個訂閱号,可以使用 az account set --subscription "your subscription id" 指定資源所建立的訂閱
執行Terraform init, plan, apply指令
第一步:初始化 terraform init
指令
terraform init
輸出
PS C:\LBWorkSpace\MyCode\24-Terraform> terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/tls from the dependency lock file
- Reusing previous version of hashicorp/azurerm from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Using previously-installed hashicorp/tls v3.1.0
- Using previously-installed hashicorp/azurerm v2.56.0
- Using previously-installed hashicorp/random v3.1.0
╷
│ Warning: Version constraints inside provider configuration blocks are deprecated
│
│ on terraform_azure.tf line 5, in provider "azurerm":
│ 5: version = "~>2.0"
│
│ Terraform 0.13 and earlier allowed provider version constraints inside the provider configuration block, but that is now deprecated and will
│ be removed in a future version of Terraform. To silence this warning, move the provider version constraint into the required_providers block.
╵
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
第二步:檢查并驗證模闆 terraform plan
terraform plan
PS C:\LBWorkSpace\MyCode\24-Terraform> terraform plan
tls_private_key.example_ssh: Refreshing state... [id=4b9fa2d1e40856b8ed19e1978c7713feb660ce9b]
azurerm_resource_group.myterraformgroup: Refreshing state... [id=/subscriptions/a9dc7515-7692-4316-9ad4-762f383eec10/resourceGroups/myResourceGroup]
╷
│ Warning: Version constraints inside provider configuration blocks are deprecated
│
│ on terraform_azure.tf line 5, in provider "azurerm":
│ 5: version = "~>2.0"
│
│ Terraform 0.13 and earlier allowed provider version constraints inside the provider configuration block, but that is now deprecated and will be removed in a future version of Terraform. To silence this
│ warning, move the provider version constraint into the required_providers block.
╵
╷
│ Error: "eastus" was not found in the list of supported Azure Locations: "chinaeast,chinanorth,chinanorth2,chinaeast2"
│
│ on terraform_azure.tf line 10, in resource "azurerm_resource_group" "myterraformgroup":
│ 10: resource "azurerm_resource_group" "myterraformgroup" {
│
╵
╷
│ Error: Output refers to sensitive values
│
│ on terraform_azure.tf line 126:
│ 126: output "tls_private_key" { value = tls_private_key.example_ssh.private_key_pem }
│
│ Expressions used in outputs can only refer to sensitive values if the sensitive attribute is true.
╵
PS C:\LBWorkSpace\MyCode\24-Terraform>
注意:在檢查模闆時候有兩個錯誤,是因為copy的terraform模闆是建立在global azure的,而目前是在中國區azure,是以需要修改location從eastus到chinaeast或其他。 第二個錯誤output輸出可以暫時注釋126行模闆即可。修改完成後,再次使用terraform plan指令檢查模闆,輸出結果中會包含模闆中将要建立,修改的資源清單。
第三步:構模組化闆中的資源 terraform apply
terraform apply
輸出(apply指令需要在執行前手動輸入yes,然後開始真正執行建立資源。當建立完成後,可以看見Apply complete! Resources: 9 added, 0 changed, 0 destroyed.提示消息)
PS C:\LBWorkSpace\MyCode\24-Terraform> terraform apply
tls_private_key.example_ssh: Refreshing state... [id=4b9fa2d1e40856b8ed19e1978c7713feb660ce9b]
azurerm_resource_group.myterraformgroup: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup]
random_id.randomId: Refreshing state... [id=nOAZzlk4_VY]
azurerm_network_security_group.myterraformnsg: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkSecurityGroups/myNetworkSecurityGroup]
azurerm_virtual_network.myterraformnetwork: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet]
azurerm_public_ip.myterraformpublicip: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/publicIPAddresses/myPublicIP]
azurerm_storage_account.mystorageaccount: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/diag9ce019ce5938fd56]
azurerm_subnet.myterraformsubnet: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet]
azurerm_network_interface.myterraformnic: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkInterfaces/myNIC]
azurerm_network_interface_security_group_association.example: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkInterfaces/myNIC|/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkSecurityGroups/myNetworkSecurityGroup]
azurerm_linux_virtual_machine.myterraformvm: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# azurerm_linux_virtual_machine.myterraformvm will be created
+ resource "azurerm_linux_virtual_machine" "myterraformvm" {
+ admin_username = "azureuser"
+ allow_extension_operations = true
+ computer_name = "myvm"
+ disable_password_authentication = true
+ extensions_time_budget = "PT1H30M"
+ id = (known after apply)
+ location = "chinaeast"
+ max_bid_price = -1
+ name = "myVM"
+ network_interface_ids = (known after apply)
+ platform_fault_domain = -1
+ priority = "Regular"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ provision_vm_agent = true
+ public_ip_address = (known after apply)
+ public_ip_addresses = (known after apply)
+ resource_group_name = "myResourceGroup"
+ size = "Standard_DS1_v2"
+ tags = {
+ "environment" = "Terraform Demo"
}
+ virtual_machine_id = (known after apply)
+ zone = (known after apply)
+ admin_ssh_key {
+ public_key = <<-EOT
ssh-rsa xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EOT
+ username = "azureuser"
}
+ boot_diagnostics {
+ storage_account_uri = (known after apply)
}
+ os_disk {
+ caching = "ReadWrite"
+ disk_size_gb = (known after apply)
+ name = "myOsDisk"
+ storage_account_type = "Premium_LRS"
+ write_accelerator_enabled = false
}
+ source_image_reference {
+ offer = "UbuntuServer"
+ publisher = "Canonical"
+ sku = "18.04-LTS"
+ version = "latest"
}
}
# azurerm_network_interface.myterraformnic will be created
+ resource "azurerm_network_interface" "myterraformnic" {
+ applied_dns_servers = (known after apply)
+ dns_servers = (known after apply)
+ enable_accelerated_networking = false
+ enable_ip_forwarding = false
+ id = (known after apply)
+ internal_dns_name_label = (known after apply)
+ internal_domain_name_suffix = (known after apply)
+ location = "chinaeast"
+ mac_address = (known after apply)
+ name = "myNIC"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ resource_group_name = "myResourceGroup"
+ tags = {
+ "environment" = "Terraform Demo"
}
+ virtual_machine_id = (known after apply)
+ ip_configuration {
+ name = "myNicConfiguration"
+ primary = (known after apply)
+ private_ip_address = (known after apply)
+ private_ip_address_allocation = "dynamic"
+ private_ip_address_version = "IPv4"
+ public_ip_address_id = (known after apply)
+ subnet_id = (known after apply)
}
}
# azurerm_network_interface_security_group_association.example will be created
+ resource "azurerm_network_interface_security_group_association" "example" {
+ id = (known after apply)
+ network_interface_id = (known after apply)
+ network_security_group_id = (known after apply)
}
# azurerm_network_security_group.myterraformnsg will be created
+ resource "azurerm_network_security_group" "myterraformnsg" {
+ id = (known after apply)
+ location = "chinaeast"
+ name = "myNetworkSecurityGroup"
+ resource_group_name = "myResourceGroup"
+ security_rule = [
+ {
+ access = "Allow"
+ description = ""
+ destination_address_prefix = "*"
+ destination_address_prefixes = []
+ destination_application_security_group_ids = []
+ destination_port_range = "22"
+ destination_port_ranges = []
+ direction = "Inbound"
+ name = "SSH"
+ priority = 1001
+ protocol = "Tcp"
+ source_address_prefix = "*"
+ source_address_prefixes = []
+ source_application_security_group_ids = []
+ source_port_range = "*"
+ source_port_ranges = []
},
]
+ tags = {
+ "environment" = "Terraform Demo"
}
}
# azurerm_public_ip.myterraformpublicip will be created
+ resource "azurerm_public_ip" "myterraformpublicip" {
+ allocation_method = "Dynamic"
+ fqdn = (known after apply)
+ id = (known after apply)
+ idle_timeout_in_minutes = 4
+ ip_address = (known after apply)
+ ip_version = "IPv4"
+ location = "chinaeast"
+ name = "myPublicIP"
+ resource_group_name = "myResourceGroup"
+ sku = "Basic"
+ tags = {
+ "environment" = "Terraform Demo"
}
}
# azurerm_resource_group.myterraformgroup will be created
+ resource "azurerm_resource_group" "myterraformgroup" {
+ id = (known after apply)
+ location = "chinaeast"
+ name = "myResourceGroup"
+ tags = {
+ "environment" = "Terraform Demo"
}
}
# azurerm_storage_account.mystorageaccount will be created
+ resource "azurerm_storage_account" "mystorageaccount" {
+ access_tier = (known after apply)
+ account_kind = "StorageV2"
+ account_replication_type = "LRS"
+ account_tier = "Standard"
+ allow_blob_public_access = false
+ enable_https_traffic_only = true
+ id = (known after apply)
+ is_hns_enabled = false
+ large_file_share_enabled = (known after apply)
+ location = "chinaeast"
+ min_tls_version = "TLS1_0"
+ name = "diag9ce019ce5938fd56"
+ primary_access_key = (sensitive value)
+ primary_blob_connection_string = (sensitive value)
+ primary_blob_endpoint = (known after apply)
+ primary_blob_host = (known after apply)
+ primary_connection_string = (sensitive value)
+ primary_dfs_endpoint = (known after apply)
+ primary_dfs_host = (known after apply)
+ primary_file_endpoint = (known after apply)
+ primary_file_host = (known after apply)
+ primary_location = (known after apply)
+ primary_queue_endpoint = (known after apply)
+ primary_queue_host = (known after apply)
+ primary_table_endpoint = (known after apply)
+ primary_table_host = (known after apply)
+ primary_web_endpoint = (known after apply)
+ primary_web_host = (known after apply)
+ resource_group_name = "myResourceGroup"
+ secondary_access_key = (sensitive value)
+ secondary_blob_connection_string = (sensitive value)
+ secondary_blob_endpoint = (known after apply)
+ secondary_blob_host = (known after apply)
+ secondary_connection_string = (sensitive value)
+ secondary_dfs_endpoint = (known after apply)
+ secondary_dfs_host = (known after apply)
+ secondary_file_endpoint = (known after apply)
+ secondary_file_host = (known after apply)
+ secondary_location = (known after apply)
+ secondary_queue_endpoint = (known after apply)
+ secondary_queue_host = (known after apply)
+ secondary_table_endpoint = (known after apply)
+ secondary_table_host = (known after apply)
+ secondary_web_endpoint = (known after apply)
+ secondary_web_host = (known after apply)
+ tags = {
+ "environment" = "Terraform Demo"
}
+ blob_properties {
+ container_delete_retention_policy {
+ days = (known after apply)
}
+ cors_rule {
+ allowed_headers = (known after apply)
+ allowed_methods = (known after apply)
+ allowed_origins = (known after apply)
+ exposed_headers = (known after apply)
+ max_age_in_seconds = (known after apply)
}
+ delete_retention_policy {
+ days = (known after apply)
}
}
+ identity {
+ principal_id = (known after apply)
+ tenant_id = (known after apply)
+ type = (known after apply)
}
+ network_rules {
+ bypass = (known after apply)
+ default_action = (known after apply)
+ ip_rules = (known after apply)
+ virtual_network_subnet_ids = (known after apply)
}
+ queue_properties {
+ cors_rule {
+ allowed_headers = (known after apply)
+ allowed_methods = (known after apply)
+ allowed_origins = (known after apply)
+ exposed_headers = (known after apply)
+ max_age_in_seconds = (known after apply)
}
+ hour_metrics {
+ enabled = (known after apply)
+ include_apis = (known after apply)
+ retention_policy_days = (known after apply)
+ version = (known after apply)
}
+ logging {
+ delete = (known after apply)
+ read = (known after apply)
+ retention_policy_days = (known after apply)
+ version = (known after apply)
+ write = (known after apply)
}
+ minute_metrics {
+ enabled = (known after apply)
+ include_apis = (known after apply)
+ retention_policy_days = (known after apply)
+ version = (known after apply)
}
}
}
# azurerm_subnet.myterraformsubnet will be created
+ resource "azurerm_subnet" "myterraformsubnet" {
+ address_prefix = (known after apply)
+ address_prefixes = [
+ "10.0.1.0/24",
]
+ enforce_private_link_endpoint_network_policies = false
+ enforce_private_link_service_network_policies = false
+ id = (known after apply)
+ name = "mySubnet"
+ resource_group_name = "myResourceGroup"
+ virtual_network_name = "myVnet"
}
# azurerm_virtual_network.myterraformnetwork will be created
+ resource "azurerm_virtual_network" "myterraformnetwork" {
+ address_space = [
+ "10.0.0.0/16",
]
+ guid = (known after apply)
+ id = (known after apply)
+ location = "chinaeast"
+ name = "myVnet"
+ resource_group_name = "myResourceGroup"
+ subnet = (known after apply)
+ tags = {
+ "environment" = "Terraform Demo"
}
+ vm_protection_enabled = false
}
Plan: 9 to add, 0 to change, 0 to destroy.
╷
│ Warning: Version constraints inside provider configuration blocks are deprecated
│
│ on terraform_azure.tf line 5, in provider "azurerm":
│ 5: version = "~>2.0"
│
│ Terraform 0.13 and earlier allowed provider version constraints inside the provider configuration block, but that is now deprecated and will be removed in a future version of Terraform. To silence this
│ warning, move the provider version constraint into the required_providers block.
╵
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
azurerm_resource_group.myterraformgroup: Creating...
azurerm_resource_group.myterraformgroup: Creation complete after 1s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup]
azurerm_virtual_network.myterraformnetwork: Creating...
azurerm_public_ip.myterraformpublicip: Creating...
azurerm_network_security_group.myterraformnsg: Creating...
azurerm_storage_account.mystorageaccount: Creating...
azurerm_public_ip.myterraformpublicip: Creation complete after 3s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/publicIPAddresses/myPublicIP]
azurerm_virtual_network.myterraformnetwork: Creation complete after 6s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet]
azurerm_subnet.myterraformsubnet: Creating...
azurerm_network_security_group.myterraformnsg: Creation complete after 5s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkSecurityGroups/myNetworkSecurityGroup]
azurerm_storage_account.mystorageaccount: Still creating... [10s elapsed]
azurerm_subnet.myterraformsubnet: Creation complete after 5s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet]
azurerm_network_interface.myterraformnic: Creating...
azurerm_network_interface.myterraformnic: Creation complete after 2s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkInterfaces/myNIC]
azurerm_network_interface_security_group_association.example: Creating...
azurerm_network_interface_security_group_association.example: Creation complete after 0s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkInterfaces/myNIC|/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkSecurityGroups/myNetworkSecurityGroup]
azurerm_storage_account.mystorageaccount: Still creating... [20s elapsed]
azurerm_storage_account.mystorageaccount: Creation complete after 23s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/diag9ce019ce5938fd56]
azurerm_linux_virtual_machine.myterraformvm: Creating...
azurerm_linux_virtual_machine.myterraformvm: Still creating... [10s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [20s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [30s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [40s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [50s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [1m0s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [1m10s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [1m20s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [1m30s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [1m40s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Still creating... [1m50s elapsed]
azurerm_linux_virtual_machine.myterraformvm: Creation complete after 1m51s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM]
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
恭喜!踏入Terraform建立Azure資源大門。
參考資料
“Azure 上的 Terraform”文檔: https://docs.microsoft.com/zh-cn/azure/developer/terraform/
使用 Terraform 在 Azure 中建立帶有基礎結構的 Linux VM: https://docs.microsoft.com/zh-cn/azure/developer/terraform/create-linux-virtual-machine-with-infrastructure#complete-terraform-script
Install Azure CLI on Windows:https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-powershell
當在複雜的環境中面臨問題,格物之道需:濁而靜之徐清,安以動之徐生。 雲中,恰是如此!