一、Pod的生命周期

在Kubernetes中,Pod的生命周期经历了几个关键阶段,包括创建、运行、暂停、终止和删除。

  1. 创建阶段:
1)当用户或控制器创建一个 Pod 对象时,Kubernetes API 服务器接收到请求并验证它。

2)Kubernetes Scheduler 选择一个适合的节点来运行 Pod。

3)调度器将 Pod 绑定到所选节点,并在该节点上创建 Pod 实例。
  1. 运行阶段:
1)Pod 中的容器开始启动,它们按照 Pod 的配置进行初始化。

2)一旦容器准备就绪,它们就会被放置到运行中的状态,并且可以处理请求。
  1. 暂停和重启阶段:
1)在某些情况下,Pod 可能会进入暂停状态。例如,节点上的资源不足或者容器出现了故障。

2)如果 Pod 处于暂停状态,Kubernetes 会尝试重新调度 Pod 到其他节点,或者在原节点上重新启动 Pod。
  1. 终止阶段:
1)当 Pod 完成其任务、被删除或者发生了故障,它将进入终止阶段。

2)Kubernetes 会向 Pod 发送终止信号,然后容器中的进程开始关闭。

3)容器中的进程关闭后,Pod 将进入终止状态。
  1. 删除阶段:
1)一旦 Pod 进入终止状态,Kubernetes 将其标记为删除。

2)Kubernetes 控制器会清理 Pod 的资源,包括在节点上的容器实例以及任何与 Pod 相关的存储卷等。

3)最终,Pod 对象将从 Kubernetes API 服务器中删除。

同一个pod中可以运行多个容器,我们在创建一个pod时可以通过创建多个容器来实现pod的整个生命周期。Init容器就是做初始化工作的容器。可以有一个或多个,如果多个按照定义的顺序依次执行,只有所有的初始化容器执行完后,主容器才启动。由于一个Pod里的存储卷是共享的,所以Init Container里产生的数据可以被主容器使用到,Init Container可以在多种K8S资源里被使用到,如Deployment、DaemonSet, StatefulSet、Job等,但都是在Pod启动时,在主容器启动前执行,做初始化工作。

pod数量多的架构_云原生

容器钩子

如图在init container 之后开始启动主容器,容器有一个postStart(容器启动钩子)和preStop(容器结束前钩子)都是 Pod 中容器生命周期钩子的一部分,它们用于在容器的特定生命周期事件发生时执行用户定义的操作。

资源对象:kubectl explain pods.spec.containers.lifecycle

1、postStart钩子允许在容器启动后立即执行操作。这个钩子通常用于执行容器启动后需要立即进行的初始化任务或其他操作。例如,可以在postStart钩子中启动应用程序所需的服务,初始化数据库连接或进行其他必要的设置。postStart钩子的执行发生在容器内的应用程序开始执行之前。

2、preStop钩子允许在容器终止之前执行操作。这个钩子通常用于容器在终止之前完成一些清理任务。例如,可以在 preStop 钩子中优雅地关闭应用程序,保存状态或执行其他必要的清理操作。preStop钩子的执行发生在容器内的应用程序开始终止之前。

两种方式支持下面的三种定义动作:
  1、exec命令 在容器内执行一次命令
  2、TCPSocket:在当前容器尝试访问指定的socket
  3、HTTPGet:在当前容器尝试访问某个url请求(下面有实例模仿测试访问本机的API接口)

这些钩子的执行在容器的生命周期中都非常重要,可以在应用程序启动或终止时执行必要的操作,以确保应用程序能够正常运行,并在终止时保持可靠。

容器探针

如图在容器启动运行中livenessProbe和readinessProbe 是用于监测容器健康状态的配置选项,它们都属于 Pod 的生命周期中的一部分。

1、livenessProbe(存活探针)用于确定容器是否正在运行正常。如果容器中的应用程序处于不可恢复的崩溃状态,或者陷入了无限循环等问题,livenessProbe可以检测到这种情况,并尝试重启容器。它在在容器的整个生命周期中运行,包括容器的创建、运行和终止阶段。

查看资源对象:kubectl explain pods.spec.containers.livenessProbe

2、readinessProb(就绪探针)用于确定容器中的程序是否已经就绪准备好提供服务。当容器启动后,可能需要一些时间来准备好处理请求。通过设置readinessProbe可以确保只有在容器准备好提供服务后才将访问请求调度到该容器。eadinessProbe在容器运行阶段中运行,并且只有当容器处于就绪状态时,才会向 Kubernetes 服务发出信号,表示该容器已准备好接收访问请求。

查看资源对象:kubectl explain pods.spec.containers.readinessProbe

这两种探针都可以配置为执行不同类型的检查,例如 HTTP 请求、TCP 检查或执行命令。它们的设置有助于确保应用程序在 Kubernetes 环境中能够以可靠的方式运行,并且能够在应用程序出现问题时自动进行故障恢复。

两种探针方式支持三种探测方式:
   1、exec:在容器执行一次命令如果命令执行的退出代码为0,则认为程序正常,否则不正常。
   2、TCPSocket:将方位一个用户容器的端口,如果能够建立一条连接则认为程序正常。
   3、HTTPGet: 调用容器内web应用的URL,如果返回的状态码是200和399之间则任务程序正常。

探针的属性参数

initialDelaySeconds: 10
  #容器启动后几秒后开始探测
  timeoutSeconds: 5
  #探测超时时间,默认1秒,最新1秒
  periodSeconds: 3
  #执行探测的频率,默认10秒
  successThreshold: 1
  #连续探测成功多少次认定为成功,默认1。在livenessProbe(存活探针)中只能设置为1
  failureThreshold: 2
  #连续探测多少次失败认定为失败,默认3,最新1

简单的yaml文件

apiVersion: v1 
kind: Pod
metadata:
  name: nginx-tomcat
  namespace: default
  labels: 
    web: nginx-tomcat
spec:
  hostname: nginx-tomcat
  nodeName: node02
  initContainers:
  - name: nginx-init
    image: busybox
    imagePullPolicy: IfNotPresent
    command: 
    - sh
    - -c
    - |
      mkdir -p /root/index/;
      echo "Hello nginx" > /root/index/index.html
    volumeMounts:
    - name: init-nginx-test
      mountPath: /root/index
  - name: tomcat-init
    image: busybox
    imagePullPolicy: IfNotPresent
    command: 
    - sh
    - -c
    - |
      mkdir -p /root/webapps/ROOT;
      echo "Hello tomcat" > /root/webapps/ROOT/index.html;
    volumeMounts:
    - name: init-tomcat-test
      mountPath: /root/webapps       
  containers:
  - name: nginx-test
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports: 
      - name: nginx-post
        containerPort: 80
        hostPort: 8080
    lifecycle:
      postStart:
        exec:
          command:
          - sh
          - -c
          - |
            echo "postStart Nginx" >> /usr/share/nginx/html/index.html
      preStop:
        exec:
          command:
          - sh
          - -c
          - |
            /usr/sbin/nginx -s quit
    livenessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 10
      #容器启动后几秒后开始探测
      timeoutSeconds: 5
      #探测超时时间,默认1秒,最新1秒
      periodSeconds: 3
      #执行探测的频率,默认10秒
      successThreshold: 1
      #连续探测成功多少次认定为成功,默认1
      failureThreshold: 2
      #连续探测多少次失败认定为失败,默认3,最新1
    readinessProbe:
      httpGet:
        path: /
        port: 8080
        host: 192.168.0.102
        scheme: HTTP
    volumeMounts:
    - name: init-nginx-test
      mountPath: /usr/share/nginx/html
  - name: tomcat-test
    image: tomcat 
    imagePullPolicy: IfNotPresent
    ports:
      - name: tomcat-post
        containerPort: 8080
        hostPort: 8081  
    lifecycle:
      postStart:
        httpGet:
          host: 192.168.0.102
          path: /
          port: 8080
          scheme: HTTP
      preStop:
        exec:
          command:
          - sh
          - -c
          - |
            /usr/local/tomcat/bin/shutdown.sh 
    livenessProbe:
      httpGet:
        path: /index.html
        port: 8080
      initialDelaySeconds: 10
      timeoutSeconds: 5
      periodSeconds: 3
      successThreshold: 1
      failureThreshold: 2
    readinessProbe:
      httpGet:
        path: /
        port: 8081
        host: 192.168.0.102
        scheme: HTTP
      initialDelaySeconds: 10
      timeoutSeconds: 5
      periodSeconds: 3
      successThreshold: 1
      failureThreshold: 2
    volumeMounts:
    - name: init-tomcat-test
      mountPath: /usr/local/tomcat/webapps    
  
  volumes:
  - name: init-nginx-test
    emptyDir: {}
  - name: init-tomcat-test
    emptyDir: {}     
  restartPolicy: Always

  #yaml定义了2个初始化容器分别初始化nginx和tomcat容器。
  # 定义init container时候busybox无法直接访问容器的文件系统,只能使用临时卷轴挂载。
  #emptyDir 卷是一个临时存储卷,它在 Pod 运行时创建,并且随着 Pod 的删除而删除。
  #container中的restartPolicy只能在ini容器中设置
  #初始化的过程中Init Container 在运行时无法直接访问其他容器内的文件系统或状态。如果需要为同一个 Pod 中的不同容器分别进行初始化,一种方法是为
  # 每个容器定义一个单独的 Init Container,并在这些 Init Container 中执行特定于每个容器的初始化任务。
  # "|"符号在 YAML 中用于表示多行字符串,它告诉解析器接下来的文本是一个多行字符串块。你可以按住 Shift 键并同时按下这个键来输入 "|"符号。
  #在 pod.spec.containers.ports.hostPort字段可以将Pod内端口映射给了宿主机,yaml文件nginx的Pod中将Pod的80端口映射给了宿主机的8080。有人可能有疑问,k8s的容器不是被封装到Pod中了吗?怎么能直接映射到宿主机。k8s对Pod的定义是P是最小的可部署单元,它是一组一个或多个容器的封装,共享网络和存储资源,并在同一主机上运行。Pod不是容器。