Kubernetes网络自学系列 | 最常用的Docker网络技巧

Posted COCOgsta

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes网络自学系列 | 最常用的Docker网络技巧相关的知识,希望对你有一定的参考价值。

素材来源:《Kubernetes网络权威指南》

一边学习一边整理内容,并与大家分享,侵权即删,谢谢支持!

附上汇总贴:Kubernetes网络自学系列 | 汇总_COCOgsta的博客-CSDN博客


2.3 最常用的Docker网络技巧

Docker容器既可以让外部访问,也可以访问外网,还可以容器间相互访问。Docker本身提供了很多对网络的配置命令。本节将简单介绍Docker中的网络配置、网络端口映射、容器互联、DNS配置等实战知识。bridge模式是Docker容器的默认组网模式,因此没有特别说明的情况下下文使用的都是bridge网络模式。

2.3.1 查看容器IP

查看一个正在运行的容器被分配了什么IP地址,这个需求既简单又常见。一般有两种方式:从外面看和从里面看。从外面看即使用docker inspect命令。例如:

其实也等价于:

一般情况下,默认Docker分配的IP地址范围是172.17.0.0/16,那么第一个IP地址172.17.0.1是分配给docker0的,第一个容器将会被分到172.17.0.2,第二个容器是172.17.0.3,依此类推。

从里面看就是指通过docker exec或docker attach进入容器,通过ip或ifconfig命令查看,这里省略演示。

2.3.2 端口映射

在使用docker run的时候可以使用-P或者-p命令进行容器和主机之间的端口映射。使用-P(大写)不需要指定任何映射关系,默认情况下,Docker会随机将一个49000 49900的端口映射到内部容器开放的网络端口。使用-p(小写)则需要指定主机的端口应该映射到容器的哪个端口。使用格式如下所示:

注:-p的格式是hostport:containerport。

通过docker ps查看:

Docker容器端口映射原理都是在本地的iptable的nat表中添加相应的规则,将访问本机IP地址:hostport的网包进行一次DNAT,转换成容器IP:containerport。可以通过以下命令查看iptables得到验证:

如上所示,DNAT发生在DOCKER这条iptables链,它有两处引用,分别是PREROUTING链和OUTPUT链,意味着从外面发到本机和本地进程访问本机(由iptables匹配规则ADDRTYPE match dst-type LOCAL指定)的1234端口的包目的地址都会被修改成172.17.0.2:80。

除了使用docker ps命令给出容器的端口映射关系,还可以使用docker port命令查看容器的端口在主机上的映射,形如:

2.3.3 访问外网

怎么从容器内访问外网呢?一般情况下需要两个因素:ip_forward和SNAT/MASQUERADE。在默认情况下,容器可以访问外部网络的连接,因为容器的默认网络接口为docker0网桥上的接口,即主机上的本地接口。其原理是通过Linux系统的转发功能实现的(把主机当交换机)。如果发现容器内访问不了外网,则需要确认系统的ip_forward是否已打开。

或者检查docker daemon启动的时候--ip-forward参数是不是被设置成false了,如果是的话,则需要设置--ip-forward=true重新启动Docker,Docker会打开主机的ip forward。

至于SNAT/MASQUERADE,Docker会自动在iptables的POSTROUTING链上创建形如下面的规则:

即从容器网段出来访问外网的包,都要做一次MASQUERADE,即出去的包都用主机的IP地址替换源地址。

2.3.4 DNS和主机名

容器中的DNS和主机名一般通过三个系统配置文件维护。分别是/etc/resolv.conf、/etc/hosts和/etc/hostname,其中:

·/etc/resolv/conf在创建容器的时候,默认与本地主机/etc/resolv.conf保持一致;

·/etc/hosts中则记载了容器自身的一些地址和名称;

·/etc/hostname中记录容器的主机名。

用户如果直接在容器内修改这三个文件会立即生效,但容器重启后修改又会失效。如果想统一、持久化配置所有容器的DNS,通过修改主机Docker Daemon的配置文件(一般是/etc/docker/daemon.json)的方式指定除主机/etc/resolv.conf的其他DNS信息:

同时,也可以在docker run时使用--dns=address参数来指定。

至于配置Docker容器的主机名,则可以在运行docker run创建容器时使用参数-h hostname或者--hostname hostname配置。

2.3.5 自定义网络

上文提到Docker默认会创建一个docker0网桥,其实这个网桥和Docker容器使用的网段都是可以自定义的。

当启动Docker Daemon时,可以对docker0网桥进行配置,例如:

·--bip=CIDR,即配置接到这个网桥上的Docker容器的IP地址网段,例如192.168.1.0/24;

·--mtu=BYTES,配置docker0网桥的MTU(最大传输单元)。

如果已经使用默认配置启动Docker Daemon,又希望有个自定义的容器网段却不想重启Docker Daemon,那么可以通过再创建一个自定义的网络达成目的。简而言之,一个主机上Docker支持多个网络。

Docker的命令行工具支持直接操作网络,就像操作容器一样。用户创建一个网络可以使用下面的命令:

以上命令创建了一个名为mynet的网络,网络ID是3df48fd0c8dd...。该网络使用的是bridge模式,网段是172.25.0.0/16。不难猜测,该网络的第一个IP地址172.25.0.1应该是分配给网桥了。那么,这个bridge网络的网桥叫什么名字呢?可以通过ip addr命令查看:

如上所示,新创建bridge网络的网桥是br-3df48fd0c8dd(后面这串字符其实是网络ID的前半部分),配置的也是默认的1500 MTU。该网桥的IP地址果然是172.25.0.1。

想查看某个网络的详细信息,可以使用inspect子命令,就像inspect容器一样。命令如下:

也可以加上network前缀:

查看主机上有多少个docker network,可以使用以下命令:

DRIVER字段即使用的Docker容器网络模式。可能有读者会好奇,明明我只创建了一个自定义网络3df48fd0c8dd,如果再加上一个docker0所在的网络,那么上面列出的另外两个网络是由谁、在什么时候创建的呢?原来,默认情况下,Docker Daemon会预创建3个网络,分别使用对应的网络模式作为网络名称,即上面列出的bridge、host和null(对应none模式)。我们在用docker run命令启动容器时使用的--net或--network原来是在指定使用哪个网络!

如果希望删除某个网络,则只需使用network rm子命令,例如:

连接一个容器到网络中,用法如下:

将容器和网络断开,用法如下:

2.3.6 发布服务

这里先简单介绍Docker service的概念。首先,Docker service是Docker的一个子命令,如下所示:

Docker的service子命令是对Docker容器的一层封装,有点类似于Kubernetes的Service概念。一个结合network和service的例子如下:

以上三条命令,先创建一个Docker的网络,然后在这个网络里发布一个服务,最后将这个服务和容器绑定(也就是把这个容器加入刚创建的网络中),这样就达到了把容器当作服务发布的目的。

用下面这条命令可以一次性实现以上三个步骤的效果:

2.3.7 docker link:两两互联

首先声明,docker link是一个遗留的特性,在新版本的Docker中,一般不推荐使用。考 虑到link也算是Docker发明的一个比较有意思的功能,对后面理解Kubernetes Service也有一定帮助,本节将对其做简单介绍,重点阐述其实现机制。

简单地说,docker link就是把两个容器连起来,相互通信。link的使用方式如下:

上面这条命令alias是源容器在link下的别名。link方式最大的便利在于容器可以使用容器名进行通信,而不需要依赖IP地址。不过,link方式仅解决了单机容器间点对点的互联问题。

下面将用一个例子演示docker link的具体用法。首先,创建一个名为abc的容器:

然后,创建link到容器abc的容器efg,如下所示:

上面的命令创建并启动名为efg的容器,并把该容器和名为abc的容器链接起来。而--link abc:source的意思是将启动的abc作为源容器,source是该容器在link下的别名。换句话说,站在efg容器的角度看,abc和source都指向同一个容器,并且可以作为该容器的主机名。efg容器用这两个名字中的任意一个都可以与那个容器通信。我们进入efg这个容器ping容器abc和source,并查看结果:

可见,abc和source两个主机名都指向IP地址172.17.0.2。打开efg容器的host文件一探究竟:

我们可以发现接收容器(efg)的host文件里把源容器的ID(96f07804df65)、容器名(abc)和别名(source)都映射到172.17.0.2 IP地址。如果重启了源容器,则接收容器的/etc/hosts文件会自动更新源容器的新IP。

以上是关于Kubernetes网络自学系列 | 最常用的Docker网络技巧的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes网络自学系列 | 主角登场:Linux容器

Kubernetes网络自学系列 | 打通CNI与Kubernetes:Kubernetes网络驱动

Kubernetes网络自学系列 | 终于等到你:Kubernetes网络

Kubernetes网络自学系列 | Kubernetes网络策略:为你的应用保驾护航

Kubernetes网络自学系列 | iptables

Kubernetes网络自学系列 | Linux隧道网络的代表:VXLAN