目录
3.3协调多个不同的应用程序生命周期(案例:密码轮换和应用程序生命周期)
3.1应用程序生命周期:考虑不断的变化--运维同理心
作为应用开发者需要考虑运维阶段云原生应用全流程的可持续性,不能做甩手掌柜。通过下图不难发现,在整个应用生命周期中,创建应用只是开端,一个完整的应用生命周期应该包含创建应用源码、应用运行时环境部署、应用程序配置、应用的开机与关机到最后应用的销毁。
云原生应用作为云原生的3个实体之一,其特点就是高度的分布式以及不断的变化。变化的原因多种多样,有可能因为基础架构的故障、OS升级、补丁升级等。
综上,在应用开发阶段需要关注云原生应用在整个生命周期内的可管理性、弹性、响应性、成本管理。应用程序应该高度的自动化部署,基于精准的监控及成本控制实现应用实例的弹性伸缩以及合适的响应时效性。
3.2举例:多实例应用程序生命周期管理方案
3.2.1蓝 / 绿升级
蓝 / 绿升级即同一时刻只投产一个版本的应用,升级流程更加简单,但需消耗更多的云计算资源。如下图,蓝色方框与绿色方框代表了2个不同的应用版本,为了实现从蓝到绿的平滑过渡需要借助流量负载均衡设备对用户请求进行调度。
在升级开始前LB设备将所有的用户请求调度到蓝色服务集群,当升级进程开启后为保证前后服务一致性我们微调了LB的负载策略以供业务一致性测试,我们不难发现为保证服务一致性我们同时创建了相同服务承载容量的服务器集群,即绿色方框所示。当业务测试完成后,我们第二次调整LB的负载策略,将所有业务流量迁移到绿色方框内的服务器集群,至此我们便完成了应用升级流程。
这里需要注意由于零停机时间的限制,在第二次修改LB调度算法时我们可以使用较为温柔的切换算法,比如我们可以使用所谓“软关机”策略,在不中断既有会话的前提下将新建会话与既有会话分别调度,即保持既有会话的连续性不影响原有用户,仅对新建会话生效绿色服务器集群LB调度策略。
通过以上讲解我们不难发现,由于需要并发维护2套服务器集群,所以需要投入相应资源,这种升级方式的缺点便是此,消耗更多的云计算资源。但其优点也是显而易见的,在业务回退时的便捷程度是所有升级方案中较高的。
3.2.2滚动升级
滚动升级,也称为分组交替升级,确保多版本对外仍是一个逻辑上的单一实体,多个版本同时运行使得版本迭代更加敏捷,相比蓝绿升级交替升级过程中消耗的资源更少。 这就要求软件架构师在软件开发设计阶段考虑到不同版本的对外发布一致性,不能由于版本因素导致集群对外服务异常。
滚动升级流程如下图所示,由于与蓝绿升级较为相似我就不再赘述,我们只需要注意第二点,在升级流程开始后LB需要采用适当的调度策略将前端业务请求调度到两个不太的服务器集群中(即下图V1\V2)。相比蓝绿升级交替升级过程中消耗的资源更少。
3.2.3并行部署
并行部署即同时部署多个版本的应用程序,不同版本的应用将长期存在,它可能是2个版本也可以是更多的版本,理论上只要LB支持我们可以同时创建无数个并行发布的应用。
我猜测大家对这种部署模式最不看好,但我几乎可以肯定大多数互联网企业都是这样做的,他们为不同用户提供不同版本的应用,虽然这种软件设计要求最高,因为需要保证该部署模式对消费者透明为消费者提供一致性的服务,前端负载均衡的调度策略也需要额外的会话保持设计但却为企业带来了与众不同的的业务模式。我举个例子,某互联网企业设计了3个不太的广告推广算法,通过一段时间的测量通过适当的控制变量推广,我们可以轻而易举的量化不同广告推广算法的回报率,从而为广告主以及广告推广平台带来双赢。
3.3协调多个不同的应用程序生命周期(案例:密码轮换和应用程序生命周期)
以上我们说的是单个逻辑体的升级流程,在云原生环境下我们还需要考虑更多的依赖调用关系,比如分布式系统中要考虑升级对消费者以及生产者的依赖关系。举个例子,我们需要更新数据库的访问密钥,而在消费者源代码中未有合适定义导致在升级中消费者不能正常访问数据库,这种情况就需要我们提前识别并采用合适算法规避。
既然说到这就为各位详细说明如何在云原生环境下协调多个程序的生命周期,我们拿密码轮换这个例子来说明。下图是我们计划升级的两组应用,我们采用以下2个取巧设计保证生产者在更换密码时对消费者无感知。
1)密码在程序启动时配置
2)为了支持0停机时间的密码更换,服务允许有多个密码
我们还是以最初的网站聚合服务为例,帖子关系服务需要调用帖子服务,我们的最终目标是更新帖子关系服务的调用密码即从“first secret”切换到“second secret”,与此同时业务不能中断。
在整个变更流程的第一步我们需要先升级生产者,为生产者注入1套新密码即消费者更新后的调用密码,第一步完成后的状态应该如下图所示。需要注意,变更后的生产者需要支持多密码适配,即生产者可以匹配消费者提交的密码中查询本地密码数据库,只要任意密码匹配即可成功访问本地服务。
变更第二步,消费者升级本地代码为变更后状态,即将调用密码更新为“second secret”。最后一步,我们再次更新生产者,即移除原有调用密码,以便完成整个密码轮换。
3.4不可变的基础设施 -- 处理临时运行时环境之可监控
通过前文我们已近知道了我们面对的应用实例是千奇百怪的,于是乎我们总结了以下几点云原生应用的特点。
- 不断的被创建,不断的被销毁,虽然违背了“稳定即是好事,变换即是坏事”传统观念,但在云计算中变化是不可避免的甚至可以带来一直新的稳定。
- 在应用实例开启、关闭时需要告知上下游的消费者与生产者。在广播依赖关系时还需要知道我们面对的是不可靠的网络、高度分布式的应用实例组件。
- 无论应用是否正常,都需要持续不断的探测,循环比较期望状态与实际状态,如果发现期望状态与实际状态不一致,需要考虑通过冗余机制对其进行修复。
![](https://i-blog.csdnimg.cn/blog_migrate/b1da74c1232c04c071b4902241f8ee70.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4f8e6e9fd1912cd0ebf3f6c24900b4e1.png)
为保证云原生应用在不断变化中保持稳定,需要给云原生应用赋能新的特性,即应用程序生命周期状态的可见性(可监控)。
这个可监控性需要覆盖整个应用生命周期,需要考虑服务间的依赖关系与服务的健康状态。而通过前面的学习我们不难发现,单实例服务监控相对简单,因为其状态无需告知上下游,但企业级应用往往存在极为复杂的集群间调用关系链。应用的状态也不仅仅是上图所示的几个过程,它肯定会更加复杂。比如,当应用开机后可以正常相应请求并正确对外发布自己的健康状态,突然。。。一个宇宙粒子来袭。。。它没了,就这样没了,它无声无息的没了,消失了,甚至没来得及告诉上游或下游调用者。
3.5不可变的基础设施 -- 处理临时运行时环境之可预测
可预测性确保了检测的准确性,或者我们可以这样说,正是因为应用响应结果的可预测我们才能为应用监控配置正确的监控参数。正是因为我们知道应用实例运行正常的响应结果让我们得以预测其异常行为下的响应结果。
如何做到容器的可预测性、重复性?
- 不允许修改单个容器镜像(禁止SSH到容器内)
- 重视日志、指标的获取(将日志视为事件流)
请允许我使用加粗红色斜体来概括保证容器可预测性、相应结果可重复性的两大方法。这没什么好说的,这就是金科玉律,任何情况下都不允许修改单个容器的镜像,因为容器始终在变化,上一秒一个正在对外发布的容器实例,下一秒可能就会被销毁,修改单个容器是毫无意义的,如果希望纠正某个错误请直接修改容器基镜像。当然,为了保证可以找出导致错误的蛛丝马迹,请务必重视日志的地位,将容器的所有动作、指标通过日志传递出来,保证容器的所有操作有迹可循。