ハブスポーク構成でのハブ間・スポーク間の疎通
はじめに
Azure に限らず、ネットワークモデルとして良く取られるものとして、"Hub & Spoke" ネットワークがあります。
これは、あたかもタイヤのハブ (軸) とスポーク (軸から延びる腕の部分) があって、ハブ ネットワークにスポーク ネットワークから共有されるサービを集約するといったネットワーク形態です。
この記事では、Hub & Spoke ネットワーク構成を取った際、良くトピックとして挙げられるスポーク ネットワーク間の疎通について、Azure での実現方法を確認していきます。
なお、Azure におけるスポーク間の通信については、こちら に詳しい説明があります。
スポーク ネットワーク間通信
スポーク ネットワークは、ワークロード毎に分けるように作ることが多く、そのため、スポーク ネットワークに閉じた通信が主なものとなります。
一方、ワークロード間など特定の通信が必要になるケースがあり、その場合においてスポーク ネットワーク間の通信を設計します。
なお、Azure においては Hub & Spoke ネットワークの実現方法として、以下の2通りの方法がありますが、
Virtual WAN を利用する場合、構成が楽な反面、きめ細かな制御ができないことがありますので、
2の方法で構成した場合の、スポーク間の疎通について実現方法を確認していきます。
構成
東日本、西日本でそれぞれ、Hub & Spoke 構成を取った場合の構成をしており、東西のハブ ネットワークを経由して接続されています。
ただし、仮想ネットワーク ピアリング (VNet ピアリング) は 推移的なルーティングをサポートしていない ため、隣り合っていない VNet へのアクセスについては、
明示的なルーティングの設定が必要になります。
また、下部の運用 VNet は構成に必須ではなく、各スポーク ネットワークにあるワークロードの保守を行うためのものです。
今回は、仮想マシン VM-OPS から VM-01 に入り、疎通を確認しています。
① のネットワーク疎通について
仮想マシン VM-01
から仮想マシン VM-02
についての疎通を考えてみましょう。
まず、当初のネットワークの構成から、それぞれが所属する スポーク VNet #1 およびスポーク VNet #2 において、
ハブ (Azure Firewall) に対するユーザー定義ルートが設定されています。これによって、双方の VNet から通信は、ハブ VNet #1 の Azure Firewall を経由します。
ただし、上記にあったように、推移的なルーティングはサポートされていないため、
スポーク VNet #1 -> ハブ VNet #1 -> スポーク VNet #2 という通信は成り立ちません。
そこで、Azure Firewall ルールに以下のようなネットワーク ルールを設定することでその疎通が可能となります
(許可するプロトコルやポートは要件に合わせて要調整)。
設定項目 | ルール1 | ルール2 |
---|---|---|
規則コレクションの種類 | 許可 | 許可 |
ソースの種類 | IP アドレス | IP アドレス |
ソース IP アドレス | 10.1.0.0/16 | 10.2.0.0/16 |
宛先の種類 | IP addresses | IP addresses |
宛先 IP アドレス | 10.2.0.0/16 | 10.1.0.0/16 |
プロトコル | 任意 | 任意 |
ポート | * | * |
設定後、疎通できることを確認します。
② のネットワーク疎通について
次に、仮想マシン VM-01
から仮想マシン VM-03
についての疎通を考えてみましょう (仮想マシン VM-04
も同じ考え方)。
先の場合と同様に、Azure Firewall のネットワーク ルールに対して、
スポーク VNet #3 のルールを設定します (カンマ区切りで複数の IP アドレスを指定することができます)。
設定項目 | ルール3 | ルール4 |
---|---|---|
規則コレクションの種類 | 許可 | 許可 |
ソースの種類 | IP アドレス | IP アドレス |
ソース IP アドレス | 10.1.0.0/16,10.2.0.0/16 | 192.168.3.0/24,192.168.4.0/24 |
宛先の種類 | IP addresses | IP addresses |
宛先 IP アドレス | 192.168.3.0/24,192.168.4.0/24 | 10.1.0.0/16,10.2.0.0/16 |
プロトコル | 任意 | 任意 |
ポート | * | * |
ただ、このままでは Azure Firewall からインターネットへの疎通が試行されてしまうため、
スポーク VNet #3 とのルーティングを管理するハブ VNet #2 の Azure Fireweall (azfw2) に振り向けなくてななりません。
そのため、azfw1
がある AzureFirewallSubnet に対して、以下のユーザー定義ルートを関連付けます。
これによって、スポーク VNet #3 およびスポーク VNet #4 へのトラフィックが azfw2
に振り向けられます。
また、戻りの通信のため、azfw2
のある AzureFirewallSubnet に対してもユーザー定義ルートが必要となります。
それはこちらになります。
最後に、 azfw2
の Azure Firewall ルールに対して、スポーク VNet #1 およびスポーク VNet #2 のルールを設定します。
設定項目 | ルール5 | ルール6 |
---|---|---|
規則コレクションの種類 | 許可 | 許可 |
ソースの種類 | IP アドレス | IP アドレス |
ソース IP アドレス | 10.1.0.0/16,10.2.0.0/16 | 192.168.3.0/24,192.168.4.0/24 |
宛先の種類 | IP addresses | IP addresses |
宛先 IP アドレス | 192.168.3.0/24,192.168.4.0/24 | 10.1.0.0/16,10.2.0.0/16 |
プロトコル | 任意 | 任意 |
ポート | * | * |
これで、スポーク VNet #1 からスポーク VNet #3 への疎通が可能となります。
まとめ
Hub & Spoke 構成において、Azure Firewall を使ってスポーク ネットワーク間の疎通を実現するための方法について確認しました。
これ以外にもスポーク ネットワーク間の必要な疎通が特定されているのであれば、そのスポーク ネットワーク間で VNet ピアリングを行う方が、
Azure Firewall を経由するよりも設定、性能面、コスト面でも最善かもしれませんので、併せて検討してみてください。
参考情報
- Azure Firewall を使用してマルチ ハブ アンド スポーク トポロジをルーティングする
- 環境を作成する Bicep テンプレートのサンプル
サンプル Bicep テンプレート
param location1 string = 'japaneast'
param location2 string = 'japanwest'
param hubVnetName1 string = 'hubvnet1'
param hubVnetName2 string = 'hubvnet2'
param spokeVnetName1 string = 'spokevnet1'
param spokeVnetName2 string = 'spokevnet2'
param spokeVnetName3 string = 'spokevnet3'
param spokeVnetName4 string = 'spokevnet4'
param azfirewallName1 string = 'azfw1'
param azfirewallName2 string = 'azfw2'
@secure()
param adminUserName string
@secure()
param adminPassword string
// Define the hub virtual network #1
resource hubvnet1 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: hubVnetName1
location: location1
properties: {
addressSpace: {
addressPrefixes: [
'10.0.0.0/16'
]
}
subnets: [
{
name: 'AzureFirewallSubnet'
properties: {
addressPrefix: '10.0.0.0/26'
}
}
]
}
tags: {
displayName: 'hubvnet1'
}
}
// Define the subnet for the Azure Firewall in the hub virtual network #1
resource hubSubnet1 'Microsoft.Network/virtualNetworks/subnets@2022-05-01' = {
parent: hubvnet1
name: 'AzureFirewallSubnet'
properties: {
addressPrefix: '10.0.0.0/26'
routeTable: {
id: hubRouteTable1.id
}
}
}
// Define the hub virtual network #2
resource hubvnet2 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: hubVnetName2
location: location2
properties: {
addressSpace: {
addressPrefixes: [
'192.168.0.0/24'
]
}
subnets: [
{
name: 'AzureFirewallSubnet'
properties: {
addressPrefix: '192.168.0.0/26'
}
}
]
}
tags: {
displayName: 'hubvnet2'
}
}
// Define the subnet for the Azure Firewall in the hub virtual network #2
resource hubSubnet2 'Microsoft.Network/virtualNetworks/subnets@2022-05-01' = {
parent: hubvnet2
name: 'AzureFirewallSubnet'
properties: {
addressPrefix: '192.168.0.0/26'
routeTable: {
id: hubRouteTable2.id
}
}
}
// Define the spoke virtual network #1
resource spokevnet1 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: spokeVnetName1
location: location1
properties: {
addressSpace: {
addressPrefixes: [
'10.1.0.0/16'
]
}
subnets: [
{
name: 'default'
properties: {
addressPrefix: '10.1.0.0/24'
routeTable: {
id: spokeRouteTable1.id
}
}
}
]
}
tags: {
displayName: 'spokevnet1'
}
}
// Define the spoke virtual network #2
resource spokevnet2 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: spokeVnetName2
location: location1
properties: {
addressSpace: {
addressPrefixes: [
'10.2.0.0/16'
]
}
subnets: [
{
name: 'default'
properties: {
addressPrefix: '10.2.0.0/24'
routeTable: {
id: spokeRouteTable1.id
}
}
}
]
}
tags: {
displayName: 'spokevnet2'
}
}
// Define the spoke virtual network #3
resource spokevnet3 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: spokeVnetName3
location: location2
properties: {
addressSpace: {
addressPrefixes: [
'192.168.3.0/24'
]
}
subnets: [
{
name: 'default'
properties: {
addressPrefix: '192.168.3.0/24'
routeTable: {
id: spokeRouteTable2.id
}
}
}
]
}
tags: {
displayName: 'spokevnet3'
}
}
// Define the spoke virtual network #4
resource spokevnet4 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: spokeVnetName4
location: location2
properties: {
addressSpace: {
addressPrefixes: [
'192.168.4.0/24'
]
}
subnets: [
{
name: 'default'
properties: {
addressPrefix: '192.168.4.0/24'
routeTable: {
id: spokeRouteTable2.id
}
}
}
]
}
tags: {
displayName: 'spokevnet4'
}
}
// Define the OPS virtual network
resource opsvnet 'Microsoft.Network/virtualNetworks@2022-05-01' = {
name: 'opsvnet'
location: location1
properties: {
addressSpace: {
addressPrefixes: [
'172.1.0.0/24'
]
}
subnets: [
{
name: 'default'
properties: {
addressPrefix: '172.1.0.0/24'
}
}
]
}
tags: {
displayName: 'opsvnet'
}
}
// Define the hub-to-spoke virtual network peering #1
resource hubToSpoke1 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: hubvnet1
name: 'hubToSpoke1'
properties: {
remoteVirtualNetwork: {
id: spokevnet1.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the spoke virtual network #1-to-hub virtual network peering
resource spokeToHub1 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet1
name: 'spokeToHub1'
properties: {
remoteVirtualNetwork: {
id: hubvnet1.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the hub-to-spoke virtual network peering #2
resource hubToSpoke2 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: hubvnet1
name: 'hubToSpoke2'
properties: {
remoteVirtualNetwork: {
id: spokevnet2.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the spoke virtual network #2-to-hub virtual network peering
resource spokeToHub2 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet2
name: 'spokeToHub2'
properties: {
remoteVirtualNetwork: {
id: hubvnet1.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the hub-to-spoke virtual network peering #3
resource hubToSpoke3 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: hubvnet2
name: 'hubToSpoke3'
properties: {
remoteVirtualNetwork: {
id: spokevnet3.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the spoke virtual network #3-to-hub virtual network peering
resource spokeToHub3 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet3
name: 'spokeToHub3'
properties: {
remoteVirtualNetwork: {
id: hubvnet2.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the hub-to-spoke virtual network peering #4
resource hubToSpoke4 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: hubvnet2
name: 'hubToSpoke4'
properties: {
remoteVirtualNetwork: {
id: spokevnet4.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the spoke virtual network #4-to-hub virtual network peering
resource spokeToHub4 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet4
name: 'spokeToHub4'
properties: {
remoteVirtualNetwork: {
id: hubvnet2.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the hub-to-hub virtual network peering1
resource hubToHub1 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: hubvnet1
name: 'hubToHub1'
properties: {
remoteVirtualNetwork: {
id: hubvnet2.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the hub-to-hub virtual network peering2
resource hubToHub2 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: hubvnet2
name: 'hubToHub2'
properties: {
remoteVirtualNetwork: {
id: hubvnet1.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the ops-to-spoke virtual network peering #1
resource opsToSpoke1 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: opsvnet
name: 'opsToSpoke1'
properties: {
remoteVirtualNetwork: {
id: spokevnet1.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the spoke virtual network #1-to-ops virtual network peering
resource spokeToOps1 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet1
name: 'spokeToOps1'
properties: {
remoteVirtualNetwork: {
id: opsvnet.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the ops-to-spoke virtual network peering #2
resource opsToSpoke2 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: opsvnet
name: 'opsToSpoke2'
properties: {
remoteVirtualNetwork: {
id: spokevnet2.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Deifne the spoke virtual network #2-to-ops virtual network peering
resource spokeToOps2 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet2
name: 'spokeToOps2'
properties: {
remoteVirtualNetwork: {
id: opsvnet.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the ops-to-spoke virtual network peering #3
resource opsToSpoke3 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: opsvnet
name: 'opsToSpoke3'
properties: {
remoteVirtualNetwork: {
id: spokevnet3.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the spoke virtual network #3-to-ops virtual network peering
resource spokeToOps3 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet3
name: 'spokeToOps3'
properties: {
remoteVirtualNetwork: {
id: opsvnet.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the ops-to-spoke virtual network peering #4
resource opsToSpoke4 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: opsvnet
name: 'opsToSpoke4'
properties: {
remoteVirtualNetwork: {
id: spokevnet4.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the spoke virtual network #4-to-ops virtual network peering
resource spokeToOps4 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2022-05-01' = {
parent: spokevnet4
name: 'spokeToOps4'
properties: {
remoteVirtualNetwork: {
id: opsvnet.id
}
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
}
}
// Define the public IP address for the Azure Firewall in the hub virtual network #1
resource azurePublicIp1 'Microsoft.Network/publicIPAddresses@2022-05-01' = {
name: 'azfwPublicIp1'
location: location1
sku: {
name: 'Standard'
}
properties: {
publicIPAllocationMethod: 'Static'
}
tags: {
displayName: 'azfwPublicIp1'
}
}
// Define the Azure Firewall in the hub virtual network #1
resource azureFirewall1 'Microsoft.Network/azureFirewalls@2022-05-01' = {
name: azfirewallName1
location: location1
properties: {
ipConfigurations: [
{
name: 'azureFirewallIpConfiguration'
properties: {
subnet: {
id: '${hubvnet1.id}/subnets/AzureFirewallSubnet'
}
publicIPAddress: {
id: azurePublicIp1.id
}
}
}
]
networkRuleCollections: [
{
name: 'hubspoketransition'
properties: {
action: {
type: 'Allow'
}
priority: 100
rules: [
{
name: 'towest'
description: 'Allow outgoing traffic from Japan East.'
sourceAddresses: [
'10.1.0.0/16'
'10.2.0.0/16'
]
destinationAddresses: [
'192.168.3.0/24'
'192.168.4.0/24'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
{
name: 'fromwest'
description: 'Allow incoming traffic from Japan West.'
sourceAddresses: [
'192.168.3.0/24'
'192.168.4.0/24'
]
destinationAddresses: [
'10.1.0.0/16'
'10.2.0.0/16'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
{
name: 'spoketospoke1'
description: 'Allow inter-spoke communication.'
sourceAddresses: [
'10.1.0.0/16'
]
destinationAddresses: [
'10.2.0.0/16'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
{
name: 'spoketospoke2'
description: 'Allow inter-spoke communication.'
sourceAddresses: [
'10.2.0.0/16'
]
destinationAddresses: [
'10.1.0.0/16'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
]
}
}
]
}
}
// Deifne the public IP address for the Azure Firewall in the hub virtual network #2
resource azurePublicIp2 'Microsoft.Network/publicIPAddresses@2022-05-01' = {
name: 'azfwPublicIp2'
location: location2
sku: {
name: 'Standard'
}
properties: {
publicIPAllocationMethod: 'Static'
}
tags: {
displayName: 'azfwPublicIp2'
}
}
// Define the Azure Firewall in the hub virtual network #2
resource azureFirewall2 'Microsoft.Network/azureFirewalls@2022-05-01' = {
name: azfirewallName2
location: location2
properties: {
ipConfigurations: [
{
name: 'azureFirewallIpConfiguration'
properties: {
subnet: {
id: '${hubvnet2.id}/subnets/AzureFirewallSubnet'
}
publicIPAddress: {
id: azurePublicIp2.id
}
}
}
]
networkRuleCollections: [
{
name: 'hubspoketransition'
properties: {
action: {
type: 'Allow'
}
priority: 100
rules: [
{
name: 'toeast'
description: 'Allow incoming traffic from Japan West.'
sourceAddresses: [
'192.168.3.0/24'
'192.168.4.0/24'
]
destinationAddresses: [
'10.1.0.0/16'
'10.2.0.0/16'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
{
name: 'fromeast'
description: 'Allow outgoing traffic from Japan East.'
sourceAddresses: [
'10.1.0.0/16'
'10.2.0.0/16'
]
destinationAddresses: [
'192.168.3.0/24'
'192.168.4.0/24'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
{
name: 'spoketospoke1'
description: 'Allow inter-spoke communication.'
sourceAddresses: [
'192.168.3.0/24'
]
destinationAddresses: [
'192.168.4.0/24'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
{
name: 'spoketospoke2'
description: 'Allow inter-spoke communication.'
sourceAddresses: [
'192.168.4.0/24'
]
destinationAddresses: [
'192.168.3.0/24'
]
destinationPorts: [
'*'
]
protocols: [
'Any'
]
}
]
}
}
]
}
}
// Define the route table for the hub virtual network #1
resource hubRouteTable1 'Microsoft.Network/routeTables@2022-05-01' = {
name: 'hubRouteTable1'
location: location1
properties: {
disableBgpRoutePropagation: false
routes: [
{
name: 'hubToInternet'
properties: {
addressPrefix: '0.0.0.0/0'
nextHopType: 'Internet'
}
}
{
name: 'toSpokeVnet3'
properties: {
addressPrefix: '192.168.3.0/24'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: azureFirewall2.properties.ipConfigurations[0].properties.privateIPAddress
}
}
{
name: 'toSpokeVnet4'
properties: {
addressPrefix: '192.168.4.0/24'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: azureFirewall2.properties.ipConfigurations[0].properties.privateIPAddress
}
}
]
}
tags: {
displayName: 'hubRouteTable1'
}
}
// Define the route table for the hub virtual network #2
resource hubRouteTable2 'Microsoft.Network/routeTables@2022-05-01' = {
name: 'hubRouteTable2'
location: location2
properties: {
disableBgpRoutePropagation: false
routes: [
{
name: 'hubTointernet'
properties: {
addressPrefix: '0.0.0.0/0'
nextHopType: 'Internet'
}
}
{
name: 'toSpokeVnet1'
properties: {
addressPrefix: '10.1.0.0/24'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: azureFirewall1.properties.ipConfigurations[0].properties.privateIPAddress
}
}
{
name: 'toSpokeVnet2'
properties: {
addressPrefix: '10.2.0.0/24'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: azureFirewall1.properties.ipConfigurations[0].properties.privateIPAddress
}
}
]
}
tags: {
displayName: 'hubRouteTable2'
}
}
// Define the route table toward Azure Fireweall #1
resource spokeRouteTable1 'Microsoft.Network/routeTables@2022-05-01' = {
name: 'spokeRouteTable1'
location: location1
properties: {
disableBgpRoutePropagation: false
routes: [
{
name: 'toHubVnet1'
properties: {
addressPrefix: '0.0.0.0/0'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: azureFirewall1.properties.ipConfigurations[0].properties.privateIPAddress
}
}
]
}
tags: {
displayName: 'spokeRouteTable1'
}
}
// Define the routae table toward Azure Firewall #2
resource spokeRouteTable2 'Microsoft.Network/routeTables@2022-05-01' = {
name: 'spokeRouteTable2'
location: location2
properties: {
disableBgpRoutePropagation: false
routes: [
{
name: 'toHubVnet2'
properties: {
addressPrefix: '0.0.0.0/0'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: azureFirewall2.properties.ipConfigurations[0].properties.privateIPAddress
}
}
]
}
tags: {
displayName: 'spokeRouteTable2'
}
}
// Define the NIC for vm01
resource vmnic01 'Microsoft.Network/networkInterfaces@2022-09-01' = {
name: 'vmnic01'
location: location1
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: {
id: spokevnet1.properties.subnets[0].id
}
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
tags: {
displayName: 'vmnic01'
}
}
// Define the NIC for vm02
resource vmnic02 'Microsoft.Network/networkInterfaces@2022-09-01' = {
name: 'vmnic02'
location: location1
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: {
id: spokevnet2.properties.subnets[0].id
}
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
tags: {
displayName: 'vmnic02'
}
}
// Define the NIC for vm03
resource vmnic03 'Microsoft.Network/networkInterfaces@2022-09-01' = {
name: 'vmnic03'
location: location2
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: {
id: spokevnet3.properties.subnets[0].id
}
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
tags: {
displayName: 'vmnic03'
}
}
// Define the NIC for opvm
resource opvmnic 'Microsoft.Network/networkInterfaces@2022-09-01' = {
name: 'opvmnic'
location: location1
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: {
id: opsvnet.properties.subnets[0].id
}
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
tags: {
displayName: 'vmnic04'
}
}
// Define vm01
resource vm01 'Microsoft.Compute/virtualMachines@2022-03-01' = {
name: 'vm01'
location: location1
properties: {
hardwareProfile: {
vmSize: 'Standard_D2as_v4'
}
osProfile: {
computerName: 'vm01'
adminUsername: adminUserName
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-confidential-vm-jammy'
sku: '22_04-lts-cvm'
version: 'latest'
}
osDisk: {
name: 'osdisk01'
caching: 'ReadWrite'
createOption: 'FromImage'
}
}
networkProfile: {
networkInterfaces: [
{
id: vmnic01.id
}
]
}
}
}
// Define vm02
resource vm02 'Microsoft.Compute/virtualMachines@2022-03-01' = {
name: 'vm02'
location: location1
properties: {
hardwareProfile: {
vmSize: 'Standard_D2as_v4'
}
osProfile: {
computerName: 'vm02'
adminUsername: adminUserName
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-confidential-vm-jammy'
sku: '22_04-lts-cvm'
version: 'latest'
}
osDisk: {
name: 'osdisk02'
caching: 'ReadWrite'
createOption: 'FromImage'
}
}
networkProfile: {
networkInterfaces: [
{
id: vmnic02.id
}
]
}
}
}
// Define vm03
resource vm03 'Microsoft.Compute/virtualMachines@2022-03-01' = {
name: 'vm03'
location: location2
properties: {
hardwareProfile: {
vmSize: 'Standard_D2as_v4'
}
osProfile: {
computerName: 'vm03'
adminUsername: adminUserName
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-confidential-vm-jammy'
sku: '22_04-lts-cvm'
version: 'latest'
}
osDisk: {
name: 'osdisk03'
caching: 'ReadWrite'
createOption: 'FromImage'
}
}
networkProfile: {
networkInterfaces: [
{
id: vmnic03.id
}
]
}
}
}
// Define opsvm
resource opsvm 'Microsoft.Compute/virtualMachines@2022-03-01' = {
name: 'opsvm'
location: location1
properties: {
hardwareProfile: {
vmSize: 'Standard_D2as_v4'
}
osProfile: {
computerName: 'opsvm'
adminUsername: adminUserName
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-confidential-vm-jammy'
sku: '22_04-lts-cvm'
version: 'latest'
}
osDisk: {
name: 'osdisk04'
caching: 'ReadWrite'
createOption: 'FromImage'
}
}
networkProfile: {
networkInterfaces: [
{
id: opvmnic.id
}
]
}
}
}
Discussion