

























后端服务对接了 API 网关, 服务正常, 但是在滚动更新的时候, 会出现 502
滚动更新时, k8s会起新的pod, 同时删除老的pod
可能原因:
需要通过一系列配置, 做到 zero downtime rolling update (可以google相关的关键字了解更多), 以下给到一些建议
liveness 判断一个pod是否正常启动, 进入Running状态rediness 判断一个pod是否完成了所有必要的初始化动作, 可以开始提供服务, 进入Ready状态pod 进入 Ready 状态意味着此时会有流量进来, 此时如果进程无法提供正常服务, 会导致 502
所以, 需要确保 rediness 的正确性, 使得进程可以提供服务之后, pod 才进入 Ready 状态
terminationGracePeriodSeconds, 最长的宽限期,是允许 Pod 在收到终止信号后优雅关闭的最大时间。如果 Pod 在这个时间结束之前已经自主成功退出,那么 Kubernetes 就会立即进行后续的清理回收步骤, 默认是 30s
如果pod被删除时, 后端服务有正在处理的请求, 并且请求需要超过 30s 才能处理完, 此时服务无法正常 graceful shutdown, 会被强杀, 导致 502.
所以这个值需要设置为 terminationGracePeriodSeconds > 服务承诺的最大的请求耗时时间 + 进程graceful shutdown耗时, 例如你的服务设置的处理请求最大超时时间是 60s, 那么 terminationGracePeriodSeconds 需要大于 60s
确保正在处理的请求能被全部处理完之后再结束, 需要监听 SIGTERM 信号并且处理
例如 golang 1.18中支持 Server.Shutdown
Shutdown gracefully shuts down the server without interrupting any active connections. Shutdown works by first closing all open listeners, then closing all idle connections, and then waiting indefinitely for connections to return to idle and then shut down. If the provided context expires before the shutdown is complete, Shutdown returns the context’s error, otherwise it returns any error returned from closing the Server’s underlying Listener(s).
如何验证: 发送一个请求, 请求正在处理时, 发送SIGTERM信号给进程, 这个请求能被正常处理完
这样才能正常接收到信号
某些应用编写了自定义脚本来启动服务, 但是pid=1的进程是这个脚本而不是服务, 这样会导致服务没法接收到信号并做graceful shutdown
例如:
/bin/bash -c app, 信号是shell收到的, app收不到execpreStop建议配置 preStop
配置后执行的顺序 preStop -> SIGTERM -> SIGKILL
preStop脚本SIGTERM另外一个502可能原因, 从service中摘除 pod endpoint和删除pod是同步进行的, 但是谁先谁后是不确定的(watch到变更, 独立的事件), 此时如果删除pod先执行并且程序很快退出, 此时可能endpoint还没有被摘除, 那么会出现 502
因为 preStop 之后 k8s会发送 SIGTERM, 所以如果进程pid=1并且处理了SIGTERM信号能很好地进行graceful shutdown, 那么只需要加一个sleep确保没有流量进来
lifecycle:
preStop:
exec:
command:
- sleep
- 30
注意: 这个sleep的 30s 只是一个示例, 各个后端服务要自行压测确定, 例如如果集群使用ipvs+nodeport暴露服务到外部, 那么经验值是 sleep 120s, 此时注意terminationGracePeriodSeconds 需要配置并且大于 sleep时间+进程graceful shutdown时间
preStop也可以执行一些等待/资源回收/主动触发hook之类的操作, 但是需要注意:
preStop执行时间+进程graceful shutdown在 terminationGracePeriodSeconds 时间之内执行结束, 容器正常删除;terminationGracePeriodSeconds, 容器会被kill;preStop 阻塞住了, 直到超过terminationGracePeriodSeconds, 容器会被killpreStop 异常了, 容器会被kill这两个跟 zero downtime 无关, 但是能降低影响范围
.spec.strategy.rollingUpdate.maxUnavailable, 滚动更新过程中,允许 “不可用” 的最大 Pod 数量; 默认 25%, 可以是绝对值或百分比
.spec.strategy.rollingUpdate.maxSurge, 滚动更新过程中,允许 “超过” Desired Replicas 数的最大 Pod 数量; 默认 25%;
需要根据自身集群的资源/每个服务的负载等确定
kubectl rollout restart deployment xxxx通过rolling update的方式无法做到, 需要其他方式, 例如部署两套后通过接入层做切换
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。