K8S中默认的deployment更新方式rollingupdate
,执行更新的流程为:
- 1. K8S首先启动新的POD;
- 2. K8S等待新的POD进入Ready状态;
- 3. K8S创建Endpoint,将新的POD纳入负载;
- 4. K8S移除与老POD相关的Endpoint,并且将老POD状态设置为
Terminating
,此时将不会有新的请求到达老POD;- 5. 同时 K8S 会给老POD发送
SIGTERM
信号,并且等待terminationGracePeriodSeconds
这么长的时间让pod优雅的退出(默认为30秒);- 6. 超过
terminationGracePeriodSeconds
等待时间后, K8S 会发送SIGKILL
结束老POD;这里可以优化调整的地方在于:
- 1. 滚动更新策略的百分比改为具体数量或者降低比例。 默认是25%,如果在该项目本身定义的pod较多的情况下会产生很多新的pod。如有需求,可以改百分比为具体数量。
- 2. 为了确保新的pod能完全启动,或者里面的服务启动比较耗时,可以设置
minReadysec:xx
参数,该参数是当新pod启动后等待xx秒再执行升级流程。- 3. 可以适当调整
terminationGracePeriodSeconds
的值,默认是30秒。表示优雅终止宽限期,会等待30秒关闭pod,但是如果程序本身已经完成关闭,就会立刻释放,在30秒后程序还未关闭会发送SIGKILL到pod。- 4. 对于停止时间较长的程序,如
Tomcat
可以采用增加PreStop
钩子的方式,发送kill 信号优雅的关闭容器内进程。- 5. 可以在程序代码中引入框架配合,当接收到结束信号后老pod本身不会再接受新请求,进行程序逻辑收尾工作,自定义超时时间(看业务情况)。比如等待连接耗尽、数据上报、日志落盘刷新等。
prestop
事例:
apiVersion: v1 kind: Pod metadata: name: stop-hook labels: app: test spec: containers: - name: stop-hook image: nginx ports: - name: nginx-port containerPort: 80 lifecycle: preStop: exec: command: ["/usr/sbin/nginx","-s", "quit"]
prestop钩子参考: https://www.cnblogs.com/jasonminghao/p/12681352.html