林钟洪 分布式实验室

魅族云Docker实践_Java

介绍魅族云的场景需求,如何引入Docker,在网络、存储、镜像技术的选择,如何落地的等等。

魅族云Docker实践_Java_021、魅族云业务场景

魅族云的需求场景可以分为以下几大块:

魅族云Docker实践_Java_03
 

  • 镜像需求:应用想上Docker就需要镜像,我们跟业务运维一起定好镜像的Dockerfile,push到镜像仓库,这个私有仓库存储了公司内部使用的所有镜像。然后我们会在承载Docker的宿主机预热这些镜像,加快速度;

  • 机器申请:我们有使用KVM的历史包袱的,所以在机器申请的时候就会走不同的通道,有KVM的和Docker的;

  • 业务发布:这是应用用得最多的场景,上了Docker就涉及到一个问题,如何屏蔽掉KVM和Docker机器的区别,我们有一套自研的发布系统,它会自动屏蔽掉两者的区别,各自走各自的发布流程;

  • 监控:对容器生命周期的监控。

从这些场景或者需求里面可以知道,在使用Docker之前,我们是有历史包袱的,不仅来自KVM的使用,还有更多的是运维工具链/运维平台的搭建。

魅族运维体系魅族云Docker实践_Java_04


我们的运维体系已经很完整了,标准化、自动化、平台化、安全每一块都已建设完毕。在这完善的体系下要引入Docker,就注定了我们不能照搬传统Docker的实践,这里我们抽象出一些理念,这些理念也决定了我们到底怎么玩Docker,如何完成Docker实践。

魅族云Docker实践_Java_022、Docker设计理念

  • Docker创建的Container需要长时间运行

    这个理念尤其重要,就是说我们的Docker Container一旦创建就会运行相当长的时间,表现出一台虚拟机的特性。

    做这个特性的第一大历史原因是我们有监控系统,需要把整个虚机的历史状态记录下来,在出现问题的时候,我们需要对比这台机器,以IP为标识的这台机器,在一周内的整个行为举止,内存、CPU、磁盘等等的状况。如果Container很快被干掉,发一次包, Container就变成了全新的,这是不可接受的,历史监控数据全没了。

  • Container拥有独立、唯一的IP

    每个Container拥有终生的/唯一的代号,这个代号就是内网IP,这个IP从它创建到最终销毁是不会改变的。

  • 主机间Container的通讯是通过大二层网络,并通过vlan进行隔离

  • 开启SSH

    这个主要是考虑到用惯KVM的运维和开发,如果直接把SSH关闭,会被吐槽,最终我们是开启了SSH,并通过堡垒机进行权限控制和审计。

这就是我们开始Docker实践的几个支撑理念,它让我们的Container表现得像一台KVM虚拟机一样,以此来满足业务的需求和适应现有的运维平台。

3、 技术选型

主要是我们在网络、存储、镜像技术的选择。

网络:OVS & VLAN魅族云Docker实践_Java_06


网络我们是在大二层架构上做的,就是OVS加VLAN的方式。

  • 宿主机安装OVS,在OVS上配置网桥

  • Container的网卡跟OVS的桥关联起来

  • vlan tag打在OVS的桥上,让OVS进行封装和解封装

  • OVS跟物理网卡绑定,用bond主备模式连上物理交换机,保证高可用

  • 宿主机物理网卡跟交换机间配的是trunk模式

  • Container跟OVS的连接,用ovs internal port模式 

存储:Devicemapper+LVM

  • Docker的存储系统我们选择发展比较早也比较成熟稳定的DeviceMapper,并且DeviceMapper底层我们直接使用裸设备作为pool,来提高IO性能

  • 数据盘存储使用LVM,把磁盘划分成多个逻辑卷,每个容器分配一个卷当作数据盘的存储,这样做除了能对容器使用的卷进行限额,还可以达到在线调整容器卷大小的目的

镜像存储与同步魅族云Docker实践_Java_07


  • 镜像管理使用Distribution,前端设置LVS做负载均衡,保证Distribution的高可用

  • 镜像存储使用Ceph分布式存储,为镜像读写提供高性能,也保证了镜像存储的可靠性

  • 不同数据中心间镜像的同步,则是通过Distribution的通知机制加后端的同步机制来完成的

监控

监控/告警可以说是运维体系最核心的功能之一,我们已经有一套很成熟的监控告警平台,而且运维和开发的同学都已经习惯了这套平台。重新开发一个监控告警平台会花费很多精力,而且意义也不大。

我们在每个容器内部运行一个Agent,从/proc下面获取CPU/内存/网络IO等信息,然后上报到监控告警平台。默认情况下,容器内部的proc显示的是宿主机的信息,我们通过获取CGroup中的统计信息来覆盖掉这部分proc信息。

魅族云Docker实践_Java_024、 Docker实践落地

镜像创建魅族云Docker实践_Java_09


镜像的创建我们通过平台来做的,当然直接用Dockerfile来build也没问题,但是在可控性方面会比较弱,我们通过平台来做这件事情,降低了学习成本,也提高了镜像的质量和安全,比如可以限制哪些包可以安装,哪些端口不能开放等等。

容器创建

魅族云Docker实践_Java_10

在我们的平台上容器的地位跟虚拟机是一样的,唯一的区别就是type类型,一个type是KVM,一个是Docker,其他的跟以前的玩法都是一样的,运维和开发接入学习的成本非常低。

弹性伸缩

  • 可以对Container进行扩容和缩容,以提高资源的利用率,这里注意缩容可能会导致服务不可用

  • 魅族云Docker实践_Java_11
  • 按照业务来水平扩容,一次交付多个容器给业务方

 魅族云Docker实践_Java_12

容器发布魅族云Docker实践_Java_13


容器的发布,我们跟KVM虚拟机发布是一样的,把一个war包放到Maven,虚拟机再从Maven上把包拉下来,然后跑起来。

魅族云Docker实践_Java_02总结

  • 提供类似KVM虚拟机的用户体验

  • 利用Docker进行高密度部署

  • 快速弹性伸缩

在Docker容器化引入的过程中,我们的理念在于想提供一个类似KVM一样的虚拟机用户体验,让用户可以无障碍使用容器,我们引入容器的目的在于它的轻量和低开销,能够高密度的部署,压榨物理机资源,提高资源的利用率,从而节约成本,在弹性方面,利用容器的轻量/便捷,我们可以快速的创建/销毁,满足业务的弹性需求。