docker网络配置

目录

容器网络

docker的四种网络模式

bridge 模式

none 模式

host 模式

container 模式

ip netns命令

创建Network Namespace

操作Network Namespace

转移设备

veth pair

创建veth pair

实现Network Namespace间通信

veth设备重命名


docker的四种网络模式

ocker 有 bridge、none、host、container 四种网络模式,提供网络隔离、端口映射、容器间互通网络等各种支持,下面开门见山地直接介绍这四种网络模式。

这四种网络模式可以通过启动容器的时候指定,其命令或参数个数如下:

网络模式 参数 说明
host模式 -–net=host 容器和宿主机共享 Network namespace。
container模式 –-net={id} 容器和另外一个容器共享 Network namespace。 kubernetes 中的pod就是多个容器共享一个 Network namespace。
none模式 –-net=none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,配置IP等。
bridge模式 -–net=bridge 默认为该模式,通过 -p 指定端口映射。

这四种模式可以理解成 Docker 怎么虚拟化容器的网络,隔离程度和共享程度。

bridge 模式

使用 Docker 创建一个 bridge 模式的容器命令格式如下:

 [root@master ~]# docker run -itd --name httpd --rm tangyuxuan1/httpd:v3
 #-rm 容器停止就删除   
 33788df813689d55ee3eb2a13ed28a6321b868c9481dbb89271455f77fa82c68
 [root@master ~]# docker exec -it httpd /bin/bash
 [root@33788df81368 /]# ip a
 8: eth0@if9:  mtu 1500 qdisc noqueue state UP group default 
     link/ether 02:42: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
 [root@master ~]# docker container ls -a
 CONTAINER ID   IMAGE                  COMMAND                  CREATED              STATUS              PORTS     NAMES
 33788df81368   tangyuxuan1/httpd:v3   "/root/httpd.sh -f -…"   About a minute ago   Up About a minute             httpd
 [root@master ~]# 
 # 在创建容器时添加--network bridge与不加--network选项效果是一致的

bridge 模式称为网桥模式,首先 Docker 会在主机上创建一个名为 docker0 的虚拟网桥,这个虚拟网络处于七层网络模型的数据链路层,每当创建一个新的容器时,容器都会通过 docker0 与主机的网络连接,docker0 相当于网桥。

使用 bridge 模式新创建的容器,其内部都有一个虚拟网卡,名为 eth0,容器之间可以通过 172.17.x.x 相互访问。

一般情况下,网桥默认 IP 范围是 172.17.x.x ,可以在宿主机执行 ifpconfig 命令查看所有网卡,里面会包含 Docker 容器的虚拟网卡,可以查看某个容器的 ip。

使用了 bride 创建的容器,其网络与主机以及其他容器隔离,以太网接口、端口、路由表以及 DNS配置 都是独立的。每个容器都好像是一个独立的主机 ,这便是 bridge(网桥)的作用。但是因为 docker0 的存在,对于容器来说,可以通过 ip 访问别的容器。

docker网络配置_第1张图片

 

可以通过 172.17.0.3 访问容器2,同样,主机也可以使用这个 ip 访问容器2 中的服务。

bridge 模式 是默认模式,即使是 使用 docker run -itd nginx:latest 命令启动容器,也会创建一个虚拟 IP。

none 模式

这种网络模式下容器只有 lo 回环网络,没有其他网卡,这种类型的网络没有办法联网,外界也无法访问它,封闭的网络能很好地保证容器的安全性。

创建 none 网络的容器:

  创建容器命令如下:
  docker run -itd -network none --name httpd tangyuxuan1/httpd:v3
 ​
 -------------
 #演示:
 [root@master ~]# docker run -itd --network none --name httpd --rm tangyuxuan1/httpd:v3
 70779488b0d92207feb5bc623f14d0a836f4e416fe5172ba85eb61cdf233362c
 [root@master ~]# docker exec -it httpd  /bin/bash
 [root@70779488b0d9 /]# ip a
 1: lo:  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
 [root@70779488b0d9 /]# 
 ​
 ​

 

host 模式

host 模式会让容器与主机共享网络,此时映射的端口可能会生产冲突,但是容器的其余部分(文件系统、进程等)依然是隔离的,此时容器与宿主机共享网络。

docker网络配置_第2张图片

 

 [root@master ~]# docker run -itd --name httpd2 --rm --network host tangyuxuan1/httpd:v3
 9eba44b8b9191fe01f1df7f69c48574b0fa3396eb971b6a44b15eed89e836b15
 [root@master ~]# docker exec -it httpd2 /bin/bash
 [root@master /]# ip a
 1: lo:  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:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
     link/ether 00:0c:29:7f:82:fa brd ff:ff:ff:ff:ff:ff
     inet 192.168.245.128/24 brd 192.168.245.255 scope global noprefixroute dynamic ens33
        valid_lft 1611sec preferred_lft 1611sec
     inet6 fe80::20c:29ff:fe7f:82fa/64 scope link noprefixroute 
        valid_lft forever preferred_lft forever
 3: docker0:  mtu 1500 qdisc noqueue state DOWN group default 
     link/ether 02:42:f7:f8:1f:91 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:f7ff:fef8:1f91/64 scope link 
        valid_lft forever preferred_lft forever

此时如果我们在这个容器中启动一个http站点,我们就可以直接用宿主机的IP直接在浏览器中访问这个容器中的站点了。

container 模式

container 模式可以让多个容器之间相互通讯,即容器之间共享网络。

首先启动一个 A 容器,A 一般为 bridge 网络,接着 B 使用 –-net={id} 连接到 A 中,使用 A 的虚拟网卡,此时 A、B 共享网络,可以接着加入 B、C、D 等容器。

docker网络配置_第3张图片

 

 [root@master ~]# docker run -itd --name httpd1 --rm tangyuxuan1/httpd:v3
 d032b6652abddd7343a176b621dec0ffeeb8a24690f2038d175328bb268dd43f
 [root@master ~]# docker run -itd --name httpd2 --rm tangyuxuan1/httpd:v3
 eb0bad2427181ba89b5c7a2d70e209d57268ce3e078cce255db8f37171ab19aa
 [root@master ~]# 
 这个时候没有network选项,就代表着这两个容器用的是默认模式,IP肯定不同,也就是并没有共享网络
 再创建一个httpd3
 [root@master ~]# docker run -itd --name httpd3 --rm --network container:httpd1 tangyuxuan1/httpd:v3
 220bc1f2c8cafd02a9306a1b23d3387ad8ae9f55a33fbf588ca48588cc5ae7a1
 [root@master ~]# docker exec -it httpd1 /bin/bash
 [root@d032b6652abd /]# ip a
 ----
     inet 172.17.0.2/16 brd 172.17.255.255 scope global 
     ----
 [root@master ~]# docker run -itd --name httpd4 --rm --network container:httpd1 tangyuxuan1/httpd:v3
 ----
     inet 172.17.0.2/16 brd 172.17.255.255 scope global 
     ----
 ​

## linux内核实现名称空间的创建

ip netns命令

ip netns 命令用来管理 network namespace。它可以创建命名的 network namespace,然后通过名字来引用 network namespace,所以使用起来很方便。

ip netns 命令格式如下:

 ip [ OPTIONS ] netns { COMMAND | help }

可以通过 help 命令查看 ip netns 所有操作的帮助信息:

 [root@master ~]# ip netns help
 Usage:  ip netns list
         ip netns add NAME
         ip netns attach NAME PID
         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 [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]
 NETNSID := auto | POSITIVE-INT

默认情况下,子进程继承其父进程的 network namespace。也就是说,如果不显式创建新的 network namespace,所有进程都从 init 进程继承相同的默认 network namespace。 根据约定,命名的 network namespace 是可以打开的 /var/run/netns/ 目录下的一个对象。比如有一个名称为 net1 的 network namespace 对象,则可以由打开 /var/run/netns/net1 对象产生的文件描述符引用 network namespace net1。通过引用该文件描述符,可以修改进程的 network namespace。

创建Network Namespace

通过命令创建一个名为ns0的命名空间:

 [root@master ~]# ip netns list
 [root@master ~]# ip netns add ns0
 [root@master ~]# ip netns list
 ns0

新创建的Network Namespace会出现在/var/run/netns/目录下。如果相同名字的namespace已经存在,会提示错误。

 [root@master ~]# ip netns add ns0
 Cannot create namespace file "/var/run/netns/ns0": File exists
 [root@master 

对于每个 Network Namespace 来说,它会有自己独立的网卡、路由表、ARP 表、iptables 等和网络相关的资源。

操作Network Namespace

ip命令提供了ip netns exec子命令可以在对应的 Network Namespace 中执行命令。

查看新创建 Network Namespace 的网卡信息

 [root@master ~]# ip netns exec ns0 ip addr
 1: lo:  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

可以看到,新创建的Network Namespace中会默认创建一个lo回环网卡,此时网卡处于关闭状态。此时,尝试去ping该lo回环网卡,会提示:

 ot@master ~]# ip netns exec ns0 ping 127.0.0.1
 connect: Network is unreachable

通过下面的命令启用lo回环网卡:

 [root@master ~]# ip netns exec ns0 ip link set lo up
 [root@master ~]# ip netns exec ns0 ping 127.0.0.1
 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.024 ms
 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.032 ms

转移设备

我们可以在不同的 Network Namespace 之间转移设备(如veth)。由于一个设备只能属于一个 Network Namespace ,所以转移后在这个 Network Namespace 内就看不到这个设备了。

其中,veth设备属于可转移设备,而很多其它设备(如lo、vxlan、ppp、bridge等)是不可以转移的。

veth pair

veth pair是成对出现的一种虚拟网络设备接口,一端连着网络协议栈,一端彼此相连。如下图所示:

docker网络配置_第4张图片

由于它的这个特性,常常被用于构建虚拟网络拓扑。例如连接两个不同的网络命名空间(netns),连接docker容器,连接网桥(Bridge)等,其中一个很常见的案例就是OpenStack Neutron底层用它来构建非常复杂的网络拓扑。

创建veth pair

 [root@master ~]# ip link add type veth
 [root@master ~]# ip a
 4: veth0@veth1:  mtu 1500 qdisc noop state DOWN group default qlen 1000
     link/ether 1e:19:b3:0b:12:61 brd ff:ff:ff:ff:ff:ff
 5: veth1@veth0:  mtu 1500 qdisc noop state DOWN group default qlen 1000
     link/ether b2:02:3f:06:43:42 brd ff:ff:ff:ff:ff:ff
 此时系统中新增了一对veth pair,将veth0和veth1两个虚拟网卡连接了起来,此时这对 veth pair 处于”未启用“状态。

实现Network Namespace间通信

下面我们利用veth pair实现两个不同的 Network Namespace 之间的通信。刚才我们已经创建了一个名为ns0的 Network Namespace,下面再创建一个信息Network Namespace,命名为ns1

 [root@master ~]# ip netns add ns1
 [root@master ~]# ip netns list
 ns1
 ns0
 ​
 #将veth0加入到ns0,将veth1加入到ns1
 [root@master ~]# ip link set veth0 netns ns0
 [root@master ~]# ip link set veth1 netns ns1
 ​
 #分别为这对veth pair配置上ip地址,并启用它们
 [root@master ~]# ip netns exec ns0 ip link set veth0 up
 [root@master ~]# ip netns exec ns0 ip addr add 192.168.245.1/24 dev veth0
 [root@master ~]# ip netns exec ns1 ip link set lo up
 [root@master ~]# ip netns exec ns1 ip link set veth1 up
 [root@master ~]# ip netns exec ns1 ip addr add 192.168.245.2/24 dev veth1
 ​
 #看一下状态
 [root@master ~]# ip netns exec ns0 ip a
 1: lo:  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
 4: veth0@if5:  mtu 1500 qdisc noqueue state UP group default qlen 1000
     link/ether 1e:19:b3:0b:12:61 brd ff:ff:ff:ff:ff:ff link-netns ns1
     inet 192.168.245.1/24 scope global veth0
        valid_lft forever preferred_lft forever
     inet6 fe80::1c19:b3ff:fe0b:1261/64 scope link 
        valid_lft forever preferred_lft forever
 [root@master ~]# 
 #已经成功启用了这个veth pair,并为每个veth设备分配了对应的ip地址。我们尝试在ns1中访问ns0中的ip地址:
 [root@master ~]# ip netns exec ns1 ping 192.168.245.1
 PING 192.168.245.1 (192.168.245.1) 56(84) bytes of data.
 64 bytes from 192.168.245.1: icmp_seq=1 ttl=64 time=0.033 ms
 64 bytes from 192.168.245.1: icmp_seq=2 ttl=64 time=0.037 ms
 #可以互通

veth设备重命名

 root@master ~]# ip netns exec ns0 ip link set veth0 down
 [root@master ~]# ip netns exec ns0 ip link set dev veth0 name eth0
 [root@master ~]# ip netns exec ns0 ifconfig -a
 eth0: flags=4098  mtu 1500
         inet 192.168.245.1  netmask 255.255.255.0  broadcast 0.0.0.0
         ether 1e:19:b3:0b:12:61  txqueuelen 1000  (Ethernet)
         RX packets 17  bytes 1286 (1.2 KiB)
         RX errors 0  dropped 0  overruns 0  frame 0
         TX packets 17  bytes 1286 (1.2 KiB)
         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 ​
 lo: flags=73  mtu 65536
         inet 127.0.0.1  netmask 255.0.0.0
         inet6 ::1  prefixlen 128  scopeid 0x10
         loop  txqueuelen 1000  (Local Loopback)
         RX packets 4  bytes 336 (336.0 B)
         RX errors 0  dropped 0  overruns 0  frame 0
         TX packets 4  bytes 336 (336.0 B)
         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

你可能感兴趣的:(开源软件使用,docker,容器,运维)