【重识云原生】第六章容器6.1.12节——Docker网络模型设计

  《重识云原生系列》专题索引:

  1. 第一章——不谋全局不足以谋一域
  2. 第二章计算第1节——计算虚拟化技术总述
  3. 第二章计算第2节——主流虚拟化技术之VMare ESXi
  4. 第二章计算第3节——主流虚拟化技术之Xen
  5. 第二章计算第4节——主流虚拟化技术之KVM
  6. 第二章计算第5节——商用云主机方案
  7. 第二章计算第6节——裸金属方案
  8. 第三章云存储第1节——分布式云存储总述
  9. 第三章云存储第2节——SPDK方案综述
  10. 第三章云存储第3节——Ceph统一存储方案
  11. 第三章云存储第4节——OpenStack Swift 对象存储方案
  12. 第三章云存储第5节——商用分布式云存储方案
  13. 第四章云网络第一节——云网络技术发展简述
  14. 第四章云网络4.2节——相关基础知识准备
  15. 第四章云网络4.3节——重要网络协议
  16. 第四章云网络4.3.1节——路由技术简述
  17. 第四章云网络4.3.2节——VLAN技术
  18. 第四章云网络4.3.3节——RIP协议
  19. 第四章云网络4.3.4节——OSPF协议
  20. 第四章云网络4.3.5节——EIGRP协议
  21. 第四章云网络4.3.6节——IS-IS协议
  22. 第四章云网络4.3.7节——BGP协议
  23. 第四章云网络4.3.7.2节——BGP协议概述
  24. 第四章云网络4.3.7.3节——BGP协议实现原理
  25. 第四章云网络4.3.7.4节——高级特性
  26. 第四章云网络4.3.7.5节——实操
  27. 第四章云网络4.3.7.6节——MP-BGP协议
  28. 第四章云网络4.3.8节——策略路由
  29. 第四章云网络4.3.9节——Graceful Restart(平滑重启)技术
  30. 第四章云网络4.3.10节——VXLAN技术
  31. 第四章云网络4.3.10.2节——VXLAN Overlay网络方案设计
  32. 第四章云网络4.3.10.3节——VXLAN隧道机制
  33. 第四章云网络4.3.10.4节——VXLAN报文转发过程
  34. 第四章云网络4.3.10.5节——VXlan组网架构
  35. 第四章云网络4.3.10.6节——VXLAN应用部署方案
  36. 第四章云网络4.4节——Spine-Leaf网络架构
  37. 第四章云网络4.5节——大二层网络
  38. 第四章云网络4.6节——Underlay 和 Overlay概念
  39. 第四章云网络4.7.1节——网络虚拟化与卸载加速技术的演进简述
  40. 第四章云网络4.7.2节——virtio网络半虚拟化简介
  41. 第四章云网络4.7.3节——Vhost-net方案
  42. 第四章云网络4.7.4节vhost-user方案——virtio的DPDK卸载方案
  43. 第四章云网络4.7.5节vDPA方案——virtio的半硬件虚拟化实现
  44. 第四章云网络4.7.6节——virtio-blk存储虚拟化方案
  45. 第四章云网络4.7.8节——SR-IOV方案
  46. 第四章云网络4.7.9节——NFV
  47. 第四章云网络4.8.1节——SDN总述
  48. 第四章云网络4.8.2.1节——OpenFlow概述
  49. 第四章云网络4.8.2.2节——OpenFlow协议详解
  50. 第四章云网络4.8.2.3节——OpenFlow运行机制
  51. 第四章云网络4.8.3.1节——Open vSwitch简介
  52. 第四章云网络4.8.3.2节——Open vSwitch工作原理详解
  53. 第四章云网络4.8.4节——OpenStack与SDN的集成
  54. 第四章云网络4.8.5节——OpenDayLight
  55. 第四章云网络4.8.6节——Dragonflow
  56.  第四章云网络4.9.1节——网络卸载加速技术综述

  57. 第四章云网络4.9.2节——传统网络卸载技术

  58. 第四章云网络4.9.3.1节——DPDK技术综述

  59. 第四章云网络4.9.3.2节——DPDK原理详解

  60. 第四章云网络4.9.4.1节——智能网卡SmartNIC方案综述

  61. 第四章云网络4.9.4.2节——智能网卡实现

  62. 第六章容器6.1.1节——容器综述

  63. 第六章容器6.1.2节——容器安装部署

  64. 第六章容器6.1.3节——Docker常用命令

  65. 第六章容器6.1.4节——Docker核心技术LXC

  66. 第六章容器6.1.5节——Docker核心技术Namespace

  67. 第六章容器6.1.6节—— Docker核心技术Chroot

  68. 第六章容器6.1.7.1节——Docker核心技术cgroups综述

  69. 第六章容器6.1.7.2节——cgroups原理剖析

  70. 第六章容器6.1.7.3节——cgroups数据结构剖析

  71. 第六章容器6.1.7.4节——cgroups使用

  72. 第六章容器6.1.8节——Docker核心技术UnionFS

  73. 第六章容器6.1.9节——Docker镜像技术剖析

  74. 第六章容器6.1.10节——DockerFile解析

  75. 第六章容器6.1.11节——docker-compose容器编排

  76. 第六章容器6.1.12节——Docker网络模型设计

  77. 第六章容器6.2.1节——Kubernetes概述

  78. 第六章容器6.2.2节——K8S架构剖析

  79. 第六章容器6.3.1节——K8S核心组件总述

  80. 第六章容器6.3.2节——API Server组件

  81. 第六章容器6.3.3节——Kube-Scheduler使用篇

  82. 第六章容器6.3.4节——etcd组件

  83. 第六章容器6.3.5节——Controller Manager概述

  84. 第六章容器6.3.6节——kubelet组件

  85. 第六章容器6.3.7节——命令行工具kubectl

  86. 第六章容器6.3.8节——kube-proxy

  87. 第六章容器6.4.1节——K8S资源对象总览

  88. 第六章容器6.4.2.1节——pod详解

  89. 第六章容器6.4.2.2节——Pod使用(上)

  90. 第六章容器6.4.2.3节——Pod使用(下)

  91. 第六章容器6.4.3节——ReplicationController

  92. 第六章容器6.4.4节——ReplicaSet组件

  93. 第六章容器基础6.4.5.1节——Deployment概述

  94. 第六章容器基础6.4.5.2节——Deployment配置详细说明

  95. 第六章容器基础6.4.5.3节——Deployment实现原理解析

  96. 第六章容器基础6.4.6节——Daemonset

  97. 第六章容器基础6.4.7节——Job

  98. 第六章容器基础6.4.8节——CronJob

1 容器网络背景概述

1.1 Linux的namespace+cgroup

        先来简要回顾一下前面的内容,namespace和cgroup是Linux 内核的两大特性,namespace的诞生据说就是为了支持容器技术,那么这俩特性到底干了啥呢?

         - namespace:linux支持多种类型的namespace,包括Network,IPC,PID, Mount, UTC, User。创建不同类型的namespace就相当于从不同资源维度在主机上作隔离。

         - cgroup:为了不让某个进程一家独大,而其他进程饿死,所以它的作用就是控制各进程分配的CPU,Memory,IO等。

         - namespace+cgroup也适用进程组,即多进程运行在一个单独的ns中,此时该ns下的进程就可以交互了。

参考:Docker基础技术:Linux Namespace(上) | 酷 壳 - CoolShell

1.2 容器

        "容器"这个概念其实是Linux本身就具有的,无非就是对一个"隔离环境"的另一种说法,或者说容器就是结合了namespace 和 cgroup 的一般内核进程,注意,容器就是个进程。

        容器的实现有多种方式,其中Docker公司实现的docker 容器也是目前最为常用的一种容器技术,所以我们接下来就以docker为例,看看他的实现是怎么帮我们创建,管理这样一个个"互相隔离着的进程"。所以,当我们使用Docker起一个容器的时候,Docker会为每一个容器创建属于他自己的namespaces,即各个维度资源都专属这个容器了,此时的容器就是一个孤岛,也可以说是一个独立VM就诞生了。当然他不是VM,网上关于二者的区别和优劣有一对资料.

        更进一步,也可以将多个容器共享一个namespace,比如如果容器共享的是network 类型的namespace,那么这些容器就可以通过 localhost:[端口号]  来通信了。因为此时的两个容器从网络的角度看,和宿主机上的两个内核进程没啥区别。

        容器网络从范围上分:

  • 单机网络:none,host, bridge
  • 跨主机网络:overlay,macvlan,flannel等

        从生成方式分:

  • 原生网络:即利用宿主机操作系统本身就提供的功能构建的网络,包括:none,host, bridge
  • 自定义网络:
    • docker容器实现中自带的网络驱动:bridge(自定义),overlay,macvlan,
    • 使用第三方驱动实现的自定义网络:flannel、Calico等

        在学习网络的时候肯定遇到过关于CNM这个概念,所以首先,我们一起学习下CNM&libnetwork

1.3 CNM&libnetwork

       首先,Docker实现的容器技术中,针对网络这一块他抽象出一个模型来,就叫CNM(Container Networking Model),相当于只实现了一个框架,具体的实现可以使用原生Docker的,也可以自己实现然后接入本框架。其中libnetwork是Docker团队将Docker的网络功能从Docker的核心代码中分离出来形成的一个单独的库,libnetwork通过插件的形式接入CNM为Docker提供网络功能。

        该模型包含三部分:

  • Sandbox:容器的网络栈,包含interface、路由表、DNS设置等,可以看做就是linux network类型的namespace本身,该有的网络方面的东西都要有,另外还包含一些用于连接各种网络的endpoint;
  • Endpoint : 用来将sandbox接入到network中,典型的实现是Veth pair技术(Veth pair是Linux固有的,是一个成对的接口,用来做连接用);
  • Network (框架): 具体的网络实现,比如是brige、VLAN等,同样它包含了很多endpoint(那一头);

      一句话:sandbox代表容器,network代表由网络驱动构建的容器的网络,endpoint代表接入点即他连接了二者。

        CMN模型提供了2个可插拔的接口,让用户可以自己实现驱动然后接入该接口,支持驱动有两类:网络驱动和IPAM驱动,看看这俩类驱动干什么的?

  • Network Drivers: 即真正的网络实现,可以为Docker Engine或其他类型的集群网络同时提供多种驱动,但是每一个具体的网络只能实例化一个网络驱动。细分为本地网络驱动和远端网络驱动:   
    • 本地网络驱动:对应前面说到的原生网络;
    • 远端网络驱动:对应前面说的自定义网络;
  • IPAM Drivers — 构建docker网络的时候,每个docker容器如果不手动指定的话是会被分配ip地址的,这个分配的任务就是由该驱动完成的,同样的,Docker Engine还是给我们提供了缺省的实现。

        整个的原理模型图如下,参见官网:

         参考:https://success.docker.com/article/networking

2 Docker的四种网络模型

2.1 概述

        docker的网络模型分为四种:

  1. Bridge模式,与宿主机共享一个局域网,有自己的网络,用于单个host上多个容器之间通信,是 Docker 的默认网络模式,可以使用 –net=bridge 指定;
  2. Host模式,与宿主机共享一个网络,使用 –net=host 指定;
  3. Container模式,与另一个容器共享一个网络,eg:业务容器和数据库容器,使用 –net=container: 容器名称或ID 指定;
  4. None模式,封闭网络,使用 –net=none 指定,如果使用K8S网络模型,则需设置为此模式。

2.2 Bridge 模式

        Bridge 模式是 Docker 默认使用的网络模式。当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。接下来就要为容器分配IP了,Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。

        Docker完成以上网络配置的过程大致是这样的:

  1. Docker Daemon 利用 veth pair 技术,在宿主机上创建一对虚拟网卡veth pair设备,假设为veth0 和 veth1。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
  2. Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上,保证宿主机的网络报文可以发往 veth0,可以通过brctl show命令查看;
  3. Docker Daemon 将 veth1 添加到 新创建的Docker Container 所属的 namespace 下,并被改名为 eth0。
  4. 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
  5. 如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。
# 查看本机网络配置

ip addr

...

docker0: mtu 1500 qdisc noqueue state DOWN group default

link/ether 02:42:51:82:92:0a 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:51ff:fe82:920a/64 scope link

valid_lft forever preferred_lft forever

...

# 启动一个容器

docker run -dit ubuntu

# 查看网络配置

ip addr

...

vethc51f579@if9: mtu 1500 qdisc noqueue master docker0 state UP group default

link/ether 5e:fd:53:cc:54:58 brd ff:ff:ff:ff:ff:ff link-netnsid 0

inet6 fe80::5cfd:53ff:fecc:5458/64 scope link

valid_lft forever preferred_lft forever

# 进入容器

docker exec -it {{ID}} bash

# 安装 net-tools

apt-get update

apt-get install net-tools

# 查看网络配置

ifconfig

...

eth0: flags=4163 mtu 1500

inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255

ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)

RX packets 2452 bytes 13783808 (13.7 MB)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 2012 bytes 152399 (152.3 KB)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

        通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络:

         bridge 桥接模式下的 Docker Container 在使用时,并非为开发者包办了一切。最明显的是,该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。虽然 NAT 模式经过中间处理实现了这一点,但是 NAT 模式仍然存在问题与不便,如容器均需要在宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等。另外 NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。

2.3 Host 模式

        Docker 为了实现网络的隔离,使用了 Network Namespace 对网络进行隔离。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的 IP 和端口。

 
# 查看最开始的网络配置

ip addr

# 以host模式启动一个容器

docker run -dit -p 80:80 --net host nginx

# 查看网络配置

ip addr

# 未发现多出 veth 接口,网络配置与之前没有任何区别

        而外界访问容器中的应用,则直接使用主机IP:80 即可,不用任何NAT转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

        host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。当然,有这样的方便,肯定会损失部分其他的特性,最明显的是 Docker Container 网络环境隔离性的弱化,即容器不再拥有隔离、独立的网络栈。另外,使用 host 模式的 Docker Container 虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用。另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge 网络模式容器的端口映射。

2.4 Container 模式

        Container 模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

 
# 以默认模式一个容器

docker run -dit --name u1 ubuntu

# 以 container 模式启动另一个容器

docker run -dit --name u2 --network container:u1 ubuntu

# 查看网络配置

ifconfig

# 发现只多了一个 veth

        Docker Container 的 other container 网络模式,可以用来更好的服务于容器间的通信。在这种模式下的 Docker Container可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他容器形成网络隔离。另外,这种模式还节约了一定数量的网络资源。但是需要注意的是,它并没有改善容器与宿主机以外世界通信的情况。

2.5 None 模式

        此模式下容器不参与网络通信,运行于此类容器中的进程仅能访问本地环回接口,仅适用于进程无须网络通信的场景中,例如备份,进程诊断及各种离线任务等。如果使用K8S网络模型,则需设置为此模式。

# 以 None 模式运行一个容器

docker run -dit --network none ubuntu

# 进入容器查看

ifconfig

# 只有 lo 网卡

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 29 bytes 2569 (2.5 KiB)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 29 bytes 2569 (2.5 KiB)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

        网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container 采用了none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docker Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。在 none 网络模式下分配固定 ip:netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境。目前 netns 在 lxc 容器中被用来为容器提供网络。使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样。

3 docker 网络初始化过程

  

参考链接

Docker 四种网络模型_执笔苦行僧的博客-CSDN博客_docker网络模型

docker 网络模型_幽雨雨幽的博客-CSDN博客_docker网络模型

docker网络模型 - 德乌姆列特 - 博客园

(十四)Docker0网络详解_IT_狂奔者的博客-CSDN博客_docker0网卡的作用

Docker的docker0网络 - Kit_L - 博客园

ifconfig 中的 eth0 eth0:1 eth0.1 与 lo - JokerJason - 博客园

docker容器的四种网络模型_xbw_linux123的博客-CSDN博客

Docker容器网络基础 - 水鬼子 - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江中散人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值