docker container virtualization

Container virtualization of Docker

Virtualized network

Network Namespace is a function provided by Linux kernel and an important function to realize network virtualization. It can create multiple isolated network spaces with independent network stack information. Whether it is a virtual machine or a container, it seems as if it is running in an independent network. Moreover, the resources of different network namespaces are invisible to each other and cannot communicate with each other.

If our physical machine has four physical network cards, we need to create four namespaces, and these devices can be independently associated with a separate namespace

As shown in the figure above, assign the first network card to the first namespace, the second to the second namespace, the third to the third namespace, and the fourth to the fourth namespace. At this time, other namespaces cannot see the current namespace, because a device can only belong to one namespace.

In this way, each namespace can be configured with an IP address and communicate directly with the external network because they use a physical network card.

But what if we have more namespaces than physical network cards? At this time, we can use the virtual network card device to simulate a group of devices in a pure software way. The Linux kernel level supports the simulation of two levels of devices, one is a layer 2 device and the other is a layer 3 device.

Each network interface device simulated by the Linux kernel appears in pairs and can be simulated as both ends of a network cable. One end simulates the virtual network card of the host and the other end simulates the virtual switch, which is equivalent to connecting a host to a switch. The Linux kernel natively supports the layer-2 virtual bridge device, that is, the function of software virtual switch. As shown in the figure below:

From the physical equipment of network communication to network card, it is realized by pure software, which is called virtual network.

Single node inter container communication

If two containers on the same physical machine want to communicate, our method is to establish a virtual switch on this host, and then let the two containers create a pair of virtual network cards in pure software, half on the container and half on the virtual switch, so as to realize communication. As shown in the figure below:

This is the communication mode between two containers on a single node. The communication between two containers on a single node is also complicated. For example, do we expect the container to communicate across switches?

We make two virtual switches, each of which is connected to different containers, as shown in the figure above. At this time, how to realize C1 and C3 communication? In fact, we can create a pair of network cards through the namespace. One end is connected to SW1 and the other end is connected to SW2. In this way, the two switches C1 and C3 can communicate in different switches. However, there is another problem, that is, if C1 and C3 are in different networks? If we are not in the same network, we must use routing forwarding to make it communicate, that is, we have to add a router between the two switches. In fact, the Linux kernel itself supports routing forwarding. We only need to turn on the routing forwarding function. At this point, we can start another container, run a kernel in this container, and turn on its forwarding function. In this way, we simulate a router to realize routing forwarding through this router.

Communication between different node containers


As shown in the figure above, how can C1 communicate with C5? If we use bridging, it is easy to generate broadcast storm. Therefore, in the scene of large-scale virtual machine or container, using bridging is undoubtedly self destruction, so we should not use bridging to realize communication.

If we can't bridge and need to communicate with the outside world, we can only use NAT technology. The port of the container is exposed to the host through DNAT, and the purpose of accessing the interior of the container is realized by accessing the port of the host. On the requesting side, we need to do SNAT to forward the data packet through the real network card of the host. However, in this way, the efficiency will be low because two NAT conversions are required.

At this time, we can use a technology called Overlay Network to realize the mutual communication function of containers between different nodes.

Overlay Network will tunnel forward the message, that is, add an IP header for the message before sending it, that is, parts 1.1 and 1.2 in the figure above. Here, 1.1 is the source and 1.2 is the target. After receiving the message, host 2 unpacks and finds that the target container to be found is C2, so it forwards the packet to C2.

//View ip
[root@docker ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:d1:aa:86 brd ff:ff:ff:ff:ff:ff
    inet 192.168.71.134/24 brd 192.168.71.255 scope global dynamic noprefixroute ens33
       valid_lft 1707sec preferred_lft 1707sec
    inet6 fe80::3f7:eb08:5d5b:98f5/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 10:51:09:81:2b:62 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

//Create container view ip
[root@docker ~]# docker images 
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
linlusama/centos-nginx   v1.20.1   11bd74ac7f9e   23 hours ago   549MB
centos                   latest    5d0da3dc9764   2 months ago   231MB
[root@docker ~]# docker run -it centos:latest /bin/sh 
sh-4.4# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 10:51:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
 
//Automatically create a network card when opening a terminal
[root@docker ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:d1:aa:86 brd ff:ff:ff:ff:ff:ff
    inet 192.168.71.134/24 brd 192.168.71.255 scope global dynamic noprefixroute ens33
       valid_lft 1512sec preferred_lft 1512sec
    inet6 fe80::3f7:eb08:5d5b:98f5/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 10:51:09:81:2b:62 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:9ff:fe81:2b62/64 scope link 
       valid_lft forever preferred_lft forever
5: vethdfee1ef@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 6a:68:82:cf:89:27 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::6868:82ff:fecf:8927/64 scope link 
       valid_lft forever preferred_lft forever //This network card and the network card in the container complement each other and make a perfect match 
       
//Delete the container and find that the network card on this computer has also been deleted
[root@docker ~]# docker ps -a 
CONTAINER ID   IMAGE           COMMAND                  CREATED         STATUS                     PORTS     NAMES
00f4449241ab   centos:latest   "/bin/sh"                4 minutes ago   Exited (0) 7 seconds ago             nostalgic_knuth
[root@docker ~]# docker rm -f 00f4449241ab
00f4449241ab
[root@docker ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:d1:aa:86 brd ff:ff:ff:ff:ff:ff
    inet 192.168.71.134/24 brd 192.168.71.255 scope global dynamic noprefixroute ens33
       valid_lft 1355sec preferred_lft 1355sec
    inet6 fe80::3f7:eb08:5d5b:98f5/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 10:51:09:81:2b:62 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:9ff:fe81:2b62/64 scope link 
       valid_lft forever preferred_lft forever

Tags: Docker network Container

Posted on Sat, 04 Dec 2021 01:47:52 -0500 by keystroke