[mydocker]---网络实现测试

1. 前言

根据前面几篇文章的内容, 本文就可以实现网络部分的内容了, 所以接下来就可以进行测试.

2. network测试

需要加上network命令.

2.1 增加network命令

包括network create, network list, network remove.

var NetworkCommand = cli.Command{
    Name:  "network",
    Usage: "container network commands",
    Subcommands: []cli.Command {
        {
            Name: "create",
            Usage: "create a container network",
            Flags: []cli.Flag{
                cli.StringFlag{
                    Name:  "driver",
                    Usage: "network driver",
                },
                cli.StringFlag{
                    Name:  "subnet",
                    Usage: "subnet cidr",
                },
            },
            Action:func(context *cli.Context) error {
                if len(context.Args()) < 1 {
                    return fmt.Errorf("Missing network name")
                }
                network.Init()
                err := network.CreateNetwork(context.String("driver"), context.String("subnet"), context.Args()[0])
                if err != nil {
                    return fmt.Errorf("create network error: %+v", err)
                }
                return nil
            },
        },
        {
            Name: "list",
            Usage: "list container network",
            Action:func(context *cli.Context) error {
                network.Init()
                network.ListNetwork()
                return nil
            },
        },
        {
            Name: "remove",
            Usage: "remove container network",
            Action:func(context *cli.Context) error {
                if len(context.Args()) < 1 {
                    return fmt.Errorf("Missing network name")
                }
                network.Init()
                err := network.DeleteNetwork(context.Args()[0])
                if err != nil {
                    return fmt.Errorf("remove network error: %+v", err)
                }
                return nil
            },
        },
    },
}

2.2 测试

root@nicktming:~/go/src/github.com/nicktming/mydocker# ip link
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0:  mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:58:9a:c3 brd ff:ff:ff:ff:ff:ff
3: docker0:  mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
root@nicktming:~/go/src/github.com/nicktming/mydocker# 
root@nicktming:~/go/src/github.com/nicktming/mydocker# iptables -t nat -vnL POSTROUTING --line
Chain POSTROUTING (policy ACCEPT 2 packets, 120 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       14   998 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker network create --driver bridge --subnet 192.168.10.1/24 testbridge01
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker network list
NAME           IpRange           Driver
testbridge01   192.168.10.1/24   bridge
root@nicktming:~/go/src/github.com/nicktming/mydocker# ifconfig testbridge01
testbridge01 Link encap:Ethernet  HWaddr 02:f4:c8:97:df:39  
          inet addr:192.168.10.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
root@nicktming:~/go/src/github.com/nicktming/mydocker# iptables -t nat -vnL POSTROUTING --line
Chain POSTROUTING (policy ACCEPT 2 packets, 135 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       14   998 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
2        0     0 MASQUERADE  all  --  *      !testbridge01  192.168.10.0/24      0.0.0.0/0           
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker network remove testbridge01
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker network list
NAME        IpRange     Driver

3. 创建容器

现在已经可以创建网络了, 以网桥为例, 创建网络的时候已经在宿主机上配置好了网桥. 下一步创建容器的时候会启动一个新的network namespace, 因此只需要在network namespace配置好网络和路由就可以了. 在前面几篇文章已经分析过了.

3.1 修改Run命令

增加netp参数.

var RunCommand = cli.Command{
    Name: "run",
    Flags: []cli.Flag {
        ...
        cli.StringFlag{
            Name:  "net",
            Usage: "container network",
        },
        cli.StringSliceFlag{
            Name: "p",
            Usage: "port mapping",
        },
        ...
    },
    Action: func(c *cli.Context) error {
        ...
        network := c.String("net")
        portMapping := c.StringSlice("p")
        ...

        Run(command, tty, &cg, rootPath, volumes, containerName, imageName, envSlice, network, portMapping)
        return nil
    },
}

修改Run方法

func Run(command string, tty bool, cg *cgroups.CroupManger, rootPath string, volumes []string, containerName, imageName string, envSlice []string, nw string, portMapping []string)  {

    ...
    /**
     *   Start() will not block, so it needs to use Wait()
     *   Run() will block
     */
    if err := cmd.Start(); err != nil {
        log.Printf("Run Start err: %v.\n", err)
        log.Fatal(err)
    }

    if nw != "" {
        // config container network
        network.Init()
        containerInfo := &container.ContainerInfo{
            Id:          id,
            Pid:         strconv.Itoa(cmd.Process.Pid),
            Name:        containerName,
            PortMapping: portMapping,
        }
        if err := network.Connect(nw, containerInfo); err != nil {
            log.Printf("Error Connect Network %v", err)
            return
        }
    }

    ...
}

在这里修改了一下ContainerUUID方法, 因为之前生成UUID方法是当前时间加一个一个随机数, 由于Veth设备的名字会取前5位, 所以启动很多容器的时候设备名都是一样的, 会报错.

func ContainerUUID() string {
    //str := time.Now().UnixNano()
    //containerId := fmt.Sprintf("%d%d", str, int(math.Abs(float64(rand.Intn(10)))))
    ////log.Printf("containerId:%s\n", containerId)
    //return containerId
    letterBytes := "1234567890"
    rand.Seed(time.Now().UnixNano())
    b := make([]byte, 10)
    for i := range b {
        b[i] = letterBytes[rand.Intn(len(letterBytes))]
    }
    return string(b)
}

3.2 测试

root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -p 80:80 -net testbridge01 busybox /bin/sh
2019/05/09 22:47:17 rootPath is empaty, set rootPath: /nicktming
2019/05/09 22:47:17 current path: /nicktming/mnt/15574132372127349531.
/ # ifconfig
cif-15574 Link encap:Ethernet  HWaddr 0A:A9:1E:91:0B:BD  
          inet addr:192.168.10.3  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::8a9:1eff:fe91:bbd/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:508 (508.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.1    0.0.0.0         UG    0      0        0 cif-15574
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 cif-15574
/ # ping -c 1 192.168.10.3
PING 192.168.10.3 (192.168.10.3): 56 data bytes
64 bytes from 192.168.10.3: seq=0 ttl=64 time=0.042 ms

--- 192.168.10.3 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.042/0.042/0.042 ms
/ # ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.039 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.039/0.039/0.039 ms
/ # ping -c 1 192.168.10.1
PING 192.168.10.1 (192.168.10.1): 56 data bytes
64 bytes from 192.168.10.1: seq=0 ttl=64 time=0.067 ms

--- 192.168.10.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.067/0.067/0.067 ms
/ # ping -c 1 172.19.16.7
PING 172.19.16.7 (172.19.16.7): 56 data bytes
64 bytes from 172.19.16.7: seq=0 ttl=64 time=0.055 ms

--- 172.19.16.7 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.055/0.055/0.055 ms
/ # echo "nameserver 183.60.83.19" >> /etc/resolv.conf 
/ # echo "nameserver 183.60.82.98" >> /etc/resolv.conf 
/ # 
/ # cat /etc/resolv.conf 
nameserver 183.60.83.19
nameserver 183.60.82.98
/ # ping -c 1 www.baidu.com
PING www.baidu.com (119.63.197.139): 56 data bytes
64 bytes from 119.63.197.139: seq=0 ttl=51 time=53.213 ms

--- www.baidu.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 53.213/53.213/53.213 ms
/ # nc -lp 80

在另外一台机器访问该容器的服务

telnet 150.109.72.88 80
Trying 150.109.72.88...
Connected to 150.109.72.88.
Escape character is '^]'.
hello world!

容器中可以看到

/ # nc -lp 80
hello world!

容器之间访问

root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -net testbridge01 busybox /bin/sh
2019/05/09 23:06:18 rootPath is empaty, set rootPath: /nicktming
2019/05/09 23:06:18 current path: /nicktming/mnt/7484077863.
/ # ifconfig
cif-74840 Link encap:Ethernet  HWaddr 0E:05:F7:07:54:73  
          inet addr:192.168.10.7  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::c05:f7ff:fe07:5473/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:418 (418.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # ping -c 1 192.168.10.3
PING 192.168.10.3 (192.168.10.3): 56 data bytes
64 bytes from 192.168.10.3: seq=0 ttl=64 time=0.080 ms

--- 192.168.10.3 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.080/0.080/0.080 ms

宿主机访问容器

root@nicktming:~/go/src/github.com/nicktming/mydocker# ping -c 1 192.168.10.3
PING 192.168.10.3 (192.168.10.3) 56(84) bytes of data.
64 bytes from 192.168.10.3: icmp_seq=1 ttl=64 time=0.051 ms

--- 192.168.10.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.051/0.051/0.051/0.000 ms

Iptables查看

root@nicktming:~/go/src/github.com/nicktming/mydocker# iptables -t nat -vnL PREROUTING
Chain PREROUTING (policy ACCEPT 425 packets, 18063 bytes)
 pkts bytes target     prot opt in     out     source               destination         
1614K   62M DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
    2   104 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:192.168.10.3:80
root@nicktming:~/go/src/github.com/nicktming/mydocker# 

4. 参考

1. 自己动手写docker.(基本参考此书,加入一些自己的理解,加深对docker的理解)

5. 全部内容

[mydocker]---网络实现测试_第1张图片
mydocker.png

1. [mydocker]---环境说明
2. [mydocker]---urfave cli 理解
3. [mydocker]---Linux Namespace
4. [mydocker]---Linux Cgroup
5. [mydocker]---构造容器01-实现run命令
6. [mydocker]---构造容器02-实现资源限制01
7. [mydocker]---构造容器02-实现资源限制02
8. [mydocker]---构造容器03-实现增加管道
9. [mydocker]---通过例子理解存储驱动AUFS
10. [mydocker]---通过例子理解chroot 和 pivot_root
11. [mydocker]---一步步实现使用busybox创建容器
12. [mydocker]---一步步实现使用AUFS包装busybox
13. [mydocker]---一步步实现volume操作
14. [mydocker]---实现保存镜像
15. [mydocker]---实现容器的后台运行
16. [mydocker]---实现查看运行中容器
17. [mydocker]---实现查看容器日志
18. [mydocker]---实现进入容器Namespace
19. [mydocker]---实现停止容器
20. [mydocker]---实现删除容器
21. [mydocker]---实现容器层隔离
22. [mydocker]---实现通过容器制作镜像
23. [mydocker]---实现cp操作
24. [mydocker]---实现容器指定环境变量
25. [mydocker]---网际协议IP
26. [mydocker]---网络虚拟设备veth bridge iptables
27. [mydocker]---docker的四种网络模型与原理实现(1)
28. [mydocker]---docker的四种网络模型与原理实现(2)
29. [mydocker]---容器地址分配
30. [mydocker]---网络net/netlink api 使用解析
31. [mydocker]---网络实现
32. [mydocker]---网络实现测试

你可能感兴趣的:([mydocker]---网络实现测试)