唯品会数据库备份恢复容器化项目实践经验总结

通过docker天生隔离性和快速部署等特点,实现在单台物理机上运行多个数据库备份/恢复实例,大大提高服务器使用率,节省大量成本。通过对docker本身和相关组件的研究和改造,从普通开源产品落地到公司内部生产环境,积累宝贵的开发经验。通过对docker已经在其上层运行的数据库日常运维和监控,也积累宝贵的docker运维经验,为更大规模推广容器提供基础。

tu1

关于容器技术

通过实践,证明容器技术在易用性,可管理性,快速部署具备天然的优势。在资源利用率方面,容器部署在上百个物理节点上,提供约500多个数据库灾备实例,提升了硬件资源的利用率,节约了约400台物理机的采购成本。这些是容器技术带来的实实在在收益。在资源分配与隔离方面,又不输于虚拟机。cpu, 内存,磁盘io, 网络io限流等技术的应用,保证了资源的合理使用,从机制上阻止了单一实例的资源过分消耗的问题。

稳定性是使用容器技术非常关注的一个点,也是基石。Mysql备份/恢复属于cpu密集 + 磁盘io密集 + 网络io密集型业务,对于docker daemon是个较大的考验。就目前来看,限制每台宿主机的容器数量(5个左右)的情况下,集群跑了三个多月没有出现因为容器负载过大导致的crash现象,还是值得信赖的。遇到的唯一相关问题是docker daemon挂死,具体现象是docker info, docker ps 没有响应, docker volume, docker images 正常,下面的容器运行正常。这是偶发事件,无法重现,以后需要继续观察。

由于容器以进程方式存在,体现出几乎与物理机上相当的性能,overhead 极低(低于10%)。从数据抽取任务的结果来看,与物理机相比,使用容器对成功率没有影响,效率也差不多。这也很符合最初预想,不管跑容器还是外部服务从物理机角度来说它们之间是没有什么区别的,都是一个进程,唯一不同是父进程不一样而已。

以上是容器”RUN”带来的好处,通过统一开发流程,应用微服务化,ci/cd等方面的改进,能够进一步利用容器”BUILD”, “SHIP” 优势,容器技术还来的潜力是巨大的。要说容器技术的缺点,还真的不明显。硬要提的话一个是需要一定的学习成本,改变开发流程与方式,一个是开发人员对容器技术的接受程度。这个项目仅用了不到二百人/天,对于一个采用新技术的项目来说,真的是很低的了。一开始我们也担心因为采用新技术导致开发推广有困难,后来实际能通过技术上解决问题,打消了大部分用户对使用docker的疑虑,反而有助于该技术的普遍应用。

关于docker daemon版本的选择,我们之前是有过一些讨论的。现在docker社区非常活跃,当时我们用1.10.3, 到现在已经出了两个新版本了。在功能满足的前提下,稳定性是第一考量。docker 自1.9.0引入CNM网络模型,1.10算是比较成熟。CNM是我们希望在这个项目尝试的一部分。网络与Volume插件功能与稳定性的提升,开始支持磁盘io读写限速,device mapper的支持,等等,都是选择了这个版本的原因。另外,docker插件的引入,很好地解耦了docker与底层模块的关系,使我们可以专注于底层(网络,存储)实现而不需要修改docker daemon本身,同时避免产生升级依赖。

关于容器网络技术

容器网络基础设施使用的是Contiv Netplugin, 这是来自思科的开源方案。neplugin以网络插件的形式接入docker daemon, 网络功能作为容器生命周期的一部分被调用。Netpluign 通过管理OVS, 基于OVS VLAN作隔离,容器分配外网IP, 可以直接访问, 大大简化了容器访问的方式。

考虑使用该方案的原因在于:

1. 插件形式不会对docker产生升级依赖。

2. openvswitch也是业界SDN的事实标准,希望籍此为容器带来各种网络SDN的能力,例如 限速,QoS访问控制。事实证明,只在容器创建与删除过程中调用到netplugin, 运行中的容器所有流量只经过openvswitch, 不依赖netplugin, 它即使挂了容器也能正常访问,这个机制对网络的可靠性是好的一方面。OVS在之前一年半的openstack实践中,已经证明是非常稳定的,ovs桥使用带宽为1G的uplink,与物理机相比只有不到5%的损耗。

tu2

Netplugin原方案是有流表的,每新增一个容器都会加一条flow, 而且所有节点都添加,容器一多的话这个表的大小是不可想像的。我们把该功能去掉,以降低复杂度,提高稳定性。另外,引入了ovs rate-limit功能,把容器流控也做了,能够根据情况实时的调整每个容器的可用带宽。项目中 netplugin管理的ip地址池有三个,很好地支持了500+容器的运行。

为了防止同一个二层广播域容器增长,导致路由器arp表过快增长的的问题,在大规模部署中,需要在netplugin增加arp proxy功能。

netplugin 很多优秀的功能例如vxlan, 多租户,访问控制我们都没有用到。虽然社区在不断成长,但代码还没完全成熟。也遇到过一些bug,比如容器异常退出IP地址不能释放的问题,这都需要我们自己去解决。我们的做法是基于某一版本,吃透代码,只用基本功能,经过充分测试,边测边改,逐渐扩大上线规模。

关于容器存储

容器外部卷使用convoy, 以插件的形式支持容器持久化数据。容器本身与外部卷均使用device mapper作为底层。没有选择分布式存储原因,主要是为了简化实现,更稳定。通过限制每个容器的BlkioDeviceReadBps,  BlkioDeviceWriteBps, BlkioDeviceReadIOps, BlkioDeviceWriteIOps, 使磁盘 IO 稳定地达到相当于 95% 物理机性能。

tu3

对于 device mapper,因为是红帽推荐的,而OS又是用的CENTOS7.2, 所以就用了它。测试过程中发现device mapper健壮性不是很好,仅仅在低并发下,也会出现容器删除失败的情况,容器并发启停偶尔出现找不到设备的情况。这种使用映射关系的设备,功能是丰富,实现上过于复杂,每次对设备的修改都需要额外去更新meta data, 并发场景出错的机会就大了。让我再选的话我会考虑overlay这种更简单的driver。

对于convoy, 是来自rancher的产品,go语言,仍然处于未成熟阶段,版本号0.5, 并没有完全实现volume pluign接口。相比其它模块它的问题也是最多的,例如volume创建失败,无法删除,unix socket泄漏,重名冲突,异常自动退出等。属于能用,但未完善的状态,你自己得有一定开发调试能力去解决发现的问题。其它几个存储插件情况也差不多,Flocker, Blockbridge, Horcrux等等,有的连第一个正式发布版都还没有,convoy反而相对好点,有点烂柿子堆里挑的感觉。

对于docker 本身的volume plugin接口,我们也遇到一些坑。

下面是其中一些:

• Docker volume plugin 不支持获取 volume 使用状态数据

• Docker volume plugin 存在 file descriptor leaks bug – https://github.com/docker/docker/pull/20686

• Swarm 定期 list 会偶然触发 Docker volume cache bug – https://github.com/docker/docker/issues/21403

关于容器监控

容器监控在这个项目里还可以有很大的空间可以改进。项目里用的是cadvisor, 容器内top,free,iostat命令劫持,基于已有的zabbix体系作数据收集与展示。结论是zabbix完全不合适做容器监控,数据收集密度,展示质量,灵活度都没能满足需求。

后来在测试中尝试使用telegraf + influxDB + grafana。 只需要telegraf简单的配置,能够帮忙我们清晰地展示容器及服务进程cpu, 内存,网络,磁盘等情况。grafana上sql查询语句的调试与开发,确实需要不少的时间,但这个工作量是一次性的。因为是go写的,telegraf cpu占用属于比较低的水平(0.4 – 5%)。功能上比较丰富,同时支持外部进程与容器的数据收集,多达55种数据源插件,有它就不需要布cadvisor了,个人比较推荐。需要告警的同学,可以考虑把influxDB改成Prometheus。它包含Alertmanager实现email, pagerduty等消息通知。数据backend可以选择自带的DB, 也可以外接influxDB, graphite, opentsdb等流行方案。

监控领域业界已经有很多开源方案可以参考,以下是需要衡量的标准:易扩展,开销低,入侵小,大集中,易部署,实时性,展现清晰灵活。这方面希望与各位有更多的交流。

以上是本次分享的全部内容

分享到:更多 ()