[k8s]滚动更新机制-不宕机发布
svc的转发
首先会通过 集群的 DNS 服务解析到 Service 的 ClusterIP,
然后转发到 Service 后面的 Pod 实例,这是每个节点上面的 kube-proxy 通过更新 iptables 规则来实现的。
Kubernetes 会根据 Pods 的状态去更新 Endpoints 对象,这样就可以保证 Endpoints 中包含的都是准备好处理请求的 Pod。
Ingress的转发
大部分 Ingress Controller,比如 nginx-ingress、traefik 都是通过直接 watch Endpoints 对象来直接获取 Pod 的地址的,而不用通过 iptables 做一层转发了。
滚动更新
Kubernetes 的目标都是在滚动更新的过程中最大程度地减少服务的中断。
一旦新的 Pod 处于活动状态并准备就绪后,
Kubernetes 就将会停止就的 Pod,从而将 Pod 的状态更新为 “Terminating”,
然后从 Endpoints 对象中移除,
并且发送一个 SIGTERM 信号给 Pod 的主进程。
SIGTERM 信号就会让容器以正常的方式关闭,并且不接受任何新的连接。
Pod 从 Endpoints 对象中被移除后,前面的负载均衡器就会将流量路由到其他(新的)Pod 中去。
因为在负责均衡器注意到变更并更新其配置之前,
终止信号就会去停用 Pod,这个重新配置过程又是异步发生的,
所以并不能保证正确的顺序,所以就可能导致很少的请求会被路由到终止的 Pod 上去。
零宕机
这里我们在 zero-downtime 这个 Deployment 中添加一个 preStop 钩子:
apiVersion: apps/v1
kind: Deployment
metadata:
name: zero-downtime
labels:
app: zero-downtime
spec:
replicas: 3
selector:
matchLabels:
app: zero-downtime
template:
spec:
containers:
- name: zero-downtime
image: nginx
livenessProbe:
# ...
readinessProbe:
# ...
lifecycle:
preStop:
exec:
command: ["/bin/bash", "-c", "sleep 20"]
strategy:
# ...