# Pod Hook
Kubernetes 为我们的容器提供了生命周期钩子,就是我们说的Pod Hook
,Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都配置 hook。
Kubernetes 为我们提供了两种钩子函数:
- PostStart:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器
ENTRYPOINT
之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到running
状态。 - PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起, Pod阶段将停留在
running
状态并且永不会达到failed
状态。
如果PostStart
或者PreStop
钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。
环境
192.168.48.101 master01
192.168.48.201 node01
192.168.48.202 node02
准备
编写hook-pod.yaml作模板用。
vim hook-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: hook-pod
namespace: default
labels:
app: myapp
type: pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "mkdir -p /usr/share/nginx/html; echo $(date) >> /usr/share/nginx/html/test.html;sleep 3600"
PostStart
PostStart:这个钩子在容器创建后立即执行
编写poststart-hook-pod.yaml
cp hook-pod.yaml poststart-hook-pod.yaml
vim poststart-hook-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: poststart-hook-pod
namespace: default
labels:
app: myapp
type: pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "mkdir -p /usr/share/nginx/html; echo $(date) >> /usr/share/nginx/html/test.html;sleep 3600"
创建poststart-hook-pod.yaml
[root@master01 pod_yaml]# kubectl apply -f poststart-hook-pod.yaml
pod/poststart-hook-pod created
[root@master01 pod_yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 13 6d4h 10.244.2.7 node02 <none> <none>
demo-pod-ssd 1/1 Running 2 4d20h 10.244.1.7 node01 <none> <none>
poststart-hook-pod 2/2 Running 0 8m51s 10.244.1.8 node01 <none> <none>
进入容器查看poststart hook是否生效
[root@master01 pod_yaml]# kubectl exec poststart-hook-pod -c myapp -it -- /bin/sh
/ # cat /usr/share/message
Hello from the postStart handler
prestop
当用户请求删除含有 pod 的资源对象时,K8S 为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知:
- 默认:K8S 通知 node 执行
docker stop
命令,docker 会先向容器中PID
为1的进程发送系统信号SIGTERM
,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL
的系统信号强行 kill 掉进程。 - 使用 pod 生命周期(利用
PreStop
回调函数),它执行在发送终止信号之前。
默认所有的优雅退出时间都在30秒内。kubectl delete 命令支持 --grace-period=<seconds>
选项,这个选项允许用户用他们自己指定的值覆盖默认值。值’0’代表 强制删除 pod. 在 kubectl 1.5 及以上的版本里,执行强制删除时必须同时指定 --force --grace-period=0
。
强制删除一个 pod 是从集群状态还有 etcd 里立刻删除这个 pod。 当 Pod 被强制删除时, api 服务器不会等待来自 Pod 所在节点上的 kubelet 的确认信息:pod 已经被终止。在 API 里 pod 会被立刻删除,在节点上, pods 被设置成立刻终止后,在强行杀掉前还会有一个很小的宽限期。
编写prestop-hook-pod.yaml
cp hook-pod.yaml prestop-hook-pod.yaml
vim prestop-hook-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: prestop-hook-pod
namespace: default
labels:
app: myapp
type: pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
volumeMounts:
- name: message
mountPath: /usr/share/
lifecycle:
preStop:
exec:
command: ['/bin/sh', '-c', 'echo Hello from the preStop Handler > /usr/share/message']
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "mkdir -p /usr/share/nginx/html; echo $(date) >> /usr/share/nginx/html/test.html;sleep 3600"
volumes:
- name: message
hostPath:
path: /tmp
创建prestop-hook-pod.yaml
[root@master01 pod_yaml]# kubectl apply -f prestop-hook-pod.yaml
pod/prestop-hook-pod created
[root@master01 pod_yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 13 6d4h 10.244.2.7 node02 <none> <none>
demo-pod-ssd 1/1 Running 2 4d20h 10.244.1.7 node01 <none> <none>
poststart-hook-pod 2/2 Running 0 28m 10.244.1.8 node01 <none> <none>
prestop-hook-pod 2/2 Running 0 76s 10.244.2.8 node02 <none> <none>
删掉pod 查看prestop hook是否生效
[root@master01 pod_yaml]# kubectl delete pod prestop-hook-pod
pod "prestop-hook-pod" deleted
因为我的prestop-hook-pod在node02上,所以去node02上查看
[root@node02 ~]# cd /tmp/
[root@node02 tmp]# ll
total 4
-rw-r--r-- 1 root root 31 Apr 6 17:14 message
drwx------ 2 root root 6 Mar 30 23:07 vmware-root
[root@node02 tmp]# cat message
Hello from the preStop Handler