Deploy VirtualNetworkRouter in Cloud-Native Contrail Networking
SUMMARY Cloud-Native Contrail® Networking™ supports the
VirtualNetworkRouter (VNR) construct. This construct provides connectivity
between VirtualNetworks.
VirtualNetworkRouter Overview
Typically, VirtualNetwork traffic is isolated to maintain tenant
separation. In Cloud-Native Contrail Networking, VirtualNetworkRouter (VNR)
performs route leaking. Route leaking establishes connectivity between
VirtualNetworks by importing routing instances (RI) and the routing
tables associated with these instances. As a result, devices on one routing table can access
resources from devices on another routing table.
The VNR provides connectivity for the following two common network models:
-
Mesh: Pods in all connected
VirtualNetworkscommunicate with each other. -
Hub-spoke:
VirtualNetworksconnect to two different VNR types (spoke, hub).VirtualNetworksconnected to spoke-type VNRs communicate withVirtualNetworksconnected to hub-type VNRs and vice versa.VirtualNetworksconnected to spoke VNRs cannot communicate with otherVirtualNetworksattached to spoke VNRs.
VNR is a Kubernetes construct deployed within Cloud-Native Contrail Networking.
VirtualNetworkRouter Use Cases
The following examples are common use cases that demonstrate the functionality of VNR in Cloud-Native Contrail Networking.
Mesh Use Cases
Hub-spoke Use Cases
Mesh VNR That Connects Two or More Virtual Networks in the Same Namespace

- Figure-1: The user creates VN1 and VN2 in namespace-1. Pods in VN1 cannot connect to
pods in VN2. This is the default behavior of
VirtualNetworksin Cloud-Native Contrail Networking. - Figure-2: The user defines a VNR of type mesh that selects VN1 and VN2. This VNR allows Pods in VN1 to communicate with Pods in VN2 and vice-versa.
- Figure-3: Pods in VN1 connect to Pods in VN2. The route-target of VNR is
importExportedto bothVirtualNetworks.
Add New Virtual Networks Within the Same Namespace to an Existing Mesh-Type VNR

- Figure-1: Two
VirtualNetworks(VN1, VN2) connect to VNR in namespace-1. - Figure-2: The user creates two new
VirtualNetworks(VN3, VN4). - Figure-3: VN3 and VN4 connect to VNR. As a result, all
VirtualNetworksconnected to the VNR receive connectivity.
Two Mesh VNRs in the Same Namespace

- Figure-1: VNR-web and VNR-db of type mesh already exist in namespace-1. Only VNRs connected to respective VNRs communicate with each other.
- Figure-2: VNR-web and VNR-db communicate with each other.
- Figure-3: All
VirtualNetworksconnected to both VNR-web and VNR-db communicate with each other.
Two Mesh VNRs with Different Namespaces

- Fig-1: VNR-web selects VN1 and VN2. Pods in VN1 and VN2 communicate with each other. VN1 and VN2 cannot communicate with VN3 and VN4.
- Fig-2: VNR-db selects VN3 and VN4. Pods in VN3 and VN4 communicate with each other. VN3 and VN4 cannot communicate with VN1 and VN2.
- Fig-3: The user updates VNR-web to select VNR-db.
- Fig-3: The user updates VNR-db to select VNR-web.
- Fig-3: Since two VNRs select each other, VNR-web's RT (route target) is added to VN3 and VN4. VNR-db's RT is added to VN1 and VN2. Pods in VN1, VN2, VN3, and VN4 communicate with each other.
Hub and Spoke VNRs in the Same Namespace

- Figure-1: Pods in VN1 cannot communicate with pods in VN2. VN1 and VN2 cannot communicate with VN3.
- Figure-2: The user creates a VNR of type "spoke" and "hub". VNR-spoke and VNR-hub import each other's RTs.
- Figure-3: VNR-spoke and VNR-hub's RTs are added to VN1, VN2, and VN3 because they import each other's RTs. As a result, pods in VN1 and VN2 communicate with VN3. Pods in VN1 and VN2 cannot communicate.
Hub and Spoke VNRs in Different Namespaces

- Figure-1-Figure-3 are the same as Hub and Spoke VNRs in the Same Namespace, except VNR-spoke and VNR-hub operate in different namespaces.
Same Virtual Networks Under Multiple VNRs

- Figure-1: Pods in VN1 and VN2 cannot communicate with each other. but VN3, VN4. Also resources on VN3, VN4 can communicate each other
- Figure-2: Create VNR-spoke selecting VN1, VN2, VNR-hub selecting VN3, VN4, VNR-mesh selecting VN3, VN4
- Figure-3: VNR-spoke ensures VN1, VN2 can not communicate each other, VNR-hub lets VN1, VN2 to reach VN3, VN4 while VNR-mesh enable communication between VN3, VN4
Use Case Explanation
This section comprises the following two VNR use cases along with end-to-end explanations of each use case:
Standard Use Case: Single VNR Connecting Two Virtual Networks
apiVersion: v1
kind: Namespace
metadata:
name: ns-single-mesh
labels:
ns: ns-single-mesh
spec:
finalizers:
- kubernetes
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
metadata:
namespace: ns-single-mesh
name: subnet-1
annotations:
core.juniper.net/display-name: subnet_vn_1
spec:
cidr: "10.10.1.0/24"
defaultGateway: 10.10.1.254
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
metadata:
namespace: ns-single-mesh
name: subnet-2
annotations:
core.juniper.net/display-name: subnet_vn_2
spec:
cidr: "10.10.2.0/24"
defaultGateway: 10.10.2.254
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetwork
metadata:
namespace: ns-single-mesh
name: vn-1
annotations:
core.juniper.net/display-name: vn-1
labels:
vn: web
spec:
v4SubnetReference:
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
namespace: ns-single-mesh
name: subnet-1
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetwork
metadata:
namespace: ns-single-mesh
name: vn-2
annotations:
core.juniper.net/display-name: vn-2
labels:
vn: web
spec:
v4SubnetReference:
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
namespace: ns-single-mesh
name: subnet-2
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetworkRouter
metadata:
namespace: ns-single-mesh
name: vnr-1
annotations:
core.juniper.net/display-name: vnr-1
labels:
vnr: web
spec:
type: mesh
virtualNetworkSelector:
matchExpressions:
- key: vn
operator: In
values:
- web
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vn-1
namespace: ns-single-mesh
annotations:
k8s.v1.cni.cncf.io/networks: vn-1
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: agent-mode
operator: NotIn
values:
- dpdk
containers:
- name: pod-vn-1
image: svl-artifactory.juniper.net/atom-docker/cn2/bazel-build/dev/google-containers/toolbox
command: ["bash","-c","while true; do sleep 60s; done"]
securityContext:
privileged: true
imagePullPolicy: IfNotPresent
restartPolicy: OnFailure
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vn-2
namespace: ns-single-mesh
annotations:
k8s.v1.cni.cncf.io/networks: vn-2
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: agent-mode
operator: NotIn
values:
- dpdk
containers:
- name: pod-vn-2
image: svl-artifactory.juniper.net/atom-docker/cn2/bazel-build/dev/google-containers/toolbox
command: ["bash","-c","while true; do sleep 60s; done"]
securityContext:
privileged: true
imagePullPolicy: IfNotPresent
restartPolicy: OnFailure
This use case comprises two VirtualNetworks (vn-1,
vn-2) in namespace ns-single-mesh. Both virtual networks
have the label
vn: web. Each VirtualNetwork contains a single pod. The
VirtualNetwork
vn-1 contains pod-vn-1. The
VirtualNetwork
vn-2 contains pod-vn-2. A type: mesh VNR
with the name vnr-1 establishes connectivity between the two
VirtualNetworks using matchExpressions
vn: web. The VNR imports the RI and routing table of vn-1
to vn-2 and vice versa. Since vnr-1 is a mesh-type VNR,
all pods in connected VirtualNetworks communicate with each other.
Update Use Case: Single VNR Connecting Two Additional Virtual Networks
apiVersion: v1
kind: Namespace
metadata:
name: ns-single-mesh
labels:
ns: ns-single-mesh
spec:
finalizers:
- kubernetes
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
metadata:
namespace: ns-single-mesh
name: subnet-2
annotations:
core.juniper.net/display-name: subnet_vn_1
spec:
cidr: "10.10.3.0/24"
defaultGateway: 10.10.3.254
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
metadata:
namespace: ns-single-mesh
name: subnet-4
annotations:
core.juniper.net/display-name: subnet_vn_2
spec:
cidr: "10.10.4.0/24"
defaultGateway: 10.10.4.254
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetwork
metadata:
namespace: ns-single-mesh
name: vn-3
annotations:
core.juniper.net/display-name: vn-1
labels:
vn: db
spec:
v4SubnetReference:
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
namespace: ns-single-mesh
name: subnet-3
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetwork
metadata:
namespace: ns-single-mesh
name: vn-4
annotations:
core.juniper.net/display-name: vn-2
labels:
vn: middleware
spec:
v4SubnetReference:
apiVersion: core.contrail.juniper.net/v1alpha1
kind: Subnet
namespace: ns-single-mesh
name: subnet-4
---
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetworkRouter
metadata:
namespace: ns-single-mesh
name: vnr-2
annotations:
core.juniper.net/display-name: vnr-1
labels:
vnr: db
vnr: middleware
spec:
type: mesh
virtualNetworkSelector:
matchExpressions:
- key: vn
operator: In
values:
- db, middlware
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vn-3
namespace: ns-single-mesh
annotations:
k8s.v1.cni.cncf.io/networks: vn-1
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: agent-mode
operator: NotIn
values:
- dpdk
containers:
- name: pod-vn-3
image: svl-artifactory.juniper.net/atom-docker/cn2/bazel-build/dev/google-containers/toolbox
command: ["bash","-c","while true; do sleep 60s; done"]
securityContext:
privileged: true
imagePullPolicy: IfNotPresent
restartPolicy: OnFailure
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vn-4
namespace: ns-single-mesh
annotations:
k8s.v1.cni.cncf.io/networks: vn-2
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: agent-mode
operator: NotIn
values:
- dpdk
containers:
- name: pod-vn-4
image: svl-artifactory.juniper.net/atom-docker/cn2/bazel-build/dev/google-containers/toolbox
command: ["bash","-c","while true; do sleep 60s; done"]
securityContext:
privileged: true
imagePullPolicy: IfNotPresent
restartPolicy: OnFailure
This use case is similar to the standard use case, except that in this use case the user
updates the YAML with an additional type: mesh VNR to connect two new
VirtualNetworks (vn-3, vn-4) in
namespace ns-single-mesh. The VNR shown has the name vnr-2
in namespace ns-single-mesh with matchExpressions: db,
middlware. The VirtualNetwork
vn-3 has the label vn: db and vn-4 has
the label vn: middleware. As a result, vnr-2 imports the
RI and routing table of vn-3 to vn-4 and vice versa.
VirtualNetworkRouter Configuration
The following section provides YAML configuration information for the following resources:
API Type (Schema)
type VirtualNetworkRouterSpec struct {
// Common spec fields
CommonSpec `json:",inline" protobuf:"bytes,1,opt,name=commonSpec"`
// Type of VirtualNetworkRouter. valid types - mesh, spoke, hub
Type VirtualNetworkRouterType `json:"type,omitempty" protobuf:"bytes,2,opt,name=type"`
// Select VirtualNetworks to which this VNR's RT be shared
VirtualNetworkSelector *metav1.LabelSelector `json:"virtualNetworkSelector,omitempty" protobuf:"bytes,3,opt,name=virtualNetworkSelector"`
// Import Router targets from other virtualnetworkrouters
Import ImportVirtualNetworkRouter `json:"import,omitempty" protobuf:"bytes,4,opt,name=import"`
}
type ImportVirtualNetworkRouter struct {
VirtualNetworkRouters []VirtualNetworkRouterEntry `json:"virtualNetworkRouters,omitempty" protobuf:"bytes,1,opt,name=virtualNetworkRouters"`
}
type VirtualNetworkRouterEntry struct {
VirtualNetworkRouterSelector *metav1.LabelSelector `json:"virtualNetworkRouterSelector,omitempty" protobuf:"bytes,1,opt,name=virtualNetworkRouterSelector"`
NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty" protobuf:"bytes,2,opt,name=namespaceSelector"`
}
Mesh VNR
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetworkRouter
metadata:
namespace: frontend
name: vnr-1
annotations:
core.juniper.net/display-name: vnr-1
labels:
vnr: web
ns: frontend
spec:
type: mesh
virtualNetworkSelector:
matchLabels:
vn: web
import:
virtualNetworkRouters:
- virtualNetworkRouterSelector:
matchLabels:
vnr: db
namespaceSelector:
matchLabels:
ns: backend
This YAML is an example of a mesh VNR with the name vnr-1 in namespace
frontend, with the labels
vnr: web and ns: frontend. This VNR imports its
route-target to any VNR in the namespace backend with
matchLabel
vnr: db.
Spoke VNR
kind: VirtualNetworkRouter
metadata:
namespace: frontend
name: vnr-1
annotations:
core.juniper.net/display-name: vnr-1
labels:
vnrgroup: spokes
ns: frontend
spec:
type: spoke
virtualNetworkSelector:
matchLabels:
vngroup: spokes
import:
virtualNetworkRouters:
- virtualNetworkRouterSelector:
matchLabels:
vnrgroup: hubs
namespaceSelector:
matchLabels:
ns: backend
This YAML is an example of a spoke VNR with the name vnr-1 in namespace
frontend with the labels
vnrgroup: spokes and ns: frontend. This VNR imports its
route-targets to any VNR in the namespace backend with
matchLabel
vnrgroup: hubs.
Hub VNR
apiVersion: core.contrail.juniper.net/v1alpha1
kind: VirtualNetworkRouter
metadata:
namespace: backend
name: vnr-2
annotations:
core.juniper.net/display-name: vnr-2
labels:
vnrgroup: hubs
ns: backend
spec:
type: hub
virtualNetworkSelector:
matchLabels:
vngroup: hubs
import:
virtualNetworkRouters:
- virtualNetworkRouterSelector:
matchLabels:
vnrgroup: spokes
namespaceSelector:
matchLabels:
ns: frontend
This YAML is an example of a hub VNR with the name vnr-2 in the namespace
backend with labels
vnrgroup: hubs and ns: backend. This VNR imports its
route-targets to any VNR in the namespace frontend with
matchLabels
vnrgroup: spokes.