MySQL on Docker: Single Host Networking for MySQL Containers

1月 28th, 2017

对于MySQL来说,网络是非常关键的,它是管理客户端访问服务器和集群节点之间访问的基础资源;容器化的MySQL服务行为取决于MySQL镜像如何使用docker run命令衍生出容器;使用Docker单主机网络,MySQL容器可以运行于一个独立的环境(只能访问相同网络的容器),或者一个开放的环境(通过端口映射,MySQL服务完全暴露到外部),或者运行一个完全无网络的实例;

— 三种类型的网络;
默认情况下,Docker在安装的时候会在宿主机上创建三种类型的网络:
[root@docker ~]# docker network ls;
NETWORK ID NAME DRIVER SCOPE
4c18ec95ca54 bridge bridge local
5c10d699ceb7 host host local
e0ce99953647 none null local

1.主机网络;
主机网络在宿主机的网络堆栈上添加一个容器,可以想象为在此网络中运行的容器正在连接到与宿主机相同的网络接口;它有以下特点:
1)容器的网络接口与宿主机是相同的;
2)每个宿主机只能有一个主机网络,不能创建更多;
3)如果要分配一个容器使用此网络,需要在docker run命令中显示指定”–net=host”参数;
4)不支持容器链接(比如:–link mysql-container:mysql);
5)不支持端口映射(比如:-p 3307:3306);

使用”–net=host”参数在主机网络上创建一个容器:docker run -d –restart=always –name=mysql-host –net=host -e MYSQL_ROOT_PASSWORD=pwd mysql

进入容器并查看对应的网络接口,发现与宿主机一样:
[root@docker ~]# docker exec -it mysql-host /bin/bash
root@docker:/# ip addr
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:9c:e6:2d brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
valid_lft 84565sec preferred_lft 84565sec
inet6 fe80::a00:27ff:fe9c:e62d/64 scope link
valid_lft forever preferred_lft forever
3: enp0s8:
mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:95:f6:b6 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.100/24 brd 192.168.10.255 scope global enp0s8
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe95:f6b6/64 scope link
valid_lft forever preferred_lft forever
4: docker0: mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:8c:49:90:73 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever

这种设置下,容器不需要在防火墙中设置任何的转发规则,因为它已经与主机网络连接了;因此也就不再支持端口映射了;

如果想要查看主机上某个端口是否在监听:[root@docker ~]# netstat -tulpn | grep 3306 (yum install -y net-tools)
tcp6 0 0 :::3306 :::* LISTEN 3572/mysqld

把MySQL容器以主机网络模式运行在宿主机上与直接标准安装到宿主机上是相似的,唯一的好处是有一个独立的MySQL服务器,尽管是Docker管理的;

基于主机网络创建的容器可以被基于默认桥网络docker0和用户自定义的桥网络创建的容器直接访问;

2.桥网络;
桥接允许同一台物理主机上的多个网络保持分离并独立通信;可以想象成这类似于宿主机的另一个内部网络,只有处于同一网络的容器才能访问其它的容器和主机,如果主机可以连接广域网,则容器也可以;

有两种类型的桥网络:1)默认的桥网络(docker0);2)用户定义的桥网络;

1)默认的桥网络(docker0):
在Docker安装的时候会自动创建docker0,可以通过”ip addr”命令进行验证;默认的IP范围是172.17.0.1/16,可以通过配置文件(Debian:/etc/default/docker;RedHat:/etc/sysconfig/docker)进行修改;

一般的,如果运行docker run命令时不指定–net参数,Docker会默认使用docker0网络创建容器;
[root@docker ~]# docker run -d –restart=always –name=mysql-bridge -p 3307:3306 -e MYSQL_ROOT_PASSWORD=pwd mysql

进入容器并查看对应的网络接口,Docker创建了一个网络接口eth0:
[root@docker ~]# docker exec -it mysql-bridge /bin/bash
root@db0336cafef9:/# ip addr
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
5: eth0@if6: mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever

默认情况下,Docker使用iptables来管理转发到桥网络的包;每个传出连接将显示为源自某一个宿主机自己的IP地址;以下是上述容器启动后宿主机的NAT链:
[root@docker ~]# iptables -L -n -t nat
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all — 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp — 172.17.0.2 172.17.0.2 tcp dpt:3306

Chain DOCKER (2 references)
target prot opt source destination
RETURN all — 0.0.0.0/0 0.0.0.0/0
DNAT tcp — 0.0.0.0/0 0.0.0.0/0 tcp dpt:3307 to:172.17.0.2:3306

上面的规则允许3307端口基于docker run命令中端口映射选项”-p 3307:3306″暴露在宿主机上;如果查看主机上的netstat分析,会发现MySQL时监听在3307端口的,并且属于docker-proxy进程;
[root@docker ~]# netstat -tulpn | grep 3307
tcp6 0 0 :::3307 :::* LISTEN 3916/docker-proxy

默认的桥网络支持端口映射和容器链接,如果想要链接到其它的容器,可以使用docker run命令的”–link”选项,容器会自动暴露环境变量并且通过/etc/hosts文件自动配置主机映射;

2)用户自定义桥网络:
Docker允许创建自定义的桥网络(也可以创建自定义的overlay网络),它的行为与docker0网络一致,网络中每一个容器都可以立即与其它容器通信;网络本身与外部的网络是隔离的;

这种网络的最大的优点是所有的容器都有解析容器名字的能力:
s1:首先创建一个自定义桥网络:
[root@docker ~]# docker network create –driver=bridge mysql-network

s2:基于用户定义网络创建5个mysql容器;
[root@docker ~]# for i in {1..5}; do docker run -d –name=mysql$i –net=mysql-network -e MYSQL_ROOT_PASSWORD=pwd mysql; done

s3:登陆其中任意一个容器,然后ping其它所有的容器;
root@docker ~]# docker exec -it mysql3 /bin/bash
root@eb3ba9f5ffc5:/# for i in {1..5}; do ping -c 1 mysql$i ; done
PING mysql1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.099 ms
— mysql1 ping statistics —
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.099/0.099/0.099/0.000 ms
PING mysql2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: icmp_seq=0 ttl=64 time=0.097 ms
— mysql2 ping statistics —
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.097/0.097/0.097/0.000 ms
PING mysql3 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: icmp_seq=0 ttl=64 time=0.055 ms
— mysql3 ping statistics —
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.055/0.055/0.055/0.000 ms
PING mysql4 (172.18.0.5): 56 data bytes
64 bytes from 172.18.0.5: icmp_seq=0 ttl=64 time=0.069 ms
— mysql4 ping statistics —
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.069/0.069/0.069/0.000 ms
PING mysql5 (172.18.0.6): 56 data bytes
64 bytes from 172.18.0.6: icmp_seq=0 ttl=64 time=0.067 ms
— mysql5 ping statistics —
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.067/0.067/0.067/0.000 ms

s4:查看DNS配置,发现Docker配置了一个内置的DNS服务器;
[root@docker ~]# docker exec -it mysql3 /bin/bash
root@eb3ba9f5ffc5:/# cat /etc/resolv.conf
search htsec.com
nameserver 127.0.0.11
options ndots:0
root@eb3ba9f5ffc5:/#

内置的DNS服务器维护了容器名称到它IP地址的映射关系,这个网络里面的所有容器都会指向此DNS服务器;这个特性可以用于网络中的节点发现,而且对于构建一个MySQL容器集群特别有用,可选的集群技术有MySQL复制,Galera集群或者MySQL集群;

Default vs User-defined Bridge
Area Default bridge (docker0) User-defined bridge
Network deployment Docker creates upon installation Created by user
Container deployment Default to this network Explicitly specify “–net=[network-name]” in
the “docker run” command
Container linking Allows you to link multiple containers Not supported
together and send connection information
from one to another by using
“–link [container-name]:[service-name]”.
When containers are linked, information
about a source container can be sent to
a recipient container.
Port mapping Supported e.g, by using “-p 3307:3306” Supported e.g, by using “-p 3307:3306”
Name resolver Not supported (unless you link them) All containers in this network are able to
resolve each other’s container name to IP address.
Version <1.10 use /etc/hosts, >=1.10 use embedded
DNS server.
Packet forwarding Yes, via iptables Yes, via iptables
Example usage for MySQL MySQL standalone MySQL replication, Galera Cluster, MySQL Cluster
(involving more than one MySQL container setup)

3.无网络;
同样可以利用docker run命令并指定”–net=none”选项创建一个不依附于任何网络的容器,这种容器只能通过交互的shell访问,容器里面不会配置任何附加的网络接口;
[root@docker ~]# docker run -d –restart=always –name=mysql-none –net=none -e MYSQL_ROOT_PASSWORD=pwd mysql

进入容器并查看相应的网络:
[root@docker ~]# docker exec -it mysql-none /bin/bash
root@3e0b1012db86:/# ip addr
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever

无网络中的容器不能加入任何网络,然而MySQL容器依然可以运行并且可以直接使用mysql客户端进行访问;

使用场景:可以运行一个MySQL容器做备份恢复验证;

标签:
目前还没有任何评论.