不停机发布讨论
近期公司的运维同事对一些系统尝试利用 K8S 的滚动发布机制不停机发布系统,应用和系统的状况是:POD 里的应用实例是注册在 Consul 上,Consul 的健康检查间隔是 10 秒;它们配置的 K8S 滚动发布机制直接把跑应用的 POD 终止了。
这样出现了:应用实例被终止后到 Consul 下次健康检查之前,Consul 认为应用实例是还存活的,把请求分发给了已经被停止的实例,这些请求当然是失败的。有的系统因为下游不支持重试,之前出现应用重试导致出现异常数据,就把 Ribbon、Feign、Hystrix 等的重试机制禁用了。而没有了重试机制请求就直接失败了,这样用户就会感知到系统发布。
大家开会讨论怎么才能让系统发布不会影响请求响应:
-
另一个部门的同事说他们就是所有接口都支持重试,所以允许对服务的某个实例请求失败可以重试到另一个实例,这样基本不会影响请求处理。让所有接口支持重试是需要上下游系统协调的,而且需要比较长的时间来实现。还有个问题是,不是所有接口都能重试的,举个行业特定的例子:信贷审批一般都会去查借款人的人行征信报告,多查一次可能导致借款人几个月都没法借款,设想一个报告查询的请求发出去了、在响应还没落地之前,应用实例就被终止了,这肯定是没法接受的。所以应用实例需要在被终止之前得到一个机会—-可以优雅停机的机会,它需要一个停机的通知。对于前面的问题,就是 K8S 要在停机前通知到 POD 里的实例,等通知返回后再终止 POD。
-
这就带来这个小插曲,我提出 K8S 在停止 POD 之前给 POD 里的应用发个通知的时候,运维同事说 Consul 和 K8S 是不同的系统,没法做到,他们说的非常肯定。。。
K8S POD 生命周期管理
对于一个问题,自己解决不了 跟 问题无解 是有区别。
在网上搜索一番后找到了 POD 生命周期钩子
文档提到有两种钩子:
-
PostStart: 在容器创建后立即执行;
-
PreStop: 在容器被终止前立即执行。它是阻塞的,意味着它是同步的,这样必须在它完成之后删除容器的命令才能发送。
钩子处理器的实现有两种:
-
Exec: 执行指定的命令,例如
pre-stop.sh
,在容器的 cgroups 和命名空间里执行。 -
HTTP: 在容器的指定 endpoint 上执行 HTTP 请求。
钩子至少执行一次,意味着钩子可能在执行多次。
Pod 的 liveness 和 readiness 探针
-
liveness probe, 存活探针:用来确定何时重启容器;
-
readiness probe, 就绪探针:用来确定容器是否已经就绪可以接受流量。有的应用启动后可能需要加载很多缓存数据或做其他的一些初始化动作,不能立即处理请求,或许可以利用这个探针来宣告应用是否就绪。这个要结合应用请求分发的具体情况。
这两个是搜索时看到的,先记录下。
欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。