
最近,潭主陷于新云项目选型的工作中不能自拔。
为了多些挑战,特意选了自己并不擅长的容器和微服务,几圈工作下来,感觉学习曲线非常陡,只能硬着头破上。
技术欠缺是一部分原因,更重要的是对云厂商产品缺乏了解,经常被领导和厂商“挑战”。
这也是没办法的事,虽然学了不少新东西,但对很多技术的了解都浮于表面,缺少对基础细节的实操掌控。
从NSX到TanZu,统统不跟
从前在VMware时代运维虚拟化平台,其上的网络被VMware很好的屏蔽掉了,设计更多聚焦在Mgmt,Kernel和Service的规划上,即使后来有了SDN,在VxLAN模式下,感觉传统运维并不受影响。
遗憾的是当年我司止步于VMware的vSphere,并没有跟随其SDDC的脚步,以至于在NSX这个新物种上没有形成相应的技术积累。
前两年VMware为了应对云原生而推出了TanZu,也无法力挽狂澜,现在想来更多是大势已去的悲凉。
这就是云计算时代下的一个厂商的缩影,也是一个客户的缩影。
回看过往,即使客户赶上了云计算,因为这样那样的原因依旧走了不少弯路。
你的圈子,决定了你的方向
潭主在2015年开始接触容器,因为当时和Redhat合作紧密,上手的环境就选了OCP(OpenShift)。
那会儿很多技术不成熟,Docker也显得过于新潮,Openshift提供什么就用什么,以至于kubectl都被oc给屏蔽掉了。
现如今到了云原生时代,大家把注意力都投向了Kubernetes这样的新基建,技术工作的管理单元也从虚拟机转移到了Docker和Pod。
学习内容太多,计划分几期分享Kubernetes的网络知识,其中涉及主流的开源CNI插件以及几大云厂商的容器网络技术和选型。
今天,先从最基础的Docker容器网络讲起。
单主机上的Docker网络
容器网络通讯的方案大体可以分成两类,单主机上容器之间的通信和跨主机间容器的通讯。为了搞清楚细节,潭主特意去看了官方文档。
https://docs.docker.com/engine/reference/run/#network-settings

如上图所示,在单个主机上Docker支持四种网络模型,在运行docker run命令时通过--network参数可以对网络命名空间进行相应的设置。
# docker ps -f name=alpineCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES974b69651d5b alpine "/bin/sh" About an hour ago Up About an hour alpine-container66ab8e65c68d alpine "/bin/sh" About an hour ago Up About an hour alpine-host03a08cb18aa2 alpine "/bin/sh" About an hour ago Up About an hour alpine-bridgeb04052f0bf0c alpine "/bin/sh" 3 hours ago Up 3 hours alpine-none
None模式:
该模式下,Docker有自己的Network命名空间,但并不对其进行网络配置,也可以通过在宿主机上安装pipework工具来人工设置容器IP。
封闭意味着隔离,对于这样的一个封闭网络有什么用呢?说是可用于纯后端服务,但潭主觉得这种场景过于小众。
如下图所示:除了lo,网卡和路由表啥都没有。
# docker run -itd --net=none --name alpine-none alpine# docker exec -it alpine-none bin/sh/ # ifconfig -alo Link encap:Local Loopbackinet addr:127.0.0.1 Mask:255.0.0.0UP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)/ # route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface
Bridge模式:
网桥是Docker本地网络默认的部署模式。
当Docker进程启动时,系统会自动在主机上创建一个docker0的虚拟网桥设备,默认网段为172.17.0.0/16。
网桥模式下,容器创建时Docker会在容器和Docker0之间建立veth pair,veth是一种虚拟网络设备,它总是成对出现,一端连接Docker0网桥(通常为vethxxxxxxxx),另一端连接到容器网卡对应的网络命名空间中(通常为eth0),veth pair实现数据包的直接转发。
关于veth的配对信息,可以通过命令在宿主机和容器上分别查看对应的网卡标号,brctl show 命令也能协助查询相关信息。
如下所示,在容器中查看到的标号为19的网卡,对应在宿主机上的网卡设备编号为20。
# docker run -itd --net=bridge --name alpine-bridge alpine# docker exec -it alpine-bridge /bin/sh/ # ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UPlink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever/ # route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
Host模式
该模式的特征是容器没有自己独立的网络命名空间,而是借用宿主机的网络空间。
该模式下容器跟传统操作系统上的进程一样,直接使用宿主机网络资源,容器可以直接通过宿主机的IP和端口与外部进行通信,没有NAT地址转换。
虽然容器与主机共享网络空间,但是容器的文件系统和进程资源还是与宿主机隔离的。
Host模式网络性能虽好,但安全性较差,也可能会因为容器异常导致主机系统崩溃,不建议用于生产环境。
Container模式
在该模式下Docker容器使用其他容器的网络空间,这一点跟Host有点像,都是“借”用别人的,只是Host模式借用的宿主机网络,而Container模式借用的是其他容器的网络空间。
在创建容器的时候通过容器的Name或ID指定需要借用的容器。
该模式下同一命名空间下的容器之间通过localhost进行通信。
K8S中引入了Pod概念,一个Pod可以包含多个Container,而这些Pod中的容器间通讯跟Container模式是一样的。
找到一张架构图,可以对本文做一个很好的总结。

网络小白的成长之路
这次借着学习的机会动手做了几个实验,对容器网络有了比较细的了解。
主机内的容器通信只是最简单和基础的场景,主机间的容器通信才是真实世界的样子,而且从目前的技术发展趋势看,情况只会更加复杂。
Kubernetes设计了一种网络模型,通过提供一个扁平的网络平面可以让集群内的所有容器进行直接通信,而不管它们是否运行在集群中的同一节点。
接下来的Level 2,就该进入Kubernetes的领域探讨容器网络了。
新春将至,潭主预祝朋友们在新的一年扬眉兔气、奋发兔强、兔飞猛进,大展宏兔!
- END -
感谢阅读。如果觉得写得还不错,就请点个赞或“在看”吧。
公众号所有文章仅代表个人观点,与供职单位无关。





