初识网络协议:什么是容器

容器(Container)的思想是要变成软件交付的集装箱。而集装箱最重要的就是“打包”和“标准”两大特点。所谓打包,就是将所有的货物打包在一起,然后放到集装箱里面;所谓标准,就是集装箱的尺寸全部都是一样的。

对于容器而言,打包就是将货物封装起来,使货物之间互不干扰,相互隔离。隔离主要使用了两种技术,namespacecgroup

命名空间(namespace)

命名空间是用来解决在不同的空间里面,类名相同引起的冲突。这在很多编程语言里面都很常见,比如PHP。

在Linux下也是这样的,很多的资源都是全局的。比如进程有全局的进程ID,网络也有全局的路由表。但是,当一台Linux上跑多个进程的时候,如果我们觉得使用不同的路由策略,这些进程可能会冲突,那就需要将这个进程放在一个独立的namespace里面,这样就可以独立配置网络了。

Linux中网络的namespaceip netns命令操作。它可以创建、删除、查询namespace

机制网络(cgroup)

cgroup全称control groups,是Linux内核提供的一种可以限制、隔离进程使用的资源机制。

cgroup能控制哪些资源呢?它有很多子系统:

  • CPU子系统使用调度程序为进程控制CPU的访问;

  • cpuset,如果是多核心的CPU,这个子系统会为进程分配单独的CPU和内存;

  • memory子系统,设置进程的内存限制以及产生内存资源报告;

  • blkio子系统,设置限制每个块设备的输入输出控制;

  • net_cls,这个子系统使用等级识别符(classid)标记网络数据包,可允许Linux流量控制程序(tc)识别从具体cgroup中生成的数据包。

Docker

谈及容器,必然会说到docker。docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。

当我们使用docker run运行一个容器的时候,能看到这样一个拓扑结构。

这张图和之前虚拟机的图有点像,容器里面有张网卡,容器外面有张网卡。容器外的网卡连到docker0网桥,通过这个网桥,容器能够直接实现相互访问。

不过虚拟机的虚拟网卡是通过TUN/TAP设备虚拟出来的,而容器场景下并没有虚拟化软件,是通过创建一对veth pair的网卡实现的。从一边发包,另一边就能收到。使用ip link add创建好一对网卡后,一端打通到docker0网桥上,一端打通到容器里。

如何打通到容器里面?

每一个容器的启动都会对应一个namespace,在docker中,pid就是namespace的名字,可以通过如下命令获取。

此时创建的namespace不在默认路径下,所以ip netns看不到,需要ln软链接一下。这样就可以将另一端打通到容器里面了。

然后重命名容器内的网卡,并给容器内网卡设置IP地址,这样一台机器内部的容器就可以相互访问了。

访问外网的话有之前说过的桥接模式NAT模式,docker默认使用NAT模式。NAT模式分为SNATDNAT,如果是容器内部访问外部,需要通过SNAT,反过来外部访问容器内部,需要通过DNAT

如果在容器内部属于一个服务,例如上面部署一个Nginx(docker run --name nginx-test -p 18080:80 -d nginx),提供给外部进行访问,需要通过docker的端口映射技术,将容器内部的端口映射到物理机上来。

那端口是如何映射的呢?

docker有两种方式,一种是通过一个进程docker-proxy的方式,监听18080,转换为80端口。

另一种方式是通过DNAT方式,在-A PREROUTING阶段加一个规则,将到端口18080的访问DNAT成为到容器的私有网络的访问。

 

参考资料:《趣谈网络协议》

posted @ 2020-03-31 13:34  灯无焰  阅读(416)  评论(0编辑  收藏  举报