Kubernetes(k8s)的Pod资源清单生命周期Lifecycle相关属性详细讲解

目录

  • 1. 概述
  • 2. Pod的创建和删除过程
    • 2.1 Pod的创建过程
    • 2.2 Pod的删除过程
  • 3. init container初始化容器
  • 4. 钩子函数
  • 5. 容器探测
    • 5.1 exec方式
    • 5.2 tcpSocket方式
    • 5.3 httpGet方式
  • 6. 重启策略

1. 概述

Pod对象从创建到删除的这段时间范围称为Pod的生命周期,主要包含下面的过程:

  1. Pod创建
  2. 运行初始化容器(init container)
  3. 运行主容器(main container)
    1. 容器启动后钩子(post start)
    2. 容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
    3. 容器删除前钩子(pre stop)
  4. Pod删除

Kubernetes(k8s)的Pod资源清单生命周期Lifecycle相关属性详细讲解_第1张图片

在整个生命周期中,Pod会出现5种状态:

  • 挂起(Pending):API Server已经创建了Pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
  • 运行中(Running):Pod已经被调度到某节点,并且所有容器都已经被kubelet创建完成
  • 成功(Succeeded):Pod中的所有容器都已经成功删除并且不会被重启
  • 失败(Failed):所有容器都已经删除,但至少有一个容器删除失败,即容器返回了非0值的退出状态
  • 未知(Unknown):API Server无法正常获取到Pod对象的状态信息,通常由于网络通信失败所导致

2. Pod的创建和删除过程

2.1 Pod的创建过程

Kubernetes(k8s)的Pod资源清单生命周期Lifecycle相关属性详细讲解_第2张图片

  1. 用户通过kubectl或其他的API客户端提交需要创建的Pod信息给API Server
  2. API Server开始生成Pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端
  3. API Server开始反映etcd中的Pod对象的变化,其它组件使用watch机制来跟踪检查API Server上的变动
  4. Scheduler发现有新的Pod对象要创建,开始为Pod分配主机并将结果信息更新至API Server
  5. Node节点上的kubelet发现有Pod调度过来,尝试调度Docker启动容器,并将结果返回至API Server
  6. API Server将接收到的Pod状态信息存入到etcd中

2.2 Pod的删除过程

  1. 用户向API Server发送删除Pod对象的命令
  2. 将Pod标记为terminating状态
  3. kubelet在监控到Pod对象转为terminating状态的同时启动Pod关闭过程
  4. 端点控制器监控到Pod对象的关闭行为时,将其从所有匹配到此端点的service资源的端点列表中移除
  5. 如果当前Pod对象定义了preStop钩子处理器,则在其标记为terminating后会以同步的方式启动执行
  6. Pod对象中的容器进程收到停止信号
  7. 宽限期结束后(默认30s),如果Pod中还存在运行的进程,那么Pod对象会收到立即删除的信号
  8. kubectl请求API Server将此Pod资源的宽限期设置为0从而完成删除操作,此时Pod对于用户已经不可用

3. init container初始化容器

初始化容器是在Pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:

  • 初始化容器必须运行完成直至结束,如果某个初始化容器运行失败,那么kubernetes需要重启它直至成功完成
  • 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行

初始化容器有很多的应用场景,下面列出的是最常见的几个:

  • 提供主容器镜像中不具备的工具程序或自定义代码
  • 初始化容器要先于应用容器串行启动并运行完成,可用于满足应用容器启动的先决要求

接下来做一个案例,模拟下面这个需求:

  • 假设主容器运行Nginx,但是要求在运行Nginx之前要能够连接上MySQL和Redis所在的服务器
  • 为了简化测试,事先规定好MySQL和Redis所在的IP地址分别为192.168.23.188和192.168.23.189(188的IP目前能ping通,189的IP目前不能ping通)

新建pod-lifecycle.yaml,内容如下。然后进行pod创建


    user: bulut
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
  initContainers:
    - name: init-mysql
      image: busybox
      command: ['/bin/sh', '-c', 'until ping 192.168.23.188 -c 1; do echo waiting for mysql; sleep 3; done;']
    - name: init-redis
      image: busybox
      command: ['/bin/sh', '-c', 'until ping 192.168.23.189 -c 1; do echo waiting for redis; sleep 3; done;']
[root@k8s-master ~]# 
[root@k8s-master ~]# kubectl apply -f pod-lifecycle.yaml 
pod/pod-lifecycle created
[root@k8s-master ~]#

查看pod启动状态。只有第一个init成功,卡在第二个init container了

[root@k8s-master ~]# kubectl get pod -n dev
NAME            READY   STATUS     RESTARTS   AGE
pod-lifecycle   0/1     Init:1/2   0          28s
[root@k8s-master ~]# 

4. 钩子函数

kubernetes在主容器启动之后和删除之前提供了两个钩子函数:

  • post start:容器创建之后执行,如果失败会重启容器
  • pre stop:容器删除之前执行,执行完成之后容器将成功删除,在其完成之前会阻塞删除容器的操作

钩子处理器支持三种定义方式:

  1. exec命令:在容器内执行一次命令。语法如下:
  lifecycle:
    postStart: 
      exec:
        command:
             - cat
             - /tmp/test.txt
  1. tcpSocket:在当前容器尝试访问指定的socket
   lifecycle:
     postStart:
       tcpSocket:
         port: 8080
  1. httpGet:在当前容器中向某url发起HTTP请求
   lifecycle:
     postStart:
       httpGet:
         path: /                   # URI地址
         port: 80                  # 端口号
         host: 192.168.23.161     # 主机地址  
         scheme: HTTP              # 支持的协议,http或者https

新建pod-lifecycle.yaml,内容如下。然后进行pod创建

[root@k8s-master ~]# cat pod-lifecycle.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-lifecycle
  namespace: dev
  labels:
    user: bulut
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
      lifecycle:
        postStart:
          exec:                  # 修改Nginx的首页内容
            command: ["/bin/sh", "-c", "echo postStart > /usr/share/nginx/html/index.html"]
        preStop:
          exec:                  # 停止Nginx的服务
            command: ["/usr/sbin/nginx", "-s", "quit"]
[root@k8s-master ~]# 
[root@k8s-master ~]# kubectl apply -f pod-lifecycle.yaml 
pod/pod-lifecycle created
[root@k8s-master ~]# 

访问nginx服务。可以看到postStat起作用了

[root@k8s-master ~]# kubectl get pod -n dev -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
pod-lifecycle   1/1     Running   0          64s   10.244.169.150   k8s-node2              
[root@k8s-master ~]# 
[root@k8s-master ~]# curl 10.244.169.150:80
postStart
[root@k8s-master ~]# 

5. 容器探测

容器探测用于检测容器中的应用实例是否正常工作,kubernetes提供了三种探针来实现容器探测,本文主要讲解liveness probes和readiness probes

  • liveness probes:存活性探测,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器
  • readiness probes:就绪性探测,用于检测应用实例是否可以接受请求,如果不能,k8s不会转发流量到该应用实例
  • startupProbe探针,用于判断容器内应用程序是否已经启动,一旦成功将不再进行探测。如果配置了startupProbe探针,就会先禁止其他的探针,直到startupProbe探针成功为止

liveness probes和readiness probes均支持三种探测方式。语法如下,readinessProbe和livenessProbe的语法一样

  1. exec命令:在容器内执行一次命令。如果命令执行的退出码为0,则认为程序正常,否则不正常
livenessProbe:
  exec:
    command:
      - cat
      -	/tmp/test.txt
  1. tcpSocket:在当前容器尝试访问指定的socket。如果能够建立连接,则认为程序正常,否则不正常
livenessProbe:
  tcpSocket:
    port: 8080
  1. httpGet:在当前容器中向某url发起HTTP请求。如果返回的状态码在200和399之间,则认为程序正常,否则不正常
livenessProbe:
  httpGet:
    path: /                         # URI地址
    port: 80                        # 端口号
    host: 192.168.23.161            # 主机地址
    scheme: HTTP                    # 支持的协议,http或者https

通过命令kubectl explain pod.spec.containers.livenessProbe查看其它属性,整理如下:

exec 
tcpSocket  
httpGet
initialDelaySeconds       # 容器启动后等待多少秒执行第一次探测
timeoutSeconds            # 探测超时时间。默认1秒,最小1秒
periodSeconds             # 执行探测的频率。默认是10秒,最小1秒
failureThreshold          # 连续探测失败多少次才被认定为失败。默认是3。最小值是1
successThreshold          # 连续探测成功多少次才被认定为成功。默认是1

5.1 exec方式

新建pod-lifecycle.yaml,内容如下:

[root@k8s-master ~]# cat pod-lifecycle.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-lifecycle
  namespace: dev
  labels:
    user: bulut
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
      livenessProbe:
        exec:
          command: ["ls", "/tmp"] 
[root@k8s-master ~]# 

5.2 tcpSocket方式

新建pod-lifecycle.yaml,内容如下:

[root@k8s-master ~]# cat pod-lifecycle.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-lifecycle
  namespace: dev
  labels:
    user: bulut
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
      livenessProbe:
        tcpSocket:
          port: 80
[root@k8s-master ~]# 

5.3 httpGet方式

新建pod-lifecycle.yaml,内容如下:

[root@k8s-master ~]# cat pod-lifecycle.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-lifecycle
  namespace: dev
  labels:
    user: bulut
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
      livenessProbe:
        httpGet:        # 其实就是访问http://127.0.0.1:80/
          port: 80
          scheme: HTTP
          path: /
          host: 127.0.0.0
[root@k8s-master ~]# 

6. 重启策略

在容器探测中,一旦容器探测出现了问题,kubernetes就会对容器所在的Pod进行重启,其实这是由Pod的默认重启策略决定的。Pod的重启策略有3种:

  • Always:容器失效时,自动重启该容器,默认值
  • OnFailure:容器终止运行且退出码不为0时重启
  • Never:不论状态如何,都不重启该容器

重启策略是针对Pod设定的。首次需要重启的容器,将在其需要的时候立即进行重启,随后再次重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长依次为10s、20s、40s、80s、160s和300s,300s是最大的延迟时长

新建pod-lifecycle.yaml,内容如下:

[root@k8s-master ~]# cat pod-lifecycle.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-lifecycle
  namespace: dev
  labels:
    user: bulut
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
  restartPolicy: Never
[root@k8s-master ~]#

你可能感兴趣的:(Kubernetes,kubernetes,k8s,生命周期,钩子函数,容器探测)