本文摘自 istio 学习笔记
本文介绍在 istio 场景下实现优雅终止时需要重点关注的点,一些容器场景通用的关注点请参考 Kubenretes 最佳实践: 优雅终止 。
当业务上了 istio 之后,流量被 sidecar 劫持,进程之间不会直接建立连接,而是经过了 sidecar 这一层代理:
当 Pod 开始停止时,它将从服务的 endpoints 中摘除掉,不再转发流量给它,同时 Sidecar 也会收到 SIGTERM
信号,立刻不再接受 inbound 新连接,但会保持存量 inbound 连接继续处理,outbound 方向流量仍然可以正常发起。
不过有个值得注意的细节,若 Pod 没有很快退出,istio 默认是会在停止开始的 5s 后强制杀死 envoy,当 envoy 进程不在了也就无法转发任何流量(不管是 inbound 还是 outbound 方向),所以就可能存在一些问题:
istio 提供了 terminationDrainDuration
这个连接优雅终止时长的自定义配置,表示 sleep 多长时间之后才强制杀死 envoy,默认是 5s,可以使用 proxy.istio.io/config
这个 Resource Annotation 来对需要自定义连接优雅终止时长的服务配置 terminationDrainDuration
,用法示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
annotations:
proxy.istio.io/config: |
terminationDrainDuration: 60s # 这里自定义 Envoy 优雅终止时长
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 60 # 若 terminationDrainDuration 超时 30s 则显式指定 terminationGracePeriodSeconds
containers:
- name: nginx
image: "nginx"
terminationDrainDuration
大于 30s,需要显式给 Pod 指定 terminationGracePeriodSeconds
,因为这个值默认为 30s,即 30s 之后容器内进程还未退出就发 SIGKILL 信号将其强制杀死。所以要确保 terminationGracePeriodSeconds
大于等于 terminationDrainDuration
才好让优雅终止时长完全生效。terminationDrainDuration
设置的越大,同时也意味着 Pod 会停止得越慢,所以建议根据业务场景进行自定义,只给需要的服务进行合理自定义,其它情况可以使用默认值。如果业务停止需要的时长不太固定,不好使用固定的 terminationDrainDuration
去控制 sidecar 停止时间,其实也可以通过给 sidecar 加一个 preStop 脚本,在脚本里通过判断是否还要连接来间接判断应用是否已经退出,等应用退出了之后 envoy 才真正开始退出 (默认再等 5s)。
添加 preStop 可以通过修改 sidecar injector 的全局 configmap 来实现:
kubectl -n istio-system edit configmap istio-sidecar-injector
如果使用 TCM,托管网格添加 preStop 需要提工单后台操作,独立网格可以自行修改主集群里的 configmap,但 configmap 名称和这里不一样,会带上版本后缀。
在 values 里面的 global.proxy
加入以下 lifecycle 字段:
"lifecycle": {
"preStop": {
"exec": {
"command": ["/bin/sh", "-c", "while [ $(netstat -plunt | grep tcp | grep -v envoy | wc -l | xargs) -ne 0 ]; do sleep 1; done"]
},
},
},
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。