原作者:李周     转载来源:http://dockone.io/article/1673

PPTV Docker集群的网络方案选型

作者介绍:李周,现PPTVDCOS技术主要负责人。专注于Docker网络解决方案、容器监控、DevOps。目前主要研究方向是容器网络改造、多套测试环境隔离、容器深度监控。之前在中小创业公司长期负责客户现场实施工作;积累了大量关于网络、监控、权限认证、大数据、Oracle、中间件等经验;擅长linux系统和网络的各种操作,同时也喜欢研究各种新兴技术。

PPTV OAK项目介绍

项目背景

PPTV作为国内视频领域的领先者,对于大规模流媒体的存储、处理、分发及应用,有着迫切的要求。容器技术及微服务模式的出现,使大规模的研发交付效率大为提高。本文介绍了PPTVOAK项目中Docker网络方案选型,以及对比了多种docker网络解决方案的特点后,最终结合PPTV网络架构的特点,选定了PPTV的Docker网络方案。

刚才有一个关键词叫OAK,OAK是橡树的英文单词。PPTV的OAK项目,基于Docker技术打造了DCOS。底层基于Mesos + Marathon 为核心,结合Docker和Nginx,在此基础上开发了DCOS管理控制台、权限管理模块、统一日志管理模块、IP池管理模块、存储管理模块,并与持续集成平台Jenkins集成,实现应用容器的创建、运行。OAK致力于快速部署、弹性扩缩容、助力敏捷开发、实现故障自愈以及提高资源利用率。

OAK建设历程

图 1 OAK建设历程

OAK功能框架

图 2 OAK功能框架

2016年初的时候,我们开始在测试环境引入Docker。最早的计划是将PPTV的所有开发测试环境都迁移到容器里,考虑用户群(研发/测试人员)对Docker的命令行操作不熟悉,如果我们直接把Docker底层的管理操作暴露给用户,他们的学习成本会很高。为此我们使用了Mesos+ Marathon,可以通过Marathon快速创建容器,实现容器故障自动恢复。而实际上用户对于容器的操作和原理完全不关心,他们只关心如何可以快速、简单的构建一个开发或者测试环境。Marathon对于用户来说还是过于生疏。为了让用户能更容易接受Docker,我们将容器的创建与Jenkins平台结合。Jenkins是开发、测试人员比较熟悉的平台。我们在Jenkins的编译job中,把编译出来的应用包保存到一台集中的服务器上,同时调用Marathon的API创建一个与之对应的APP。这个APP会通过Marathon的uri参数把编译好的应用包挂载到容器中,实现应用自动部署。

到了这里,还存在一个问题,用户要怎么访问已经部署好的应用?容器里的网络默认用是一个私网的IP,此IP与容器所在宿主机上的Docker0网卡做了桥接,是不能跟外界通信。所以Marathon在创建容器的时候,通过NAT将容器服务端口映射到宿主机的一个随机端口上。也就是说,每一次容器重启之后,对应的服务地址是会动态变化的。为此,我们引入了consul实现服务注册和服务发现。每次容器服务地址变化时,将其更新到nginx反向代理的记录中。同时,,应用的域名解析到nginx上。用户访问应用域名的时候,nginx会将请求转发到具体的容器里。到此为止,用户已经可以通过Jenkins“一键”生成运行环境。

OAK架构图

图 3 OAK架构图

2016年6月的时候,PPTV已经有80%以上的应用将测试环境迁移到了Docker中,所以我们也开始将目标转移到了生产环境上。与测试环境不同,PPTV的生产环境网络流量很大(以视频播放为主),所以对网络性能要求非常严格。Docker默认的bridge模式无法满足。另外,生产环境是运维在管理。运维人员希望像管理虚拟机一样管理容器,希望容器有自己的IP,通过这个IP SSH登录到这个容器里,他可以查日志,监控,同步配置,或做一些其他的操作。到了这里,就对容器的网络有了更高的要求,除了性能,还需要独立IP,docker集群之间的容器要互通,容器还需要和传统环境的网络打通,能和传统环境里的应用IP通讯。

对Docker了解比较早同学应该会清楚。在Docker早期,还有Mesos+Marathon框架早期,是没法满足容器独立IP的需求的。一直到2015年的11月,Docker1.9发布,正式支持Overlay网络,支持跨主机网络模块的通讯。

Docker网络方案对比

早期的容器网络

早期的容器网络,就是主机内部的网络,想要把服务暴露出去需要通过iptables做端口映射。这是属于“远古时代”的东西,很难被企业使用。

图 4 早期的容器网络

Docker早期的4种网络模式:

  1. Bridge模式:默认模式,为容器分配Namespace、网卡和IP等,并连接到宿主机的虚拟网桥(docker0)
  2. HOST模式:使用宿主机Namespace、IP和端口
  3. Container模式:使用已经存在容器的Namespace、IP和端口
  4. None模式:容器拥有自己的Namespace,需要另外添加网卡、配置IP等

Docker Overlay网络

图 5 Docker overlay网络

Overlay网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。这样不但能够充分利用成熟的IP路由协议进程数据分发,而且在Overlay技术中采用扩展的隔离标识位数,能够突破VLAN的4000数量限制,支持高达16M的用户,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。因此,Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案。

在Docker的1.9中版本中正式加入了Overlay网络的支持。

Flannel容器网络

图 6 Flannel容器网络
Flannel是由CoreOS主导的解决方案。Flannel为每一个主机的Dockerdaemon分配一个IP段,通过etcd维护一个跨主机的路由表,容器之间IP是可以互相连通的,当两个跨主机的容器要通信的时候。会在主机上修改数据包的header,修改目的地址和源地址,经过路由表发送到目标主机后解包。封包的方式,可以支持udp、vxlan、host-gw等,但是如果一个容器要暴露服务,还是需要映射IP到主机侧的。

Calico 网络方案

图 7 Calico网络
Calico是个年轻的项目,基于BGP协议.完全通过三层路由实现,对网络不熟悉的同学可能都没有听说过。Calico的目标很大,可以应用在虚机,物理机,容器环境中。在Calico运行的主机上可以看到大量由linux路由组成的路由表,这是calico通过自有组件动态生成和管理的。这种实现并没有使用隧道,没有NAT,导致没有性能的损耗,性能很好,从技术上来看是一种很优越的方案。这样做的好处在于,容器的IP可以直接对外部访问,可以直接分配到业务IP,而且如果网络设备支持BGP的话,可以用它实现大规模的容器网络。但BGP带给它的好处的同时也带给他的劣势,BGP协议在企业内部还很少被接受,企业网管不太愿意在跨网络的路由器上开启BGP协议。

方案对比小结

简单总结一下上边提到的几种网络方案,不外乎出自两个技术流派,隧道方案和路由方案。

  • 隧道方案
    比如Flannel的VxLan。特点是对底层的网络没有过高的要求,一般来说只要是三层可达就可以,只要是在一个三层可达网络里,就能构建出一个基于隧道的容器网络。问题也很明显,一个大家共识是随着节点规模的增长复杂度会提升,而且出了网络问题跟踪起来比较麻烦,大规模集群情况下这是需要考虑的一个点。
  • 路由方案
    路由技术从三层实现跨主机容器互通,没有NAT,效率比较高,和目前的网络能够融合在一起,每一个容器都可以像虚拟机一样分配一个业务的IP。但路由网络也有问题,路由网络对现有网络设备影响比较大,路由器的路由表应该有空间限制一般是两三万条。而容器的大部分应用场景是运行微服务,数量集很大。如果几万新的容器IP冲击到路由表里,导致下层的物理设备没办法承受;而且每一个容器都分配一个业务IP,业务IP消耗会很快。

PPTV Docker网络解决方案

对比了几种解决方案之后,结合PPTV的实际情况:

  1. 网络组人力不足以维护一个Overlay网络,Overlay网络出问题排查复杂,会出现失控的状态。
  2. 隧道技术影响性能,不能满足生产环境对网络性能的要求。
  3. 开启bgp对现有网络改动太大,无法接受。
  4. 运维组同学希望能通过网络桥接的方案解决容器网络。

容器网络桥接

最终,我们的解决方案,基于Docker的bridge模式,将默认的Docker bridge网桥替换为Linux bridge,把Linux bridge网段的IP加入到容器里,实现容器与传统环境应用的互通。

实现思路很简洁清晰,现在有一个Mesos主机:

  1. 首先会在该主机上添加一个Linux bridge,把主机网卡,可以是物理机的,也可以是虚拟机的,把这个网卡加入bridge里面,bridge配上网卡原本的管理IP。
  2. 创建一个新的Docker bridge网络,指定bridge子网,并将该网络的网桥绑定到上一步创建的网桥上。
  3. 容器启动时候,指定容器网络为第二步中创建的bridge网络,同时为容器指定一个该网络子网内的IP。容器启动后网络IP默认即可与外界互通。

这里要注意的是第二步,我们的同学在研究这个方案的时候绕了一个很大的圈子,因为Docker容器使用Docker bridge网络模式的时候,在容器启动时会默认把容器的网关指向到宿主机上的网桥IP,即Linux bridge的IP,而这个IP并不是该网段的网关。所以我们需要在容器启动的时候将容器网关指向到实际的网关地址,而解决这个问题的方法在docker官方文档中并没有提到,我们最终是在一个issue里找到了解决办法。
链接在此 https://github.com/docker/docker/issues/20758

给个简单的例子

docker network create --gateway10.199.45.200 --subnet 10.199.45.0/24 -o com.docker.network.bridge.name=br-oak--aux-address "DefaultGatewayIPv4=10.199.45.1"  oak-net

关键参数:--aux-address"DefaultGatewayIPv4=10.199.45.1"

以上边的命令为例,该命令中创建了一个Docker bridge网络,并与Docker所在主机的br-oak网桥做桥接,该网络的使用了10.199.45.0/24这个子网,同时通过 --aux-address"DefaultGatewayIPv4=10.199.45.1" 这个参数将容器启动时的网关指向到10.199.45.1

通过网桥的方式解决容器网络有两个问题:

  1. Linux bridge 只能添加跟slavehost 同一个vlan的IP,也就是说容器IP必须要和宿主机在同一vlan下,这在一定程度上就限制了容器跨宿主机漂移的范围。

    不过这个问题在PPTV的生产环境中天然不存在,因为我们的生产环境中,每个数据中心的主机都在一个很大的子网内,基本能满足容器在整个数据中心的任意节点下漂移。

  2. 要让容器IP在不同的宿主机上漂移,宿主机的Docker网络需要使用同一个CIDR,也就是各宿主机的容器使用同一个网段。而不同宿主机的使用同一个容器网段就会涉及到IPAM的问题,因为宿主机的Docker daemon只知道他本机上的容器使用了哪些IP,而这些IP在其他宿主机上有没有被使用,是不知道的。

    在默认的Docker bridge中,因为这些ip不会直接与外部通信,所以容器使用相同IP也不会有问题,但是当容器网络通过linux bridge打通以后,所有容器都是2层互通的,也就是会出现IP冲突的问题。

为了解决上边提到的问题,实现全局的IP管控,我们开发了IP池管理平台,实现对容器IP的分配管理。由这个平台管理的IP有三种状态:

  1. 未分配给应用
  2. 已非配给应用并且在使用中
  3. 已分配给应用但是当前未使用

管理平台以Marathon上的APP信息作为数据源,定期去调用Marathon的API更新IP列表。当我们要在Marathon上创建一个使用固定IP的容器时,首先会请求IP池管理平台的IP分配接口,请求的时候把APP ID发给分配接口,管理平台根据APP ID判断这个应用是否是新应用,如果是新应用则从IP池中返回一个未使用的IP,并将此IP与应用关联。如果是已经存在的应用则分配已关联的IP。IP与应用关联之后,此IP就不会再分配给其他应用,除非IP池已经没有可用IP,这样做是为了防止应用如果重启或者重新构建的时候,IP有可能会被其他在同一时间启动的实例使用掉的风险。

IP池管理模块分配IP的流程图大致如下:

图 8 IP分配流程图

后续工作

网络方案搞定,固定IP搞定。我们要做的还有很多。

通过网桥的方式、解决了容器网络的问题,我们接下来还要面临其他的问题。

首当其冲的就是原先的服务自动注册、自动发现,不再适应了。因为原先的方案是基于NAT的模式做的,而现在实现了独立IP的功能。我们需要将现有的平台与PPTV内部的DNS做自动化对接,每当有容器创建和生成时,都会自动对容器的IP做DNS解析。

另外一个问题是负载均衡,PPTV的负载均衡基本都是通过LVS + Nginx实现的,但对于后台的容器应用来说,每次扩容和缩容、或者创建新的应用,负载均衡的后端配置也是需要自动更新的。

原文链接:PPTV Docker集群的网络方案选型

PPTV Docker集群的网络方案选型相关推荐

  1. Docker集群(一) —— Docker网络及flannel介绍

    [摘要]本文介绍docker网络原理和设置,以及在docker集群中需要解决的问题.最后介绍flannel在解决docker网络问题中的作用. 1   基础 在介绍docker的网络之前,必须先认识d ...

  2. docker集群搭建

    1.docker集群的概念 在docker集群搭建之前,一台机器中的容器和其他机器之间的容器是不能很方便的通信的,像下面这个样子:     在docker集群搭建之后,一台机器上的容器与其他机器之间的 ...

  3. 《Kubernetes部署篇:基于docker使用kubespray工具部署高可用K8S集群(国内互联网方案四)》

    文章目录 一.部署背景简介 二.部署工具介绍 三.部署方案介绍 四.部署环境信息 五.部署资源下载 六.部署准备工作 6.1.系统内核升级 6.2.设置主机名 6.3.环境初始化 6.4.ssh多机互 ...

  4. 《Kubernetes部署篇:基于docker使用kubespray工具部署高可用K8S集群(国内互联网方案三)》

    文章目录 一.部署背景简介 二.部署工具介绍 三.部署方案介绍 四.部署环境信息 五.部署资源下载 六.部署准备工作 6.1.系统内核升级 6.2.设置主机名 6.3.环境初始化 6.4.ssh多机互 ...

  5. docker集群运行在calico网络上

    2019独角兽企业重金招聘Python工程师标准>>> ##网络及版本信息 docker1 centos7 192.168.75.200 docker2 centos7 192.16 ...

  6. Kubernetes与docker集群管理常见问题解析

    很荣幸受邀参加开源中国社区的高手问答,我是时速云团队的后端工程师,负责主机管理功能开发.在互动过程中,发现大家在使用/调研kubernetes(简称k8s)过程中遇到了很多问题,这里我总结为几点: l ...

  7. Docker集群管理(DockerHub Harbor 打包-Jib 任务编排工具- docker-compose和Swarm)

    Docker 集群管理 Docker 集群管理 镜像仓库管理 DockerHUb仓库管理 什么是DockerHUb 账号注册和登陆 Docker客户端登录 管理镜像 推送镜像 仓库镜像测试 regis ...

  8. k8s docker集群搭建

    一.Kubernetes系列之介绍篇 1.背景介绍 云计算飞速发展 - IaaS - PaaS - SaaS Docker技术突飞猛进 - 一次构建,到处运行 - 容器的快速轻量 - 完整的生态环境 ...

  9. docker swarm的应用----docker集群的构建

    一.docker安装 这里我们安装docker-ce 的18.03版本 yum    -y remove docker  删除原有版本 #安装依赖包 [root@Docker ~]# yum -y i ...

最新文章

  1. 【廖雪峰python入门笔记】for循环
  2. python转行it好学吗-想转行学python过来人提醒大家几点
  3. 杭州线下|2019产品经理年终轰趴
  4. 【实例】销售合同VA41屏幕字段增强实例
  5. python2.7怎么升级python3_如何将Mac OS X10.9下的Python2.7升级到最新的Python3.3
  6. mysql 学习笔记03 常用数据类型
  7. define定义的是什么类型_DEFINE_PROFILE用法介绍(1)
  8. String类比较,String类运算比较,String运算
  9. MTK 驱动---(11) EMI定制
  10. python的传参是传值还是传址
  11. MonoDevelop 0.14 on Ubuntu
  12. VB.NET与 sql数据库
  13. 2021免费注册TK域名使用一年的方法
  14. 定理在数学中的简写形式_初中数学定义、定理(大全)
  15. 开源资产扫描系统-ARL资产灯塔系统
  16. 微信上网卡WeSim悄然发布
  17. props的动态传值 以及 v-for列表渲染
  18. 阿里云服务器ECS购买教程
  19. 冰湖,风筝,喜鹊,跳水台
  20. ChinaSoft 论坛巡礼 | 软件工程教学案例交流与竞赛

热门文章

  1. 搜索互联网缓存页面 How to View the Cached Page of any URL or Website
  2. PHP生成唯一会员卡号
  3. WordPress 不用插件实现对长文章进行分页
  4. BrainFuck——C实现BrainFuck解释器
  5. spring中需要掌握的25个常用注解
  6. 【vim小记】vim的复制粘贴(包括系统剪贴板)
  7. rsync常用参数组合
  8. 华为机试——取近似值
  9. 【今日CV 计算机视觉论文速览】 11 Mar 2019
  10. DDL 创建与查询数据库