👏

(ER + hub) x2 - spoke 構成で spoke 折り返しを実現する

2022/08/18に公開

こんな感じの構成を検討する

Azure VMware Solution のネットワーク設計に関する考慮事項 の トランジット スポーク仮想ネットワーク トポロジ に載っている、こちらのアーキテクチャを参考にします。

vmware-solution-to-on-premises

こちらの構成を少し変更して、hub から ExpressRoute でつながった VNet 同士が spoke 折り返しで通信ができるような構成を考えます。

establish two VNets connected via ExpressRoute and multi-hub and spoke architecture

ポイントとしてはいくつかあります。

  • VNet peering が 2 つあるため、どちらかの Hub への VNet Peering でしか use remoteGateways の設定が使えない
    なお、ちなみに今回はどちらの peering にも使っていません
  • use remoteGateway の設定を使わないため、ExpressRoute Gateway が spoke の IP アドレス空間を BGP で経路広報しない
    そのため、Azure Route Server などで意図的に経路を流し込む必要があります
  • Azure Route Server がすべて AS65515 で動作するため、片方の hub にある ARS から受け取った経路をもう片方の hub にある ARS に広報するためには少し工夫がいる

インフラの作成

毎度のことながら Bicep でさくっと準備していきます。
1 時間くらいかかる気がします。

  • VNet x5
  • Route Table x1
  • [existing] ExpressRoute circuit x2
  • ExpressRoute Gateway x4
  • Connection (ExpressRoute) x4
  • Azure Bastion x4
  • Azure Route Server x2
  • Azure VM x5

あとはそれらに必要な NIC とか Public IP がいっぱい作られます。

main.bicep
main.bicep
param location01 string = 'eastasia'

param circuit01 object
param circuit02 object

param sshKeyRGName string

param isInitialDeploy bool = false
var useExisting = !isInitialDeploy

param publicKeyName string

resource public_key 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = {
  name: publicKeyName
  scope: resourceGroup(sshKeyRGName)
}

resource cct01 'Microsoft.Network/expressRouteCircuits@2022-01-01' existing = {
  name: circuit01.name
  scope: resourceGroup(circuit01.rgName)
}

resource cct02 'Microsoft.Network/expressRouteCircuits@2022-01-01' existing = {
  name: circuit02.name
  scope: resourceGroup(circuit02.rgName)
}

/* ****************************** hub00 ****************************** */

resource hub00 'Microsoft.Network/virtualNetworks@2022-01-01' = {
  name: 'vnet-hub00'
  location: location01
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'default'
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
      {
        name: 'AzureBastionSubnet'
        properties: {
          addressPrefix: '10.0.100.0/24'
        }
      }
      {
        name: 'GatewaySubnet'
        properties: {
          addressPrefix: '10.0.200.0/24'
        }
      }
      {
        name: 'RouteServerSubnet'
        properties: {
          addressPrefix: '10.0.210.0/24'
        }
      }
    ]
  }

  resource defaultsubnet 'subnets' existing = {
    name: 'default'
  }
}

var ergw00Name = 'ergw-hub00'
module ergw00 '../lib/ergw_single.bicep' = {
  name: ergw00Name
  params: {
    location: location01
    gatewayName: ergw00Name
    vnetName: hub00.name
    useExisting: useExisting
  }
}

var conn00Name = 'conn-hub00'
resource conn_hub00 'Microsoft.Network/connections@2022-01-01' = {
  name: conn00Name
  location: location01
  properties: {
    connectionType: 'ExpressRoute'
    virtualNetworkGateway1: {
      id: ergw00.outputs.ergwId
    }
    peer: {
      id: cct01.id
    }
  }
}

var bast00Name = 'bast-hub00'
module bast00 '../lib/bastion.bicep' = {
  name: bast00Name
  params: {
    location: location01
    bastionName: bast00Name
    vnetName: hub00.name
  }
}

var rs00Name = 'rs-hub00'
module rs00 '../lib/route-server.bicep' = {
  name: rs00Name
  params: {
    location: location01
    routeServerName: rs00Name
    vnetName: hub00.name
    bgpConnections: [
      {
        name: vm_spoke50.name
        ip: vm_spoke50.outputs.privateIP
        asn: '65001'
      }
    ]
    useExisting: useExisting
  }
}

var vm00Name = 'vm-hub00'
module vm_hub00 '../lib/ubuntu2004.bicep' = {
  name: vm00Name
  params: {
    location: location01
    keyData: public_key.properties.publicKey
    subnetId: hub00::defaultsubnet.id
    vmName: vm00Name
    enableIPForwarding: true
  }
}

/* ****************************** hub10 ****************************** */

resource hub10 'Microsoft.Network/virtualNetworks@2022-01-01' = {
  name: 'vnet-hub10'
  location: location01
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.10.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'default'
        properties: {
          addressPrefix: '10.10.0.0/24'
        }
      }
      {
        name: 'AzureBastionSubnet'
        properties: {
          addressPrefix: '10.10.100.0/24'
        }
      }
      {
        name: 'GatewaySubnet'
        properties: {
          addressPrefix: '10.10.200.0/24'
        }
      }
      {
        name: 'RouteServerSubnet'
        properties: {
          addressPrefix: '10.10.210.0/24'
        }
      }
    ]
  }

  resource defaultsubnet 'subnets' existing = {
    name: 'default'
  }
}

var ergw10Name = 'ergw-hub10'
module ergw10 '../lib/ergw_single.bicep' = {
  name: ergw10Name
  params: {
    location: location01
    gatewayName: ergw10Name
    vnetName: hub10.name
    useExisting: useExisting
  }
}

var conn10Name = 'conn-hub10'
resource conn_hub10 'Microsoft.Network/connections@2022-01-01' = {
  name: conn10Name
  location: location01
  properties: {
    connectionType: 'ExpressRoute'
    virtualNetworkGateway1: {
      id: ergw10.outputs.ergwId
    }
    peer: {
      id: cct02.id
    }
  }
}

var bast10Name = 'bast-hub10'
module bast10 '../lib/bastion.bicep' = {
  name: bast10Name
  params: {
    location: location01
    bastionName: bast10Name
    vnetName: hub10.name
  }
}

var rs01Name = 'rs-hub10'
module rs10 '../lib/route-server.bicep' = {
  name: rs01Name
  params: {
    location: location01
    routeServerName: rs01Name
    vnetName: hub10.name
    bgpConnections: [
      {
        name: vm_spoke50.name
        ip: vm_spoke50.outputs.privateIP
        asn: '65001'
      }
    ]
    useExisting: useExisting
  }
}

var vm10Name = 'vm-hub10'
module vm_hub10 '../lib/ubuntu2004.bicep' = {
  name: vm10Name
  params: {
    location: location01
    keyData: public_key.properties.publicKey
    subnetId: hub10::defaultsubnet.id
    vmName: vm10Name
    enableIPForwarding: true
  }
}

/* ****************************** spoke50 ****************************** */

resource spoke50 'Microsoft.Network/virtualNetworks@2022-01-01' = {
  name: 'vnet-spoke50'
  location: location01
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.50.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'default'
        properties: {
          addressPrefix: '10.50.0.0/24'
          routeTable: { id: rt_spoke50.id }
        }
      }
    ]
  }

  resource defaultsubnet 'subnets' existing = {
    name: 'default'
  }
}

resource rt_spoke50 'Microsoft.Network/routeTables@2022-01-01' = {
  name: 'rt-spoke50'
  location: location01
  properties: {
    routes: [
      {
        name: '10_100_0_0_16'
        properties: {
          addressPrefix: '10.100.0.0/16'
          nextHopIpAddress: vm_hub00.outputs.privateIP
          nextHopType: 'VirtualAppliance'
        }
      }
      {
        name: '10_200_0_0_16'
        properties: {
          addressPrefix: '10.200.0.0/16'
          nextHopIpAddress: vm_hub10.outputs.privateIP
          nextHopType: 'VirtualAppliance'
        }
      }
    ]
  }
}

module peering_hub0050 '../lib/vnet-peering.bicep' = {
  name: 'peering-hub00-spoke50'
  params: {
    vnet01Name: hub00.name
    vnet02Name: spoke50.name
  }
}

module peering_hub1050 '../lib/vnet-peering.bicep' = {
  name: 'peering-hub10-spoke50'
  params: {
    vnet01Name: hub10.name
    vnet02Name: spoke50.name
  }
}

var vm50Name = 'vm-spoke50'
module vm_spoke50 '../lib/ubuntu2004.bicep' = {
  name: vm50Name
  params: {
    location: location01
    keyData: public_key.properties.publicKey
    subnetId: spoke50::defaultsubnet.id
    vmName: vm50Name
    enableIPForwarding: true
  }
}

/* ****************************** hub100 ****************************** */

resource hub100 'Microsoft.Network/virtualNetworks@2022-01-01' = {
  name: 'vnet-hub100'
  location: location01
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.100.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'default'
        properties: {
          addressPrefix: '10.100.0.0/24'
        }
      }
      {
        name: 'AzureBastionSubnet'
        properties: {
          addressPrefix: '10.100.100.0/24'
        }
      }
      {
        name: 'GatewaySubnet'
        properties: {
          addressPrefix: '10.100.200.0/24'
        }
      }
    ]
  }

  resource defaultsubnet 'subnets' existing = {
    name: 'default'
  }
}

var ergw100Name = 'ergw-hub100'
module ergw100 '../lib/ergw_single.bicep' = {
  name: ergw100Name
  params: {
    location: location01
    gatewayName: ergw100Name
    vnetName: hub100.name
    useExisting: useExisting
  }
}

var conn100Name = 'conn-hub100'
resource conn_hub100 'Microsoft.Network/connections@2022-01-01' = {
  name: conn100Name
  location: location01
  properties: {
    connectionType: 'ExpressRoute'
    virtualNetworkGateway1: {
      id: ergw100.outputs.ergwId
    }
    peer: {
      id: cct01.id
    }
  }
}

var bast100Name = 'bast-hub100'
module bas1t00 '../lib/bastion.bicep' = {
  name: bast100Name
  params: {
    location: location01
    bastionName: bast100Name
    vnetName: hub100.name
  }
}

var vm100Name = 'vm-hub100'
module vm_hub100 '../lib/ubuntu2004.bicep' = {
  name: vm100Name
  params: {
    location: location01
    keyData: public_key.properties.publicKey
    subnetId: hub100::defaultsubnet.id
    vmName: vm100Name
    enableNetWatchExtention: true
  }
}

/* ****************************** hub200 ****************************** */

resource hub200 'Microsoft.Network/virtualNetworks@2022-01-01' = {
  name: 'vnet-hub200'
  location: location01
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.200.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'default'
        properties: {
          addressPrefix: '10.200.0.0/24'
        }
      }
      {
        name: 'AzureBastionSubnet'
        properties: {
          addressPrefix: '10.200.100.0/24'
        }
      }
      {
        name: 'GatewaySubnet'
        properties: {
          addressPrefix: '10.200.200.0/24'
        }
      }
    ]
  }

  resource defaultsubnet 'subnets' existing = {
    name: 'default'
  }
}

var ergw200Name = 'ergw-hub200'
module ergw200 '../lib/ergw_single.bicep' = {
  name: ergw200Name
  params: {
    location: location01
    gatewayName: ergw200Name
    vnetName: hub200.name
    useExisting: useExisting
  }
}

var conn200Name = 'conn-hub200'
resource conn_hub200 'Microsoft.Network/connections@2022-01-01' = {
  name: conn200Name
  location: location01
  properties: {
    connectionType: 'ExpressRoute'
    virtualNetworkGateway1: {
      id: ergw200.outputs.ergwId
    }
    peer: {
      id: cct01.id
    }
  }
}

var bast200Name = 'bast-hub200'
module bast200 '../lib/bastion.bicep' = {
  name: bast200Name
  params: {
    location: location01
    bastionName: bast200Name
    vnetName: hub200.name
  }
}

var vm200Name = 'vm-hub200'
module vm_hub200 '../lib/ubuntu2004.bicep' = {
  name: vm200Name
  params: {
    location: location01
    keyData: public_key.properties.publicKey
    subnetId: hub200::defaultsubnet.id
    vmName: vm200Name
    enableNetWatchExtention: true
  }
}

NVA の構成

簡単なインストール方法などはこちらを参照いただければと。

https://zenn.dev/skmkzyk/articles/azure-route-server-frrouting

んで、Frrouting の config は以下のような感じになりました。

vm-spoke50# show run
Building configuration...

Current configuration:
!
frr version 8.3
frr defaults traditional
hostname vm-spoke50
log syslog informational
no ipv6 forwarding
service integrated-vtysh-config
!
ip route 10.0.210.0/24 10.50.0.1
ip route 10.10.210.0/24 10.50.0.1
!
router bgp 65001
 neighbor 10.0.210.4 remote-as 65515
 neighbor 10.0.210.4 ebgp-multihop 255
 neighbor 10.0.210.5 remote-as 65515
 neighbor 10.0.210.5 ebgp-multihop 255
 neighbor 10.10.210.4 remote-as 65515
 neighbor 10.10.210.4 ebgp-multihop 255
 neighbor 10.10.210.5 remote-as 65515
 neighbor 10.10.210.5 ebgp-multihop 255
 !
 address-family ipv4 unicast
  network 10.50.0.0/24
  neighbor 10.0.210.4 soft-reconfiguration inbound
  neighbor 10.0.210.4 prefix-list rs-hub00 out
  neighbor 10.0.210.4 route-map rmap-bogon-asns in
  neighbor 10.0.210.4 route-map rmap-azure-asns out
  neighbor 10.0.210.5 soft-reconfiguration inbound
  neighbor 10.0.210.5 prefix-list rs-hub00 out
  neighbor 10.0.210.5 route-map rmap-bogon-asns in
  neighbor 10.0.210.5 route-map rmap-azure-asns out
  neighbor 10.10.210.4 soft-reconfiguration inbound
  neighbor 10.10.210.4 prefix-list rs-hub10 out
  neighbor 10.10.210.4 route-map rmap-bogon-asns in
  neighbor 10.10.210.4 route-map rmap-azure-asns out
  neighbor 10.10.210.5 soft-reconfiguration inbound
  neighbor 10.10.210.5 prefix-list rs-hub10 out
  neighbor 10.10.210.5 route-map rmap-bogon-asns in
  neighbor 10.10.210.5 route-map rmap-azure-asns out
 exit-address-family
exit
!
ip prefix-list rs-hub00 seq 5 deny 10.0.0.0/16
ip prefix-list rs-hub00 seq 10 deny 10.100.0.0/16
ip prefix-list rs-hub00 seq 15 permit any
ip prefix-list rs-hub10 seq 5 deny 10.10.0.0/16
ip prefix-list rs-hub10 seq 10 deny 10.200.0.0/16
ip prefix-list rs-hub10 seq 15 permit any
!
bgp as-path access-list azure-asns seq 5 permit _65515_
bgp as-path access-list bogon-asns seq 5 permit _0_
bgp as-path access-list bogon-asns seq 10 permit _23456_
bgp as-path access-list bogon-asns seq 15 permit _1310[0-6][0-9]_|_13107[0-1]_
bgp as-path access-list bogon-asns seq 20 deny _65515_
bgp as-path access-list bogon-asns seq 25 permit ^65
!
route-map rmap-bogon-asns deny 5
 match as-path bogon-asns
exit
!
route-map rmap-bogon-asns permit 10
 set as-path replace any
exit
!
route-map rmap-azure-asns deny 5
 match as-path azure-asns
exit
!
route-map rmap-azure-asns permit 10
exit
!
end

簡単な解説です。

  • ip route 10.0.210.0/24 10.50.0.1ip route 10.10.210.0/24 10.50.0.1
    hub にある ARS が connected にはいないため、static route を入れておきます
  • neighbor 10.0.210.4 remote-as 65515neighbor 10.0.210.4 ebgp-multihop 255
    BGP の peer を指定する config と、connected な peer ではないため ebgp-multihop を入れます
  • network 10.50.0.0/24
    connected である 10.50.0.0/24 を BGP に乗せるための設定です
    これがあることで、10.50.0.0/16 全体ではなく、NVA がある 10.50.0.0/24 のみが経路広報されます
  • neighbor 10.0.210.4 soft-reconfiguration inbound
    show ip bgp nei x.x.x.x received-routes を叩くための設定です
  • neighbor 10.0.210.4 prefix-list rs-hub00 out
    片方の ARS から受け取った経路をもう片方の ARS に経路広報しますが、不要なものを捨てるための prefix-list です
    rs-hub00 向けと rs-hub10 向けで 2 つあります
  • neighbor 10.0.210.4 route-map rmap-bogon-asns in
    こちらは前の記事と異なり、受け取った経路の AS_PATH を書き換えるようにしています
    実際の書き換え個所は route-map rmap-bogon-asns permit 10 です
  • neighbor 10.0.210.4 route-map rmap-azure-asns out
    こちらは前の記事と変わっていません
  • route-map rmap-bogon-asns permit 10set as-path replace any
    ある ARS から別の ARS への経路広報は、BGP 目線では AS65515 からもらった経路を AS65515 に広報しなおすことになるため、規定では経路広報してくれません
    route-map rmap-bogon-asns deny 5 で deny されなかった経路は受け取ることになりますが、それの AS_PATH をすべて自 ASN で置き換えてしまっています
    これであってるかわからんのですが動いてるので許して。。

動作確認 (BGP)

  • show ip route

multi-path を有効化していないため、一応片方に寄っています。
ARS にもしメンテナンスの概念があり (たぶんあるんだとは思うんですが)、BGP の peer が一時的に切れてもまぁ特に問題はないと思います。

vm-spoke50# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

K>* 0.0.0.0/0 [0/100] via 10.50.0.1, eth0, src 10.50.0.4, 03:31:00
B>  10.0.0.0/16 [20/0] via 10.0.210.4 (recursive), weight 1, 02:56:30
  *                      via 10.50.0.1, eth0, weight 1, 02:56:30
                       via 10.0.210.5 (recursive), weight 1, 02:56:30
                         via 10.50.0.1, eth0, weight 1, 02:56:30
S>* 10.0.210.0/24 [1/0] via 10.50.0.1, eth0, weight 1, 03:30:13
B>  10.10.0.0/16 [20/0] via 10.10.210.4 (recursive), weight 1, 02:56:30
  *                       via 10.50.0.1, eth0, weight 1, 02:56:30
                        via 10.10.210.5 (recursive), weight 1, 02:56:30
                          via 10.50.0.1, eth0, weight 1, 02:56:30
S>* 10.10.210.0/24 [1/0] via 10.50.0.1, eth0, weight 1, 03:30:03
C>* 10.50.0.0/24 is directly connected, eth0, 03:31:00
B>  10.100.0.0/16 [20/0] via 10.0.210.4 (recursive), weight 1, 02:56:30
  *                        via 10.50.0.1, eth0, weight 1, 02:56:30
                         via 10.0.210.5 (recursive), weight 1, 02:56:30
                           via 10.50.0.1, eth0, weight 1, 02:56:30
B>  10.200.0.0/16 [20/0] via 10.10.210.4 (recursive), weight 1, 02:56:30
  *                        via 10.50.0.1, eth0, weight 1, 02:56:30
                         via 10.10.210.5 (recursive), weight 1, 02:56:30
                           via 10.50.0.1, eth0, weight 1, 02:56:30
K>* 168.63.129.16/32 [0/100] via 10.50.0.1, eth0, src 10.50.0.4, 03:31:00
K>* 169.254.169.254/32 [0/100] via 10.50.0.1, eth0, src 10.50.0.4, 03:31:00
  • show ip bgp
vm-spoke50# show ip bgp
BGP table version is 9, local router ID is 10.50.0.4, vrf id 0
Default local pref 100, local AS 65001
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
*= 10.0.0.0/16      10.0.210.5                             0 65001 i
*>                  10.0.210.4                             0 65001 i
*= 10.10.0.0/16     10.10.210.5                            0 65001 i
*>                  10.10.210.4                            0 65001 i
*> 10.50.0.0/24     0.0.0.0                  0         32768 i
*= 10.100.0.0/16    10.0.210.5                             0 65001 65001 65001 i
*>                  10.0.210.4                             0 65001 65001 65001 i
*= 10.200.0.0/16    10.10.210.5                            0 65001 65001 65001 i
*>                  10.10.210.4                            0 65001 65001 65001 i

Displayed  5 routes and 9 total paths
  • show ip bgp nei 10.0.210.4 received-routes

ここでは先ほどの概要図における、中央上の VNet にある ARS との BGP peer について見ていきます。
ARS から ARS のある VNet のアドレス空間および ExpressRoute でつながった VNet のアドレス空間が聞こえてきています。

vm-spoke50# show ip bgp nei 10.0.210.4 received-routes
BGP table version is 9, local router ID is 10.50.0.4, vrf id 0
Default local pref 100, local AS 65001
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
*> 10.0.0.0/16      10.0.210.4                             0 65001 i
*> 10.100.0.0/16    10.0.210.4                             0 65001 65001 65001 i

Total number of prefixes 2
  • show ip bgp nei 10.0.210.4 advertised-routes

この peer から受け取っている 10.0.0.0/16 と 10.100.0.0/16 は経路広報しないようになっています。

vm-spoke50# show ip bgp nei 10.0.210.4 advertised-routes
BGP table version is 9, local router ID is 10.50.0.4, vrf id 0
Default local pref 100, local AS 65001
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
*> 10.10.0.0/16     0.0.0.0                                0 65001 i
*> 10.50.0.0/24     0.0.0.0                  0         32768 i
*> 10.200.0.0/16    0.0.0.0                                0 65001 65001 65001 i

Total number of prefixes 3

動作確認 (Effective Route)

ここでは、まず概要図における左上にあった VNet 内の Azure VM について、Effective Route を確認します。
左上の VNet にもかかわらず、中央下の Hub VNet および左下の VNet のアドレス空間が認識できています。
加えて、10.50.0.0/24 も認識されています。

Source State Address Prefixes Next Hop Type Next Hop IP Address User Defined Route Name
Default Active 10.100.0.0/16 Virtual network - -
Virtual network gateway Active 10.0.0.0/16 Virtual network gateway 10.2.146.76 -
Virtual network gateway Active 10.0.0.0/16 Virtual network gateway 10.2.146.77 -
Virtual network gateway Active 10.10.0.0/16 Virtual network gateway 10.2.146.76 -
Virtual network gateway Active 10.10.0.0/16 Virtual network gateway 10.2.146.77 -
Virtual network gateway Active 10.50.0.0/24 Virtual network gateway 10.2.146.76 -
Virtual network gateway Active 10.50.0.0/24 Virtual network gateway 10.2.146.77 -
Virtual network gateway Active 10.200.0.0/16 Virtual network gateway 10.2.146.76 -
Virtual network gateway Active 10.200.0.0/16 Virtual network gateway 10.2.146.77 -

で、ここまではよかったんですが、問題は右の VNet の Azure VM における Effective Route でした。
Source が User となっているものが UDR なのですが、これがないと 10.100.0.0/16 および 10.200.0.0/16 への経路がない、という状況になります。
かつその UDR で指定する Next Hop Type として Virtual network gateway が使えないため、このためだけに中央上下の VNet に NVA 代わりの Azure VM を立て、それを介して通信させることになっています。

Source State Address Prefixes Next Hop Type Next Hop IP Address User Defined Route Name
Default Active 10.50.0.0/16 Virtual network - -
Default Active 10.0.0.0/16 VNet peering - -
Default Active 10.10.0.0/16 VNet peering - -
User Active 10.100.0.0/16 Virtual appliance 10.0.0.4 10_100_0_0_16
User Active 10.200.0.0/16 Virtual appliance 10.10.0.4 10_200_0_0_16

動作確認 (Ethr)

Microsoft/Ethr を使って TCP レベルでの traceroute を行い通信確認をとります。
通信確認をしているのは左上の VNet から左下の VNet 宛で、すべての VNet を経由して通信しているはずです。
latency が長いのは諸事情によるためあまり気にしなくてよいですが、22/tcp での通信が可能なことが確認できました。

# ./ethr -c 10.200.0.4 -p tcp --port 22 -t tr

Ethr: Comprehensive Network Performance Measurement Tool (Version: v1.0.0)
Maintainer: Pankaj Garg (ipankajg @ LinkedIn | GitHub | Gmail | Twitter)

Using destination: 10.200.0.4, ip: 10.200.0.4, port: 22
Tracing route to 10.200.0.4 over 30 hops:
 1.|--???
 2.|--10.50.0.4 []                                                           111.432ms
 3.|--10.10.0.4 []                                                           112.505ms
 4.|--???
 5.|--10.200.0.4 []                                                          220.453ms
Ethr done, measurement complete.

経路上にいる 10.10.0.4 というのが追加の NVA で、これをどうにか外せないかこれから検討します。

まとめ

とりあえず通信ができる状態まではこぎつけたんですがどうも納得がいかないので何とかしたい。

Microsoft (有志)

Discussion