5、Docker容器网络

使用Linux进行IP层网络管理的指     http://linux-ip.net/html/

# yum install iproute   

http://linux-ip.net/html/tools-ip-route.html

https://segmentfault.com/a/1190000000638244

参考:https://cizixs.com/2017/02/10/network-virtualization-network-namespace/

network namespace 是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自的网络栈信息。不管是虚拟机还是容器,运行的时候仿佛自己就在独立的网络中。

介绍 network namespace 的基本概念和用法,network namespace 是 linux 内核提供的功能,借助 ip 命令来完成各种操作。ip 命令来自于 iproute2 安装包,一般系统会默认安装,如果没有的话,请读者自行安装。

NOTE:ip 命令因为需要修改系统的网络配置,默认需要 sudo 权限。这篇文章使用 root 用户执行,请不要在生产环境或者重要的系统中用 root 直接执行,以防产生错误。

ip 命令管理的功能很多,和 network namespace 有关的操作都是在子命令 ip netns 下进行的,可以通过 ip netns help` 查看所有操作的帮助信息。

默认情况下,使用 ip netns 是没有网络 namespace 的,所以 ip netns ls 命令看不到任何输出。

# ip
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
       ip [ -force ] -batch filename
where  OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |
                   tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |
                   netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |
                   vrf }
       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |
                    -h[uman-readable] | -iec |
                    -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |
                    -4 | -6 | -I | -D | -B | -0 |
                    -l[oops] { maximum-addr-flush-attempts } | -br[ief] |
                    -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |
                    -rc[vbuf] [size] | -n[etns] name | -a[ll] |?-c[olor]}
# ip netns help
Usage: ip netns list
       ip netns add NAME
       ip netns set NAME NETNSID
       ip [-all] netns delete [NAME]
       ip netns identify [PID]
       ip netns pids NAME
       ip [-all] netns exec [NAME] cmd ...
       ip netns monitor
       ip netns list-id
创建 network namespace 也非常简单,直接使用 ip netns add 后面跟着要创建的 namespace 名称。如果相同名字的 namespace 已经存在,命令会报 Cannot create namespace 的错误。

# ip netns add r1
# ip netns list
    r1

ip netns 命令创建的 network namespace 会出现在 /var/run/netns/ 目录下,如果需要管理其他不是 ip netns 创建的 network namespace,只要在这个目录下创建一个指向对应 network namespace 文件的链接就行。

有了自己创建的 network namespace,我们还需要看看它里面有哪些东西。对于每个 network namespace 来说,它会有自己独立的网卡、路由表、ARP 表、iptables 等和网络相关的资源。ip命令提供了 ip netns exec 子命令可以在对应的 network namespace 中执行命令,比如我们要看一下这个 network namespace 中有哪些网卡。更棒的是,要执行的可以是任何命令,不只是和网络相关的(当然,和网络无关命令执行的结果和在外部执行没有区别)。比如下面例子中,执行 bash 命令了之后,后面所有的命令都是在这个 network namespace 中执行的,好处是不用每次执行命令都要把 ip netns exec NAME 补全,缺点是你无法清楚知道自己当前所在的 shell,容易混淆。

[@node3 ~]# ip netns exec r1 ifconfig
[@node3 ~]# ip netns exec r1 ip addr
     1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

[@node3 ~]# ip netns exec r1 bash
[@node3 ~]# ip addr
    1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

每个 namespace在创建的时候会自动创建一个 lo 的 interface,它的作用和 linux 系统中默认看到的 lo 一样,都是为了实现 loopback 通信。如果希望 lo 能工作,不要忘记启用它:

[root@node3 ~]# ip netns exec r1 ip link set lo up

默认情况下,network namespace 是不能和主机网络,或者其他 network namespace 通信的。

# ip link help
Usage: ip link add [link DEV] [ name ] NAME
                   [ txqueuelen PACKETS ]
                   [ address LLADDR ]
                   [ broadcast LLADDR ]
                   [ mtu MTU ] [index IDX ]
                   [ numtxqueues QUEUE_COUNT ]
                   [ numrxqueues QUEUE_COUNT ]
                   type TYPE [ ARGS ]

       ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]

       ip link set { DEVICE | dev DEVICE | group DEVGROUP }
                      [ { up | down } ]
                      [ type TYPE ARGS ]
                      [ arp { on | off } ]
                      [ dynamic { on | off } ]
                      [ multicast { on | off } ]
                      [ allmulticast { on | off } ]
                      [ promisc { on | off } ]
                      [ trailers { on | off } ]
                      [ carrier { on | off } ]
                      [ txqueuelen PACKETS ]
                      [ name NEWNAME ]
                      [ address LLADDR ]
                      [ broadcast LLADDR ]
                      [ mtu MTU ]
                      [ netns { PID | NAME } ]
                      [ link-netnsid ID ]
              [ alias NAME ]
                      [ vf NUM [ mac LLADDR ]
                   [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]
                   [ rate TXRATE ]
                   [ max_tx_rate TXRATE ]
                   [ min_tx_rate TXRATE ]
                   [ spoofchk { on | off} ]
                   [ query_rss { on | off} ]
                   [ state { auto | enable | disable} ] ]
                   [ trust { on | off} ] ]
                   [ node_guid { eui64 } ]
                   [ port_guid { eui64 } ]
              [ xdp { off |
                  object FILE [ section NAME ] [ verbose ] |
                  pinned FILE } ]
              [ master DEVICE ][ vrf NAME ]
              [ nomaster ]
              [ addrgenmode { eui64 | none | stable_secret | random } ]
                      [ protodown { on | off } ]

       ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]

       ip link xstats type TYPE [ ARGS ]

       ip link afstats [ dev DEVICE ]

       ip link help [ TYPE ]

TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
          bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |
          gre | gretap | ip6gre | ip6gretap | vti | nlmon | team_slave |
          bond_slave | ipvlan | geneve | bridge_slave | vrf | macsec }

network namespace 之间通信

有了不同 network namespace 之后,也就有了网络的隔离,但是如果它们之间没有办法通信,也没有实际用处。要把两个网络连接起来,linux 提供了 veth pair 。可以把 veth pair 当做是双向的 pipe(管道),从一个方向发送的网络数据,可以直接被另外一端接收到;或者也可以想象成两个 namespace 直接通过一个特殊的虚拟网卡连接起来,可以直接通信。

使用 ip link add type veth 来创建一对 veth pair 出来,需要记住的是 veth pair 无法单独存在,删除其中一个,另一个也会自动消失。

# ip link add name veth1.1 type veth peer name veth1.2

# ip link sh

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:82:17:a2 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 02:42:1a:5e:9d:4e brd ff:ff:ff:ff:ff:ff
4: [email protected]: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000    //此时veth1.1和veth1.2都是在宿主机上
    link/ether 36:59:f5:02:39:1d brd ff:ff:ff:ff:ff:ff
5: [email protected]: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 0e:b8:58:dd:5d:5a brd ff:ff:ff:ff:ff:ff
# ip addr list
2: veth1.2@veth1.1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000 //此时都是没有启动的 link/ether d2:e2:d8:fd:50:60 brd ff:ff:ff:ff:ff:ff 3: veth1.1@veth1.2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 2a:b1:4b:19:fa:b8 brd ff:ff:ff:ff:ff:ff

创建 veth pair 的时候可以自己指定它们的名字,比如 ip link add veth1.1 type veth peer name veth1.2 创建出来的两个名字就是 veth1.1 和 veth1.2 。

如果 pair 的一端接口处于 DOWN 状态,另一端能自动检测到这个信息,并把自己的状态设置为 NO-CARRIER

创建结束之后,能看到名字为 veth1.1 和 veth1.2 两个网络接口。

# ip link help

Usage: ip link add [link DEV] [ name ] NAME
                  

       ip link set { DEVICE | dev DEVICE | group DEVGROUP }
                      [ { up | down } ]
                      [ type TYPE ARGS ]
                      [ arp { on | off } ]
                      [ dynamic { on | off } ]
                      [ multicast { on | off } ]
                      [ allmulticast { on | off } ]
                      [ promisc { on | off } ]
                      [ trailers { on | off } ]
                      [ carrier { on | off } ]
                      [ txqueuelen PACKETS ]
                      [ name NEWNAME ]
                      [ address LLADDR ]
                      [ broadcast LLADDR ]
                      [ mtu MTU ]
                      [ netns { PID | NAME } ]
                      [ link-netnsid ID ]
              [ alias NAME ]
                      [ vf NUM [ mac LLADDR ]
                

TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
          bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |
          gre | gretap | ip6gre | ip6gretap | vti | nlmon | team_slave |
          bond_slave | ipvlan | geneve | bridge_slave | vrf | macsec }

接下来,要做的是把veth1.2放到namespace --> r1,把veth1.1留在宿主机上,这个可以使用 ip link set DEV netns NAME 来实现

# ip link set dev veth1.2 netns r1

# ip link sh

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:82:17:a2 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 02:42:1a:5e:9d:4e brd ff:ff:ff:ff:ff:ff
5: veth1.1@if4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000    //此时宿主机空间只有veth1.1了
    link/ether 0e:b8:58:dd:5d:5a brd ff:ff:ff:ff:ff:ff link-netnsid 0

# ip netns exec r1 ifconfig -a    //一个设备只能属于一个名称空间,查看r1名称空间信息

lo: flags=8<LOOPBACK>  mtu 65536
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth1.2: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 36:59:f5:02:39:1d  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 

猜你喜欢

转载自www.cnblogs.com/hanshanxiaoheshang/p/10414118.html