Kubernetes

Kubernetes Pod重启策略

本文主要是介绍Kubernetes Pod重启策略,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、概述

在Pod的spec中有一个restartPolicy字段,如下:

apiVersion: v1
kind: Pod
metadata:
  name: xxx
spec:
  restartPolicy: Always
  ...

restartPolicy的值有三个:Always、OnFailure、Never;默认值为Always。 

注意 1:虽然restartPolicy字段是Pod的配置,但是其实是作用于Pod的Container,换句话说,不应该叫Pod的重启策略,而是叫Container的重启策略;Pod中的所有Container都适用于这个策略。

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

三种策略的区别在于:

  • Always:只要Container退出就重启,即使用它的退出码为0(即成功退出)
  • OnFailure:如果Container的退出码不是0(即失败退出),就重启
  • Never:Container退出后永不重启

所谓Container的退出码,就是Container中进程号为1的进程的退出码。每个进程退出时都有一个退出码,我们常见的提示exit 0表示退出码为0(即成功退出)。举个例子:shell命令cat /tmp/file,如果文件/tmp/file存在,则该命令(进程)的退出码为0。

2、Pod中的Container重启规则

2.1 Pod中Container重启命名规则

上面谈到当Container退出后,Container可能会被重启,那么Container是如何被重启的呢?是Kubelet调用类似于docker start的API拉起?还是重新创建一个docker容器(docker create && docker start)?
答案是,Kubelet会重新创建一个docker容器。
我们给一个例子,创建一个如下的Pod,这个Pod中有两个Container,其中demo1这个Container在启动后60秒就会退出(退出码为0),demo2这个Container则会一直运行。

apiVersion: v1
kind: Pod
metadata:
  name: test-restartpolicy
  namespace: test-restartpolicy
spec:
  restartPolicy: Always
  containers:
  - name: demo1
    image: busybox:1.31.1
    command: 
    - /bin/sh
    - -c
    - sleep 60
  - name: demo2
    image: tomcat:9.0.37

接下来我们创建test-restartpolicy这个命名空间和Pod。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   2/2     Running   0          44s

然后观察demo1这个Container的docker名字与ID,发现名字(docker name字段)为k8s_demo1_test-restartpolicy_test-restartpolicy_88d4575b-5d59-4e25-8b61-ea0e0bfef035_0,ID为f09dd4d59d76。

[root@node1 test]# docker ps|grep demo1
f09dd4d59d76   1c35c4412082    "/bin/sh -c 'sleep 6…"   32 seconds ago  Up 30 seconds  k8s_demo1_test-restartpolicy_test-restartpolicy_88d4575b-5d59-4e25-8b61-ea0e0bfef035_0

再过一分钟,我们再看这个Container的名字和ID,发现名字为k8s_demo1_test-restartpolicy_test-restartpolicy_88d4575b-5d59-4e25-8b61-ea0e0bfef035_1,ID为7ba3cc9685eb。这说明,重启后已经不是同一个docker容器了。

[root@node1 test]# docker ps|grep demo1
7ba3cc9685eb   1c35c4412082  "/bin/sh -c 'sleep 6…"   14 seconds ago    Up 13 seconds  k8s_demo1_test-restartpolicy_test-restartpolicy_88d4575b-5d59-4e25-8b61-ea0e0bfef035_1

同理,再过一分钟,我们再看这个Container的名字和ID,发现名字为k8s_demo1_test-restartpolicy_test-restartpolicy_88d4575b-5d59-4e25-8b61-ea0e0bfef035_2,ID为d71f73027239。这说明,重启后已经不是同一个docker容器了。

d71f73027239   1c35c4412082    "/bin/sh -c 'sleep 6…"   7 seconds ago   Up 5 seconds   k8s_demo1_test-restartpolicy_test-restartpolicy_88d4575b-5d59-4e25-8b61-ea0e0bfef035_2

如果我们细心的会发现,docker容器的名字其实是有规则的,为  

k8s_<ContainerName_In_Pod>_<PodName>_<Namespace>_<PodID>_<Index>

其中最后一个<Index>一开始为0,每重启一次就会递增1。

2.2 查看Pod状态规则

在2.1查看Pod中的容器重启命名规则的时候,同时开了一个Shell窗口,一直观察Pod的状态。 

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   2/2     Running   0          1s

可以看到在demo1容器第一次重启后,Pod容器状态从NotReady变成了Running。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   2/2     Running   0          64s
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS     RESTARTS   AGE
test-restartpolicy   1/2     NotReady   0          65s
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   2/2     Running   1          67s

可以看到在demo1容器第一次重启后,Pod容器状态从NotReady先变成了CrashLoopBackOff再变成Running。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   2/2     Running   1          2m5s
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS     RESTARTS   AGE
test-restartpolicy   1/2     NotReady   1          2m6s
........
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS     RESTARTS   AGE
test-restartpolicy   1/2     NotReady   1          2m20s
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS             RESTARTS   AGE
test-restartpolicy   1/2     CrashLoopBackOff   1          2m21s
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS             RESTARTS   AGE
test-restartpolicy   1/2     CrashLoopBackOff   1          2m22s
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   2/2     Running   2          2m23s

过一段时间后,可以看到Pod容器状态大部分时间为CrashLoopBackOff,这是因为容器频繁重启的话会有退避延迟时间,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由Kubelet延迟一段时间后进行,且反复的重启操作的延迟时长为10s,20s,40s,80s,160s,300s,300s是最大延迟时长,过一段时间后demo1容器的重启延迟时间变成了300s,此时Pod状态为CrashLoopBackOff,重启延迟时间过后demo1容器状态会变成running,再过60s,demo1容器退出后,demo1的状态又会从NotReady变成CrashLoopBackOff,之后周而复始。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS             RESTARTS   AGE
test-restartpolicy   1/2     CrashLoopBackOff   7          22m
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS             RESTARTS   AGE
test-restartpolicy   1/2     CrashLoopBackOff   7          22m

如果我们细心的会发现,对于Always重启策略的Pod来说,Pod中容器重启时,查看Pod 状态字段值是有规则的,Pod中容器整个重启过程Pod状态会从Running -> NotReady -> CrashLoopBackOff -> Running,周而复始。

注意 1:NotReady(不可用):当容器重启或出现故障时,Pod的状态会变为NotReady。这表示其中至少一个容器无法正常工作,导致Pod无法提供服务。

注意 2:CrashLoopBackOff(崩溃循环回退):如果容器频繁重启且无法成功启动,Pod的状态将变为CrashLoopBackOff。这意味着容器在启动后不断崩溃并尝试重新启动,但仍无法正常运行。

注意 3:Pod状态为CrashLoopBackOff表示其中的一个或多个容器出现了崩溃循环回退的情况。这种状态通常是由以下情况引起的:

  • 容器崩溃:Pod中的一个或多个容器在启动后立即崩溃。这可能是由于容器应用程序内部错误、配置问题、资源不足或依赖项问题等引起的。

  • 容器重启循环:当容器崩溃后,Kubernetes会尝试自动重新启动容器。如果容器在启动后仍然崩溃,并且持续进行容器重启尝试,就会导致CrashLoopBackOff状态。

  CrashLoopBackOff状态表示Kubernetes在一段时间内尝试重启容器,但容器仍然无法正常运行。为了避免对底层系统资源的无限消耗,Kubernetes会暂停一段时间后再次尝试重启。这种循环会持续进行,直到问题得到解决或达到重试次数的限制。

2.3 查看Pod RESTARTS字段值规则

实例一:

过一段查看2.1中创建Pod,可以看到RESTARTS字段的值为8。

[root@node1 ~]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   2/2     Running   8          24m

此时我们查看Pod的yaml文件,会发现demo1这个Container的restartCount为8,demo2这个Container的restartCount为0。

kubectl get pods -n=test-restartpolicy -o yaml
......
status:
 containerStatuses:
    - containerID: docker://75a85ae72574d5edb42486dc58d3526b3c7ed5d29c9959c898a4689f12fef7f5
      ......
      name: demo1
      ready: true
      restartCount: 8
      started: true
      ......
- containerID: docker://1d7fe0cb75d5a6aa9074f2ceb0dc7515df0aa6082b1e4bb9e77931b5724445ca
    ......
    name: demo2
    ready: true
    restartCount: 0
    started: true
    ......

示例2:

此时删除test-restartpolicy这个Pod,修改Pod规格配置文件如下,让demo2这个Container在启动30秒后也退出(退出码为0)。

apiVersion: v1
kind: Pod
metadata:
  name: test-restartpolicy
  namespace: test-restartpolicy
spec:
  restartPolicy: Always
  containers:
  - name: demo1
    image: busybox:1.31.1
    command: 
    - /bin/sh
    - -c
    - sleep 60
  - name: demo2
    image: busybox:1.31.1
    command:
    - /bin/sh
    - -c
    - sleep 30
  nodeSelector:
    kubernetes.io/hostname: node1 

接下来我们创建test-restartpolicy这个Pod,过几分钟查看Pod。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS             RESTARTS   AGE
test-restartpolicy   1/2     CrashLoopBackOff   7          4m27s

此时我们查看Pod的yaml文件,会发现demo1这个Container的restartCount为3,demo2这个Container的restartCount为4。

[root@node1 test]# kubectl get pods -n=test-restartpolicy -o yaml
......
  status:
    ......
    containerStatuses:
    - containerID: docker://a34abd3d662c0d5c309f7967ccb2e3a70e25bda520a8b55b63eee8cff7892762
      ......
      name: demo1
      ready: true
      restartCount: 3
      started: true
      ......
    - containerID: docker://4f97cccf338fff56f0d894cf4f89bda48b6108046d3ff6cfd8097bd2e6efe86b
      ......
      name: demo2
      ready: false
      restartCount: 4
      started: false
      .......

如果我们细心的会发现,查看Pod RESTARTS字段值是有规则的,RESTARTS字段表示整个Pod中所有容器的累计重启次数。如果任何一个容器在Pod中重启,RESTARTS字段的值会增加。这意味着即使只有一个容器重启了,整个Pod的RESTARTS字段值也会增加。

2.4 进入Pod容器规则

以sh方式登陆到Pod中的某个容器里:

kubectl exec -it <pod-name> -c <container-name> /bin/sh 

 还是2.1创建的Pod实例,进入demo1容器内部

[root@node1 ~]# kubectl exec -it -n=test-restartpolicy test-restartpolicy -c demo1 /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # top
Mem: 194720396K used, 1279444K free, 611808K shrd, 647372K buff, 109342248K cached
CPU: 10.5% usr  6.5% sys  0.0% nic 76.6% idle  5.8% io  0.0% irq  0.3% sirq
Load average: 16.27 15.37 15.43 6/20460 19
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
   13     0 root     S     1296  0.0   0  0.0 /bin/sh
   19    13 root     R     1292  0.0   3  0.0 top
    1     0 root     S     1280  0.0   8  0.0 sleep 60

进入demo2容器内部

[root@node1 test]# kubectl exec -it -n=test-restartpolicy test-restartpolicy -c demo2 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@test-restartpolicy:/usr/local/tomcat# top

top - 00:16:39 up 55 days, 19:23,  0 users,  load average: 16.37, 17.25, 16.98
Tasks:   3 total,   1 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):  7.4 us,  4.7 sy,  0.1 ni, 81.8 id,  5.9 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem : 191406.1 total,   3684.6 free,  78569.1 used, 109152.4 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used. 111506.1 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                   
    1 root      20   0   33.3g  98848  16712 S   0.3   0.1   0:03.01 java                                                                      
   38 root      20   0    5740   2172   1676 S   0.0   0.0   0:00.01 bash                                                                      
   46 root      20   0    9752   1804   1348 R   0.0   0.0   0:00.01 top       

可以看到,同一个Pod中每个容器都有自己的进程空间, 当同一个Pod中的一个容器宕掉时,它的故障通常不会直接影响其他容器的运行。其他容器仍然可以继续运行,除非它们与宕掉容器之间存在依赖关系。

注意 1:每个容器都有自己的进程空间,因此一个容器的崩溃不会直接影响其他容器的进程。此外,Kubernetes会监控容器的运行状况,并在发现容器不再处于运行状态时采取相应的行动。它可以自动重新启动容器,使其恢复正常运行。然而,如果多个容器之间有依赖关系或紧密耦合,那么一个容器的故障可能会影响其他容器的功能。例如,如果一个容器负责提供共享服务,而其他容器依赖于该服务进行通信,那么当该容器宕掉时,其他容器可能无法正常工作。

3、Pod中Container重启策略实战

由于在第2章节已经演示了Pod默认的重启策略, 在这一节,将实战演示下Never、OnFailure重启策略。

3.1 Never重启策略

示例一:

创建一个如下的Pod,重启策略为Nerver。

apiVersion: v1
kind: Pod
metadata:
  name: test-restartpolicy
  namespace: test-restartpolicy
spec:
  containers:
  - name: demo1
    image: nginx:1.14-alpine
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:
        scheme: HTTP
        port: 80
        path: /hello
  restartPolicy: Never

查看Pod详情,关注下存活探针Liveness配置和状态码。

其中对于存活探针配置,容器启动后立即进行探测,如果1s内容器没有给出回应则记作探测失败。每次间隔10s进行一次探测,在探测连续失败3次后重启容器。

  • delay:延迟,delay=0s,表示在容器启动后立即开始探测,没有延迟时间
  • timeout:超时,timeout=1s,表示容器必须在1s内进行响应,否则这次探测记作失败
  • period:周期,period=10s,表示每10s探测一次容器
  • success:成功,#success=1,表示连续1次成功后记作成功
  • failure:失败,#failure=3,表示连续3次失败后会重启容器

对于状态码,Pod中容器退出状态码为0,这说明存活探针是正常的使容器停止。

[root@node1 test]# kubectl describe pod -n=test-restartpolicy test-restartpolicy 
Containers:
  demo1:
    Container ID:   docker://183a5fb4ad7556ba74460dc2af1afe2821f60100fadb0d2882cc0db929348ecc
    ......
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 14 Jun 2023 16:32:57 +0800
      Finished:     Wed, 14 Jun 2023 16:33:24 +0800
    Ready:          False
    Restart Count:  0
    Liveness:       http-get http://:80/hello delay=0s timeout=1s period=10s #success=1 #failure=3
    ......
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age   From               Message
  ----     ------     ----  ----               -------
  Normal   Scheduled  11s   default-scheduler  Successfully assigned test-restartpolicy/test-restartpolicy to node1
  Normal   Pulled     9s    kubelet            Container image "nginx:1.14-alpine" already present on machine
  Normal   Created    8s    kubelet            Created container demo1
  Normal   Started    8s    kubelet            Started container demo1
  Warning  Unhealthy  1s    kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS    RESTARTS   AGE
test-restartpolicy   1/1     Running   0    

Pod创建30秒后再查看Pod状态,Pod中容器退出状态码为0的话,Pod状态为Completed。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS      RESTARTS   AGE
test-restartpolicy   0/1     Completed   0          4m13s

注意 1:Pod的Completed状态表示其中的所有容器已成功完成任务并终止。一旦Pod中的所有容器完成其工作并退出,Pod的状态将变为Completed。当Pod状态为Completed时,说明该Pod中的所有容器已成功完成其任务,这可以是一个批处理作业、定时任务或其他短暂的工作。一旦任务完成,Pod将进入Completed状态,并保持在该状态,直到被删除。Completed状态的Pod不会自动重启,也不会再次运行其中的容器。它们保留在集群中的历史记录中,但不会继续占用资源。

查看Pod日志,虽然Pod状态是Completed,但是是能查看Pod日志的,那么Never重启策略的Pod在某些场景下是非常有用的,比如Pod中的容器频繁重启,这时如果Pod是默认的Always,可以通过临时将Pod的重启策略改成Never,这样可以通过describe Pod和查看Pod日志来分析Pod重启原因。

[root@node1 test]# kubectl logs -f -n=test-restartpolicy test-restartpolicy 
2023/06/14 07:57:11 [error] 7#7: *1 open() "/usr/share/nginx/html/hello" failed (2: No such file or directory), client: 10.233.64.1, server: localhost, request: "GET /hello HTTP/1.1", host: "10.233.64.161:80"
10.233.64.1 - - [14/Jun/2023:07:57:11 +0000] "GET /hello HTTP/1.1" 404 169 "-" "kube-probe/1.21" "-"
2023/06/14 07:57:21 [error] 7#7: *2 open() "/usr/share/nginx/html/hello" failed (2: No such file or directory), client: 10.233.64.1, server: localhost, request: "GET /hello HTTP/1.1", host: "10.233.64.161:80"
10.233.64.1 - - [14/Jun/2023:07:57:21 +0000] "GET /hello HTTP/1.1" 404 169 "-" "kube-probe/1.21" "-"
2023/06/14 07:57:31 [error] 7#7: *3 open() "/usr/share/nginx/html/hello" failed (2: No such file or directory), client: 10.233.64.1, server: localhost, request: "GET /hello HTTP/1.1", host: "10.233.64.161:80"
10.233.64.1 - - [14/Jun/2023:07:57:31 +0000] "GET /hello HTTP/1.1" 404 169 "-" "kube-probe/1.21" "-"

示例二:

创建一个如下的Pod,重启策略为Nerver。

apiVersion: v1
kind: Pod
metadata:
  name: test-restartpolicy
  namespace: test-restartpolicy
spec:
  restartPolicy: Never
  containers:
  - name: demo1
    image: harbor.openserver.cn:443/library/busybox:1.31.1
    command: ["/bin/sh","-c","sleep 60,exit 1"]

查看Pod详情,可以看到Pod中容器退出状态码是1。

[root@node1 test]# kubectl describe pod -n=test-restartpolicy test-restartpolicy 
......
Containers:
  demo1:
    Container ID:  docker://bfb7417114d852e33ce299c5267587fa1be0103ebb9bc106c18c35401777260b
    ......
    Command:
      /bin/sh
      -c
      sleep 60,exit 1
    State:          Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Thu, 15 Jun 2023 05:26:50 +0800
      Finished:     Thu, 15 Jun 2023 05:26:50 +0800
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-btfrd (ro)
......

查看Pod状态,Pod中容器退出状态码为非0的话,Pod状态为Error。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS   RESTARTS   AGE
test-restartpolicy   0/1     Error    0          2m41s

示例三:

创建一个如下的Pod,重启策略为Nerver。

apiVersion: v1
kind: Pod
metadata:
  name: test-restartpolicy
  namespace: test-restartpolicy
spec:
  restartPolicy: Never
  containers:
  - name: demo1
    image: busybox:1.31.1 
    command: ["/bin/sh","-c","sleep 60,exit 1"] 
  - name: demo2
    image: busybox:1.31.1
    command:
    - /bin/sh
    - -c
    - sleep 3000

创建Pod大约1分钟后查看Pod状态,只要Pod中有一个容器异常退出,那么它的状态就会变成error。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS   RESTARTS   AGE
test-restartpolicy   1/2     Error    0          2m

此时进入demo2容器,可以正常进入,说明demo2容器是正常运行的。

[root@node1 test]# kubectl exec -it -n=test-restartpolicy test-restartpolicy -c demo2 /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # exit

对于Never重启策略的Pod,通过以上三个示例可以得出如下结论:

  • Pod中只要有容器停止,并且停止容器的状态码都为0,那么Pod状态为Completed。
  • Pod中只要有容器停止,并且存在非0退出状态码,那么Pod状态为Error。
  • 不管退出状态码是Completed还是Error,都能查看Pod日志的,那么Never重启策略的Pod在某些场景下是非常有用的,比如Pod中的容器频繁重启,这时如果Pod是默认的Always,可以通过临时将Pod的重启策略改成Never,这样可以通过describe Pod和查看Pod日志来分析Pod重启原因。
  • 同一个Pod中的一个容器宕掉时,它的故障通常不会直接影响其他容器的运行。其他容器仍然可以继续运行,除非它们与宕掉容器之间存在依赖关系。

3.2 OnFailure重启策略

示例一:

创建一个如下的Pod,重启策略为OnFailure。

apiVersion: v1
kind: Pod
metadata:
  name: test-restartpolicy
  namespace: test-restartpolicy
spec:
  containers:
  - name: demo1
    image: nginx:1.14-alpine
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:
        scheme: HTTP
        port: 80
        path: /hello
  restartPolicy: OnFailure

这个示例在3.1示例一中已经讲过,这里不再详述,Pod中的demo1容器在启动30秒后会因为存活探针检测导致容器停止,容器退出码是0,此时查看Pod信息,Pod状态是Completed。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS      RESTARTS   AGE
test-restartpolicy   0/1     Completed   4          3m9s  

注意 1:查看Pod信息的时候和3.1示例一中不同的是Pod RESTARTS字段重启次数为4(为什么3.1示例一重启次数是0这里是4,目前原理没搞清楚)。

查看Pod详情,重启次数为4是因为探针导致。

[root@node1 test]# kubectl describe pods -n=test-restartpolicy test-restartpolicy 
Name:         test-restartpolicy
Namespace:    test-restartpolicy
Priority:     0
Node:         node1/10.20.30.31
Start Time:   Wed, 14 Jun 2023 17:07:10 +0800
Labels:       <none>
Annotations:  <none>
Status:       Running
IP:           10.233.64.164
IPs:
  IP:  10.233.64.164
Containers:
  demo1:
    ......
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 14 Jun 2023 17:08:41 +0800
      Finished:     Wed, 14 Jun 2023 17:09:10 +0800
    Ready:          True
    Restart Count:  4
    Liveness:       http-get http://:80/hello delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8pj6p (ro)
.......
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  2m12s                default-scheduler  Successfully assigned test-restartpolicy/test-restartpolicy to node1
  Normal   Killing    42s (x3 over 102s)   kubelet            Container demo1 failed liveness probe, will be restarted
  Normal   Pulled     41s (x4 over 2m9s)   kubelet            Container image "nginx:1.14-alpine" already present on machine
  Normal   Created    41s (x4 over 2m9s)   kubelet            Created container demo1
  Normal   Started    41s (x4 over 2m8s)   kubelet            Started container demo1
  Warning  Unhealthy  32s (x10 over 2m2s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404 

示例二:

创建一个如下的Pod,重启策略为OnFailure。

apiVersion: v1
kind: Pod
metadata:
  name: test-restartpolicy
  namespace: test-restartpolicy
spec:
  restartPolicy: OnFailure
  containers:
  - name: demo1
    image: harbor.openserver.cn:443/library/busybox:1.31.1
    command: ["/bin/sh","-c","sleep 10,exit"]

创建几分钟后,查看Pod状态,可看到容器当前已经重启了 5 次。

[root@node1 test]# kubectl get pods -n=test-restartpolicy 
NAME                 READY   STATUS             RESTARTS   AGE
test-restartpolicy   0/1     CrashLoopBackOff   5          4m5s 

对于OnFailure重启策略的Pod,通过以上两个示例可以得出如下结论:

  • Pod中容器停止,并且停止容器的状态码为0,那么Pod状态为Completed。
  • Pod中容器停止,并且停止容器的状态码为非0,那么Pod就会像Always策略那样重启容器。

4、总结

  • 一般Pod是通过工作负载去管理的,在五种工作负载中,一般建议:Deployment、StatefulSet、DaemonSet设置为Always;Job与CronJob设置为OnFailure或Never。 
  • 虽然restartPolicy字段是Pod的配置,但是其实是作用于Pod的Container,换句话说,不应该叫Pod的重启策略,而是叫Container的重启策略;Pod中的所有Container都适用于这个策略。
  • 重启策略适用于Pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由Kubelet延迟一段时间后进行,且反复的重启操作的延迟时长为10s,20s,40s,80s,160s,300s,300s是最大延迟时长。
  • Pod中重启的容器以k8s_<ContainerName_In_Pod>_<PodName>_<Namespace>_<PodID>_<Index>规则命名。
  • 对于Always重启策略的Pod来说,Pod中容器重启时,查看Pod 状态字段值是有规则的,Pod中容器整个重启过程Pod状态会从Running -> NotReady -> CrashLoopBackOff -> Running,周而复始。
  • 查看Pod RESTARTS字段值是有规则的,RESTARTS字段表示整个Pod中所有容器的累计重启次数。如果任何一个容器在Pod中重启,RESTARTS字段的值会增加。这意味着即使只有一个容器重启了,整个Pod的RESTARTS字段值也会增加。
  • 同一个Pod中每个容器都有自己的进程空间, 当同一个Pod中的一个容器宕掉时,它的故障通常不会直接影响其他容器的运行。其他容器仍然可以继续运行,除非它们与宕掉容器之间存在依赖关系。
  • 对于Never重启策略的Pod:
    • Pod中只要有容器停止,并且停止容器的状态码都为0,那么Pod状态为Completed。
    • Pod中只要有容器停止,并且存在非0退出状态码,那么Pod状态为Error。
    • 不管退出状态码是Completed还是Error,都能查看Pod日志的,那么Never重启策略的Pod在某些场景下是非常有用的,比如Pod中的容器频繁重启,这时如果Pod是默认的Always,可以通过临时将Pod的重启策略改成Never,这样可以通过describe Pod和查看Pod日志来分析Pod重启原因。
    • 同一个Pod中的一个容器宕掉时,它的故障通常不会直接影响其他容器的运行。其他容器仍然可以继续运行,除非它们与宕掉容器之间存在依赖关系。
    对于OnFailure重启策略的Pod:
    • Pod中容器停止,并且停止容器的状态码为0,那么Pod状态为Completed。
    • Pod中容器停止,并且停止容器的状态码为非0,那么Pod就会像Always策略那样重启容器。

参考:https://www.kancloud.cn/pshizhsysu/kubernetes/1802621

参考:https://developer.aliyun.com/article/932900

这篇关于Kubernetes Pod重启策略的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!