云原生(Cloud Native)不仅仅是趋势,更是现在进行时,它是构建现代的,可弹性伸缩的,快速迭代的计算网络服务的事实标准。其中容器编排系统Kubernetes和容器是基石。
英语好且想直接读英文原版的朋友转这里:Design Patterns for Container-based Distributed Systems,作者是Brendan Burns和David Oppenheimer,论文发表于2016年,是云原生领域系统设计的代表作。
跟我一样不想读那么长英语的朋友看下来哈哈(好吧我偷偷的去拜读了他的论文,果然通俗易懂)。
Container就好比OOP C++编程语言中的Object(Class),是容器分布式系统的最基础对象。
在现实的设计中,需要把一个应用拆为多个容器来实现,这么做的理由有三个:
我对设计模式的看法一直很明确:具体问题具体分析,脱离了实际的辩论都是虾扯蛋。一定要设计,一定不要过度设计。
为什么Pod(含有一个或者多个Container)是最小的部署单元,而不能直接是容器?这个问题前面几篇就解答过了。Pod是一组共享生命周期,并部署在同一个节点的容器的组合,他们可以通过共享的volume/network和IPC来进行通讯。之所以不是一个单一容器,而是多个容器来完成特定功能的原因在于:这些容器要完成的职责不同,根据单一职责(single responsibility)的原则,他们应该属于不同的组件;其次因为职责不同,维护他们的team也不同,迭代周期也不一样;最后其中一些容器是可以被复用在其他的环境中的。所以从“解耦”和“复用”的设计原则出发,Kubernetes通过增加一个虚拟层即POD,给系统设计带来了极大的灵活性,同时也产生了多种设计模式。即在一个POD中除了抗流量完成业务的容器外,还存在其他的辅助容器,可以分为两类:1. Init Container 2. Sidecar container。
听说过 “装饰器模式” 吗?
Sidecar 容器是与 Pod 中的主容器一起运行的容器。Sidecar 模式可以在不更改的情况下扩展并增强当前容器的功能。
当带有单容器 Pod 正常运行时,我们想在不接触、不更改的情况下向当前容器添加或扩展一些功能,这种情况下,Sidecar 容器模式可以提供帮助。
举个栗子,不然这样我自己过段时间也看不懂了:
App Container是一个web server,sidecar container定期从github sync代码下来,两者通过Pod的volume来共享文件。这样做的好处是把从github定期sync代码的逻辑剥离出来,成为一个可以重用的模块,并且能用到其他的场合。而app container只需要单纯的做web服务就好,不需要考虑sync之类的逻辑。
什么时候考虑使用sidecar呢?当这两个container需要同时部署,但是各有自己的职责,而且可以分别去迭代和演进,而且有重用的可能性。
那么什么时候不适合sidecar呢?当这两个container有不同的扩容需求时候,即两者需要独立的扩容时候,不要sidecar这种模式;另外,两者的通信可能会带来一些网络的消耗,带来一定的延迟,如果这点延迟是业务无法接受的话,也不要使用sidecar。
这样就明了多了,我突然想到了 ORM 框架,也是这么个意思。
听说过 “代理模式” 吗?
它是一种特殊的sidecar,其实就是app container的一个proxy,它来接流量,然后进行处理,然后把流量转发给app container,让其完成真正的商业逻辑。
例如:我想给一个web server加上认证逻辑或者SSL,但是我又不想改动原来的web server或者改动比较困难,我可以在其所在pod内再部署一个proxy,让这个proxy来处理这些认证的逻辑,而原有的app container无需任何改动。
了解过 “适配器模式” 吗?
又是一种特殊的sidecar,如果希望对外输出的内容符合下游的要求而不对app container进行修改,可以增加一个adapter的sidecar,由它来做类似日志转换的事情。例如:
App container按照自身的要求生成日志并保存到文件系统中,另外的adapter container通过共享存储读取该日志,然后进行日志转换等工作,以便把内容输出给下游的metrics系统。