一、Pod 生命周期

pod 从开始创建到终止退出的时间范围称为 pod 的生命周期

#主要分为如下几个流程:
1、初始化容器(initContainers)
2、创建主容器(containers)是必须的操作
3、容器启动后钩子
4、启动探测
5、存活性探测
6、就绪性探测
7、容器停止前钩子

初始化容器字段:initContainers

K8s中Pod的生命周期及初始化容器(init)、主容器(containers)及容器启动后钩子、容器删除前钩子,Pod容器健康探测及探测模式_初始化

1.1 pod 生命周期过程中的状态

pod 更多状态描述请移步该链接的“目录六“

#pod 在整个生命周期的过程中总会处于以下几个状态

Pending:创建了pod资源并存入etcd中,但尚未完成调度。

ContainerCreating:Pod 的调度完成,被分配到指定 Node 上。处于容器创建的过程中。通常是在拉取镜像的过程中。

Running:Pod 包含的所有容器都已经成功创建,并且成功运行起来。

Succeeded:Pod中的所有容器都已经成功终止并且不会被重启

Failed:所有容器都已经终止,但至少有一个容器终止失败,也就是说容器返回了非0值的退出状态或已经被系统终止。

Unknown:因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。

1.2 pod 生命周期的重要行为

pod 容器重启策略描述请移步该链接”目录六“

1.在启动任何容器之前,先创建pause基础容器,它初始化Pod的环境并为后续加入的容器提供共享的名称空间。

2.初始化容器(initContainers)
  一个pod可以拥有任意数量的init(初始化)容器,init容器是按照顺序依次执行的,并且仅当最后一个init容器执行完毕后才会去执行主容器。

3.生命周期钩子
  pod允许定义两种类型的生命周期钩子,启动后(post-start)钩子和停止前(pre-stop)钩子
  这些生命周期钩子是基于每个容器来制定的,和init容器不同的是,init容器是应用到整个pod,而这些钩子是针对容器的,是在容器启动后和停止前执行的。

4.容器探测
  是kubectl对容器的健康状态诊断,分为三种:Startupprobe、Livenessprobe(存活性探测), Readinessprobe(就绪性检测)
  Startup  (启动探测)  :判断容器是否正常运行。
  Liveness (存活性探测):判断容器是否处于running状态,根据重启策略决定是重启容器。
  Readiness(就绪性探测):判断容器是否准备就绪并对外提供服务,将容器设置为不可用,不接受service转发的请求。

  三种探针用于pod检测:
  ExecAction:     在容器中执行一个命令,并根据返回的状态码进行诊断,只有返回0为成功
  TCPSocketAction:通过与容器的某TCP端口尝试建立连接
  HTTPGetAction:  通过向容器IP地址的某指定端口的path发起HTTP GET请求。

1.3 Pod 的终止过程

#终止过程主要分为如下几个步骤:
1.用户发出删除pod命令:kubectl delete pods “pod-name” / kubectl delete -f “name.yaml”

2.Pod随着时间的推移更新,在宽限期下(默认情况30秒),Pod被视为“dead”状态

3.将Pod标记为“Terminating”状态

4.与第三步同时运行,监控到 Pod 对象为“Terminating”状态的同时启动 Pod 关闭过程

5.与第三步同时进行,endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除

6.如果 pod 中定义了 preStop 钩子处理程序,则 pod 被标记为“Terminating”状态时以同步的方式启动执行;若宽限期结束后,preStop 仍未执行结束,第二步会重新执行并额外获得一个2秒的小宽限期

7.Pod 内对象的容器收到 TERM 信号

8.宽限期结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号

9.Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作

二、init容器(初始化容器)

初始化容器字段:initContainers
字段详情可通过 kubectl explain pods.spec.initContainers 该命令查看,下图是部分字段详情(参考)
该字段可定义一个或多个初始化容器并依次执行,等最后一个初始化容器执行完毕后,才会执行containers(主容器)

初始化容器可以生成一些数据或产生一些配置文件,可以被主容器使用,(初始化容器与主容器共享同一个数据目录)

K8s中Pod的生命周期及初始化容器(init)、主容器(containers)及容器启动后钩子、容器删除前钩子,Pod容器健康探测及探测模式_初始化_02

2.1 初始化容器与主容器区别

1.初始化容器不支持 Readinessprobe,因为它们必须在Pod就绪之前运行完成
2.每个Init容器必须运行成功,下一个才能够运行

2.1.1 测试初始化容器失败主容器是否创建

案例背景:

编写yaml文件,定义两个初始化容器,如果初始化容器不运行成功,主容器不会运行,需要等所有初始化容器都运行成功,主容器才会运行。

#创建yaml文件
[root@k8s-master ~]# vim pod-01.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: pod-01
  labels:
    a01: aa01
    a02: aa02
spec:
  initContainers:           #定义初始化容器
  - name: lisi              #定义第一个
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command:                #定义命令,解析域名(参考官网)
    - 'sh'
    - '-c'
    - "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"
  - name: zhangsan          #定义第二个
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  containers:
  - name: wangwu
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command:
    - 'sh'
    - '-c'
    - 'echo The app is running! && sleep 3600'

#创建容器
[root@k8s-master ~]# kubectl apply -f pod-01.yaml 
pod/pod-01 created

#创建容器过程(正在初始化),Init:0/2(表示两个初始化容器,目前初始化成功0个)
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-01   0/1     Pending   0          0s
pod-01   0/1     Pending   0          1s
pod-01   0/1     Init:0/2   0          1s
pod-01   0/1     Init:0/2   0          2s
pod-01   0/1     Init:0/2   0          15s

[root@k8s-master ~]# kubectl get pods 
NAME     READY   STATUS     RESTARTS   AGE
pod-01   0/1     Init:0/2   0          46s

#由于创建pod的yaml文件定义的解析命令是个循环,且当前环境无法正确解析,
所以会一直卡在这,初始化容器无法初始化完成,主容器也无法创建

容器创建过程记录如下:

K8s中Pod的生命周期及初始化容器(init)、主容器(containers)及容器启动后钩子、容器删除前钩子,Pod容器健康探测及探测模式_Pod_03

2.1.2 测试初始化容器成功主容器是否创建

基于上面的yaml文件,修改command命令,修改为当前环境可执行成功的命令,使初始化容器成功,测试主容器是否创建。

#删除当前容器
[root@k8s-master ~]# kubectl delete -f pod-01.yaml 
pod "pod-01" deleted

[root@k8s-master ~]# cp pod-01.yaml pod-02.yaml 
[root@k8s-master ~]# vim pod-02.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: pod-02
  labels:
    a02: aa02
spec:
  initContainers:           #定义初始化容器
  - name: lisi              #定义第一个
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command:                #定义命令,等待两秒结束
    - 'sh'
    - '-c'
    - 'sleep 2'
  - name: zhangsan          #定义第二个,等待两秒结束
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'sleep 2']
  containers:
  - name: wangwu
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command:
    - 'sh'
    - '-c'
    - 'echo  running and OK! && sleep 3600'

#创建容器
[root@k8s-master ~]# kubectl apply -f pod-02.yaml 
pod/pod-02 created

#创建过程(两个初始化容器完成之后,主容器创建成功)
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-02   0/1     Pending   0          0s
pod-02   0/1     Pending   0          0s
pod-02   0/1     Init:0/2   0          0s
pod-02   0/1     Init:0/2   0          1s
pod-02   0/1     Init:0/2   0          2s
pod-02   0/1     Init:1/2   0          4s
pod-02   0/1     Init:1/2   0          5s
pod-02   0/1     PodInitializing   0          7s
pod-02   1/1     Running           0          8s

[root@k8s-master ~]# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
pod-02   1/1     Running   0          18s

2.2 初始化容器使用案列

测试初始化容器的实际使用

案例背景:

主容器运行nginx服务,初始化容器用来给主容器生成index.html 文件。

[root@k8s-master ~]# vim pod-03.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-03
  labels:
    a03: aa03
spec:
  initContainers:           #定义初始化容器
  - name: lisi
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command:                #定义命令,下载百度首页存放在/mynginx/index.html文件中
    - 'wget'
    - '-O'
    - "/mynginx/index.html"
    - "https://www.baidu.com"
    volumeMounts:           #指定容器内的卷挂载规则 
    - name: nginx001        #指定物理机的卷名称(使用的是下方volumes指定创建在node节点上的nginx001目录)
      mountPath: /mynginx   #挂载到容器内的路径名称
  containers:               #创建主容器
  - name: my-nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx001        #同样使用下方volumes指定创建在node节点上的nginx001目录
      mountPath: /usr/share/nginx/html #将nginx001挂载到主容器的 /usr/share/nginx/html 路径下
  volumes:                  #定义存储卷
  - name: nginx001          #定义创建的卷名称
    emptyDir: {}            #表示当pod调度到某个node上之后,在该node节点上创建一个nginx001的目录

#相当于是该pod调度在的那个节点上创建一个nginx001目录,初始化容器将该目录挂载到了/mynginx路径下,主容器将nginx001目录挂载到了/usr/share/nginx/html 路径,使它们同步。


#创建pod
[root@k8s-master ~]# kubectl apply -f pod-03.yaml 
pod/pod-03 created

#创建pod过程
[root@k8s-master ~]# kubectl get pods -w 
NAME     READY   STATUS    RESTARTS   AGE
pod-03   0/1     Pending   0          0s
pod-03   0/1     Pending   0          0s
pod-03   0/1     Init:0/1   0          0s
pod-03   0/1     Init:0/1   0          1s
pod-03   0/1     PodInitializing   0          2s
pod-03   1/1     Running           0          88s

#验证pod状态,确认调度在哪个node上
root@k8s-master ~]# kubectl get pods -owide
NAME     READY   STATUS    RESTARTS   AGE     IP             NODE          NOMINATED NODE   READINESS GATES
pod-03   1/1     Running   0          2m39s   10.244.126.3   k8s-worker2   <none>           <none>

#验证请求node节点如下图一:
[root@k8s-master ~]# curl 10.244.126.3

#进入pod主容器内验证html 如下图二:
[root@k8s-master ~]# kubectl exec -it pod-03 -- /bin/bash
Defaulted container "my-nginx" out of: my-nginx, lisi (init)
root@pod-03:/# ls /usr/share/nginx/html/
index.html
root@pod-03:/#

K8s中Pod的生命周期及初始化容器(init)、主容器(containers)及容器启动后钩子、容器删除前钩子,Pod容器健康探测及探测模式_nginx_04

K8s中Pod的生命周期及初始化容器(init)、主容器(containers)及容器启动后钩子、容器删除前钩子,Pod容器健康探测及探测模式_初始化_05

三、主容器

容器钩子

初始化容器启动之后,开始启动主容器,在主容器启动之后有一个post start hook(容器启动后钩子)和pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以把它放两个钩子,这个钩子就表示用户可以用它来钩住一些命令,非必须选项

 

postStart:该钩子在容器被创建后立刻执行,如果该钩子对应的探测执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。

 

preStop:该钩子在容器被删除前执行,主要用于释放资源和优雅关闭程序

3.1 容器钩子:postStart和preStop

postStart:主容器创建之后立刻执行,用于资源部署、环境准备等。(定义容器启动后执行的命令)

preStop:在容器被终止前执行,用于优雅关闭应用程序、通知其他系统等。(定义容器关闭前执行的命令)


字段介绍如下:kubectl explain pods.spec.containers.lifecycle

K8s中Pod的生命周期及初始化容器(init)、主容器(containers)及容器启动后钩子、容器删除前钩子,Pod容器健康探测及探测模式_初始化_06

#定义创建容器时:
#1.使用postStart定义容器启动后创建/usr/share/nginx/html/test.html文件并写入内容
#2.使用preStop定义容器删除前,执行nginx -s stop 停止容器后并删除pod

#创建
[root@k8s-master ~]# vim pod-04.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: pod-04
  labels:
    a04: aa04
spec:
  containers:               #创建主容器
  - name: my-nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    lifecycle:
      postStart:
        exec:
          command:
          - '/bin/sh'
          - '-c'
          - "echo 'How are you' > /usr/share/nginx/html/test.html"
      preStop:
        exec:
          command: ['/bin/sh','-c','ngninx -s stop']

[root@k8s-master ~]# kubectl apply -f pod-04.yaml 
pod/pod-04 created

[root@k8s-master ~]# kubectl get pods 
NAME     READY   STATUS    RESTARTS   AGE
pod-04   1/1     Running   0          7s

#进入到容器里面确认yaml文件中指定的路径有 test.html文件,且内容是 “How are you”
[root@k8s-master ~]# kubectl exec -it  pod-04 -- /bin/bash
root@pod-04:/# ls /usr/share/nginx/html/
50x.html  index.html  test.html
root@pod-04:/# cat /usr/share/nginx/html/test.html 
How are you

#删除容器
[root@k8s-master ~]# kubectl delete -f pod-04.yaml 
pod "pod-04" deleted

#由于测试环境下,删除pod时,容器没有业务使用,所以删除的非常快,无法看到停止过程,删除效果如下
#可以通过kubectl get event -w 查看集群的事件信息
[root@k8s-master ~]# kubectl get event -w
LAST SEEN   TYPE      REASON              OBJECT       MESSAGE
#创建过程
0s          Normal    Scheduled           pod/pod-04   Successfully assigned default/pod-04 to k8s-worker2
0s          Normal    Pulled              pod/pod-04   Container image "nginx" already present on machine
0s          Normal    Created             pod/pod-04   Created container my-nginx
0s          Normal    Started             pod/pod-04   Started container my-nginx
#停止容器并删除过程
0s          Normal    Killing             pod/pod-04   Stopping container my-nginx

四、Pod容器健康探测

4.1 容器探测的方法

k8s 提供了三种来实现容器探测的方法,分别是:

1、startupProbe:(启动探测)探测容器中的应用是否已经启动。如果提供了启动探测(startup probe),则禁用所有其他探测,直到它成功为止,才会进行下面配置的探测。如果启动探测失败,kubelet 将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为成功(Success)。

     

2、livenessprobe:(存活性探测)用指定的方式(exec、tcp、http)检测pod中的容器是否正常运行,如果检测失败,则认为容器不健康,那么Kubelet将根据Pod中设置的 restartPolicy策略来判断Pod 是否要进行重启操作,如果容器配置中没有配置 livenessProbe,Kubelet 将认为存活探针探测一直为success(成功)状态。

 

3、readnessprobe:(就绪性探测)用于检测容器中的应用是否可以接受请求,当探测成功后才使Pod对外提供网络访问,将容器标记为就绪状态,可以加到pod前端负载,如果探测失败,则将容器标记为未就绪状态,会把pod从前端负载移除。


可以自定义在pod启动时是否执行这些检测,如果不设置,则检测结果均默认为通过,如果设置,则顺序为startupProbe>readinessProbe和livenessProbe,readinessProbe和livenessProbe是并发关系

4.1.1 探测字段支持的探针

LivenessProbe和ReadinessProbe、startupprobe探测都支持下面三种探针:

1、exec:在容器中执行指定的命令,如果执行成功,退出码为 0 则探测成功。

2、TCPSocket:(定义字段)通过容器的 IP 地址和端口号执行 TCP 检 查,如果能够建立 TCP 连接,则表明容器健康。

3、HTTPGet:通过容器的IP地址、端口号及路径调用 HTTP Get方法,如果响应的状态码大于等于200且小于400,则认为容器健康


探针探测结果有以下值:

1、Success:   表示通过检测。

2、Failure:    表示未通过检测。

3、Unknown:表示检测没有正常进行。

4.1.2 Pod探针相关的属性

探针(Probe)有许多可选字段,可以用来更加精确的控制Liveness和Readiness两种探针的行为

initialDelaySeconds:容器启动后要等待多少秒后探针开始工作,单位“秒”,默认是 0 秒,最小值是

periodSeconds:    执行探测的时间间隔(单位是秒),默认为 10s,单位“秒”,最小值是1

timeoutSeconds:  探针执行检测请求后,等待响应的超时时间,默认为1,单位“秒”。

successThreshold: 连续探测几次成功,才认为探测成功,默认为 1,在 Liveness 探针中必须为1,最小值为1。

failureThreshold:  探测失败的重试次数,重试一定次数后将认为失败,在 readiness 探针中,Pod会被标记为未就绪,默认为 3,最小值为1 

4.1.3 Liveness和Readiness两种探针的区别

 两种探针区别:

ReadinessProbe 和 livenessProbe 可以使用相同探测方式,只是对 Pod 的处置方式不同:

readinessProbe 当检测失败后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删除。

livenessProbe 当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施。

4.2 启动探测 startupProbe

4.2.1 exec 模式

探测成功及探测失败

#探测成功 演示
#创建一个探测成功的yaml文件
[root@k8s-master ~]# vim pod-01.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-01
  labels:
    a01: aa01
spec:
  containers:
  - name: mytomcat
    image: tomcat
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:             #定义探测
      exec:                   #定义探测模式(启动容器后执行某个命令)
        command:
        - '/bin/sh'
        - '-c'
        - 'ps -ef | grep tomcat'
      initialDelaySeconds: 20 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 20       #定义执行探测的时间间隔(单位秒)
      successThreshold: 1     #定义成功多少次算是成功
      failureThreshold: 3     #定义失败多少次才算失败
      timeoutSeconds: 10      #定义执行探测请求后,等待的超时时间(单位秒)
      

#创建
[root@k8s-master ~]# kubectl apply -f pod-01.yaml 
pod/pod-01 created

[root@k8s-master ~]# kubectl get pods 
NAME     READY   STATUS    RESTARTS   AGE
pod-01   1/1     Running   0          79s

#创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-01   0/1     Pending   0          0s
pod-01   0/1     Pending   0          0s
pod-01   0/1     ContainerCreating   0          0s
pod-01   0/1     ContainerCreating   0          1s
pod-01   0/1     Running             0          2s
pod-01   0/1     Running             0          40s   #启动容器20秒后探测+20秒的探测间隔
pod-01   1/1     Running             0          40s   #探测成功之后启动成功 (1/1)


#探测失败 演示
#删除pod
[root@k8s-master ~]# kubectl delete -f pod-01.yaml 
pod "pod-01" deleted

#基于上方yaml文件修改command 命令,修改一个错误的命令
[root@k8s-master ~]# cat pod-01.yaml | grep -A 3 command
        command:
        - '/bin/sh'
        - '-c'
        - 'who are you'

#创建
[root@k8s-master ~]# kubectl apply -f pod-01.yaml 
pod/pod-01 created

[root@k8s-master ~]# kubectl get pods
NAME     READY   STATUS    RESTARTS      AGE
pod-01   0/1     Running   2 (12s ago)   2m13s

#创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-01   0/1     Pending   0          0s
pod-01   0/1     Pending   0          0s
pod-01   0/1     ContainerCreating   0          0s
pod-01   0/1     ContainerCreating   0          1s
pod-01   0/1     Running             0          1s
pod-01   0/1     Running             1 (1s ago)   62s   #探测失败重启第一次
pod-01   0/1     Running             2 (1s ago)   2m2s  #两分钟后重启第二次

#定义的是容器启动后20秒探测、间隔是二十秒、 探测三次算失败, 所以 20s*3=60s 发生重启

4.2.2 tcpSocket 模式

#探测成功 演示
#创建一个探测成功的yaml文件
[root@k8s-master ~]# vim pod-02.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-02
  labels:
    a02: aa02
spec:
  containers:
  - name: mytomcat
    image: tomcat
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:             #定义探测
      tcpSocket:              #定义探测模式(探测tomcat的端口是否存在)
        port: 8080
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 10       #定义执行探测的时间间隔(单位秒)
      successThreshold: 1     #定义成功多少次算是成功
      failureThreshold: 3     #定义失败多少次才算失败
      timeoutSeconds: 5       #定义执行探测请求后,等待的超时时间(单位秒)
      

#创建
[root@k8s-master ~]# kubectl apply -f pod-02.yaml 
pod/pod-02 created

[root@k8s-master ~]# kubectl get pods 
NAME     READY   STATUS    RESTARTS   AGE
pod-02   1/1     Running   0          62s

#创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-02   0/1     Pending   0          0s
pod-02   0/1     Pending   0          0s
pod-02   0/1     ContainerCreating   0          0s
pod-02   0/1     ContainerCreating   0          1s
pod-02   0/1     Running             0          1s
pod-02   0/1     Running             0          11s
pod-02   1/1     Running             0          11s
pod-02   1/1     Running             0          34s


ps:8080端口存在 pod容器正常启动,如果探测的是其他的不存在的端口,那么就会同上方测试exec模式时一样,启动失败且会一直重启。

4.2.3 httpGet 模式

#探测成功 演示
#创建一个探测成功的yaml文件
[root@k8s-master ~]# vim pod-03.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-03
  labels:
    a03: aa03
spec:
  containers:
  - name: mytomcat
    image: tomcat:v1          #这里最好准备一个已经部署应用的tomcat镜像,否则探测请求时会失败
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:             #定义探测
      httpGet:                #定义探测模式(请求8080端口)
        path: /               #定义根路径(相当于请求localhost:8080)
        port: 8080
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 10       #定义执行探测的时间间隔(单位秒)
      successThreshold: 1     #定义成功多少次算是成功
      failureThreshold: 3     #定义失败多少次才算失败
      timeoutSeconds: 5       #定义执行探测请求后,等待的超时时间(单位秒)
      

#创建
[root@k8s-master ~]# kubectl apply -f pod-03.yaml 
pod/pod-03 created

[root@k8s-master ~]# kubectl get pods 
NAME     READY   STATUS    RESTARTS   AGE
pod-03   1/1     Running   0          2m55s

#创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-03   0/1     Pending   0          0s
pod-03   0/1     Pending   0          0s
pod-03   0/1     ContainerCreating   0          0s
pod-03   0/1     ContainerCreating   0          0s
pod-03   0/1     Running             0          1s
pod-03   0/1     Running             0          18s
pod-03   0/1     Running             0          21s
pod-03   1/1     Running             0          21s


#如果请求时,使用的tomcat镜像没有部署应用或者应用没有部署在指定的根目录(/)中,也会探测失败,
#最好准备一个已部署应用的tomcat镜像,或者填写正确的路径。

4.3 存活性探测 livenessProbe

4.3.1 exec 模式

以容器内某个文件或进程等为介质,探测该介质是否存在,存在及容器正常运行,不存在的话重启pod

(根据重启策略,默认不配置重启策略就会重启)

[root@k8s-master ~]# vim pod-01.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: pod-01
  labels:
    a01: aa01
spec:
  containers:
  - name: mycentos
    image: centos
    imagePullPolicy: IfNotPresent
    command:
    - /bin/bash
    - -c
    - touch /tmp/test; sleep 20; rm -rf /tmp/test; sleep 200
    livenessProbe:            #定义探测
      exec:                   #定义探测模式(查看文件是否存在)
        command:
          - cat 
          - /tmp/test
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 5        #定义执行探测的时间间隔(单位秒)
      

#创建
[root@k8s-master ~]# kubectl apply -f pod-01.yaml 
pod/pod-01 created

NAME     READY   STATUS    RESTARTS      AGE
pod-01   1/1     Running   1 (55s ago)   51s

#创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-01   0/1     Pending   0          0s
pod-01   0/1     Pending   0          0s
pod-01   0/1     ContainerCreating   0          0s
pod-01   0/1     ContainerCreating   0          1s
pod-01   1/1     Running             0          2s
pod-01   1/1     Running             1 (1s ago)   67s
pod-01   1/1     Running             2 (1s ago)   2m12s

#定义了创建容器后创建文件,十秒后探测后发现有该文件就是正常的,
#还定义了20秒后删除该文件,探测后发现没有该文件,没有设置探测失败次数,默认为3次,探测失败三次之后重启pod。

4.3.2 httpGet 模式

[root@k8s-master ~]# vim pod-02.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-02
  labels:
    a02: aa02
spec:
  containers:
  - name: hellowork
    image: sprintboot:v1
    imagePullPolicy: IfNotPresent
    livenessProbe:            #定义探测
      httpGet:                #通过该sprintboot镜像启动容器,访问节点ip:8081端口的/actuator/health接口路径,返回状态码如果在httpget探针
默认的大于等于200小于400,则正常
        scheme: HTTP
        path: /actuator/health
        port: 8081
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 5        #定义执行探测的时间间隔(单位秒)
      timeoutSeconds: 6


#相当与请求的是容器本身IP(localhost:8081/actuator/health),如果能正常请求,且返回码在httpGet探针默认规则范围内,
#那么就是正常,如果某天端口down,或者其它原因导致请求失败,那么则按照容器重启策略进行重启重启及Pod。

#创建
[root@k8s-master ~]# kubectl apply -f pod-02.yaml 
pod/pod-02 created

[root@k8s-master ~]# kubectl get pods -owide
NAME     READY   STATUS    RESTARTS   AGE   IP             NODE          NOMINATED NODE   READINESS GATES
pod-02   1/1     Running   0          12s   10.244.126.1   k8s-worker2   <none>           <none>

#创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-02   0/1     Pending   0          0s
pod-02   0/1     Pending   0          0s
pod-02   0/1     ContainerCreating   0          0s
pod-02   0/1     ContainerCreating   0          1s
pod-02   1/1     Running             0          2s

#请求访问端口接口测试,显示状态为 “UP”
[root@k8s-master ~]# curl 10.244.126.1:8081/actuator/health
{"status":"UP"}[root@k8s-master ~]#

4.3.3 tcpSocket 模式

[root@k8s-master ~]# vim pod-03.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-03
  labels:
    a03: aa03
spec:
  containers:
  - name: mynginx
    image: nginx
    imagePullPolicy: IfNotPresent
    livenessProbe:            #定义探测
      tcpSocket:              #探测 80端口是否存在
        port: 80
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 5        #定义执行探测的时间间隔(单位秒)
      timeoutSeconds: 6


#创建
[root@k8s-master ~]# kubectl apply -f pod-03.yaml 
pod/pod-03 created

[root@k8s-master ~]# kubectl get pods -owide
NAME     READY   STATUS    RESTARTS   AGE   IP             NODE          NOMINATED NODE   READINESS GATES
pod-03   1/1     Running   0          84s   10.244.126.2   k8s-worker2   <none>           <none>

#由于使用的是存活性探测,只要nginx服务正常起来,80端口正常,容器就正常,
#如果进入到容器中将nginx服务停掉,那么就会根据容器重启策略进行重启重启及Pod。

4.4 就绪性探测 readnessprobe

[root@k8s-master ~]# vim pod-02.yaml

apiVersion: v1                #创建第一个pod
kind: Service                 #通过service指定selector关联具有目标标签的pod(下方定义了selector)
metadata:
  name: spring-01
  labels:
    a01: spring-001
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 32678           #定义映射物理机端口,(映射到node节点的端口)
  - name: spring
    port: 8081
    targetPort: 8081
    nodePort: 32679
  selector:                   #定义关联下方pod的标签
    a01: aa01                 #下方pod的标签 a01: aa01
---
apiVersion: v1                #创建第二个pod用于第一个pod关联
kind: Pod
metadata:
  name: pod-01
  labels:
    a01: aa01
spec:
  containers:
  - name: hellowork
    image: sprintboot:v1
    imagePullPolicy: IfNotPresent
    ports:                    #定义服务端口8080,和管理端口8081(8081开发镜像时提供的)
    - name: server
      containerPort: 8080
    - name: spring
      containerPort: 8081
    readinessProbe:           #定义就绪性探测
      httpGet:
        scheme: HTTP
        path: /actuator/health
        port: 8081
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 5        #定义执行探测的时间间隔(单位秒)
      timeoutSeconds: 6       #定义探测超时等待时间(单位秒)
      
      
#创建 完成两个pod
[root@k8s-master ~]# kubectl apply -f pod-02.yaml 
service/spring-01 created
pod/pod-01 created

[root@k8s-master ~]# kubectl get pods -owide
NAME     READY   STATUS    RESTARTS   AGE   IP             NODE          NOMINATED NODE   READINESS GATES
pod-01   0/1     Running   0          10s   10.244.126.9   k8s-worker2   <none>           <none>

#查看创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-01   0/1     Pending   0          0s
pod-01   0/1     Pending   0          0s
pod-01   0/1     ContainerCreating   0          0s
pod-01   0/1     ContainerCreating   0          1s
pod-01   0/1     Running             0          1s    #虽然running但是并没有起来
pod-01   1/1     Running             0          15s   #进行探测完成,确认容器及服务正常之后才running(1/1)

#查看service 详细信息绑定
[root@k8s-master ~]# kubectl describe svc spring-01
Name:                     spring-01
Namespace:                default
Labels:                   a01=spring-001
Annotations:              <none>
Selector:                 a01=aa01
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.125.1
IPs:                      10.100.125.1
Port:                     server  8080/TCP
TargetPort:               8080/TCP
NodePort:                 server  32678/TCP
Endpoints:                10.244.126.9:8080     #已经成功关联绑定了pod所在节点的ip及端口
Port:                     spring  8081/TCP
TargetPort:               8081/TCP
NodePort:                 spring  32679/TCP
Endpoints:                10.244.126.9:8081     #已经成功关联绑定了pod所在节点的ip及端口
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

4.5 配合使用ReadinessProbe + LivenessProbe + startupProbe

[root@k8s-master ~]# vim pod-04.yaml


apiVersion: v1                #创建第一个pod
kind: Service                 #通过service指定selector关联具有目标标签的pod(下方定义了selector)
metadata:
  name: spring-04
  labels:
    a01: spring-004
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 32678           #定义映射物理机端口,(映射到node节点的端口)
  - name: spring
    port: 8081
    targetPort: 8081
    nodePort: 32679
  selector:                   #定义关联下方pod的标签
    a01: aa04                 #下方pod的标签 a01: aa01
---
apiVersion: v1                #创建第二个pod用于第一个pod关联
kind: Pod
metadata:
  name: pod-04
  labels:
    a01: aa04
spec:
  containers:
  - name: hellowork
    image: sprintboot:v1
    imagePullPolicy: IfNotPresent
    Ports:                    #定义服务端口8080,和管理端口8081(8081开发镜像时提供的)
    - name: server
      containerPort: 8080
    - name: spring
      containerPort: 8081
    readinessProbe:           #定义就绪性探测 (探测该端口通过该端口探测容器内的程序是否已就绪是否可以正常访问,如不能则失败,根据默认规则重启)
      httpGet:
        scheme: HTTP
        path: /actuator/health
        port: 8081
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 5        #定义执行探测的时间间隔(单位秒)
      timeoutSeconds: 6       #定义探测超时等待时间(单位秒)
    livenessProbe:            #定义存活性探测 (探测接口,如不能返回正常的状态码,则根据容器重启策略重启容器)
      httpGet:
        scheme: HTTP
        path: /actuator/health
        port: 8081
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 5        #定义执行探测的时间间隔(单位秒)
      timeoutSeconds: 6       #定义探测超时等待时间(单位秒)
    startupProbe:             #定义启动探测  (三种探测方式书写顺序无所谓,默认先执行启动探测,启动探测执行成功之后才会执行另外两个,另外两个是并行执行的)
      httpGet:
        scheme: HTTP
        path: /actuator/health
        port: 8081
      initialDelaySeconds: 10 #定义容器启动后多久开始探测(单位秒)
      periodSeconds: 5        #定义执行探测的时间间隔(单位秒)
      timeoutSeconds: 6       #定义探测超时等待时间(单位秒)


#创建
[root@k8s-master ~]# kubectl apply -f pod-04.yaml 
service/spring-04 created
pod/pod-04 created

[root@k8s-master ~]# kubectl get pods -owide
NAME     READY   STATUS    RESTARTS   AGE     IP              NODE          NOMINATED NODE   READINESS GATES
pod-04   1/1     Running   0          4m56s   10.244.126.10   k8s-worker2   <none>           <none>

[root@k8s-master ~]# kubectl get svc  spring-04
NAME        TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
spring-04   NodePort   10.107.77.127   <none>        8080:32678/TCP,8081:32679/TCP   5m26s

#创建过程
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-04   0/1     Pending   0          0s
pod-04   0/1     Pending   0          0s
pod-04   0/1     ContainerCreating   0          0s
pod-04   0/1     ContainerCreating   0          0s
pod-04   0/1     Running             0          1s    #正在做启动探测
pod-04   0/1     Running             0          16s
pod-04   1/1     Running             0          16s   #启动探测成功,探测存活和就绪探测,都成功的话则正常,不成功则重启

#查看service绑定信息
[root@k8s-master ~]# kubectl describe svc spring-04
Name:                     spring-04
Namespace:                default
Labels:                   a01=spring-004
Annotations:              <none>
Selector:                 a01=aa04
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.107.77.127
IPs:                      10.107.77.127
Port:                     server  8080/TCP
TargetPort:               8080/TCP
NodePort:                 server  32678/TCP
Endpoints:                10.244.126.10:8080
Port:                     spring  8081/TCP
TargetPort:               8081/TCP
NodePort:                 spring  32679/TCP
Endpoints:                10.244.126.10:8081
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

#进入到容器中停掉服务
[root@k8s-master ~]# kubectl exec -it pod-04 -- /bin/sh
/ # kill 1                               #默认容器内的进程pid 是1  kill 1 停掉
/ # command terminated with exit code 137

#再次查看创建过程,发生了重启
[root@k8s-master ~]# kubectl get pods -w
NAME     READY   STATUS    RESTARTS   AGE
pod-04   0/1     Pending   0          0s
pod-04   0/1     Pending   0          0s
pod-04   0/1     ContainerCreating   0          0s
pod-04   0/1     ContainerCreating   0          0s
pod-04   0/1     Running             0          1s
pod-04   0/1     Running             0          16s
pod-04   1/1     Running             0          16s
pod-04   0/1     Error               0          8m24s     #停掉之后探测失败 容器状态error
pod-04   0/1     Running             1 (2s ago)   8m25s   #发生重启
pod-04   0/1     Running             1 (12s ago)   8m35s  #重启后重新探测
pod-04   1/1     Running             1 (13s ago)   8m36s  #停掉的进程重启后自动起来可以访问了,容器状态running(1/1)