Docker学习(11) Docker 网络
- Docker网络体系的基本原理:容器网络模型、以及Libnetwork
Docker网络简介
- Docker的网络架构源自一个叫做容器网络模型(CNM)
- Libnetwork是Docker对CNM的一种实现,提供了Docker核心网络架构的全部功能。
- 为了实现开箱即用的效果,Docker封装了一系列的本地驱动,包括:
-
-
- 单机桥接网络(Single-Host Brige Network)
- 多机覆盖网络(Multi-Host Overlay)
-
- Libnetwork提供了本地服务发现和容器的负载均衡解决方案。
Docker网络——详解
基础理论
- Docker的网络架构主要由3个部分过程:CNM、Libnetwork和驱动
CNM
- CNM是docker网络的设计标准:规定了Docker网络架构的基础组成要素。
- 具体内容:https://github.com/docker/libnetwork
- CNM定义了三个基本要素:沙盒(Sandbox)、终端(Endpoint)和网络(network)
-
- 沙盒:独立的网络桟,包括以太网的接口、端口、路由表以及NDS配置。
- 终端:虚拟网络接口,和普通网络接口一样,主要负责创建网络,在CNM中,主要是将沙盒连接到网络
- 网络:是802.1d网桥的软件实现,网络就是需要交互终端的集合,并且终端直接相互集合。
- docker环境中最小的调度单位是容器。
Libnetwork
- Libnetwork是CNM的具体实现,通过Go语言编写的,实现了CNM列出的核心组件。
- Libnetwork实现了CNM定义的3个组件。还实现了本地发现功能,基于Ingress的容器负载均衡,以及网络控制层和管理层的功能。
驱动
通过实现特定网络拓扑的方式来拓扑该模型的能力。
驱动负责实现了网络的数据层。
Docker封装了内置驱动,包括bridge,Overlay以及macvlan
单机桥接网络
- 单机:该网络只在单个docker主机中运行,并且只能在docker主机内的容器进行连接。
- 桥接:802.1d桥接的一种实现。
- linux Docker创建网络时采用的是内置的桥接驱动。默认的单机桥接网络时bridge
- 查看docker主机默认的网络
lhf@lhf-virtual-machine:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
3c6fd32ed9fb bridge bridge local
8b95e29168fa counter-app-master_counter-net bridge local
682a75797ba4 host host local
596066e2fd78 none null local
- 查看docker网络的详细信息
lhf@lhf-virtual-machine:~$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "3c6fd32ed9fbe215b5ee34a773ba14703ea7d0a295a3b54cd01906c3c2b749b6",
"Created": "2019-11-08T21:51:18.740007297+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
- docker网络由bridge驱动创建的。bridge底层基于linux内核 linux bridge技术。
- 查看bridge网络
lhf@lhf-virtual-machine:~$ ip link show docker0
4: docker0: mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:03:5f:82:17 brd ff:ff:ff:ff:ff:ff
- 默认的“bridge”网络映射到内核中为“docker0”的linux网桥
lhf@lhf-virtual-machine:~$ docker network inspect bridge | grep bridge.name
"com.docker.network.bridge.name": "docker0",
- 创建一个新的单机桥接网络,名为“localnet”
lhf@lhf-virtual-machine:~$ docker network create -d bridge localnet
2b5ed819e9331ffa5c109f5f81dc6080f18e78cee7fc8ad05df9455247c01a0b
lhf@lhf-virtual-machine:~$ docker network ls | grep localnet
2b5ed819e933 localnet bridge local
- 通过使用brctl工具查看系统中的linux网桥。
lhf@lhf-virtual-machine:~$ brctl show
bridge name bridge id STP enabled interfaces
br-2b5ed819e933 8000.02421d8b6570 no
br-8b95e29168fa 8000.024223c21723 no
docker0 8000.0242035f8217 no
- 创建一个新的容器,并接入新建网络localnet中
$ docker container run -d --name c1 \
> --network c1 \
> alpine sleep 1d
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f8bf6041757a alpine "sleep 1d" 46 seconds ago Up 43 seconds c1
- 查看详细输出
$ docker network inspect localnet --format
"ConfigOnly": false,
"Containers": {
"f8bf6041757a51afc6b56d35a84a8370037d207230101c0df6fc565da1d68741": {
"Name": "c1",
"EndpointID": "7016a80031330e87c3073c1cd148a5bbef6aa39738cd84bcdfe1657cf19f214e",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
$ brctl show
bridge name bridge id STP enabled interfaces
br-2b5ed819e933 8000.02421d8b6570 no veth53c5236
br-8b95e29168fa 8000.024223c21723 no
docker0 8000.0242035f8217 no
- 查看到c1网络已经接入到veth53c5236
如果在相同的网络接入新的容器c2的话,是可以ping通c1的
创建一个c2容器
$ docker container run -it --name c2 \
> --network localnet \
> alpine sh
/ # ping c1
PING c1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.296 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.143 ms
^C
--- c1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.143/0.219/0.296 ms
/ #
- 新容器都指定了docker的DNS服务。,所有相同网络的容器可以解析到其他容器的名称。
端口映射
- 端口映射:将某个容器的端口映射到docker主机的端口上。
- 将容器运行一个web'服务80映射到docker主机 5000
$ docker container run -d --name web \
> --network localnet \
> --publish 5000:80 \
> nginx
- 确认端口映射
$ docker port web
80/tcp -> 0.0.0.0:5000
-
通过web查看服务
多机覆盖网络
- 覆盖网络适用于多机环境,允许单个网络包含多个主机。不同主机的容器可以通过链路层实现通信。
- docker主机为覆盖网络提供了本地驱动,在创建网络时docker network create 时添加参数 --d overlay
接入现有网络
- 将容器化的应用接入到外部系统以及物理网络功能。比如:
-
- 容器化的应用于运行的物理网络和VLAN上未容器化的部分进行通信。
- docker 的内置驱动(Macvlan),为容器提供mac和IP地址
用于故障排查的容器和服务日志
容器间网络连接问题,检查daemon日志和容器日志
在linux上,daemon日志存放位置取决于当前系统使用的初始化方式。
-
如果是systemd,日志会存储在Journald,通过journalctl -u docker.service查看
如果不是systemd,需要查看如下存放位置
-
- Ubuntu系统:upstart:/var/log/upstart/docker.log
- RHEl系统:systems:/var/log/messages
- Debian系统: /var/log/daemon.log
可以设置daemon日志的详细程度。通过编辑daemon的配置文件(daemon.json),将debug改为true,设置log-level为某个值:
-
- debug:最详细的日志
- info:默认值,仅次于最详细日志
- warn:第三详细日志级别
- error:第四详细日志级别
- fatal;最粗略的日志级别
- 查看单个容器日志
$ docker container logs web
172.18.0.1 - - [08/Nov/2019:16:15:38 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0" "-"
服务发现
服务发现(Service Discovery)允许容器和Swarm服务通过名称相互定位,需要在同一个网络中。
底层实现是利用Docker内置的DNS功能,为每个容器提供DNS解析。上述例子c2可以ping通c1
具体过程分析
-
- ping c2 命令调用本地DNS解释器,尝试将c2解析成具体的IP地址,每个docker都有本地的DNS解释器。
- 如果本地DNS解释器在本地缓存没有c2相对应的IP地址的映射关系。本地DNS会想dockerDNS发起一个递归查询。
- Docker DNS服务器器记录了全部容器的容器名和IP地址的映射关系。
- Docker DNS服务器会返回给“c2”相对应的IP地址给c1的本地DNS解释器,
- ping 命令返回给c2对应的IP地址。
Ingress网络
- Swarm支持两种服务发布模式。
-
- Ingress模式:保证swarm服务中任意节点都可以访问该服务(默认的模式)
- Host模式:只能通过运行服务副本的节点来访问。
docker网络——命令
- docker network ls :列出运行在本地的docker主机的全部网络
- docker network create :创建新的docker网络。默认采用的是bridge 加-d参数指定(网络类型)
- docker network inspect:提供docker网络的详细配置信息。
- docker network prune:删除docker主机上全部未使用的网络。
- docker network rm :删除docker主机上指定的网络