Kubernetes

Container lifeCycle中的postStart和preStop两种hook小结

一 postStart hook小结

1 应用场景是什么

对于那些在Container启动之后,在正式对外提供服务之后,需要预热的场景,可以通过在Container级别配置postStart hook来实现。比如:一个NGINX服务启动之后,在正式对外提供之前,可以先在Container内部做一个预热,通过执行某个命令请求,使得服务可以提前缓存一些数据。这样,正式对外提供服务时,可以直接使用

2 postStart类型

postStart只支持httpGet和exec类型的probe,不支持tcpSocket。

3 postStart工作机制

它随着Container中的主进程的运行而运行。如果postStart hook执行失败了,那么它会认为整个Container失败。Container将会被重启。

4 postStart作用范围

它是作用在pod中的Container级别的。

5 postStart举例

[root@master-node Chapter06]# pwd
/root/kubernetes-in-action-2nd-edition/Chapter06
[root@master-node Chapter06]# cat pod.quote-poststart.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: quote-poststart
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - name: http
      containerPort: 80
    lifecycle:
      postStart:
        exec:
          command:
          - sh
          - -c
          - |
            apk add fortune && \
            curl -O https://luksa.github.io/kiada/book-quotes.txt && \
            curl -O https://luksa.github.io/kiada/book-quotes.txt.dat && \
            fortune book-quotes.txt > /usr/share/nginx/html/quote
[root@master-node Chapter06]# 

执行,并启动:

[root@master-node Chapter06]# kubectl apply -f pod.quote-poststart.yaml 
pod/quote-poststart created
[root@master-node Chapter06]#
​
===================================
[root@master-node ~]# kubectl get events -w
LAST SEEN   TYPE      REASON                 OBJECT                                   MESSAGE
21s         Normal    Scheduled              pod/quote-poststart                      Successfully assigned default/quote-poststart to node-1
19s         Normal    Pulled                 pod/quote-poststart                      Container image "nginx:alpine" already present on machine
19s         Normal    Created                pod/quote-poststart                      Created container nginx
19s         Normal    Started                pod/quote-poststart                      Started container nginx
...
​
0s          Warning   FailedPostStartHook    pod/quote-poststart                      Exec lifecycle hook ([sh -c apk add fortune && \...
0s          Normal    Killing                pod/quote-poststart                      FailedPostStartHook
0s          Normal    Pulled                 pod/quote-poststart                      Container image "nginx:alpine" already present on machine
0s          Normal    Created                pod/quote-poststart                      Created container nginx
0s          Normal    Started                pod/quote-poststart                      Started container nginx
​
==================================
[root@master-node Chapter06]# kubectl get pods -w
NAME                                   READY   STATUS               RESTARTS         AGE
quote-poststart                        0/1     PostStartHookError   0 (91s ago)      6m18s
...
quote-poststart                        1/1     Running              1 (4m32s ago)    9m19s

同时,从kubectl describe pod quote-poststart 可以看到postStart报错:

[root@master-node Chapter06]# kubectl describe pod quote-poststart 
Name:         quote-poststart
Namespace:    default
Priority:     0
Node:         node-1/172.16.11.148
Start Time:   Mon, 30 May 2022 09:11:19 +0800
...
Events:
  Type     Reason               Age                  From               Message
  ----     ------               ----                 ----               -------
  Normal   Scheduled            5m34s                default-scheduler  Successfully assigned default/quote-poststart to node-1
  Normal   Pulled               47s (x2 over 5m32s)  kubelet            Container image "nginx:alpine" already present on machine
  Warning  FailedPostStartHook  47s                  kubelet            Exec lifecycle hook ([sh -c apk add fortune && \
curl -O https://luksa.github.io/kiada/book-quotes.txt && \
curl -O https://luksa.github.io/kiada/book-quotes.txt.dat && \
fortune book-quotes.txt > /usr/share/nginx/html/quote
]) for Container "nginx" in Pod "quote-poststart_default(0a375afc-e51b-4033-bd56-d5c932a4171b)" failed - error: command 'sh -c apk add fortune && \
curl -O https://luksa.github.io/kiada/book-quotes.txt && \
curl -O https://luksa.github.io/kiada/book-quotes.txt.dat && \
fortune book-quotes.txt > /usr/share/nginx/html/quote
' exited with 2: ERROR: https://dl-cdn.alpinelinux.org/alpine/v3.15/main: BAD signature
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.15/main: No such file or directory
ERROR: unable to select packages:
, message: "fetch https://dl-cdn.alpinelinux.org/alpine/v3.15/main/x86_64/APKINDEX.tar.gz\nfetch https://dl-cdn.alpinelinux.org/alpine/v3.15/community/x86_64/APKINDEX.tar.gz\n  so:libbsd.so.0 (no such package):\n    required by: fortune-0.1-r1[so:libbsd.so.0]\nERROR: https://dl-cdn.alpinelinux.org/alpine/v3.15/main: BAD signature\nWARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.15/main: No such file or directory\nERROR: unable to select packages:\n"
  Normal  Killing  47s                  kubelet  FailedPostStartHook
  Normal  Created  46s (x2 over 5m32s)  kubelet  Created container nginx
  Normal  Started  46s (x2 over 5m32s)  kubelet  Started container nginx
[root@master-node Chapter06]# 

原来报错是,postStart hook中的下载命令失败了,由于网络原因。此时,我们进入pod中的Container里,却是可以看到NGINX已经正常运行的:

[root@master-node Chapter06]# kubectl exec -it quote-poststart -- /bin/sh
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 nginx: master process nginx -g daemon off;
   31 nginx     0:00 nginx: worker process
   32 nginx     0:00 nginx: worker process
   33 root      0:00 sh -c apk add fortune && \ curl -O https://luksa.github.io/kiada/book-quotes.txt && \ curl -O https://luksa.github.io/kiada/book-quotes.txt.dat && \ fortune
   38 root      0:00 apk add fortune
   44 root      0:00 /bin/sh
   49 root      0:00 ps aux
/ # exit
[root@master-node Chapter06]#

二 preStop hook小结

1 应用场景

如果想要在停止Container中的应用之前,做一些“压轴收尾”工作。那么,可以通过在Container中指定lifecycle字段,并指定preStop类型的探针来实现。比如:想要优雅的停止一个NGINX的服务,可以通过在NGINX Container里指定preStop的类型为exec,并执行nginx -s quit命令,这个命令会告知NGINX,对于新起的请求就不响应了,对于已经建立会话的连接,直到client正常退出,而不是直接杀掉所有会话连接。

2 preStop类型

httpGet和exec类型

3 preStop工作机制

它会在Container退出之前,执行该preStop hook。需要注意的是 ,即使preStop hook执行失败了,它也不会导致Container进入terminate状态。

4 preStop作用范围

Container级别

5 preStop举例

[root@master-node Chapter06]# pwd
/root/kubernetes-in-action-2nd-edition/Chapter06
[root@master-node Chapter06]# cat pod.quote-prestop.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: quote-prestop
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - name: http
      containerPort: 80
    lifecycle:
      postStart:
        exec:
          command:
          - sh
          - -c
          - |
            apk add fortune && \
            curl -O https://luksa.github.io/kiada/book-quotes.txt && \
            curl -O https://luksa.github.io/kiada/book-quotes.txt.dat && \
            fortune book-quotes.txt > /usr/share/nginx/html/quote
      preStop:
        exec:
          command:
          - nginx
          - -s
          - quit
[root@master-node Chapter06]# 

三 小结和参考

Container中的lifecycle hook包含postStart和preStop两种类型。见名知意,postStart是在Container启动后,马上执行,其实它是跟Container main process同时执行的;preStop则是在Container停止前,执行的hook,通常用于优雅的关闭容器。

参考:

《Kubernetes in Action Second Edition》 Marko luksa Chapter 06 managing the lifecycle of the Pod’s containers P160–P169.

留言