[root@docker-node1 ~]# docker network Usage: docker network COMMAND Manage networks Commands: connect Connect a container to a network create Create a network disconnect Disconnect a container from a network inspect Display detailed information on one or more networks ls List networks prune Remove all unused networks rm Remove one or more networks Run ‘docker network COMMAND —help’ for more information on a command. [root@docker-node1 ~]# |
---|
开启网络转发
echo 1 > /proc/sys/net/ipv4/ip_forward
ipvs
iptable
http://www.zsythink.net/archives/1199
1.网络基础
docker0
linux虚拟网桥
1.可以设置ip地址
2.类似一个虚拟网卡
2.查看网桥
yum -y install bridge-utils
brctl show
ifconfig 查看网卡
启动一个容器
docker run -itd centos bash
查看网桥和ip接口
3.自定义docker0
通过ifconfig
4.添加虚拟网桥
brctl addbr br0
ifconfig br0 192.168.12.1 netmask 255.255.255.0
5.docker容器互联
1.允许所有容器互联
—link
docker run —link=[container_name]:[alias] [image] [commond]
docker run —name web03 —link=web01:web02 centos bash
Docker 网络模块
通过插件形式提供网络
创建容器和网络过程就是解耦
CNI:container Network Interface (CNCF)
CNM
Docker容器网络标准
Libnetowrk是其中的一个实现(Bridge模式)
Endpoint
Network
Sandbox
Docker网络
Docker 网络架构源自一种叫作容器网络模型(CNM)的方案,该方案是开源的并且支持插接式连接
Libnetwork 是 Docker 对 CNM 的一种实现,提供了 Docker 核心网络架构的全部功能。不同的驱动可以通过插拔的方式接入 Libnetwork 来提供定制化的网络拓扑
为了实现开箱即用的效果,Docker 封装了一系列本地驱动,覆盖了大部分常见的网络需求。其中包括单机桥接网络(Single-Host Bridge Network)、多机覆盖网络(Multi-Host Overlay),并且支持接入现有 VLAN。
Libnetwork 提供了本地服务发现和基础的容器负载均衡解决方案
在顶层设计中,Docker 网络架构由 3 个主要部分构成:CNM、Libnetwork 和驱动。
- CNM 是设计标准。在 CNM 中,规定了 Docker 网络架构的基础组成要素。
- Libnetwork 是 CNM 的具体实现,并且被 Docker 采用,Libnetwork 通过 Go 语言编写,并实现了 CNM 中列举的核心组件。
- 驱动通过实现特定网络拓扑的方式来拓展该模型的能力。
抽象来讲,CNM 定义了 3 个基本要素:沙盒(Sandbox)、终端(Endpoint)和网络(Network)。
- 沙盒是一个独立的网络栈。其中包括以太网接口、端口、路由表以及 DNS 配置。
- 终端就是虚拟网络接口。就像普通网络接口一样,终端主要职责是负责创建连接。在 CNM 中,终端负责将沙盒连接到网络。
- 网络是 802.1d 网桥(类似大家熟知的交换机)的软件实现。因此,网络就是需要交互的终端的集合,并且终端之间相互独立。
Docker 环境中最小的调度单位就是容器,而 CNM 也恰如其名,负责为容器提供网络功能。
CNM 组件是如何与容器进行关联的——沙盒被放置在容器内部,为容器提供网络连接。
容器 A 只有一个接口(终端)并连接到了网络 A。容器 B 有两个接口(终端)并且分别接入了网络 A 和网络 B。容器 A 与 B 之间是可以相互通信的,因为都接入了网络 A。但是,如果没有三层路由器的支持,容器 B 的两个终端之间是不能进行通信的。
对前面的内容进行拓展,加上了 Docker 主机。虽然容器 A 和容器 B 运行在同一个主机上,但其网络堆栈在操作系统层面是互相独立的,这一点由沙盒机制保证。
2) Libnetwork
CNM 是设计规范文档,Libnetwork 是标准的实现。Libnetwork 是开源的,采用 Go 语言编写,它跨平台(Linux 以及 Windows),并且被 Docker 所使用。
在 Docker 早期阶段,网络部分代码都存在于 daemon 当中。daemon 变得臃肿,并且不符合 UNIX 工具模块化设计原则,即既能独立工作,又易于集成到其他项目。
所以,Docker 将该网络部分从 daemon 中拆分,并重构为一个叫作 Libnetwork 的外部类库。
现在,Docker 核心网络架构代码都在 Libnetwork 当中。Libnetwork 实现了 CNM 中定义的全部 3 个组件。此外它还实现了本地服务发现(Service Discovery)、基于 Ingress 的容器负载均衡,以及网络控制层和管理层功能。
3) 驱动
如果说 Libnetwork 实现了控制层和管理层功能,那么驱动就负责实现数据层。比如,网络连通性和隔离性是由驱动来处理的,驱动层实际创建网络对象也是如此,其关系如下图所示。
Docker 封装了若干内置驱动,通常被称作原生驱动或者本地驱动。
在 Linux 上包括 Bridge、Overlay 以及 Macvlan,在 Windows 上包括 NAT、Overlay、Transport 以及 L2 Bridge。
第三方也可以编写 Docker 网络驱动。这些驱动叫作远程驱动,例如 Calico、Contiv、Kuryr 以及 Weave。
每个驱动都负责其上所有网络资源的创建和管理。举例说明,一个叫作“prod-fe-cuda”的覆盖网络由 Overlay 驱动所有并管理。这意味着 Overlay 驱动会在创建、管理和删除其上网络资源的时候被调用。
为了满足复杂且不固定的环境需求,Libnetwork 支持同时激活多个网络驱动。这意味着 Docker 环境可以支持一个庞大的异构网络。
最简单的 Docker 网络就是单机桥接网络。
从名称中可以看到两点,单机意味着该网络只能在单个 Docker 主机上运行,并且只能与所在 Docker 主机上的容器进行连接,桥接意味着这是 802.1.d 桥接的一种实现(二层交换机)。
Linux Docker 创建单机桥接网络采用内置的桥接驱动,而 Windows Docker 创建时使用内置的 NAT 驱动。实际上,这两种驱动工作起来毫无差异。
下图展示了两个均包含相同本地桥接网络 mynet 的 Docker 主机。虽然网络是相同的,但却是两个独立的网络。这意味着图中容器无法直接进行通信,因为并不在一个网络当中。
每个 Docker 主机都有一个默认的单机桥接网络。
在 Linux 上网络名称为 bridge,在 Windows 上叫作 nat。除非读者通过命令行创建容器时指定参数—network,否则默认情况下,新创建的容器都会连接到该网络。
//Linux
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
333e184cd343 bridge bridge local
docker network inspect bridge
[
{
“Name”: “bridge”, << 在 Windows 上是nat
“Id”: “333e184…d9e55”,
“Created”: “2018-01-15T20:43:02.566345779Z”,
“Scope”: “local”,
“Driver”: “bridge”, << 在 Windows 上是nat
“EnableIPv6”: false,
“IPAM”: {
“Driver”: “default”,
“Options”: null,
“Config”: [
{
“Subnet”: “172.17.0.0/16”
}
]
},
“Internal”: false,
“Attachable”: false,
“Ingress”: false,
“ConfigFrom”: {
“Network”: “”
},
}
]
在 Linux 主机上,Docker 网络由 Bridge 驱动创建,而 Bridge 底层是基于 Linux 内核中久经考验达 15 年之久的 Linux Bridge 技术。
$ ip link show docker0
3: docker0:
link/ether 02:42:af:f9:eb:4f brd ff:ff:ff:ff:ff:ff
在 Linux Docker 主机之上,默认的“bridge”网络被映射到内核中为“docker0”的 Linux 网桥。可以通过 docker network inspect
命令观察到上面的输出内容。
$ docker network inspect bridge | grep bridge.name
“com.docker.network.bridge.name”: “docker0”,
Docker 默认“bridge”网络和 Linux 内核中的“docker0”网桥之间的关系如下图所示
对上图的内容进行了扩展,在顶部补充了接入“bridge”网络的容器。
“bridge”网络在主机内核中映射到名为“docker0”的 Linux 网桥,该网桥可以通过主机以太网接口的端口映射进行反向关联。
接下来使用 docker network create 命令创建新的单机桥接网络,名为“localnet”。
//Linux
$ docker network create -d bridge localnet
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242aff9eb4f no
br-20c2e8ae4bbb 8000.02429636237c no
输出内容中包含了两个网桥。第一行是前文提过的 docker0 网桥,该网桥对应 Docker 中的默认网络 bridge;第二个网桥(br-20c2e8ae4bbb)与新建的“localnet”Docker 桥接网络相对应。
两个网桥目前都没有开启 STP,并且也都没有任何设备接入(对应的 interfaces 列为空)。
目前,主机上的网桥配置如下图所示。
创建一个新的容器,并接入到新建桥接网络 localnet 当中。如果是在 Windows 上进行操作,需要将命令中“alpine sleep 1d”替换为“microsoft/powershell:nanoserver pwsh.exe -Command Start-Sleep 86400”。
$ docker container run -d —name c1 \
—network localnet \
alpine sleep 1d
容器现在接入了 localnet 网络当中。读者可以通过 docker network inspect
命令来确认。
$ docker network inspect localnet —format
‘{{json .Containers}}’ {
“4edcbd…842c3aa”: {
“Name”: “c1”,
“EndpointID”: “43a13b…3219b8c13”,
“MacAddress”: “02:42:ac:14:00:02”,
“IPv4Address”: “172.20.0.2/16”,
“IPv6Address”: “”
}
},
再次运行 brctl show
命令,就能看到 c1 的网络接口连接到了 br-20c2e8ae4bbb 网桥。
$ brctl show
bridge name bridge id STP enabled interfaces
br-20c2e8ae4bbb 8000.02429636237c no vethe792ac0
docker0 8000.0242aff9eb4f no
如果在相同网络中继续接入新的容器,那么在新接入容器中是可以通过“c1”的容器名称来 ping 通的。这是因为新容器都注册到了指定的 Docker DNS 服务,所以相同网络中的容器可以解析其他容器的名称。
Linux 上默认的 Bridge 网络是不支持通过 Docker DNS 服务进行域名解析的。自定义桥接网络可以!
到目前为止,前面提到的桥接网络中的容器只能与位于相同网络中的容器进行通信。但是,可以使用端口映射(Port Mapping)来绕开这个限制。
上图所示,容器内部应用开放端口为 80。该端口被映射到了 Docker 主机的 10.0.0.15 接口的 5000 端口之上。最终结果就是访问 10.0.0.15:5000 的所有流量都被转发到了容器的 80 端口。
接下来通过示例了解将容器上运行着 Web 服务的端口 80,映射到 Docker 主机端口 5000 的过程。
1) 运行一个新的 Web 服务容器,并将容器 80 端口映射到 Docker 主机的 5000 端口。
$ docker container run -d —name web \
—network localnet \
—publish 5000:80 \
nginx
2) 确认端口映射。
$ docker port web
80/tcp -> 0.0.0.0:5000
) 通过 Web 浏览器访问 Docker 主机 5000 端口,验证配置是否生效,如下图所示。为了完成测试,需要知道 Docker 主机的 IP 地址或者 DNS 名称。如果使用 Windows 版 Docker 或者 Mac 版 Docker,可以使用 localhost 或者 127.0.0.1
外部系统现在可以通过 Docker 主机的 TCP 端口 5000,来访问运行在桥接网络上的 Nginx 容器了。
端口映射工作原理大致如此,但这种方式比较笨重并且不能扩展。举个例子,在只有单一容器的情况下,它可以绑定到主机的任意端口。这意味着其他容器就不能再使用已经被 Nginx 容器占用的 5000 端口了。这也是单机桥接网络只适用于本地开发环境以及非常小的应用的原因
Docker 内置的 Macvlan 驱动(Windows 上是 Transparent)就是为此场景而生。通过为容器提供 MAC 和 IP 地址,让容器在物理网络上成为“一等公民”。下图展示了具体内容
Macvlan 的优点是性能优异,因为无须端口映射或者额外桥接,可以直接通过主机接口(或者子接口)访问容器接口。但是,Macvlan 的缺点是需要将主机网卡(NIC)设置为混杂模式(Promiscuous Mode),这在大部分公有云平台上是不允许的。
假设有一个物理网络,其上配置了两个 VLAN——VLAN 100:10.0.0.0/24 和 VLAN 200:192.168.3.0/24,如下图所示
添加一个 Docker 主机并连接到该网络,如下图所示。
有一个需求是将容器接入 VLAN 100。为了实现该需求,首先使用 Macvlan 驱动创建新的 Docker 网络。但是,Macvlan 驱动在连接到目标网络前,需要设置几个参数。比如以下几点。
- 子网信息。
- 网关。
- 可分配给容器的IP范围。
- 主机使用的接口或者子接口。
下面的命令会创建一个名为 macvlan100 的 Macvlan 网络,该网络会连接到 VLAN 100。
$ docker network create -d macvlan \
—subnet=10.0.0.0/24 \
—ip-range=10.0.00/25 \
—gateway=10.0.0.1 \
-o parent=eth0.100 \
macvlan100
创建 macvlan100 网络以及 eth0.100 子接口。当前配置如下图所示
Macvlan 采用标准 Linux 子接口,需要为其打上目标 VLAN 网络对应的 ID。在本例中目标网络是 VLAN 100,所以将子接口标记为 .100(etho.100)。
通过 —ip-range 参数告知 Macvlan 网络在子网中有哪些 IP 地址可以分配给容器。这些地址必须被保留,不能用于其他节点或者 DHCP 服务器,因为没有任何管理层功能来检查 IP 区域重合的问题。
macvlan100 网络已为容器准备就绪,执行以下命令将容器部署到该网络中。
$ docker container run -d —name mactainer1 \
—network macvlan100 \
alpine sleep 1d
当前配置如下图所示。但是切记,下层网络(VLAN 100)对 Macvlan 的魔法毫不知情,只能看到容器的 MAC 和 IP 地址。在该基础之上,mactainer1 容器可以 ping 通任何加入 VLAN 100 的系统,并进行通信。
如果上述命令不能执行,可能是因为主机 NIC 不支持混杂模式。切记公有云平台不允许混杂模式
目前已经拥有了 Macvlan 网络,并有一台容器通过 Macvlan 接入了现有的 VLAN 当中。但是,这并不是结束。Docker Macvlan 驱动基于稳定可靠的同名 Linux内核驱动构建而成。
因此,Macvlan 也支持 VLAN 的 Trunk 功能。这意味着可以在相同的 Docker 主机上创建多个 Macvlan 网络,并且将容器按照下图的方式连接起来。
http://c.biancheng.net/view/3185.html
http://c.biancheng.net/view/3189.html