Contrail and Network Namespace

1 Network Namespace

Network namespace is a feature of Linux kernel. A separate network stack can be created as a network namespace for an application to run on.

Network namespace is one of basic technologies used by Linux Container (LXC) and Docker. The goal of this document is to walk you through a workflow to connect an application in netnamespace to be part of a Contrail Virtual network.

2 Connect Network Namespace and Virtual Network

The application running in network namespace is similar as running on bare-metal server. Contrail has the capability to connect such application to a virtual network, so that it can connect to other virtual machines. Essentially, from Contrail point of view, a network namespace is the same as a virtual machine.

Opencontrail-netns is a program to connect network namespace and virtual network in Contrail.

https://github.com/pedro-r-marques/opencontrail-netns

Here is the workflow of script daemon_start.py.

  1. Create a virtual machine on an existing virtual network, virtual machine interface and IP address in Contrail. Virtual machine here is not the real virtual machine running in system. Creating those objects makes Contrail treat network namespace as the same as virtual machine.
  2. Create network namespace and virtual Ethernet device (veth) that is like a pipe. The interface on one end of veth is in network namespace, which is equivalent to the interface in virtual machine. The interface on another end of veth is in default namespace, which is like the tap interface. Configure MAC address for the interface in network namespace.
  3. Register interface in default namespace to vRouter.
  4. Configure address on the interface in network namespace.

The script daemon_stop.py removes all configurations in the reversed order.

3 Demo with MySQL

Here is a demo to show how Contrail connects MySQL server in network namespace to virtual network, so it can be accessed from other virtual machine. This demo runs on Contrail 1.05 Ubuntu based compute node. The MySQL server will run in network namespace. A MySQL client will run in VM.

blogpost_july_23_2014_image1

  1. Create virtual networks and VM.

Create virtual networks “database” and “client” on Contrail Web UI.

Create network policy to allow all traffic, attach the policy to virtual networks “database” and “client”.

Launch VM “client” on virtual network “client” on OpenStack Web UI.

  1. Build and install opencontrail-netns package.

https://github.com/pedro-r-marques/opencontrail-netns

Clone the code and build the package.

 $ git clone https://github.com/pedro-r-marques/opencontrail-netns.git
 $ cd opencontrail-netns/
 $ python ./setup.py sdist
 $ ls dist
 opencontrail-netns-0.1.tar.gz

Copy the package to compute node and install it.

 # tar xzf opencontrail-netns-0.1.tar.gz
 # cd opencontrail-netns-0.1/
 # python setup.py install
 # ls /usr/local/bin/netns-daemon-start
 /usr/local/bin/netns-daemon-start

3. Install MySQL on compute node.

# apt-get install mysql-server

4. Initialize MySQL server to add user “tony” and allow the access.

 # mysql -uroot -ppassword
 mysql> CREATE USER 'tony'@'%' IDENTIFIED BY 'password';
 mysql> GRANT ALL PRIVILEGES ON *.* TO 'tony'@'%' WITH GRANT OPTION;
 mysql> FLUSH PRIVILEGES;
 mysql> quit
 # service mysql stop

5. Update /etc/mysql/my.cnf.

 /etc/mysql# diff -u my.cnf.orig my.cnf
 --- my.cnf.orig
 +++ my.cnf
 @@ -44,7 +44,7 @@
 #
 # Instead of skip-networking the default is now to listen only on
 # localhost which is more compatible and is not less secure.
 -bind-address = 127.0.0.1
 +bind-address = 0.0.0.0
 #
 # * Fine Tuning
 #

6. Update /etc/init/mysql.conf.

 /etc/init# diff -u mysql.conf.orig mysql.conf
 --- mysql.conf.orig
 +++ mysql.conf
 @@ -16,6 +16,8 @@
 kill timeout 300
 pre-start script
 + /usr/local/bin/netns-daemon-start -s 10.84.18.2 --network default-domain:demo:database mysql
 +
 #Sanity checks
 [ -r $HOME/my.cnf ]
 [ -d /var/run/mysqld ] || install -m 755 -o mysql -g root -d /var/run/mysqld
 @@ -23,7 +25,9 @@
 LC_ALL=C BLOCKSIZE= df --portability /var/lib/mysql/. | tail -n 1 | awk '{ exit ($4<4096) }'
 end script
 -exec /usr/sbin/mysqld
 +exec ip netns exec ns-mysql /usr/sbin/mysqld
 post-start script
 for i in `seq 1 30` ; do
 @@ -42,3 +46,7 @@
 done
 exit 1
 end script
 +
 +post-stop script
 + /usr/local/bin/netns-daemon-stop -s 10.84.18.2 mysql
 +end script

7. Start MySQL server.

# service mysql start

8.Connect to MySQL server from VM “client”.

 [root@client ~]# mysql -h 192.168.10.252 -utony -ppassword
 Welcome to the MySQL monitor. Commands end with ; or \g.
 Your MySQL connection id is 37
 Server version: 5.5.34-0ubuntu0.12.04.1 (Ubuntu)
 Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 Oracle is a registered trademark of Oracle Corporation and/or its
 affiliates. Other names may be trademarks of their respective
 owners.
 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 mysql>
4 Step by Step

This shows how netns-daemon-start works step by step.

1. Get ready

 # cd opencontrail-netns-0.1/opencontrail_netns
 # python
 Python 2.7.3 (default, Apr 10 2013, 06:20:15)
 [GCC 4.6.3] on linux2
 Type "help", "copyright", "credits" or "license" for more information.
 >>> from vnc_api import vnc_api
 >>> import subprocess
 >>> vnc = vnc_api.VncApi(username = 'admin', password = 'contrail123', tenant_name = 'admin', api_server_host = '10.84.18.2')

2. Configure Contrail

 >>> vm_instance = vnc_api.VirtualMachine(name = 'a4s5-mysql')
 >>> vnc.virtual_machine_create(vm_instance)
 u'3bf9a099-c25a-493f-ab83-a8ed21047e50'
 >>>
 >>> vm_interface = vnc_api.VirtualMachineInterface(name = 'veth0', parent_obj = vm_instance)
 >>> vn = vnc.virtual_network_read(fq_name = ['default-domain', 'demo', 'database'])
 >>> vm_interface.set_virtual_network(vn)
 >>> vnc.virtual_machine_interface_create(vm_interface)
 u'a0590a72-2952-445f-a9bf-b5762d8cb9fe'
 >>> vm_interface = vnc.virtual_machine_interface_read(id = vm_interface.uuid)
 >>>
 >>> ip = vnc_api.InstanceIp(name = 'a4s5-mysql.veth0')
 >>> ip.set_virtual_machine_interface(vm_interface)
 >>> ip.set_virtual_network(vn)
 >>> vnc.instance_ip_create(ip)
 u'3dc7f645-6863-4b30-9a5a-14ce052e2ca3'
 >>> ip = vnc.instance_ip_read(id = ip.uuid)
 >>> ip.get_instance_ip_address()
 u'192.168.10.252'

3. Configure network namespace

 >>> subprocess.call('ip netns add ns-mysql', shell = True)
 0
 >>> subprocess.call('ip netns list', shell = True)
 ns-mysql
 0
 >>> subprocess.call('ip link add veth0 type veth peer name instance0', shell = True)
 0
 >>> subprocess.call('ip link set veth0 netns ns-mysql', shell = True)
 0
 >>> subprocess.call('ip link set instance0 up', shell = True)
 0
 >>> mac = vm_interface.virtual_machine_interface_mac_addresses.mac_address[0]
 >>> subprocess.call('ip netns exec ns-mysql ifconfig veth0 hw ether %s' %(mac), shell = True)
 0

4. Register to vRouter

 >>> import vrouter_control
 >>> vrouter_control.add_interface('instance0', vm_interface.uuid, vm_instance.uuid, mac)

5. Configure interface

 >>> subprocess.call('ip netns exec ns-mysql dhclient veth0', shell = True)
 0
 >>> subprocess.call('ip netns exec ns-mysql ip addr list', shell = True)
 1: lo: mtu 65536 qdisc noop state DOWN
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 11: veth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 link/ether 02:a0:59:0a:72:29 brd ff:ff:ff:ff:ff:ff
 inet 192.168.10.252/24 brd 192.168.10.255 scope global veth0
 inet6 fe80::a0:59ff:fe0a:7229/64 scope link
 valid_lft forever preferred_lft forever

Now, in Contrail, virtual machine, virtual machine interface and routes are all set.

 

blogpost_july_23_2014_image3blogpost_july_23_2014_image4

6. Start MySQL server in network namespace

# ip netns exec ns-mysql /usr/sbin/mysqld

7. Connect MySQL server from VM “client”

[root@client ~]# ip addr list
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 inet 127.0.0.1/8 scope host lo
 inet6 ::1/128 scope host
 valid_lft forever preferred_lft forever
 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 link/ether 02:b8:43:bb:24:41 brd ff:ff:ff:ff:ff:ff
 inet 192.168.1.253/24 brd 192.168.1.255 scope global eth0
 inet6 fe80::b8:43ff:febb:2441/64 scope link
 valid_lft forever preferred_lft forever
 [root@client ~]#
 [root@client ~]# mysql -h 192.168.10.252 -utony -ppassword
 Welcome to the MySQL monitor. Commands end with ; or \g.
 Your MySQL connection id is 37
 Server version: 5.5.34-0ubuntu0.12.04.1 (Ubuntu)
 Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 Oracle is a registered trademark of Oracle Corporation and/or its
 affiliates. Other names may be trademarks of their respective
 owners.
 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 mysql>