CNI and Network Namespaces — Complete Guide — Part 1
Introduction
Container Runtimes such as Containerd or CRI-O leverages Network Namespaces and the Container Network Interface to seamlessly create and maintain the containers’ network.
Throughout this guide, you will learn how to use network namespaces, create your own CNI Plugin from scratch and use your CNI Plugin with containerd.
The guide is divided in 5 parts:
- In Part I, you’ll learn to create network namespaces with
iproute2and enable communication between 2 namespaces. - In Part II, you will learn how to use bridge devices to decouple the network.
- In Part III the fun begins, you’ll learn about the Container Network Interface and create a dummy plugin.
- In Part IV, you’ll create a real CNI Plugin from scratch.
- In Part V, you’ll put things in practice by configuring a Container Runtime to use the CNI Plugin.
Part I: Network between 2 namespaces
In this part, you will learn how to create two network namespaces with iproute2 and connect them with veth devices.
First step is to create the network namespaces:
# --- create new namespaces
sudo ip netns add ns-0
sudo ip netns add ns-1For convenience, we will create 2 aliases to execute theip command from within a network namespace.
# --- create 2 aliases for convenience
alias ip0="sudo ip netns exec ns-0 ip"
alias ip1="sudo ip netns exec ns-1 ip"Additionally, we will set up a few helper functions to display the network links and addresses of our namespaces.
# --- create a funct to display links
displayLinks() {
echo --- netns ns-0 ---
ip0 link
echo --- netns ns-1 ---
ip1 link
}
# --- create a func to display ip addresses
displayAddr() {
echo --- netns ns-0 ---
ip0 a
echo --- netns ns-1 ---
ip1 a
}We can display the links of our 2 newly created namespaces.
displayLinksOur network namespaces only have a loopback interface. To allow communication between these two namespaces, we will create two virtual ethernet devices on the host, connect them and set each of them to a namespace.
# --- create 2 peered veth
sudo ip link add veth-0 type veth peer veth-1
# --- assign each veth to a namespace
sudo ip link set veth-0 netns ns-0
sudo ip link set veth-1 netns ns-1
# --- display links
displayLinkGreat, both our namespaces displays a veth device. However, we are still unable to communicate between devices. Configure their IP addresses and set up the devices:
# --- give those devices an ip addr
ip0 addr add 172.16.0.2 dev veth-0
ip1 addr add 172.16.0.3 dev veth-1
# --- set the interfaces up
ip0 link set veth-0 up
ip1 link set veth-1 up
# --- display their ip addr
displayAddrNice, we should be able to ping each other instances.
sudo ip netns exec ns-0 ping -c 1 172.16.0.3Something must went wrong, it’s not going through. We forgot to set the routes.
# let's route all traffic in 172.16/16 to the veth.
ip0 route add 172.16.0.0/16 dev veth-0
ip1 route add 172.16.0.0/16 dev veth-1That’s better. Try pinging again, it should work.
sudo ip netns exec ns-0 ping -c 1 172.16.0.3
sudo ip netns exec ns-1 ping -c 1 172.16.0.2It works and this almost mark the end of the first part, we still need to clean up our mess.
sudo ip netns del ns-0
sudo ip netns del ns-1🎉 Congrats, we created 2 network namespaces and set up communication between them.
Conclusion
While setting up connectivity b/w 2 namespaces was straightforward, the approach we used will not scale. The number of links in the network grows following a geometric serie, which is approximately quadratic. In Part II: Container Networking with Bridge, you will learn how to decouple the network using bridge interfaces.