# Pod删除的过程

在删除 Kubernetes pod 的过程中,有两条平行的时间线,一是改变网络规则的时间线,另一个是 pod 的删除

管道执行kubectl delete pod 命令时,两个过程开始
网络规则生效
1. kube-apiserver 接收到 pod 删除请求,将 pod 在 Etcd 中的状态更新为 Terminating
2. Endpoint Controller 从 Endpoint 对象中删除 pod 的 IP
3. kuber-proxy 根据 Endpoint 对象的变化更新 iptables 的规则,不再将流量路由到被删除的 Pod
删除pod
1. kube-apiserver 接收到 Pod 删除请求,将 Pod 的再 Etcd 中的状态更新为 Terminating
2. Kubelet 在节点清理容器相关资源,如存储、网络
3. Kubelet 向容器发送 SIGTERM;如果容器内的进程没有配置,容器将立即退出
4. 如果容器在默认的 30 秒内没有退出,Kubelet 将发送 SIGKILL 并强制它退出
如果在上述过程中没有正常关闭,可能会出现两个问题:
当前正在处理请求的pod被移除,如果请求不是幂等的,则会导致状态不一致返回502
Kubernetes 将流量路由到已经被删除的Pod,导致处理请求失败返回500,用户体验差
# 解决方案
## 为容器内的进程设置正常关闭
以SpringBoot为例,启用优雅关闭可以 Spring Boot 配置文件中添加下面设置,可以解决502问题
```bash
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase:
```
## 添加preStopHook
当kube-apiserver接收到pod删除请求后,必须要预留一段时间,来等待网络规则的更新,避免新的流量路由到一个不可用的pod上,因此应该让Kubelet在收到删除pod事件时“sleep 一下”,并在给Pod发送SIGTERM之前留出足够的时间来更新网络规则,可以解决502问题
```bash
containers:
- name: test
#添加下面这部分
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- "sleep 10"
```
## 修改终止GracePeriodSeconds
Kubernetes为容器删除留下了30秒的最大时间尺度。如果Spring的优雅关闭超时时间和 Kubernetes的preStopHooks之和超过30秒,可能会导致Kubernetes在Spring Boot处理完请求之前强行删除容器。因此如果过程超过30秒,则应改timerminationGracePeriodSeconds 调整为大于30秒
```bash
apiVersion: apps/v1
kind: Deployment
metadata:
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- name: test
image: oms-center:latest
ports:
- containerPort: 8080
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"] #prestop hook
terminationGracePeriodSeconds: 45 #terminationGracePeriodSeconds
```
设置正常关闭可确保在容器终止之前完成处理正在进行的请求,设置preStopHook确认删除pod和更新网络规则之间的顺序关系,最后给进程留出充裕的时间来处理所有请求,设置terminationGracePeriodSeconds
# 制作可优雅关闭的镜像
Dockerfile使用exec的方式能够实现K8S容器应用优雅关闭,系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变
## 示例
```bash
[root@base test]# cat Dockerfile
FROM centos7_jdk:latset
COPY app.jar /home
ENV JVM_OPTS="-Xms500m -Xmx1024m -Xmn250m -Xss256k"
ENV JAVA_OPTS=""
EXPOSE 8080
WORKDIR /home
ENTRYPOINT [ "sh", "-c", "java $JVM_OPTS $JAVA_OPTS -jar app.jar"]
```

k8s集群pod优雅关闭