docker目前提供了多种网络模式,但是相信大部分运维人员还是比较相信物理网络,所以就想着将容器的网络配置成物理网络。可以看到开源项目Pipework,当然 Pipework的功能比较强大,这里我只关注容器使用物理网络的实现,如果你手动去配置容器的IP,可以只需要以下几个步骤:
1、创建网桥并配置,将eth0绑定到网桥br0,docker Daemon 监听br0
2、启动容器
1 | docker run -d --net=none --name web 10.110.17.138:5000/library/tomcat:7.0.67-jre7 |
3、创建Container对应的网络命名空间
1 | mkdir -p /var/run/netns |
4、容器配置网卡
1 | ip link add veth-a type veth peer name veth-b |
不是很复杂,业务系统可以定义一个脚本执行就OK,但是我们再开发使用过程中发现,当我们想着将这种网络模式运用到Compose时,却发现用不了,但是Compose支持docker 的网络插件机制,所以就需要考虑使用docker的网络插件机制实现。参考了Weave和ovs-plugin的实现方式,整理出了docker使用物理网络的插件docker-network-plugin-local,当然github上开源的仅仅是网络配置OK,和我们生产环境上的肯定有所区别,不过大家可以参考,在这里说一下几处关键代码。
1 | func (driver \*PipeNetworkDriver) CreateNetwork(createNetworkRequest \*network.CreateNetworkRequest) error { |
此处是命令行执行docker network create 时调用的API,这个插件是将网络信息缓存到了本地,其他什么也没有做(如果你想在集群环境中使用,可以修改此处,将网络信息保存到Etcd数据库)
1 | func (driver \*PipeNetworkDriver) CreateEndpoint(createEndpointRequest \*network.CreateEndpointRequest) (\*network.CreateEndpointResponse, error) { |
此处是在创建容器时,指定driver时调用的API,该插件只是定义了需要创建的link 对(veth pair),然后缓存起来
1 | func (driver \*PipeNetworkDriver) Join(joinRequest \*network.JoinRequest) (\*network.JoinResponse, error) { |
此处代码也是在docker 创建/启动容器时调用的API,该API完成link对的创建,并未改link(在容器内部的部分)配置IP,定义网卡名称,此处最重要的是返回值中将正确的vethpari那么返回,docker daemon会将veth pair加入到容器的网络空间 (PS:开始验证的时候,一直尝试自己将这个veth pair加入到命名空间,总是不成功,后来才发现,docker Daemon 已经把这件事干了)