Red Hat blog
This document gives steps to enable the Macvlan CNI plug-in in OCP4.7 to run on OSP 13. We assume that your OSP 13 is up and running and all the prerequisites for installing OCP are met.
What Is Macvlan?
With VLAN, you can create multiple interfaces on top of a single one and filter packages based on a VLAN tag. With macvlan you can create multiple interfaces with different Layer 2 (Ethernet MAC) addresses on top of a single one.
Without macvlan, if you wanted to connect to a physical network from a VM or namespace, you would have needed to create TAP/VETH devices and attach one side to a bridge and attach a physical interface to the bridge on the host at the same time, as shown below:
However, with MACVLAN, you can bind a physical interface that is associated with a MACVLAN directly to namespaces, without the need for a bridge:
There are five Macvlan types.
- Private: does not allow communication between MACVLAN instances on the same physical interface, even if the external switch supports hairpin mode.
- VEPA: data from one MACVLAN instance to the other on the same physical interface is transmitted over the physical interface. Either the attached switch needs to support hairpin mode, or there must be a TCP/IP router forwarding the packets to allow communication.
- Bridge: all endpoints are directly connected to each other with a simple bridge via the physical interface.
- Passthru: allows a single VM to be connected directly to the physical interface.
- Source: the source mode is used to filter traffic based on a list of allowed source MAC addresses to create MAC-based VLAN associations.
What Is Multus CNI?
CNI is the container network interface that provides a pluggable application programming interface to configure network interfaces in Linux containers. Multus CNI is such a plug-in and is referred to as a meta-plug-in: a CNI plug-in that can run other CNI plug-ins. It works like a wrapper that calls other CNI plug-ins for attaching multiple network interfaces to pods in OpenShift/Kubernetes.
Multus allows pods to have multiple network interface connections that can address various use cases; for example:
- Splitting the control/data plane traffic, mostly applicable to VNF/CNF applications
- Legacy/storage intensive applications
- Multitenant networks
OpenShift provides and supports the following CNI plug-ins for creating additional networks in your cluster:
- Bridge: allows Pods on the same host to communicate with each other and the host
- Host-device: allows Pods access to a physical Ethernet network device on the host system. This simple plugin will move the requested device from the host’s network namespace to the pod network namespace. The limitation of using this plugin is that the physical device is used solely by a single pod and will not be available to multiple pods.
- Macvlan: allows pods on a host to communicate with other hosts and pods on those hosts by using a physical network interface. Each pod that is attached to a macvlan-based additional network is provided a unique MAC address. Macvlan needs to be used in cases where a common DHCP server is used since the DHCP server would need a unique mac address which ipvlan does not have.
- Ipvlan: allows pods on a host to communicate with other hosts and pods on those hosts, similar to a macvlan-based additional network. Unlike a macvlan-based additional network, each pod shares the same MAC address as the parent physical network interface. Ipvlan should be used in cases where some switches restrict the maximum number of mac addresses per physical port due to port security configuration.
- SR-IOV: allows pods to attach to a virtual function (VF) interface on SR-IOV capable hardware on the host system
For more information on the official support list refer to :
https://access.redhat.com/articles/4763741
Preparing OpenStack environment
For installing Openshift on OpenStack to enable Macvlan at a later stage, we have to prepare the environment as follows:
Login as admin and create an external network:
#source overcloudrc
(overcloud)#openstack network create --external —provider-network-type vlan \
--provider-segment 80 --provider-physical-network datacentre vlan80
(overcloud)#openstack subnet create --network vlan80 --dhcp \
--allocation-pool start=192.168.80.200,end=192.168.80.250 \
--dns-nameserver 192.168.80.1 --gateway 192.168.80.1 \
--subnet-range 192.168.80.0/24 vlan80-subnet
Create a provider network:
(Overcloud)#openstack network create --share --provider-physical-network datacentre
--provider-network-type vlan —provider-segment 10 vlan10
(overcloud)#openstack subnet create --network vlan10 --dhcp \
--allocation-pool start=192.168.10.201,end=192.168.10.240 \
--dns-nameserver 192.168.10.1 --gateway 192.168.10.1 \
--subnet-range 192.168.10.0/24 vlan10-subnet
Installing OCP on OpenStack With Additional Network
Now let us start installing Openshift on OpenStack. Make sure that all the prerequisites are met.
- Verify that your network configuration does not rely on a provider network. Provider networks are not supported.
- Have a storage service installed in RHOSP, like block storage (Cinder) or object storage (Swift). Object storage is the recommended storage technology for OpenShift Container Platform registry cluster deployment. For more information, see Optimizing storage.
- Have metadata service enabled in RHOSP
We will follow the RedHat OpenShift installation document. We will customize the installation by adding an additional network to the worker nodes. Here is a snippet of the install-config.yaml file showing where to specify the additional network:
compute:
- architecture: amd64
hyperthreading: Enabled
name: worker
platform:
openstack:
additionalNetworkIDs: [“85fe165b-82d8-40f9-99c0-3d7b7b6f26dc"]
replicas: 3
We are adding an additional network at installation time because this will create a trunk port on the additional network and add it to the VM instances it creates. We will later add a sub-port to it.
Start the installation of OpenShift (IPI):
./openshift-install create cluster --dir pluto —log-level=debug
…………..
DEBUG Still waiting for the cluster to initialize: Working towards 4.7.12: 663 of 669 done (99% complete)
DEBUG Still waiting for the cluster to initialize: Cluster operator authentication is not available
DEBUG Cluster is initialized
INFO Waiting up to 10m0s for the openshift-console route to be created...
DEBUG Route found in openshift-console namespace: console
DEBUG OpenShift console route is admitted
INFO Install complete!
INFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/Users/aaggarwa/Work/Lab/ocp-clusters/osp/pluto/auth/kubeconfig'
INFO Access the OpenShift web-console here: https://console-openshift-console.apps.pluto.home.lab
INFO Login to the console with user: "kubeadmin", and password: "UHr9S-kXWIJ-mS82f-grEV4"
DEBUG Time elapsed per stage:
DEBUG Infrastructure: 5m2s
DEBUG Bootstrap Complete: 16m52s
DEBUG API: 1m29s
DEBUG Bootstrap Destroy: 47s
DEBUG Cluster Operators: 27m5s
INFO Time elapsed: 53m38s
Once the Openshift Installation is successful, our network topology will look like this:
Now let us examine the trunks created during the installation:
As we can see, each worker has two trunk ports attached to it. One is for OpenShift SDN, and another one is from an additional network we mentioned in install-config.yaml.
(Overcloud)#openstack network create --share --provider-physical-network datacentre
--provider-network-type vlan —provider-segment 30 vlan30
(overcloud)#openstack subnet create --network vlan30 --dhcp \
--allocation-pool start=192.168.30.101,end=192.168.30.200 \
--dns-nameserver 192.168.30.1 --gateway 192.168.30.1 \
--subnet-range 192.168.30.0/24 vlan30-subnet
Now, let us add sub-port to additional network trunks. First, we have to create another provider network. If you have existing DHCP use --no-dhcp as DHCP in network might interfere with existing DHCP:
Now we will create ports in the network created above. For easy management, keep the name of the port as per the node name:
(Overcloud)#openstack port create worker-0-ftmxg --network vlan30
(Overcloud)#openstack port create worker-0-c5gd5 --network vlan30
(Overcloud)#openstack port create worker-0-47njf --network vlan30
Now add these ports as subports in the trunk. Make sure that the trunk is the one that has the parent port as the additional network:
(Overcloud)#openstack network trunk set --subport port=worker-0-c5gd5,segmentation-type=inherit 0bca67f0-613f-42e0-bb9e-dbc57fdbfa89
(Overcloud)#openstack network trunk set --subport port=worker-0-47njf,segmentation-type=inherit 541d1a9c-0c9d-4303-8842-e295f692c848
(Overcloud)#openstack network trunk set --subport port=worker-0-ftmxg,segmentation-type=inherit da42a06e-a588-4c61-99e3-346024bbc150
Here is the diagram for a better understanding:
Enabling Macvlan CNI in OpenShift
Once the installation is done and we have added sub-ports to the trunk, we will now configure OpenShift so that Macvlan can be enabled and used by the pods.
Install NMState operator
The Kubernetes NMState Operator provides a Kubernetes API for performing state-driven network configuration across the OpenShift Container Platform cluster’s nodes with NMState. The Kubernetes NMState Operator provides users with functionality to configure various network interface types, DNS, and routing on cluster nodes. Additionally, the daemons on the cluster nodes periodically report on the state of each node’s network interfaces to the API server. To install the NMState operator, please click here.
Once complete, the Operator has deployed the NMState State Controller as a daemon set across all of the cluster nodes.
Create a VLAN interface on the nodes in the cluster by applying a NodeNetworkConfigurationPolicy manifest to the nodes. We have to create configuration for each node as the MAC address has to match the sub-port attached to it. Following is an example:
#cat nmstate-worker-0-47njf.yaml
apiVersion: nmstate.io/v1alpha1
kind: NodeNetworkConfigurationPolicy
metadata:
name: vlan-ens4-policy-worker-0-47njf
spec:
nodeSelector:
kubernetes.io/hostname: pluto-jttmc-worker-0-47njf
desiredState:
interfaces:
- name: ens4.30
description: VLAN using ens4
type: vlan
state: up
mac-address: fa:16:3e:d9:7a:27
vlan:
base-iface: ens4
id: 30
#oc apply -f nmstate-worker-0-47njf.yaml
Confirm the policy has been applied to the cluster; list the policies and their status:
oc get nncp
NAME STATUS
vlan-ens4-policy-worker-0-47njf SuccessfullyConfigured
vlan-ens4-policy-worker-0-c5gd5 SuccessfullyConfigured
vlan-ens4-policy-worker-0-ftmxg SuccessfullyConfigured
Login to worker node to see if the interface has been created:
ens4.30: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether fa:16:3e:d9:7a:27 txqueuelen 1000 (Ethernet)
RX packets 1073 bytes 120094 (117.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 800 bytes 146198 (142.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Create a project in OpenShift:
#oc new-project networking-demos
Create a network attach definition in the new namespace by adding the following snippet in network operator:
#oc edit networks.operator.openshift.io
………
Spec:
additionalNetworks:
- name: macvlan-30
namespace: networking-demos
simpleMacvlanConfig:
ipamConfig:
type: dhcp
master: ens4.30
mode: bridge
type: SimpleMacvlan
clusterNetwork:
…………
Check the status:
#oc get network-attachment-definitions
NAME AGE
macvlan-30 10s
Now we will create a pod with an additional network:
#vi test-pod1.yaml
apiVersion: v1
kind: Pod
metadata:
name: example-pod1
namespace: networking-demos
annotations:
k8s.v1.cni.cncf.io/networks: |-
[
{
"name": "macvlan-30",
"namespace": "networking-demos",
"default-route": ["192.168.30.1"]
}
]
spec:
containers:
- name: example-pod
command: ["/bin/bash", "-c", "sleep 2000000000000"]
image: centos/tools
#oc apply -f test-pod1.yaml
If everything is configured correctly, you should see that the pod is able to get IP from DHCP IP from vlan30 subnet:
You can also check in you DHCP logs:
Login to pod to check the status: