Docker容器+k8s|Docker网络详解


Docker网络

    • Docker网络架构
    • libnetwork中的5种内置驱动
    • Docker原生网络
      • bridge模式
      • host模式
      • none模式
    • Docker自定义网络
      • 创建自定义网桥bridge
        • 如何让不同网段的容器可以相互通信

Docker基础知识可点击查看之前文章 【Docker容器+k8s|Docker网络详解】
Docker网络架构 Docker有自己的网络库,即libnetwork
容器的网络模式被抽象变成了统一接口的驱动
使用CNM ( Container Network Model)容器网络模型对Docker网络进行了抽象

CNM定义了构建容器虚拟化网络的模型,同时还提供了可以用于开发多种网络驱动的标准化接口和组件。
CNM的3个核心组件:
1、Sandbox沙盒:一个沙盒包含了一个容器网络栈的信息。沙盒可以对容器的接口、路由和DNS设置等进行管理。沙盒的实现可以是Linux network namespace、FreeBSD Jail或者类似的机制。一个沙盒可以有多个端点和多个网络
2、Endpoint端点:一个端点可以加入一个沙盒和一个网络。端点的实现可以是veth pair、Open vSwitch内部端口或者相似的设备。一个端点只可以属于一个网络并且只属于一个沙盒
3、Network网络:一个网络是一组可以直接互相联通的端点。网络的实现可以是Linux bridge、VLAN等。一个网络可以包含多个端点
Docker网络虛拟化架构:
Docker daemon通过调用libnetwork对外提供的API完成网络的创建和管理等功能。
libnetwork中则使用了CNM来完成网络功能的提供。
libnetwork中内置的5种驱动则为libnetwork提供了不同类型的网络服务。
Docker容器+k8s|Docker网络详解
文章图片

libnetwork中的5种内置驱动 1、bridge驱动:此驱动为Docker的默认设置,docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口。但与外界通信使用NAT,增加了通信的复杂性,在复杂场景下使用会有诸多限制。
2、host驱动使用这种驱动的时候,Docker容器和宿主机共用同一个network namespace,使用宿主机的网卡、IP和端口等信息。但是,容器其他方面,如文件系统、进程列表等还是和宿主机隔离的。host模式不存在虚拟化网络带来的额外性能负担。但是host驱动也降低了容器与容器之间、容器与宿主机之间网络层面的隔离性,引起网络资源的竞争与冲突。
3、overlay驱动:此驱动采用IETF标准的VXLAN方式,并且是VXLAN中被普遍认为最适合大规模的云计算虚拟化环境的SDN controller模式。在使用的过程中,需要一个额外的配置存储服务, 还需要在启动Docker daemon的的时候额外添加参数来指定所使用的配置存储服务地址。
4、remote驱动:这个驱动实际上并未做真正的网络服务实现,而是调用了用户自行实现的网络驱动插件,使libnetwork实现了驱动的可插件化
5、null驱动:使用这种驱动的时候,Docker容器拥有自己的network namespace,但是并不为Docker容器进行任何网络配置。也就是说,这个Docker容器除了network namespace自带的loopback网卡外,没有其他任何网卡、IP、路由等信息,需要用户为Docker容器添加网卡、配置IP等。这种模式如果不进行特定的配置是无法正常使用的,但是优点也非常明显,它给了用户最大的自由度来自定义容器的网络环境。
Network namespace 在逻辑上是网络堆栈的一个副本,它有自己的路由、防火墙规则和网络设备。默认情况下,子进程继承其父进程的 network namespace。也就是说,如果不显式创建新的 network namespace,所有进程都从 init 进程继承相同的默认 network namespace。
每个新创建的 network namespace 默认有一个本地环回接口 lo,除此之外,所有的其他网络设备(物理/虚拟网络接口,网桥等)只能属于一个 network namespace。每个 socket 也只能属于一个 network namespace。
Docker原生网络 docker安装后会自动创建3种网络:bridge、host、none
可以用命令docker network ls查看

Docker容器+k8s|Docker网络详解
文章图片

bridge模式
Docker默认网络模式是bridge模式, docker0网桥是在docker daemon启动时自动创建的,之后创建的docker容器都会在docker0自网范围内选取一个未占用的ip并连接到docker0网桥上,docker0以veth pair连接各容器的网络,容器中的数据通过docker0网桥转发到eth0网卡上。

veth pair:就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。

docker0网桥的概念等同于交换机,为连在其上的设备转发数据帧。网桥上的veth网卡设备相当 于交换机上的端口,可以将多个容器或虚拟机连接在其上,这些端口工作在二层(数据链路层),所以是不需要配置IP信息的。下图docker0网桥就为连在其上的容器转发数据帧,使得同一台宿主机上的Docker 容器之问可以相互通信。docker0是普通的Linux网桥,它是可以在上面配置IP的,可以认为其内部有一个可以用于配置IP信息的网卡接口。在Docker的桥接 网络模式中,docker0的IP地址作为连于之上的容器的默认网关地址存在。
Docker容器+k8s|Docker网络详解
文章图片

使用命令ip addr | grep docker可以看到网桥docker0
Docker容器+k8s|Docker网络详解
文章图片

使用命令route -n查看网关,此条路由表示所有目的ip为172.17.0.0/16的数据包从docker0发出
Docker容器+k8s|Docker网络详解
文章图片

我们运行一个容器,查看ip
[root@server1 ~]# docker run -it --rm --network mynet1 busybox

在容器内查看ip可以看到有lo和eth0两个网卡,lo网卡是容器的回环网卡,eth0是容器与外界通信的网卡,ip地址和docker0在一个网段,这时我们ip addr查看宿主机的网卡就会看到以veth开头的网卡,就是我们上面解释的为了将容器和docker0连接起来的设备
Docker容器+k8s|Docker网络详解
文章图片

bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。容器通过宿主机的NAT规则后可以访问外网。
host模式
host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。
host网络模式需要在容器创建时指定 --network=host [root@server1 ~]# docker network create mynet1 [root@server1 ~]# docker run -it --rm --network mynet1 busybox

查看docker网络,自己创建的已经在里边了
Docker容器+k8s|Docker网络详解
文章图片

可以看到我们自己创建的网络ip不是和docker0一个网段的
Docker容器+k8s|Docker网络详解
文章图片

因为是和宿主机共享网络的,所以可以ping通docker0
Docker容器+k8s|Docker网络详解
文章图片

删除使用docker network rm mynet1命令即可Docker容器+k8s|Docker网络详解
文章图片

none模式
none模式是指禁用网络功能,只有lo接口,在容器创建时使用。
--network=none指定 [root@server1 ~]# docker run -it --rm --network none busybox

Docker容器+k8s|Docker网络详解
文章图片

Docker自定义网络 自定义网络模式,docker提供了三种自定义网络驱动:bridge、overlay、macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能。
overlay和macvlan是用于创建跨主机网络。
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
创建自定义网桥bridge
支持自定义网段、网关等
--subnet 网段 --gateway 网关 [root@server1 ~]# docker network create -d bridge my_net1 #未指定参数直接创建 [root@server1 ~]# docker network create --subnet 172.77.0.0/24 --gateway 172.77.0.1 my_net2#指定参数 [root@server1 ~]# docker network ls

Docker容器+k8s|Docker网络详解
文章图片

在运行容器时使用–ip参数可以指定容器ip地址,但必须是在自定义网桥上,默认的bridge模式不支持。
Docker容器+k8s|Docker网络详解
文章图片

如何让不同网段的容器可以相互通信 同一网桥上的容器是可以互通的。桥接到不同网桥上的容器,彼此是不通信的。docker在设计上就是要隔离不同network的。
如下图统一网桥的容器可以ping通
Docker容器+k8s|Docker网络详解
文章图片

ping时直接指定容器名也是可以的
Docker容器+k8s|Docker网络详解
文章图片

新创建一个不同网段的网桥,运行一个容器,ping我们之前后台运行的不同网段的nginx服务,会看到ping不通,因为不是一个网段的。
Docker容器+k8s|Docker网络详解
文章图片

让两个不同网段的可以通信的方法就是使用 docker network connect命令为test1容器添加一块my_net2 的网卡(即其中一个容器添加了一个ip)。
[root@server1 ~]# docker run -it -d --name test --network my_net2 --ip 172.77.0.9 busybox [root@server1 ~]# docker run -it -d --name test1 --network my_net3 --ip 172.99.0.9 busybox [root@server1 ~]# docker ps [root@server1 ~]# docker network connect my_net2 85ac7badf952 [root@server1 ~]# docker container attach 85ac7badf952

Docker容器+k8s|Docker网络详解
文章图片

示意图如下
Docker容器+k8s|Docker网络详解
文章图片

    推荐阅读