Kubernetes最小单元Pod的生命周期

  • 1.1 Pod生命周期

    1.1.1 过程及状态

    Pod 的生命周期管理是 Kubernetes 集群中非常重要的一部分,它涉及到 Pod 从创建到销毁的整个过程。下面是 Pod 生命周期中各个阶段的简要说明:

    • Pod 创建过程:当一个 Pod 被创建时,Kubernetes 会为它分配资源并开始调度过程。

    • 运行初始化容器(Init Container):在 Pod 的主容器启动之前,可以定义一个或多个初始化容器。这些容器会先于主容器运行,通常用于执行一些初始化操作,比如设置配置文件或等待其他服务就绪。

    • 运行主容器(Main Container):初始化容器完成后,Pod 中的主容器会启动。主容器是 Pod 的核心部分,它负责执行应用程序的主要逻辑。

    • 容器启动后钩子(Post Start Hook):这是 Kubernetes 提供的一种回调机制,当容器创建并启动后,会调用这个钩子。可以在这个钩子中执行一些容器启动后需要立即进行的操作。

    • 容器终止前钩子(Pre Stop Hook):当容器即将被终止时,Kubernetes 会调用这个钩子。这允许容器进行一些清理工作,比如保存状态、释放资源等。

    • 容器的存活性探测(Liveness Probe):Kubernetes 会定期检查容器的存活性,以确保容器仍在正常运行。如果探测失败,Kubernetes 会重启该容器。

    • 就绪性探测(Readiness Probe):与存活性探测类似,就绪性探测用于确定容器是否已经准备好接收流量。如果探测失败,Kubernetes 会将该容器从服务的端点列表中移除,直到它再次就绪。

    • Pod 终止过程:当 Pod 被标记为需要终止时,Kubernetes 会停止所有的容器,并进行清理工作。在 Pod 被完全终止之前,可能会执行一些终止前的操作,比如保存状态或执行其他必要的清理任务。

    image-20240509100139686

    Pod 的状态确实可以反映其当前的生命周期阶段。以下是 Pod 的五种状态(相位)的详细解释:

    • 挂起(Pending):这个阶段表示 Pod 已经被 Kubernetes API 服务器创建,但尚未被调度到任何节点上。这可能是因为没有合适的节点可供调度,或者因为 Pod 正在等待某些依赖的资源(如 ConfigMaps、Secrets 或者容器镜像)。

    • 运行中(Running):在这个状态中,Pod 已经被调度到节点上,并且所有的容器都已经被创建。至少有一个容器正在运行,或者正在启动或重启。

    • 成功(Succeeded):当 Pod 中的所有容器都正常运行并成功退出(返回了退出代码 0),并且不会被重启时,Pod 就会进入成功状态。这通常用于表示批处理任务已经完成。

    • 失败(Failed):如果 Pod 中的所有容器都终止了,但至少有一个容器是因为失败而终止的(即返回了非零的退出代码),Pod 就会进入失败状态。这表明 Pod 没有成功完成任务。

    • 未知(Unknown):当 Kubernetes 控制平面无法获取到 Pod 的状态信息时,Pod 就会进入未知状态。这通常是由于与 Pod 所在节点的通信失败导致的。如果节点长时间无法与控制平面通信,可能会认为节点及其上的 Pods 处于未知状态。

    1.1.2 创建和终止

    1.1.2.1 Pod创建过程

    Pod 的创建过程可以简写为以下几个步骤:

    • 提交请求:用户通过 kubectl 或 API 客户端向 API 服务器提交创建 Pod 的请求。

    • 创建对象:API 服务器创建 Pod 对象并存储到 etcd,然后向客户端确认创建成功。

    • 监听变化:其他组件通过 watch 机制监听 API 服务器上的 Pod 对象变化。

    • 调度决策:调度器为 Pod 选择节点,并将调度结果更新到 API 服务器。

    • 启动容器:节点上的 kubelet 启动容器,并将状态回传给 API 服务器。

    • 状态更新:API 服务器更新 etcd 中的 Pod 状态信息。

    image-20240509100813009

    1.1.2.2 Pod终止过程
    • 发送删除命令:用户通过 kubectl 或 API 客户端向 API 服务器发送删除 Pod 对象的命令。

    • 宽限期:API 服务器开始等待宽限期(默认为 30 秒),在此期间 Pod 被视为 "dead",但尚未被立即删除。

    • 标记为终止:Pod 被标记为 terminating 状态,告知系统它正在被删除。

    • Kubelet 启动关闭过程:节点上的 kubelet 监控到 Pod 状态变为 terminating,开始关闭 Pod。

    • 端点控制器移除:端点控制器发现 Pod 正在关闭,将其从所有相关服务的端点列表中移除。

    • PreStop 钩子:如果 Pod 定义了 preStop 钩子,这些钩子会被触发并同步执行,以进行清理操作。

    • 停止容器:Pod 中的容器进程收到停止信号,开始正常关闭。

    • 强制终止:如果宽限期结束,仍有进程在运行,kubelet 会发送信号强制终止这些进程。

    • 完成删除:Kubelet 请求 API 服务器将 Pod 的宽限期设置为 0,完成删除操作,此时 Pod 对用户不可见。

    1.1.3 初始化容器

    初始化容器(Init Container)在 Kubernetes 中用于执行 Pod 中主容器启动前的一些初始化任务。

    • 必须成功完成:每个初始化容器必须运行成功直至结束。如果某个初始化容器失败,Kubernetes 会尝试重启该容器,直到它成功完成。这确保了在主容器启动之前,所有的初始化工作都已经正确执行。

    • 顺序执行:初始化容器按照在 Pod 定义中出现的顺序执行。只有当前一个初始化容器成功完成后,下一个才会开始执行。这允许复杂的初始化逻辑被分解成有序的步骤。

    1.1.3.1 应用场景
    • 环境检查:初始化容器可以用于检查外部服务是否可用,例如数据库或配置服务器,然后才启动应用容器。

    • 数据加载:在启动应用之前,可能需要从外部源加载数据或配置文件到 Pod 中。

    • 权限设置:有时需要在启动主容器之前设置文件权限或创建必要的目录结构。

    • 依赖安装:安装主容器运行所需的依赖库或工具,特别是当这些依赖不包含在主容器镜像中时。

    • 资源等待:等待某些资源(如 PersistentVolume 卷)准备就绪。

    • 健康检查:对系统进行健康检查,确保所有依赖服务都处于健康状态,然后才启动应用。

    • 自定义脚本执行:运行自定义脚本,执行如数据库迁移或缓存预热等操作。

    1.1.3.2 测试
    • 创建一个包含两个初始化容器的 Pod,其中一个初始化容器用于检查 MySQL 服务是否可达,另一个用于检查 Redis 服务是否可达。只有在两个服务都可达的情况下,主容器(Nginx)才会启动。

    [root@K8s-master ~]# vim pod-initcontainer.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-initcontainer
      namespace: test
    spec:
      containers:
      - name: main-container
        image: nginx:1.17.1
        ports:
        - name: nginx-port
          containerPort: 80
      initContainers:
      - name: test-mysql
        image: busybox
        command: ['sh', '-c', 'until ping -c 1 192.168.110.100; do echo waiting for mysql...; sleep 2; done;']
      - name: test-redis
        image: busybox
        command: ['sh', '-c', 'until ping -c 1 192.168.110.200; do echo waiting for redis...; sleep 2; done;']
        
    ​
    - 根据 Kubernetes 的行为,initContainers 中的容器将按照它们在配置中出现的顺序依次执行。
    - 只有当 test-mysql 成功完成后,test-redis 才会开始执行。
    - 只有当所有的初始化容器都成功完成后,Kubernetes 才会启动主容器 main-container。
    ​
    [root@K8s-master ~]# kubectl apply -f pod-initcontainer.yaml
    pod/pod-initcontainer created
    [root@K8s-master ~]# kubectl get pod pod-initcontainer -n test   #处于初始化过程,因为两台服务器不可达
    NAME                READY   STATUS     RESTARTS   AGE
    pod-initcontainer   0/1     Init:0/2   0          2m51s
    [root@K8s-master ~]# nmcli connection modify ens33 +ipv4.addresses 192.168.110.100/24  #增加两台主机地址
    [root@K8s-master ~]# nmcli connection modify ens33 +ipv4.addresses 192.168.110.200/24
    [root@K8s-master ~]# nmcli connection up ens33 
    [root@K8s-master ~]# kubectl get pod pod-initcontainer -n test   #主容器正常运行
    NAME                READY   STATUS    RESTARTS   AGE
    pod-initcontainer   1/1     Running   0          33s
    [root@K8s-master ~]# kubectl describe pod pod-initcontainer -n test 
    Events:
      Type    Reason     Age    From               Message
      ----    ------     ----   ----               -------
      Normal  Scheduled  4m49s  default-scheduler  Successfully assigned test/pod-initcontainer to k8s-node-02
      Normal  Pulling    4m48s  kubelet            Pulling image "busybox"
      Normal  Pulled     4m45s  kubelet            Successfully pulled image "busybox" in 2.488707224s
      Normal  Created    4m45s  kubelet            Created container test-mysql
      Normal  Started    4m45s  kubelet            Started container test-mysql
      Normal  Pulling    4m44s  kubelet            Pulling image "busybox"
      Normal  Pulled     4m42s  kubelet            Successfully pulled image "busybox" in 2.403816887s
      Normal  Created    4m42s  kubelet            Created container test-redis
      Normal  Started    4m41s  kubelet            Started container test-redis
      Normal  Pulled     4m41s  kubelet            Container image "nginx:1.17.1" already present on machine
      Normal  Created    4m41s  kubelet            Created container main-container
      Normal  Started    4m41s  kubelet            Started container main-container
      #可以看到把mysql和redis都搞定Nginx才能起来,主容器才能起来

    1.1.4 钩子函数

    • Kubernetes 中的容器生命周期钩子(lifecycle hooks)些钩子允许开发者在容器的生命周期中的特定时刻执行自定义操作。kubernetes在主容器的启动之后和停止之前提供了两个钩子函数:

      • Post Start Hook

        • 这个钩子在容器创建并成功运行之后立即执行。它可以用来执行容器启动后需要立即进行的任务,比如发送信号给其他服务,或者执行某些初始化逻辑。

        • 如果 Post Start 钩子失败,即执行的命令返回非零退出码,Kubernetes 会认为容器启动失败,并根据容器的重启策略决定是否重启容器。

      • Pre Stop Hook

        • 这个钩子在容器即将终止之前执行。它通常用于执行清理工作,如保存状态、优雅地关闭服务、释放资源等。

        • Pre Stop 钩子提供了一种优雅关闭容器的方式。如果容器在 Pre Stop 钩子执行期间没有停止,Kubernetes 将等待一段时间(默认为 30 秒)之后,发送 SIGKILL 信号强制终止容器。

    Kubernetes 中容器生命周期钩子处理器支持的三种动作类型:ExecTCPSocketHTTPGet

    • Exec 命令

      • 这个动作类型允许在容器内执行一个命令行命令。

      • 如果命令执行成功(退出状态码为0),钩子继续执行;如果失败(非零退出状态码),则容器将被重启。

      lifecycle:
        postStart:
          exec:
            command: ["cat", "/tmp/healthy"]
    • TCPSocket

      • 这个动作类型尝试在容器内访问指定的 TCP 端口。

      • 如果能够建立连接,则钩子动作成功;否则,容器将被重启。

      lifecycle:
        postStart:
          tcpSocket:
            port: 8080
    • HTTPGet

      • 这个动作类型在容器内向指定的 URL 发起 HTTP GET 请求。

      • 如果请求成功(HTTP 状态码为 200-399),钩子动作成功;如果失败,则容器将被重启。

      lifecycle:
        postStart:
          httpGet:
            path: /healthz  # URI地址
            port: 80        # 端口号
            host: 192.168.110.100  # 主机地址
            scheme: HTTP    # 支持的协议,可以是 HTTP 或 HTTPS
    1.1.4.1 钩子函数使用实例(Exec为例)
    [root@K8s-master ~]# vim pod-hook-exec.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-hook-exec
      namespace: test
    spec:
      containers:
      - name: main-container
        image: nginx:1.17.1
        ports:
        - name: nginx-port
          containerPort: 80
        lifecycle:
          postStart:
            exec:
              command: ["/bin/bash", "-c", "echo 'postStart...' > /usr/share/nginx/html/index.html"]
          preStop:
            exec:
              command: ["/usr/sbin/nginx", "-s", "quit"]
              
    [root@K8s-master ~]# kubectl apply -f pod-hook-exec.yaml 
    pod/pod-hook-exec created
    [root@K8s-master ~]# kubectl get pod -n test -o wide
    NAME            READY   STATUS    RESTARTS   AGE     IP            NODE          NOMINATED NODE   READINESS GATES
    pod-hook-exec   1/1     Running   0          3m17s   10.244.2.11   k8s-node-02   <none>           <none>
    [root@K8s-master ~]# curl 10.244.2.11
    postStart...

    1.1.5 容器探测

    在Kubernetes中,确实存在两种类型的探针,用于确保容器实例的健康和可用性:

    • Liveness Probe(存活性探针):这种探针用于判断容器是否仍然处于“存活”状态。如果一个容器的存活性探针失败,Kubernetes会认为这个容器无法正常工作,因此会重启这个容器。存活性探针的典型用途是检测应用程序是否已经崩溃或者变得无响应。

    • Readiness Probe(就绪性探针):这种探针用于判断容器是否已经准备好接受流量。如果一个容器的就绪性探针失败,Kubernetes会从服务的负载均衡池中将该容器摘除,直到该容器再次报告它已经准备好。就绪性探针常用于确保新启动的容器在开始接收流量之前已经完成了初始化过程。

    这两种探针都可以通过HTTP请求、TCP连接尝试或者执行容器内命令等方式来实现。它们可以配置为定期执行,并且可以设置初始延迟、超时时间以及探测间隔。

    在配置时,可以为每个探针设置以下参数:

    • InitialDelaySeconds:在容器启动后等待多少秒才开始执行探针检查。

    • TimeoutSeconds:探针检查超时的时间。

    • PeriodSeconds:探针检查的执行频率。

    • SuccessThreshold:探测成功后,需要连续成功多少次才认为容器健康。

    • FailureThreshold:探测失败后,需要连续失败多少次才认为容器不健康。

    Kubernetes 中存活性探针(Liveness Probe)和就绪性探针(Readiness Probe)支持的三种探测方式。以下是对这三种方式的简要说明:

    • Exec 命令探针:通过在容器内部执行一个命令来检查容器的健康状况。如果命令执行成功(即退出码为0),则认为容器是健康的。例如:

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

    这个例子中,如果容器内 /tmp/healthy 文件存在,cat 命令将成功执行,探针将返回健康状态。

    • TCP Socket 探针:通过尝试与容器内部的某个端口建立 TCP 连接来检查容器的健康状况。如果连接成功建立,探针认为容器是健康的。例如:

    livenessProbe:
      tcpSocket:
        port: 8080

    在这个例子中,Kubernetes 将尝试连接到容器的 8080 端口,如果连接成功,容器被认为是健康的。

    • HTTP GET 探针:通过向容器内部的 Web 应用发送 HTTP GET 请求来检查容器的健康状况。如果 HTTP 响应的状态码在 200 到 399 之间,探针认为容器是健康的。例如:

    livenessProbe:
      httpGet:
        path: /healthz  # 这里是健康检查的URI路径
        port: 80        # 这里是容器内部的端口号
        host: 127.0.0.1 # 这里是主机地址,通常设置为localhost或127.0.0.1
        scheme: HTTP    # 这里指定使用的是HTTP协议
    1.1.5.1 Exec命令探针
    [root@K8s-master ~]# vim pod-liveness-exec.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-liveness-exec
      namespace: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - name: nginx-port
          containerPort: 80
        livenessProbe:
          exec:
            command: ["/bin/cat", "/tmp/hello.txt"]
            
    [root@K8s-master ~]# kubectl apply -f pod-liveness-exec.yaml 
    pod/pod-liveness-exec created
    [root@K8s-master ~]# kubectl describe pods pod-liveness-exec -n test
    Events:
      Type     Reason     Age                From               Message
      ----     ------     ----               ----               -------
      Normal   Scheduled  52s                default-scheduler  Successfully assigned test/pod-liveness-exec to k8s-node-02
      Normal   Pulled     21s (x2 over 51s)  kubelet            Container image "nginx:1.17.1" already present on machine
      Normal   Created    21s (x2 over 51s)  kubelet            Created container nginx
      Normal   Killing    21s                kubelet            Container nginx failed liveness probe, will be restarted
      Normal   Started    20s (x2 over 50s)  kubelet            Started container nginx
      Warning  Unhealthy  1s (x5 over 41s)   kubelet            Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory
    # 观察上面的信息就会发现nginx容器启动之后就进行了健康检查
    # 检查失败之后,容器被kill掉,然后尝试进行重启(这是重启策略的作用,后面讲解)
    # 稍等一会之后,再观察pod信息,就可以看到RESTARTS不再是0,而是一直增长
    [root@K8s-master ~]# kubectl get pods pod-liveness-exec -n test   #启动后进行健康检测
    NAME                READY   STATUS    RESTARTS      AGE
    pod-liveness-exec   1/1     Running   3 (24s ago)   115s
    [root@K8s-master ~]# kubectl get pods pod-liveness-exec -n test   #稍等会被杀掉
    NAME                READY   STATUS             RESTARTS      AGE
    pod-liveness-exec   0/1     CrashLoopBackOff   4 (17s ago)   2m48s
    # 可以修改成一个存在的文件,就正常了
    [root@K8s-master ~]# kubectl exec pod-liveness-exec -n test -it -c nginx /bin/sh
    # echo hello > /tmp/hello.txt
    
    [root@K8s-master ~]# kubectl get pod pod-liveness-exec -n test 
    NAME                READY   STATUS    RESTARTS       AGE
    pod-liveness-exec   1/1     Running   20 (39s ago)   46m
    1.1.5.2 TCP Socket 探针
    [root@K8s-master ~]# vim pod-liveness-tcpsocket.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-liveness-tcpsocket
      namespace: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - name: nginx-port
          containerPort: 80
        livenessProbe:
          tcpSocket:
            port: 8080
    
    
    [root@K8s-master ~]# kubectl apply -f pod-liveness-tcpsocket.yaml
    pod/pod-liveness-tcpsocket created
    [root@K8s-master ~]# kubectl describe pod pod-liveness-tcpsocket -n test
    Events:
      Type     Reason     Age                  From               Message
      ----     ------     ----                 ----               -------
      Normal   Scheduled  2m14s                default-scheduler  Successfully assigned test/pod-liveness-tcpsocket to k8s-node-02
      Normal   Pulled     44s (x4 over 2m13s)  kubelet            Container image "nginx:1.17.1" already present on machine
      Normal   Created    44s (x4 over 2m13s)  kubelet            Created container nginx
      Normal   Killing    44s (x3 over 104s)   kubelet            Container nginx failed liveness probe, will be restarted
      Normal   Started    43s (x4 over 2m13s)  kubelet            Started container nginx
      Warning  Unhealthy  34s (x10 over 2m4s)  kubelet            Liveness probe failed: dial tcp 10.244.2.18:8080: connect: connection refused
    # 观察上面的信息,发现尝试访问8080端口,但是失败了
    # 稍等一会之后,再观察pod信息,就可以看到RESTARTS不再是0,而是一直增长
    [root@K8s-master ~]# kubectl get pod pod-liveness-tcpsocket -n test
    NAME                     READY   STATUS    RESTARTS      AGE
    pod-liveness-tcpsocket   1/1     Running   5 (46s ago)   3m16s
    [root@K8s-master ~]# kubectl get pod pod-liveness-tcpsocket -n test
    NAME                     READY   STATUS             RESTARTS      AGE
    pod-liveness-tcpsocket   0/1     CrashLoopBackOff   5 (33s ago)   4m13s
    
    #可以修改成一个可以访问的端口,比如80,再试,结果就正常了
    [root@K8s-master ~]# sed -i 's/8080/80/' pod-liveness-tcpsocket.yaml 
    [root@K8s-master ~]# kubectl delete -f pod-liveness-tcpsocket.yaml 
    pod "pod-liveness-tcpsocket" deleted
    [root@K8s-master ~]# kubectl apply -f pod-liveness-tcpsocket.yaml 
    pod/pod-liveness-tcpsocket created
    [root@K8s-master ~]# kubectl get pod pod-liveness-tcpsocket -n test
    NAME                     READY   STATUS    RESTARTS   AGE
    pod-liveness-tcpsocket   1/1     Running   0          12s
    1.1.5.3 HTTP GET 探针
    [root@K8s-master ~]# vim pod-liveness-httpget.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-liveness-httpget
      namespace: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - name: nginx-port
          containerPort: 80
        livenessProbe:
          httpGet:
            scheme: HTTP
            port: 80
            path: /hello
    
    [root@K8s-master ~]# kubectl apply -f pod-liveness-httpget.yaml 
    pod/pod-liveness-httpget created
    [root@K8s-master ~]# kubectl describe pod pod-liveness-httpget -n test
    Events:
      Type     Reason     Age               From               Message
      ----     ------     ----              ----               -------
      Normal   Scheduled  66s               default-scheduler  Successfully assigned test/pod-liveness-httpget to k8s-node-01
      Normal   Pulled     5s (x3 over 65s)  kubelet            Container image "nginx:1.17.1" already present on machine
      Normal   Created    5s (x3 over 65s)  kubelet            Created container nginx
      Warning  Unhealthy  5s (x6 over 55s)  kubelet            Liveness probe failed: Get "http://10.244.1.6:80/hello": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
      Normal   Killing    5s (x2 over 35s)  kubelet            Container nginx failed liveness probe, will be restarted
      Normal   Started    4s (x3 over 65s)  kubelet            Started container nginx
    [root@K8s-master ~]# kubectl get pod pod-liveness-httpget -n test
    NAME                   READY   STATUS             RESTARTS      AGE
    pod-liveness-httpget   0/1     CrashLoopBackOff   4 (16s ago)   2m47s
    
    # 观察上面信息,尝试访问路径,但是未找到,出现404错误
    # 稍等一会之后,再观察pod信息,就可以看到RESTARTS不再是0,而是一直增长
    
    #修改一个可以访问的路径
    [root@K8s-master ~]# sed -i 's#/hello#/#' pod-liveness-httpget.yaml 
    [root@K8s-master ~]# kubectl delete -f pod-liveness-httpget.yaml 
    pod "pod-liveness-httpget" deleted
    [root@K8s-master ~]# kubectl apply -f pod-liveness-httpget.yaml 
    pod/pod-liveness-httpget created
    [root@K8s-master ~]# kubectl get pod pod-liveness-httpget -n test
    NAME                   READY   STATUS    RESTARTS   AGE
    pod-liveness-httpget   1/1     Running   0          3s
    1.1.5.4 livenessProbe的子属性
    [root@K8s-master ~]# kubectl explain pod.spec.containers.livenessProbe
    livenessProbe:
      exec: <Object> # 在容器内执行的命令
      tcpSocket: <Object> # 用于探测的TCP端口和IP
      httpGet: <Object> # 用于探测的HTTP GET请求
      initialDelaySeconds: <integer> # 容器启动后等待多少秒执行第一次探测
      timeoutSeconds: <integer> # 探测超时时间,默认为1秒,最小1秒
      periodSeconds: <integer> # 执行探测的频率,默认为10秒,最小1秒
      failureThreshold: <integer> # 连续探测失败多少次才被认定为失败,默认为3,最小1
      successThreshold: <integer> # 连续探测成功多少次才被认定为成功,默认为1
    • 配置实例

    [root@K8s-master ~]# vim pod-liveness-httpget.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-liveness-httpget
      namespace: dev
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - name: nginx-port
          containerPort: 80
        livenessProbe:
          httpGet:
            scheme: HTTP
            port: 80
            path: /
          initialDelaySeconds: 30 # 容器启动后30秒开始探测
          timeoutSeconds: 5       # 探测超时时间为5秒

    1.1.6 重启策略

    1.1.6.1 三种策略

    Kubernetes 中的 Pod 支持以下三种重启策略:

    • Always

      • 描述:无论容器退出的原因是什么,都会自动重启容器。

      • 默认值:如果未指定重启策略,Kubernetes 默认使用 Always。

    • OnFailure

      • 描述:仅当容器以非零退出码终止时,才会重启容器。

      • 条件:需要指定退出码来触发重启。

    • Never

      • 描述:不论容器退出的原因是什么,都不会重启容器。

    1.1.6.2 重启延迟
    • 首次重启:首次需要重启的容器将立即进行重启。

    • 后续重启:随后如果再次需要重启,kubelet 将会引入延迟,延迟时长从 10 秒开始,并呈指数增长。

    • 延迟时长序列:10s、20s、40s、80s、160s,之后达到最大延迟时长。

    • 最大延迟时长:300s,这是后续重启操作的最大延迟时长。

    [root@K8s-master ~]# vim pod-restartpolicy.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-restartpolicy
      namespace: test
    spec:
      restartPolicy: Never   #论容器退出的原因是什么,都不会重启容器
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80
          name: nginx-port
        livenessProbe:
          httpGet:
            scheme: HTTP
            port: 80
            path: /hello
    ​
    [root@K8s-master ~]# kubectl apply -f pod-restartpolicy.yaml 
    pod/pod-restartpolicy created
    [root@K8s-master ~]# kubectl describe pod pod-restartpolicy -n test  # 查看Pod详情,发现nginx容器失败
    Events:
      Type     Reason     Age                From               Message
      ----     ------     ----               ----               -------
      Normal   Scheduled  94s                default-scheduler  Successfully assigned test/pod-restartpolicy to k8s-node-02
      Normal   Pulled     92s                kubelet            Container image "nginx:1.17.1" already present on machine
      Normal   Created    92s                kubelet            Created container nginx
      Normal   Started    92s                kubelet            Started container nginx
      Warning  Unhealthy  63s (x3 over 83s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
      Normal   Killing    63s                kubelet            Stopping container nginx
    [root@K8s-master ~]# kubectl get pod pod-restartpolicy -n test  # 再观察pod的重启次数,发现一直是0,并未重启
    NAME                READY   STATUS      RESTARTS   AGE
    pod-restartpolicy   0/1     Completed   0          2m3s

    1.1.7 Pod常见状态转换场景

    Pod中的容器数Pod状态发生事件AlwaysOnFailureNever
    包含一个容器Running容器成功退出RunningSucceededSucceeded
    包含一个容器Running容器失败退出RunningRunningFailed
    包含两个容器Running1个容器失败退出RunningRunningRunning
    包含两个容器Running容器内存溢出挂掉RunningRunningFailed

    注释:

    • 对于 Always 重启策略,容器将立即重启。

    • 对于 OnFailureNever 重启策略,如果容器成功退出且退出码为0,Pod状态将变为Succeeded。

    • 对于 Always 重启策略,容器将立即重启。

    • 对于 OnFailure 重启策略,容器将以非零退出码退出,因此会重启。

    • 对于 Never 重启策略,容器将不会重启,Pod状态将变为Failed。

    • 对于 Always 重启策略,由于内存溢出导致的容器终止将重启容器。

    • 对于 OnFailure 重启策略,内存溢出导致的容器终止会触发重启,因为退出码是非零的。

    • 对于 Never 重启策略,容器将不会重启,Pod中其他容器继续运行,但失败的容器状态将为Terminated

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kubernetes(简称为k8s)中的Pod最小的可部署单元,用于运行容器化应用程序。Pod生命周期可以分为以下几个阶段: 1. Pending(等待):Pod被创建后,处于Pending状态表示Kubernetes正在为Pod分配资源(如CPU、内存等)。在这个阶段,Pod可能会处于排队等待状态。 2. Running(运行中):一旦Pod获得了所需的资源,它将进入Running状态。在这个阶段,容器正在运行,并且可以被其他组件访问。 3. Succeeded(成功):如果Pod中的所有容器成功完成了它们的任务,那么Pod将进入Succeeded状态。通常情况下,这意味着所有容器都已经退出,并且不会再重新启动。 4. Failed(失败):如果Pod中的任何一个容器退出并返回错误代码,那么Pod将进入Failed状态。通常情况下,这意味着容器无法完成其任务。 5. Unknown(未知):如果无法获取关于Pod当前状态的信息,那么Pod将进入Unknown状态。这可能是由于与集群通信故障或其他未知错误导致的。 除了上述状态之外,Pod还可以通过以下方式进行调整: 1. 创建(Create):通过创建Pod规范文件或使用Kubernetes API来创建Pod。 2. 更新(Update):可以通过更新Pod规范文件或使用Kubernetes API来更新Pod的配置(如镜像版本、资源请求等),这将触发Pod的重新调度。 3. 删除(Delete):可以通过删除Pod规范文件或使用Kubernetes API来删除Pod。一旦Pod被删除,它将不再存在于集群中。 需要注意的是,Kubernetes会根据集群的状态和配置自动处理Pod生命周期,例如自动重新调度失败的Pod或替换不健康的Pod

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值