UDN-企业互联网技术人气社区

板块导航

浏览  : 534
回复  : 1

[教程技巧] 云端基于Docker的微服务与持续交付实践(下)

[复制链接]
白青青的头像 楼主
发表于 2016-7-9 11:01:27 | 显示全部楼层 |阅读模式
  什么应用可以运行在容器中

  讲了这么多,实际上大家一定会关心:

  我的应用怎么跑在容器里?

  我哪些应用可以被容器化?

  大家都会问这些问题。
2.png

  这是我节选的一个很著名的分类方法,它可以帮助大家去挑选什么样的应用适合在容器里跑、什么样的应用不适合。

  它是根据两个维度:

  一个维度是长寿还是短命的应用;

  另外一个是看它是有状态还是无状态。

  容器化的应用最擅长的使用就是左面的短命且无状态的应用,因为这样的应用最容易部署。

  比如一个Web应用,我们可以很容易地快速把它干掉,我们不在乎它,可以非常快速地部署一个Web应用。

  另外一个维度就是那些短命,像高性能计算、批处理。

  对一个视频进行渲染一定是大量有状态的信息,但是这些信息可以通过Web对象存储来保存,这样的计算密集型任务也非常适合在上面去做,因为我们可以快速地识别一大组集群,通过这样的容器来跑这样的任务。

  还有一类是长寿但是无状态的,比如说我们的开发测试环境一直在用或者我们的监控,它会一直跑在那里,但是它本身的状态依赖度是非常小的,这样的应用我们也可以考虑。

  只有左下角这个维度一般来讲是最有挑战的,它是有状态的服务,一般有状态的服务需要一些调整,包括对存储调整、对网络调整,大家依然需要DBA做很复杂的工作,也不完全做到自动化。

  对于这样的一些应用,我们的建议是在测试与开发中可以使用容器技术,但是在生产上非常不建议使用这样的技术。

  Docker化应用实战: Ghost 博客

  接下来就拿一个特别喜闻乐见的例子跟大家解释怎么样把一个应用容器化。

  Ghost 博客是我非常喜欢的一个博客应用,非常简单,非常轻,镜像也非常好用,用很简单的方式就可以把Ghost镜像起来。
2.png

  但是还有很多问题:

  不是可伸缩;

  不是高可用的。

  它所有的数据是保存在本地的Database里面的,如果虚拟机节点宕掉之后,迁移到另外一个节点之上,数据状态都丢掉了。

  我们怎么解决?

  其实大家可以去参考THE TWELVE-FACTOR规范,这个规范得到了居多厂商的支持,它是现在很重要的一个编程规则。

  它有几个核心原则:

  应用要和运行的环境解耦

  应用要和外部调用服务解耦

  应用要和配置解耦

  通过这些解耦我们才能有一些应用变成无状态的,能够快速在云上进行部署和运营。

  Ghost 博客 高可用集群1

  我们只需要增加一个MySQL,让它支持MySQL的驱动就可以了,启动一个ghost+MySQ,通过MySQL进行连接,它们是共享状态的,我们的容器服务也做了很多的优化。
2.png

  Ghost 博客 高可用集群2

  我们不建议在生产环境中使用数据库这样有状态的服务,我们该怎么做?
2.png

  我们看到很多文章都说Docker非常不好用,说它不能运行数据库,Docker本来也不是运行数据库的。

  为什么我不直连到我的数据库的实例上呢?

  当然,这有不同的做法,但是我觉得最好的做法是我们做一个最小的改动,能够让应用层不做任何的感知就可以把一个数据库的镜像,把一个Docker的运行使用变成一个Web,我们增加了一个拓展的能力。

  我们增加拓展去引用Web的服务,我们就可以部署在生产环境,而你的应用层不做修改。

  Ghost 博客 高可用集群3

  在这个过程中依然还有一个问题没有解决,用户上传的附件,比如说图片,依然保存在本地存储中,这肯定不行。为了要做这件事情,我们有另外一件事情。

  我们可以通过Docker的 Volueme Plugin来解决,它提供了一个非常灵活的机制来支持不同的存储类型,现在已经支持了块存储、对象存储、网络文件系统。
2.png

  而且更加好玩的事情是,我们所有的网络驱动和Volume的驱动其实都是运行在容器里面的,因为只有通过这样的方式,我们才能对整个系统进行统一的运维和统一的管理。

  但是Docker在这方面依然有缺陷,Docker不能区分这样的一些网络驱动,会导致重启Docker Engine的时候,有可能先杀掉你的Volume Driver,你的数据没有保存就坏掉;

  或者说,你的网络也是一样,它可能会没有等你的应用杀掉就把你的网络驱动杀掉,这样你的应用和网络彻底中断,这样也是不行的。

  我们其实也在社区中提出了改动,我们可以对不同的守护进程进行分级,可以启动一些容器,它可以有更高的系统级别,在启动的时候被优先加载,被停止的时候会被最后停止,在社区1.11版本中会有类似的工作,社区会解决这样的工作。

  通过把网络驱动和卷驱动都作为容器处理,还可以给我们带来更大的好处。

  我们的整个系统非常可扩展,比如说我们在和一个第三方的网络存储公司谈合作,它现在就是拿一个容器来交付存储驱动,我们不用修改一行代码就可以把存储驱动跑在服务器上,这样可以使我们的系统有更大的可扩展性。

  容器化持续集成和交付

  Docker的一个重要好处就是可移植性,通过可移植性可以在开发、测试和生产的整个软件生命周期中,以同样的方式交付我们的软件产品。

  比如说,我们现在的开发人员就是这样的,只要一键就可以启动本地的开发环境,代码完成以后提交,提交的时候是相应的自身代码和原件。
2.png

  有了这个以后,相关的Docker基础设施,比如容器、镜像仓库,就可以把相关的代码编译成Docker镜像, 并且在整个测试、生产中一直用这个镜像,所有的步骤可以重复,而且保证一致性。

  在这个过程中,所有的东西都是可以支持Docker管理的,而且可以快速更新和管理。

  这件事情做完以后有什么好处呢?

  开发者在第一天就想着“我的代码怎么上线”,这是一个巨大的文化上和时间上的改变。

  以前我们讲DevOps,光运维的人员讲没有用,必须要让开发者在开发的第一天就在思考“软件怎么交付、怎么能够在云端为高可用、可伸缩”,这是必须要改变的一个文化和思想。

  如果这个改变不了,你用任何技术都改变不了。

  以前我们阿里也是一样,开发人员很牛逼,运维人员很苦逼,开发人员开发出来,运维人员熬夜上线,出了故障就回滚,非常低效。

  但是我们现在要求开发人员每个功能必须交付一个Docker镜像,把你的前置条件、后置条件、检查的脚本、健康检测的东西在一开始就交付出来,不交付的话,我们运维人员停止接受这样的代码。

  通过这样,我们可以快速地去演进。

  简化的持续交付流程

  源代码管理,我们可以有一个镜像服务,它可以订阅源代码仓库的通知,我们的容器服务也可以订阅镜像变化的通知。

  当您的代码变更,比如修改一个网页,把两栏变成三栏,它会通知镜像服务拉取相应的代码构建,打包成镜像之后,自动通知相应的容器服务更新现成的应用。

  几分钟之后,变更上线,我们也可以和其他的服务集成在一起。
2.png

  完整的持续交付流程

  阿里社交平台何以监控源代码仓库的变更,代码发射变更之后,它拉取代码进行镜像,单元测试通过之后打镜像,通知持续交付服务器进行下一步操作,它是流水线。

  在流水线中拿着Docker镜像和Docker文件在测试环境、预发环境、生产环境上部署。
2.png

  我们同样的一个Docker镜像,同样的一份Docker模板,可以在不同的环境中使用,这样我就能够保证从开发、测试、上线所有东西的一致性。

  大家一定要坚持这样的一些理念,因为DevOps很多东西大家都懂,缺的就是坚持。

  不可变架构(immutable infrastructure)

  Docker出来之后为什么得到DevOps领域人士的欢呼?

  其实它符合了我们所期望的运维方式。

  了解OOpenStac都知道这个很著名的寓言股市,你的应用到底是像一只宠物需要你整天呵护,还像牛群的一头牛,可以随时杀掉毫无伤心,你可以随时有另外一头牛补充上来。

  让这个系统变成自维护,非常健壮,不会因为任何节点的失效而导致整个系统终止。
2.png

  利用不可变性来运维基础架构: 一旦实例化后,永不改变;只会用另外的一个实例正确的取代它。

  优点

  避免环境间的不一致。这在我们日常生活中占了很大的比重,超过30%的线上错误都是因为开发环境和测试环境与线上环境不一致导致的。

  如果我不可变架构就可以保证所有代码除了门都是一模一样的,永远按照你预期的方式来运行,测试和上线、生产是同样的东西。

  简化部署复杂度。在原地打补丁升级非常难,尤其是很多系统软件,有很多副多少。

  低成本回滚。写个回滚代码复杂很多,而且很难保证正确,因为大家从来不测回滚。

  其实这个事情并不新奇,以前有个虚拟机,在家配个自动化的工具也可以,但是Docker让这件事情做得更快,变得更简单。

  就等于说,每个Docker镜像实际上是不可变的,它就是一个进程,随时可以替换出来一个新的镜像。

  Docker启动速度特别快,以前拿虚拟机做回滚可能需要几分钟时间,但是如果用Docker回滚时间在秒级,用户是感觉不到中断的。

  Docker:不可变架构梦想成真

  要达到这一点也需要大家注意,因为我知道很多人依然在今天把Docker容器当成轻量级虚拟机来使用,这个没有什么不好,只是大家的场景不一样。

  但是,我请大家在做这件事情的时候一定要三思,当你把当容器当作轻量级虚拟机的时候,你一定要再次思考一下,您这样做可能会丧失掉Docker很多好的特性,最重要的就是不可变性。

  为了达到这一点,我们需要做一些正确的工作:

  永远不要手工修改容器中的内容,你的容器应该永远是拿代码构建出来的。

  尽量不要使用latest作为镜像标签,生产中你要回滚,你要知道回滚哪些问题、哪一个版本,一个最简单的方法是在你的镜像中用Git Commit作为镜像tag一部分,便于追踪,保证你线上的产品清楚地知道运行什么版本。
2.png

  不要把任何可变数据保存在镜像中,要通过Volume抽象,可以把应用变化的部分跟您容器的生命周期进行良好的结合,它带来的好处远远大于懒、省事带来的好处。

  跨主机容器网络 云端实践

  在网上大家看到很多关于Docker网络的很多讨论,大部分讨论是基于自己的数据中心,因为在自己的数据中心很简单,你甚至可以控制交换机。

  但是在公有云上这件事很难,我们要选择在云上Docker容器互联的话,一定是按照云厂商的配置最大的优化去适配。

  通常在云上有两种方案可以实现跨虚拟机的容器网络之间的互联:

  通过Overlay的方法,只要三层是通的,通过Overlay实现虚拟网络。

  Overlay这种方式是非常通用的方式,它可以在不同的网络环境使用,甚至跨不同的云供应商都可以使用。但是它也有弱点,它自身的性能是有限的。

  我们在亚马逊、阿里云、IBM的云上都测过,通过Overlay容器互联性能和容器通过原生虚机之间通信,只有带宽的70%,也会增加20%-30%的延迟,对于网络性能敏感的人我们是非常不建议这样做的。
2.png

  通过云供应商网络自身的网络特性,比如VPC,VPC和今天网络很大的不同,在VPC中我们可以控制一些IT分配、路由规则。

  通过这种方式我们得到很多好处,因为在一个VSwitch之内整个二曾是通的,我们甚至可以不用Web技术,在相应的节点上配相应的路由表就可以实现容器之间互通。

  但是在一个VSwitch要做的话要承担一个后果,当一个数据中心掉链的话应用就挂了。

  一般生产上我们建议这样的做法,通过一个VRouter把你的应用部署在不同的VSwitch上,然后在 VRouter上配路由规则,这种方式很通用,无论是在亚马逊还是阿里云上,我们都采用这种方式。

  它的好处,容器和容器之间通信的带宽,在阿里云和亚马逊上,大概带宽基本和原生的速度没有区别,但是时延会稍微多一点,可能会在10%左右。

  所以,如果大家追求性能可能会考虑,当然它也是受限于在一个 VRouter上到底有多少条路由表的限制,最后限制到您的集群节点的最大规模。

  大家都知道,世界上没有最好的方案,一定根据自己的情况挑选合适的方案。

原文作者:易立 来源:高效运维

相关帖子

发表于 2016-7-9 13:18:52 | 显示全部楼层
赞一个
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部