拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Kubernetes(k8s)之Pod生命周期(下)

Kubernetes(k8s)之Pod生命周期(下)

上次推文我们学习了Pod生命周期(上)知识:相位、创建与终止、初始化容器,今天继续分享完余下的3个知识:钩子函数、容器探测、重启策略。

01钩子函数

钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。

k8s在主容器的启动之后和停止之前提供了两个钩子函数.

  • post start:容器创建之后执行,如果失败了会重启容器;

  • pre stop:容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作;

钩子处理器支持使用下面三种方式定义动作:

1)Exec命令:在容器内执行一次命令

...... lifecycle: postStart: exec: command: - cat - /tmp/healthy ......

2)TCPSocket:在当前容器尝试访问指定的socket

...... lifecycle: postStart: tcpSocket:

3)HttpGet:在当前容器中向某url发起http请求

...... lifecycle: postStart: httpGet: path: #uri地址 port: host: scheme: HTTP #支持的协议,http或者https ......

下面演示钩子函数的使用

创建pod-hook-exec.yaml文件,内容如下:

apiVersion: v1 kind: Pod metadata: name: pod-hook-exec namespace: dev spec: containers: - name: main-container image: nginx:1.17.1 ports: - name: nginx-port containerPort: 80 lifecycle: postStart: exec: #在容器启动的时候执行一个命令,修改掉nginx的默认首页内容 command: ["/bin/sh","-c","echo postStart... > /usr/share/nginx/html/index.html"] preStop: #在容器停止之前停止nginx服务 exec: command: ["/usr/sbin/nginx","-s","quit"]

使用配置文件

[root@master ~]# vim pod-hook-exec.yaml [root@master ~]# kubectl create -f pod-hook-exec.yaml pod/pod-hook-exec created [root@master ~]# kubectl get pod pod-hook-exec -n test -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-hook-exec 1/1 Running 0 34s 10.244.104.24 node2 <none> <none> [root@master ~]# curl 10.244.104.24:80 postStart...

02容器探测

容器探测用于检测容器中的应用实例是否能正常工作,是保障业务可用性的一种传统机制。如果经过探测,实例的状态不符合预期,那么K8S就会把该问题实例“摘除”,不承担业务流量,k8s提供了两种探针来实现容器探测,分别是:

  • livenessprobes:存活性探针,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器;

  • readinessprobes:就绪性探针,用于检测应用实例当前是否可以接受请求,如果不能,k8s不会转发流量;

即livenessProbe决定是否重启容器,readinesProbe决定是否将请求转发给容器。

  • startupProbe:使用启动探针来了解应用容器何时启动,如果配置了这个类探针,就可以控制容器在启动成功后再进行存活性liveness和就绪态readiness的检查,确保存活、就绪探针不会影响应用的启动。

探针参数

探针有很多配置参数,可以使用这些参数精确地控制启动、存活和就绪检测的行为。

--initialDelaySeconds:容器启动后要等待多少秒后才启动存活、就绪和启动探针, 默认是 0 秒,最小值是 0;

--periodSeconds:执行探测的时间间隔(单位是秒),默认是 10 秒,最小值是 1;

--timeoutSeconds:探测的超时后等待多少秒,默认值是 1 秒,最小值是 1;

--successThreshold:连续探测成功多少次才被认定为执行成功,默认值是 1,存活和启动探测的这个值必须是 1,最小值是1;

--failureThreshold:连续探测失败多少次才被认定为执行失败。对于存活探测而言,失败就意味着重新启动容器。对就绪探测而言,失败意味着 Pod 会被打上未就绪的标签,默认值是 3,最小值是 1;

上面两种探针目前均支持三种探测方式:

1)Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常​​​​​​​

...... livenessProbe: exec: command: - cat - /tmp/healthy ......

创建文件exec-liveness.yaml​​​​​​​

apiVersion: v1 kind: Pod metadata: labels: app: liveness name: liveness-exec namespace: probe spec: containers: - name: tomcat image: tomcat:latest args: - /bin/sh - -c - touch /tmp/liveness-pod; sleep 30; rm -f /tmp/liveness-pod; sleep 100 livenessProbe: exec: command: - cat - /tmp/liveness-pod initialDelaySeconds: 5 periodSeconds: 5

在配置文件中,periodSeconds 字段指定了 kubelet 每 5 秒执行一次存活探测。initialDelaySeconds指定 kubelet 在执行第一次探测前应该等待 5 秒。kubelet 在容器内执行命令 cat /tmp/liveness 来进行探测, 如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的,如果这个命令返回非0值,kubelet 会杀死这个容器并重新启动它在容器启动时,将执行如下命令:

/bin/sh -c "touch /tmp/liveness; sleep 30; rm -f /tmp/liveness; sleep 300"

容器生命的前 30 秒,/tmp/liveness 文件是存在的,即在容器启动后的 30 秒内,执行命令 cat/tmp/liveness 会返回成功,30 秒之后文件被删除,再次执行命令 cat /tmp/liveness 时就会返回失败,kubectl则会对容器进行重启操作。

创建Pod

[root@master ~]# kubectl apply -f exec-liveness.yaml

30秒内查看pod的状态

[root@master ~]# kubectl describe pod liveness-exec -n test

输出结果显示pod创建成功​​​​​​​

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 9s Successfully assigned test/livenessexec to node2 Normal Pulling 8s kubelet, node2 Pulling image "nginx:latest" Normal Pulled 4s kubelet, node2 Successfully pulled image "nginx:latest" in 3.344637979s Normal Created 4s kubelet, node2 Created container nginx Normal Started 4s kubelet, node2 Started container nginx

等到35秒再次查看pod的状态,显示liveness探测失败,Container nginx failed liveness probe, willbe restarted\n Container nginx failed liveness probe, will be restarted,容器被重启。​​​​​​​

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m41s Successfully assigned test/liveness-exec to node2 Normal Pulled 2m37s kubelet, node2 Successfully pulled image "nginx:latest" in 3.344637979s Normal Pulled 81s kubelet, node2 Successfully pulled image "nginx:latest" in 3.13232767s Warning Unhealthy 39s (x6 over 2m4s) kubelet, node2 Liveness probe failed: cat: /tmp/liveness-pod: No such file or directory Normal Killing 39s (x2 over 114s) kubelet, node2 Container nginx failed liveness probe, will be restarted Normal Pulling 9s (x3 over 2m41s) kubelet, node2 Pulling image "nginx:latest" Normal Created 5s (x3 over 2m37s) kubelet, node2 Created container nginx Normal Started 5s (x3 over 2m37s) kubelet, node2 Started container nginx Normal Pulled 5s kubelet, node2 Successfully pulled image "nginx:latest" in 3.870334984s

此时查看pod状态,显示容器重启次数增加了1​​​​​​​

[root@master ~]# kubectl get pod liveness-exec -n test NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 2 3m27s

TCPSocket:将会尝试访问同一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常​​​​​​​

...... livenessProbe: tcpSocket: port: 8080 ......

创建http-liveness.yaml​​​​​​​

apiVersion: v1 kind: Pod metadata: labels: app: liveness name: liveness-http namespace: test spec: containers: - name: nginx image: nginx:latest livenessProbe: httpGet: path: /test port: 80 scheme: HTTP httpHeaders: - name: Accept value: application/json initialDelaySeconds: 5 periodSeconds: 5

在配置文件中,periodSeconds 指定了 kubelet 应该每 5 秒执行一次存活探测,initialDelaySeconds指定 kubelet 在容器启动后等待 5 秒再开始探测。kubelet 会向容器内运行的服务(host-默认为pod的ip,port为80)发送一个HTTP GET 请求来执行探测, 如果服务器上 "/" 路径下的处理程序返回成功,则 kubelet 认为容器是健康存活的,如果处理程序返回失败,则 kubelet 会杀死这个容器并将其重启

判断标准:返回大于或等于 200 并且小于 400 的任何代码都标示成功,其它返回代码都标示失败;

创建pod​​​​​​​

[root@master ~]# kubectl apply -f http-liveness.yaml pod/liveness-http created

此时,kubelet访问的探测地址为http://podid:80/abc,因容器内nginx服务不存在该路径地址,则会返回404状态码,查看pod状态显示健康检查失败,Liveness probe failed: HTTP probe failed with statuscode: 404,kubelet 会杀死容器并再次重新启动容器。​​​​​​​

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 14m Successfully assigned test/liveness-http to master Normal Pulled 11m kubelet, master Successfully pulled image "nginx:latest" in 2m17.669916167s Normal Pulled 11m kubelet, master Successfully pulled image "nginx:latest" in 3.366871547s Normal Created 11m (x3 over 11m) kubelet, master Created container nginx Normal Pulled 11m kubelet, master Successfully pulled image "nginx:latest" in 3.539110367s Normal Started 11m (x3 over 11m) kubelet, master Started container nginx Normal Killing 10m (x3 over 11m) kubelet, master Container nginx failed liveness probe, will be restarted Normal Pulling 10m (x4 over 14m) kubelet, master Pulling image "nginx:latest" Warning Unhealthy 9m9s (x18 over 11m) kubelet, master Liveness probe failed: HTTP probe failed with statuscode: 404 Warning BackOff 4m3s (x28 over 10m) kubelet, master Back-off restarting failed container

HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常。​​​​​​​

...... lifecycle: postStart: httpGet: path: #uri地址 port: host: scheme: HTTP #支持的协议,http或者https ......

TCP 检测的配置和 HTTP 检测方式相近,只需要配置端口即可。如果能建立连接,这个容器就被看作是健康的,脚本片断如下:​​​​​​​

containers: - name: nginx image: nginx:latest readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 20

03重启策略

重启策略:Pod在遇到故障之后重启的动作

  • 1. Always:当容器终止退出后,总是重启容器,默认策略

  • 2. OnFailure:当容器异常退出(退出状态码非0)时,重启容器

  • 3. Never:当容器终止退出,从不重启容器。

(注意:k8s中不支持重启Pod资源,只有删除重建,重建)

重启策略适用于pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长为10s,20s,40s,80s,160s,300s,300s是最大延迟时长;

重启策略设置建议:

因为重启策略默认的就是Always,这也是合理的,因此在一般情况下,重启策略不需要设置,这里仅仅是作为知识点拿出来展示一下,在实际使用中,在大多数情况下都不需要进行重启策略配置。

1)Always​​​​​​​

[root@master test]# vim always.yaml apiVersion: v1 kind: Pod metadata: name: always-restart namespace: test spec: containers: - name: busybox image: busybox args: - /bin/sh - -c - sleep 30; exit 3

创建pod

[root@master ~]# kubectl apply -f always.yaml

查看pod重启情况​​​​​​​

[root@master ~]# kubectl get pods -n test NAME READY STATUS RESTARTS AGE always-restart 0/1 Error 1107s [root@master ~]# kubectl describe pods always-restart -n test Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 4m6s Successfully assigned test/always-restart to master Normal Pulled 3m28s kubelet, master Successfully pulled image "busybox"in36.172410045s Normal Pulled 2m54s kubelet, master Successfully pulled image "busybox"in3.248301356s Normal Pulled 2m10s kubelet, master Successfully pulled image "busybox"in3.068738872s Normal Created 73s (x4 over 3m28s) kubelet, master Created container busybox Normal Started 73s (x4 over 3m28s) kubelet, master Started container busybox Normal Pulled 73s kubelet, master Successfully pulled image "busybox"in3.686230207s Warning BackOff 15s (x6 over 2m23s) kubelet, master Back-off restarting failed container Normal Pulling 1s (x5 over 4m4s) kubelet, master Pulling image "busybox"

2)never​​​​​​​

[root@master test]# vim never.yaml apiVersion: v1 kind: Pod metadata: name: never-always namespace: test spec: containers: - name: busybox image: busybox args: - /bin/sh - -c - sleep 30; exit 3 restartPolicy: Never

创建pod​​​​​​​

[root@master ~]# kubectl apply -f never.yaml pod/never-restart created

查看pod重启情况​​​​​​​

[root@master ~]# kubectl get pod never-restart -n test NAME READY STATUS RESTARTS AGE never-restart 0/1Error073s

3)onfailure

终止退出容器,并且是非零状态的退出​​​​​​​

[root@master test]# vim onfailure.yaml apiVersion: v1 kind: Pod metadata: name: onfailure1-restart namespace: test spec: containers: - name: busybox image: busybox args: - /bin/sh - -c - sleep 20; exit 3 restartPolicy: OnFailure

创建pod​​​​​​​

[root@master ~]# kubectl apply -f onfailure.yaml pod/onfailure1-restart created

查看pod的状态​​​​​​​

[root@master ~]# kubectl get pod onfailure1-restart -n test NAME READY STATUS RESTARTS AGE onfailure1-restart 1/1 Running 274s

将退出状态改为0​​​​​​​

apiVersion: v1 kind: Pod metadata: name: onfailure1-restart namespace: test spec: containers: - name: busybox image: busybox args: - /bin/sh - -c - sleep 20; exit 0 restartPolicy: OnFailure

创建pod​​​​​​​

[root@master ~]# kubectl apply -f onfailure.yaml pod/onfailure1-restart created

查看 pod状态​​​​​​​

[root@master ~]# kubectl get pod onfailure1-restart -n test NAME READY STATUS RESTARTS AGE onfailure1-restart 0/1 Completed 074s
返回列表