【kubernetes系列】Kubernetes之生命周期和重启策略

概述

Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少 其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以 失败状态结束而进入 Succeeded 或者 Failed 阶段。
在 Pod 运行期间,kubelet 能够重启容器以处理一些失效场景。 在 Pod 内部,Kubernetes 跟踪不同容器的状态 并处理可能出现的状况。
在 Kubernetes API 中,Pod 包含期望部分和实际状态部分。 Pod 对象的状态包含了一组 Pod 状况(Conditions)。 如果应用需要的话,你也可以向其中注入自定义的就绪性信息。
Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止。

我们在调度、管理 Pod 时,需要熟悉 Pod 在整个生命周期的各个状态,而设置 Pod 的重启策略也是基于对 Pod 的各种状态的了解。

Pod 生命周期:(部分pod会有int容器,用于初始化,可以有多个)

pod的生命周期大致如下:
【kubernetes系列】Kubernetes之生命周期和重启策略_第1张图片

  • 说明:
    • 初始化容器阶段初始化pod中每一个容器他们是串行执行的,执行完成后就退出了
    • 启动主容器main container
    • 在main container刚刚启动之后可以执行post start命令
    • 在整个main container执行的过程中可以做两类探测:liveness probe(存活探测)和readiness probe(就绪探测)
    • 在main container结束前可以执行pre stop命令
  • 配置启动后钩子(post start)和终止前钩子(pre stop)
    • post start:容器创建之后立即执行,如果失败了就会按照重启策略重启容器
    • pre stop:容器终止前立即执行,执行完成之后容器将成功终止
  • 可以使用以下命令查看post start和pre stop的设置格式:
[root@k8s-m1 ~]# kubectl explain pod.spec.containers.lifecycle.preStop
[root@k8s-m1 ~]# kubectl explain pod.spec.containers.lifecycle.postStart 

Pod 的状态(phase):

  • Pod 的所有状态目前总共有 5 种,分别如下:
    • 挂起(Pending):Pod 已被 Kubernetes 系统接受,但由于某种原因,pod不能正常启动。如镜像未拉取下来,需要的configmap未创建,集群不能提供pod所需硬件资源,不能容忍污点等等。
    • 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
    • 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
    • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
    • 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败。

使用命令查看:

[root@k8s-m1 ~]# kubectl describe po my-nginx-7ff446c4f4-tbtpc

pod状态(phase):

【kubernetes系列】Kubernetes之生命周期和重启策略_第2张图片

容器状态:

【kubernetes系列】Kubernetes之生命周期和重启策略_第3张图片

条件状态:

【kubernetes系列】Kubernetes之生命周期和重启策略_第4张图片

容器探针:

探针 是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。有三种类型的处理程序:

  • ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
  • TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。

每次探测都将获得以下三种结果之一:

  • Success(成功):容器通过了诊断。
  • Failure(失败):容器未通过诊断。
  • Unknown(未知):诊断失败,因此不会采取任何行动。

Kubelet 可以选择是否执行在容器上运行的两种探针执行和做出反应:

  • livenessProbe:指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其 重启策略 的影响。如果容器不提供存活探针,则默认状态为 Success。
  • readinessProbe:就绪探测是用于容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success。

存活探针使用场景

如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针; kubelet 将根据 Pod 的restartPolicy 自动执行修复操作。
如果希望容器在探测失败时被杀死并重新启动,那么需要指定一个存活态探针, 并指定restartPolicy 为 “Always” 或 “OnFailure”。

就绪探针使用场景

如果要仅在探测成功时才开始向 Pod 发送请求流量,请指定就绪态探针。 在这种情况下,就绪态探针可能与存活态探针相同,但是设定了就绪态探针的存在意味着 Pod 将在启动阶段不接收任何数据,并且只有在探针探测成功后才开始接收数据。
如果你的容器需要加载大规模的数据、配置文件或者在启动期间执行迁移操作,可以添加一个就绪态探针。
如果你希望容器能够自行进入维护状态,也可以指定一个就绪态探针,检查某个特定于 就绪态的因此不同于存活态探测的端点。
注意:如果你只是想在 Pod 被删除时能够排空请求,则不一定需要使用就绪态探针; 在删除 Pod 时,Pod 会自动将自身置于未就绪状态,无论就绪态探针是否存在,等待 Pod 中的容器停止期间,Pod 会一直处于未就绪状态。

Pod的重启策略:

Pod 的重启策略有 3 种,默认值为 Always。

  • Always : 容器失效时,kubelet 自动重启该容器;
  • OnFailure : 容器终止运行且退出码不为0时重启;
  • 失败的容器由 kubelet 以五分钟为上限的指数退避延迟(10秒,20秒,40秒…)重新启动,并在成功执行十分钟后重置。
    Never : 不论状态为何, kubelet 都不重启该容器。

Pod 的生命:

一般来说,Pod 不会自动消失,直到人为删除他们。这可能是一个人或控制器。这个规则的唯一例外是成功或失败的 phase 超过一段时间(由 master 确定)的Pod将过期并被自动销毁。
有三种可用的控制器:

  • 使用 Job 运行预期会终止的 Pod,例如批量计算。Job 仅适用于重启策略为 OnFailure 或 Never 的 Pod。
  • 对预期不会终止的 Pod 使用 ReplicationController、ReplicaSet 和 Deployment ,例如 Web 服务器。ReplicationController 仅适用于具有 restartPolicy 为 Always 的 Pod。
  • 提供特定于机器的系统服务,使用 DaemonSet 为每台机器运行一个 Pod 。

所有这三种类型的控制器都包含一个 Pod模板。建议使用合适的控制器来创建 Pod,而不是直接自己创建 Pod。这是因为单独的 Pod 在机器故障的情况下没有办法自动恢复,而控制器却可以。
如果节点死亡或与集群的其余部分断开连接,则 Kubernetes 将应用一个策略将丢失节点上的所有 Pod 的 phase 设置为 Failed。

示例

LivenessProbe (存活检查):

参数说明:

[root@k8s\-master ~]# kubectl explain pod.spec.containers.livenessProbe
KIND: Pod
VERSION: v1
RESOURCE: livenessProbe <Object\
exec command的方式探测,例如 curl 一个地址
failureThreshold 探测几次失败 才算失败 默认是连续三次
httpGet http请求探测
initialDelaySeconds 初始化延迟探测,第一次探测的时候,因为主程序启动需要一定的时间
periodSeconds 每次的多长时间探测一次 默认10s
timeoutSeconds 探测超时的秒数 默认1s
tcpSocket 检测端口的探测

[root@k8s-m1 k8s-total]# kubectl explain pod.spec.containers.readinessProbe
##readiness和liveness格式类似
ExecAction探测方式:

举个例子:定义一个liveness的pod资源类型,基础镜像为busybox,在busybox这个容器启动后会执行创建/tmp/test.txt的文件,30s后删除,然后等待3600秒。随后定义了存活性探测,方式是以exec的方式执行命令判断/tmp/test.txt是否存在,存在即表示存活,不存在则表示容器已经挂了。

[root@k8s-m1 k8s-total]# cat busybox-liveness.yml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
  labels:
    name: myapp
spec:
  containers:
  - name: livess-exec
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/test.txt; sleep 30; rm -f /tmp/test.txt; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/test.txt"]
      initialDelaySeconds: 1
      periodSeconds: 3
[root@k8s-m1 k8s-total]# kubectl apply  -f busybox-liveness.yml 
pod/liveness-exec-pod created

##隔大概40s查看
[root@k8s-m1 k8s-total]# kubectl describe pod liveness-exec-pod 
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  3m16s                default-scheduler  Successfully assigned default/liveness-exec-pod to k8s-m1
  Normal   Pulled     56s (x3 over 3m14s)  kubelet            Container image "busybox:latest" already present on machine
  Normal   Created    56s (x3 over 3m14s)  kubelet            Created container livess-exec
  Normal   Started    55s (x3 over 3m14s)  kubelet            Started container livess-exec
  Warning  Unhealthy  17s (x9 over 2m41s)  kubelet            Liveness probe failed:
  Normal   Killing    17s (x3 over 2m35s)  kubelet            Container livess-exec failed liveness probe, will be restarted
##可以发现pod每隔一段时间会自动重启
HTTPGetAction探测方式:
[root@k8s-m1 k8s-total]# cat liveness-http-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-http-pod
  labels:
    app: myapp
spec:
  containers:
  - name: nginx-http
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
     - name: http
       containerPort: 80
     - name: https
       containerPort: 443
    livenessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 1
      periodSeconds: 3
##注意url的实际路径

[root@k8s-m1 k8s-total]# kubectl apply  -f liveness-http-pod.yaml 
pod/liveness-http-pod created

Pod状态(phase)说明:

  • Pod 中只有一个容器并且正在运行。容器成功退出。
    • 记录完成事件。
    • 如果 restartPolicy 为:
    • Always:重启容器;Pod phase 仍为 Running。
    • OnFailure:Pod phase 变成 Succeeded。
    • Never:Pod phase 变成 Succeeded。
  • Pod 中只有一个容器并且正在运行。容器退出失败。
    • 记录失败事件。
    • 如果 restartPolicy 为:
    • Always:重启容器;Pod phase 仍为 Running。
    • OnFailure:重启容器;Pod phase 仍为 Running。
    • Never:Pod phase 变成 Failed。
  • Pod 中有两个容器并且正在运行。有一个容器退出失败。
    • 记录失败事件。
    • 如果 restartPolicy 为:
    • Always:重启容器;Pod phase 仍为 Running。
    • OnFailure:重启容器;Pod phase 仍为 Running。
    • Never:不重启容器;Pod phase 仍为 Running。
      • 如果有一个容器没有处于运行状态,并且两个容器退出:
      • 记录失败事件。
      • 如果 restartPolicy 为:
      • Always:重启容器;Pod phase 仍为 Running。
      • OnFailure:重启容器;Pod phase 仍为 Running。
      • Never:Pod phase 变成 Failed。
  • Pod 中只有一个容器并处于运行状态。容器运行时内存超出限制:
    • 容器以失败状态终止。
    • 记录 OOM 事件。
    • 如果 restartPolicy 为:
    • Always:重启容器;Pod phase 仍为 Running。
    • OnFailure:重启容器;Pod phase 仍为 Running。
    • Never: 记录失败事件;Pod phase 仍为 Failed。
  • Pod 正在运行,磁盘故障:
    • 杀掉所有容器。
    • 记录适当事件。
    • Pod phase 变成 Failed。
    • 如果使用控制器来运行,Pod 将在别处重建。
  • Pod 正在运行,其节点被分段。
    • 节点控制器等待直到超时。
    • 节点控制器将 Pod phase 设置为 Failed。
    • 如果是用控制器来运行,Pod 将在别处重建。

ReadinessProbe (就绪检查):

就绪探测是用于容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success。(注:默认为ready状态)

[root@k8s-m1 k8s-total]# kubectl get po -n kube-system 
NAME                                        READY   STATUS    RESTARTS   AGE
calico-kube-controllers-bcc6f659f-7q2kc     1/1     Running   3          83d
calico-node-cgffm                           1/1     Running   22         231d
calico-node-f6jct                           1/1     Running   4          120d
calico-node-nxfv8                           1/1     Running   1843       54d
coredns-6d56c8448f-5p76s                    1/1     Running   2          83d
coredns-6d56c8448f-ql5lr                    1/1     Running   4          120d
fluentd-elasticsearch-hnlct                 1/1     Running   1          7d14h
fluentd-elasticsearch-j78v4                 1/1     Running   1          7d14h
fluentd-elasticsearch-t5vwh                 1/1     Running   1          7d14h
kube-apiserver-k8s-m1                       1/1     Running   300        120d
kube-apiserver-k8s-m2                       1/1     Running   279        120d
kube-apiserver-k8s-m3                       1/1     Running   1329       54d
kube-controller-manager-k8s-m1              1/1     Running   36         120d
kube-controller-manager-k8s-m2              1/1     Running   23         120d
kube-controller-manager-k8s-m3              1/1     Running   1327       120d
kube-proxy-d6swh                            1/1     Running   3          53d
kube-proxy-dlw8r                            1/1     Running   19         53d
kube-proxy-xvbwl                            1/1     Running   1          54d
kube-scheduler-k8s-m1                       1/1     Running   36         120d
kube-scheduler-k8s-m2                       1/1     Running   21         120d
kube-scheduler-k8s-m3                       1/1     Running   1261       120d
kubernetes-dashboard-55fd86cfcf-5lfbd       1/1     Running   4          120d
metrics-server-894d4897d-7777m              1/1     Running   3          53d

有时,应用程序暂时无法对外部流量提供服务。 例如,应用程序可能需要在启动期间加载大量数据或配置文件,这种有可能比较耗时。 在这种情况下,不想杀死应用程序,但也不能立马接受请求。 Kubernetes提供了readiness probe来检测和减轻这些情况。 Pod中的容器可以报告自己还没有准备,不能处理Kubernetes服务发送过来的流量。(如果在Pod没有ready的情况下是不会被加入到service中,如果已经加入到service中但设置了readiness probe检测发现Pod服务未处于ready状态也会被service移除

Readiness probe的配置跟liveness probe很像。唯一的不同是使用 readinessProbe而不是livenessProbe。
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
Readiness probe的HTTP和TCP的探测器配置跟liveness probe一样。

Readiness和livenss probe可以并行用于同一容器。 使用两者可以确保流量无法到达未准备好的容器,并且容器在失败时重新启动。

强制终止 Pod

注意: 对于某些工作负载及其 Pod 而言,强制删除很可能会带来某种破坏。

默认情况下,所有的删除操作都会附有 30 秒钟的宽限期限。 kubectl delete 命令支持 --grace-period= 选项,允许你重载默认值, 设定自己希望的期限值。
将宽限期限强制设置为 0 意味着立即从 API 服务器删除 Pod。 如果 Pod 仍然运行于某节点上,强制删除操作会触发 kubelet 立即执行清理操作。

说明: 必须在设置 --grace-period=0 的同时额外设置 --force 参数才能发起强制删除请求。
执行强制删除操作时,API 服务器不再等待来自 kubelet 的、关于 Pod 已经在原来运行的节点上终止执行的确认消息。 API 服务器直接删除 Pod 对象,这样新的与之同名的 Pod 即可以被创建。 在节点侧,被设置为立即终止的 Pod 仍然会在被强行杀死之前获得一点点的宽限时间。

更多关于kubernetes的知识分享,请前往博客主页。编写过程中,难免出现差错,敬请指出

你可能感兴趣的:(kubernetes,容器,云原生)