参考材料:https://zhuanlan.zhihu.com/p/465877731

我之前服务的公司是一家深耕于ToB领域的业界招牌,为大量的企业提供了私有化的企业服务软件。而我在该公司的七年时间,经历了公司对于新技术的两次尝试,给我留下了深刻的印象。

第一次尝试是公司开发了一套完全基于微服务架构的产品,只需要一个启动脚本就可以在一台机器上拉起几十个微服务。但是这款产品在客户现场遇到了无数的兼容性问题,导致研发中心的工程师全部被拖入无穷无尽的用户投诉中。最后这个产品经历了短暂的辉煌后默默下线,变成了我的同事们不再愿意提及的伤痛。戏剧性的是,在这个产品被公司砍掉后的半年,整个行业突然迎来了容器化技术的大爆发,这时候我们很不甘心的意识到,如果容器化技术可以早两年,哪怕早一年出现,我们的这个产品就会有一个完全不一样的结果。而这也是容器化技术第一次进入我的视野,并让我对它有了一种莫名的信任。

在接下来的一两年里,容器化技术以非常恐怖的速度成长,社区群雄并起,硝烟弥漫,彼时容器化无所不能的言论甚嚣尘上。而容器化技术对我前司的冲击,在某个技术负责人利用业余时间,以非常小的代价把我司一整套ToB产品全部塞进了k8s集群时,达到了顶峰。技术团队以上一个失败的产品作为参考,评估了整套容器环境的兼容性易用性以及技术难度以后,毅然决定将公司产品线全面转型容器化。自此开始,我用我不算太短的职业生涯,把容器化能踩的坑全部踩了一遍……因此,当有人希望我可以聊一聊“容器化的可用场景和不可用场景”这个话题的时候,我感到心中有万千沟壑,不吐不快。

关于这个话题,我尝试用我之前的经历,给出一些不太适合使用容器化技术的场景,权当讨论:

  1. 如果你的应用场景中,程序需要频繁的和一些需要特殊驱动的硬件资源交互或者内核交互,那么这个应用是不适合放在容器中运行的。虽然我们可以把设备pass through到容器,但是如果需要涉及到修改内核参数,或者内核交互,就不行,容器内无法做到这些,需要宿主机修改。

  2. 容器的优势之一对于资源的精细化管理。如果服务本身需要超大资源(CPU或者内存接近宿主机本身资源大小),那么这个服务更适合放在裸机上运行。因为容器本身的资源调度也是需要消耗性能的,把重资源的服务放在容器中跑并不能提速,对于资源的精细化管理也没有任何帮助。如果这种服务有强烈的容器化需求,建议先拆分成微服务,再分批容器化。

  3. 对读写和存储有强需求的服务,比如早些时候,数据库是不推荐放在容器中运行的。哪怕docker volumes可以提供持久存储,但是容器本身只是进程级别的运行,一旦容器崩溃,很容易导致数据库非正常关闭进而损坏数据。近两年,关于容器化数据库技术日益完善,但即使我们把数据库放在容器执行,并且保证无状态,但是由于对存储性能要求很高,在具体实现过程中,对容器调度依然有一定要求。当然,作为缓存数据库的Redis因为并不需要数据落地,即使服务崩溃也不会有很大的影响,它就是很适合放在容器中运行的。

  4. 对于需要调用图形接口的应用,或者Windows平台特定程序,容器化也是不合适的。虽然业界有Nano作为解决方案,但是这个解决方案也并不是完全可靠。

  5. 如果你的服务需要把安全性作为第一优先级考虑,那么容器化方案通常不是最优解。因为集群中运行的容器某种意义上共享机器的内存和磁盘资源,会有潜在的安全风险。虽然我们可以用不同的命名空间实现绝大部分的隔离,但是并不一定安全。

时至今日,容器化社区依然在高速发展,以上这些不适合的场景在社区中也在慢慢的改进,也许不久的将来甚至当下,就会有更合适的容器化解决方案产生。

当然,相对不适合容器化的场景,有些业务非常适合容器化,在做好清晰的系统规划和架构设计后,容器化可以极大的降低业务的运维成本,以下给出一些具体的案例:

  1. Web应用服务。容器化的飞速成长和这些年互联网业务的大规模发展有着直接关系。容器服务的快速启动,统一管理,易于监控,弹性伸缩,都是互联网业务的强需求。因此也有无数的互联网公司在积极回馈容器社区,促成的整个生态的良性循环。

  2. 微服务架构下的容器化使用。就像我前文提到的,微服务的解耦性和小模块服务运行/升级,和容器化方案本身的特性非常契合,因此容器化技术和微服务架构可以说是相互成就彼此的最佳典范。

  3. 精细化资源分配业务,容器服务由于其特殊的资源调度机制,对于计算资源的分配可以精细到小数点。因此容器化技术很适合让企业告别粗犷的资源分配模式,从成本控制上更好的帮助业务发展。

  4. 精细化资源分配业务的另一个场景是一次性业务。容器由于其即用即销毁的灵活特征,避免了计算资源的大量浪费。

  5. 持续集成和持续部署。容器化技术可以基于同一套镜像提供一致化的编译部署环境,并且配合k8s的优秀编排能力,无缝升级模式,快速完成服务的自动化升级,最大程度的简化运维成本,并且保持环境的绝对一致性。

  6. 强横向扩容业务,比如游戏行业:在联网游戏中,传统模式下游戏公司需要准备大量物理机器,随时热备等待玩家接入。再游戏结束后又要及时释放资源重新启动新的服务器进入热备队列,资源调度和管理非常麻烦。而使用容器化集群,可以非常容易的解决这个问题。

作为一个工程师,我避免使用非黑即白的二元论断来肯定或者否定容器化的使用场景。站在技术发展前沿的我们,对于新兴的容器化技术,既不应该盲目迷信容器化的无所不能,也不应该妖魔化容器技术的局限和不稳定性。没有业务支撑的技术只是屠龙之术,而没有技术支持的业务也不会有长远的发展,因此,让业务和技术相互成就,才是工程师该选择的道路。