快速入门:使用 Bicep 模板创建虚拟网络
本快速入门介绍如何创建包含两个虚拟机的虚拟网络,然后使用 Bicep 模板在虚拟网络上部署 Azure Bastion。 然后,使用 Bastion 安全地从 Internet 连接到虚拟机,并在 VM 之间开始私密通信。
虚拟网络是 Azure 中专用网络的基本构建块。 Azure 虚拟网络能让 Azure 资源(例如 VM)互相安全通信以及与 Internet 通信。
Bicep 是一种特定于域的语言 (DSL),使用声明性语法来部署 Azure 资源。 它提供简明的语法、可靠的类型安全性以及对代码重用的支持。 Bicep 会针对你的 Azure 基础结构即代码解决方案提供最佳创作体验。
先决条件
具有活动订阅的 Azure 帐户。 可创建试用帐户。
若要部署 Bicep 文件,请安装 Azure CLI 或 Azure PowerShell。
在本地安装 Azure CLI 来运行命令。 需要 Azure CLI 2.0.28 或更高版本。 运行 az 版本,查找已安装的版本和依赖库,并运行 az 升级进行升级。
使用 az login 命令登录到 Azure。
创建虚拟网络和虚拟机
本快速入门使用 Azure 资源管理器快速启动模板中的 VNET 中的两个虚拟机 Bicep 模板来创建虚拟网络、资源子网和虚拟机。 Bicep 模板定义以下 Azure 资源:
- Microsoft.Network/virtualNetworks:创建 Azure 虚拟网络。
- Microsoft.Network/virtualNetworks/subnets:为虚拟机创建子网。
- Microsoft.Compute/virtualMachines:创建虚拟机。
- Microsoft.Compute availabilitySets:创建可用性集。
- Microsoft.Network networkInterfaces:创建网络接口。
- Microsoft.Network loadBalancers:创建内部负载均衡器。
- Microsoft.Storage/storageAccounts:创建存储帐户。
查阅 Bicep 文件:
@description('Admin username')
param adminUsername string
@description('Admin password')
@secure()
param adminPassword string
@description('Prefix to use for VM names')
param vmNamePrefix string = 'BackendVM'
@description('Location for all resources.')
param location string = resourceGroup().location
@description('Size of the virtual machines')
param vmSize string = 'Standard_D2s_v3'
var availabilitySetName = 'AvSet'
var storageAccountType = 'Standard_LRS'
var storageAccountName = uniqueString(resourceGroup().id)
var virtualNetworkName = 'vNet'
var subnetName = 'backendSubnet'
var loadBalancerName = 'ilb'
var networkInterfaceName = 'nic'
var subnetRef = resourceId('Microsoft.Network/virtualNetworks/subnets', virtualNetworkName, subnetName)
var numberOfInstances = 2
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
sku: {
name: storageAccountType
}
kind: 'StorageV2'
}
resource availabilitySet 'Microsoft.Compute/availabilitySets@2023-09-01' = {
name: availabilitySetName
location: location
sku: {
name: 'Aligned'
}
properties: {
platformUpdateDomainCount: 2
platformFaultDomainCount: 2
}
}
resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-09-01' = {
name: virtualNetworkName
location: location
properties: {
addressSpace: {
addressPrefixes: [
'10.0.0.0/16'
]
}
subnets: [
{
name: subnetName
properties: {
addressPrefix: '10.0.2.0/24'
}
}
]
}
}
resource networkInterface 'Microsoft.Network/networkInterfaces@2023-09-01' = [for i in range(0, numberOfInstances): {
name: '${networkInterfaceName}${i}'
location: location
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
privateIPAllocationMethod: 'Dynamic'
subnet: {
id: subnetRef
}
loadBalancerBackendAddressPools: [
{
id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', loadBalancerName, 'BackendPool1')
}
]
}
}
]
}
dependsOn: [
virtualNetwork
loadBalancer
]
}]
resource loadBalancer 'Microsoft.Network/loadBalancers@2023-09-01' = {
name: loadBalancerName
location: location
sku: {
name: 'Standard'
}
properties: {
frontendIPConfigurations: [
{
properties: {
subnet: {
id: subnetRef
}
privateIPAddress: '10.0.2.6'
privateIPAllocationMethod: 'Static'
}
name: 'LoadBalancerFrontend'
}
]
backendAddressPools: [
{
name: 'BackendPool1'
}
]
loadBalancingRules: [
{
properties: {
frontendIPConfiguration: {
id: resourceId('Microsoft.Network/loadBalancers/frontendIpConfigurations', loadBalancerName, 'LoadBalancerFrontend')
}
backendAddressPool: {
id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', loadBalancerName, 'BackendPool1')
}
probe: {
id: resourceId('Microsoft.Network/loadBalancers/probes', loadBalancerName, 'lbprobe')
}
protocol: 'Tcp'
frontendPort: 80
backendPort: 80
idleTimeoutInMinutes: 15
}
name: 'lbrule'
}
]
probes: [
{
properties: {
protocol: 'Tcp'
port: 80
intervalInSeconds: 15
numberOfProbes: 2
}
name: 'lbprobe'
}
]
}
dependsOn: [
virtualNetwork
]
}
resource vm 'Microsoft.Compute/virtualMachines@2023-09-01' = [for i in range(0, numberOfInstances): {
name: '${vmNamePrefix}${i}'
location: location
properties: {
availabilitySet: {
id: availabilitySet.id
}
hardwareProfile: {
vmSize: vmSize
}
osProfile: {
computerName: '${vmNamePrefix}${i}'
adminUsername: adminUsername
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'MicrosoftWindowsServer'
offer: 'WindowsServer'
sku: '2019-Datacenter'
version: 'latest'
}
osDisk: {
createOption: 'FromImage'
}
}
networkProfile: {
networkInterfaces: [
{
id: networkInterface[i].id
}
]
}
diagnosticsProfile: {
bootDiagnostics: {
enabled: true
storageUri: storageAccount.properties.primaryEndpoints.blob
}
}
}
}]
output location string = location
output name string = loadBalancer.name
output resourceGroupName string = resourceGroup().name
output resourceId string = loadBalancer.id
部署 Bicep 模板
将该 Bicep 文件另存为本地计算机上的 main.bicep。
使用 Azure CLI 或 Azure PowerShell 来部署 Bicep 文件:
az group create --name TestRG --location chinanorth3 az deployment group create --resource-group TestRG --template-file main.bicep
部署完成后,会显示一条指示部署成功的消息。
部署 Azure Bastion
Bastion 使用浏览器通过安全外壳 (SSH) 或远程桌面协议 (RDP),通过使用其专用 IP 地址连接虚拟网络中的虚拟机。 虚拟机不需要公共 IP 地址、客户端软件或特殊配置。 有关 Bastion 的详细信息,请参阅《什么是 Azure Bastion?》。
注意
每小时定价从部署 Bastion 的时刻开始计算,无论出站数据的使用情况如何。 有关详细信息,请参阅定价和 SKU。 如果要将 Bastion 部署为教程或测试的一部分,建议在使用完此资源后将其删除。
使用 Azure 资源管理器快速启动模板中的 Azure Bastion 即服务 Bicep 模板,在虚拟网络中部署和配置 Azure Bastion。 该 Bicep 模板定义以下 Azure 资源:
- Microsoft.Network virtualNetworks/subnets:创建 AzureBastionSubnet 子网。
- Microsoft.Network/bastionHosts 创建 Bastion 主机。
- Microsoft.Network publicIPAddresses:为 Bastion 主机创建公共 IP 地址。
- Microsoft Network/networkSecurityGroups:控制网络安全组的设置。
查阅 Bicep 文件:
@description('Name of new or existing vnet to which Azure Bastion should be deployed')
param vnetName string = 'vnet01'
@description('IP prefix for available addresses in vnet address space')
param vnetIpPrefix string = '10.1.0.0/16'
@description('Specify whether to provision new vnet or deploy to existing vnet')
@allowed([
'new'
'existing'
])
param vnetNewOrExisting string = 'new'
@description('Bastion subnet IP prefix MUST be within vnet IP prefix address space')
param bastionSubnetIpPrefix string = '10.1.1.0/26'
@description('Name of Azure Bastion resource')
param bastionHostName string
@description('Azure region for Bastion and virtual network')
param location string = resourceGroup().location
var publicIpAddressName = '${bastionHostName}-pip'
var bastionSubnetName = 'AzureBastionSubnet'
resource publicIp 'Microsoft.Network/publicIPAddresses@2022-01-01' = {
name: publicIpAddressName
location: location
sku: {
name: 'Standard'
}
properties: {
publicIPAllocationMethod: 'Static'
}
}
// if vnetNewOrExisting == 'new', create a new vnet and subnet
resource newVirtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = if (vnetNewOrExisting == 'new') {
name: vnetName
location: location
properties: {
addressSpace: {
addressPrefixes: [
vnetIpPrefix
]
}
subnets: [
{
name: bastionSubnetName
properties: {
addressPrefix: bastionSubnetIpPrefix
}
}
]
}
}
// if vnetNewOrExisting == 'existing', reference an existing vnet and create a new subnet under it
resource existingVirtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' existing = if (vnetNewOrExisting == 'existing') {
name: vnetName
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2022-01-01' = if (vnetNewOrExisting == 'existing') {
parent: existingVirtualNetwork
name: bastionSubnetName
properties: {
addressPrefix: bastionSubnetIpPrefix
}
}
resource bastionHost 'Microsoft.Network/bastionHosts@2022-01-01' = {
name: bastionHostName
location: location
dependsOn: [
newVirtualNetwork
existingVirtualNetwork
]
properties: {
ipConfigurations: [
{
name: 'IpConf'
properties: {
subnet: {
id: subnet.id
}
publicIPAddress: {
id: publicIp.id
}
}
}
]
}
}
部署 Bicep 模板
将该 Bicep 文件另存为本地计算机上的 bastion.bicep。
使用文本或代码编辑器在文件中进行以下更改:
- 第 2 行:将
param vnetName string
从'vnet01'
更改为'VNet'
。 - 第 5 行:将
param vnetIpPrefix string
从'10.1.0.0/16'
更改为'10.0.0.0/16'
。 - 第 12 行:将
param vnetNewOrExisting string
从'new'
更改为'existing'
。 - 第 15 行:将
param bastionSubnetIpPrefix string
从'10.1.1.0/26'
更改为'10.0.1.0/26'
。 - 第 18 行:将
param bastionHostName string
更改为param bastionHostName = 'VNet-bastion'
。
更改后,Bicep 文件的前 18 行应如下示例所示:
@description('Name of new or existing vnet to which Azure Bastion should be deployed') param vnetName string = 'VNet' @description('IP prefix for available addresses in vnet address space') param vnetIpPrefix string = '10.0.0.0/16' @description('Specify whether to provision new vnet or deploy to existing vnet') @allowed([ 'new' 'existing' ]) param vnetNewOrExisting string = 'existing' @description('Bastion subnet IP prefix MUST be within vnet IP prefix address space') param bastionSubnetIpPrefix string = '10.0.1.0/26' @description('Name of Azure Bastion resource') param bastionHostName = 'VNet-bastion'
- 第 2 行:将
保存 bastion.bicep 文件。
使用 Azure CLI 或 Azure PowerShell 来部署 Bicep 文件:
az deployment group create --resource-group TestRG --template-file bastion.bicep
部署完成后,会显示一条指示部署成功的消息。
注意
虚拟网络中具有 Bastion 主机的虚拟机不需要公共 IP 地址。 Bastion 提供公共 IP,虚拟机使用专用 IP 在网络中进行通信。 可以从 Bastion 托管的虚拟网络的任何虚拟机中删除公共 IP。 有关详细信息,请参阅将公共 IP 地址与 Azure VM 取消关联。
查看已部署的资源
使用 Azure CLI、Azure PowerShell 或 Azure 门户来查看部署的资源。
az resource list --resource-group TestRG
连接到 VM
在门户中,搜索并选择“虚拟机”。
在“虚拟机”页上,选择 BackendVM1。
在“BackendVM1”页顶部,选择“连接”旁边的下拉箭头,然后选择“Bastion”。
在“Bastion”页面上,输入你为虚拟机创建的用户名和密码,然后选择“连接”。
VM 之间进行通信
从 BackendVM1 的桌面上,打开 PowerShell。
输入
ping BackendVM0
。 你会收到类似于以下消息的回复:PS C:\Users\BackendVM1> ping BackendVM0 Pinging BackendVM0.ovvzzdcazhbu5iczfvonhg2zrb.bx.internal.chinacloudapp.cn with 32 bytes of data Request timed out. Request timed out. Request timed out. Request timed out. Ping statistics for 10.0.0.5: Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),
由于它使用 Internet 控制消息协议(ICMP),因此执行 ping 操作失败。 默认情况下,不允许 ICMP 通过 Windows 防火墙。
要允许 ICMP 通过此 VM 上的 Windows 防火墙入站,请输入以下命令:
New-NetFirewallRule �DisplayName "Allow ICMPv4-In" �Protocol ICMPv4
关闭 Bastion 与 BackendVM1 的连接。
重复连接到 VM 中的步骤以连接到 BackendVM0。
在 BackendVM0 上的 PowerShell 中,输入
ping BackendVM1
。这一次,你会收到类似于以下消息的成功回复,因为你已允许 ICMP 通过 BackendVM1 上的防火墙。
PS C:\Users\BackendVM0> ping BackendVM1 Pinging BackendVM1.e5p2dibbrqtejhq04lqrusvd4g.bx.internal.chinacloudapp.cn [10.0.0.4] with 32 bytes of data: Reply from 10.0.0.4: bytes=32 time=2ms TTL=128 Reply from 10.0.0.4: bytes=32 time<1ms TTL=128 Reply from 10.0.0.4: bytes=32 time<1ms TTL=128 Reply from 10.0.0.4: bytes=32 time<1ms TTL=128 Ping statistics for 10.0.0.4: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 0ms, Maximum = 2ms, Average = 0ms
关闭 Bastion 与 BackendVM0 的连接。
清理资源
完成虚拟网络后,请使用 Azure CLI、Azure PowerShell 或 Azure 门户删除资源组及其所有资源:
az group delete --name TestRG
后续步骤
在本快速入门中,你创建了具有两个子网的虚拟网络,其中一个子网包含两个 VM,另一个子网用于 Bastion。 你部署了 Bastion,并使用它连接到了 VM 并在 VM 之间开始通信。 若要详细了解虚拟网络设置,请参阅创建、更改或删除虚拟网络。
VM 之间的专用通信在虚拟网络中不受限制。 若要详细了解如何在虚拟网络中配置各种类型的 VM 通信,请继续查看下一篇文章: