深入Pod- 探针_健康检查、Pod生命周期

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 深入Pod- 探针_健康检查、Pod生命周期

一、深入Pod

k8s 的资源清单.md

1.创建Pod -配置文件详解

1.1基本配置

创建pod-base.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
  labels:
    type: app
    version: 1.0.0
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
    imagePullPolicy: IfNotPresent
    command:
    - nginx
    - -g
    - 'daemon off;'
    workingDir: /usr/share/nginx/html
    ports:
    - name: http
      containerPort: 80
      hostPort: 80
      protocol: TCP
    env:
    - name: JVM_OPTS
      value: 'Xms128m -Xmx128m'
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 200m
        memory: 256Mi
  restartPolicy: OnFailure

apiVersion: v1     #必选,文档版本号,例如v1
kind: Pod         #必选,资源对象类型,例如 Pod,也可以配置为Deployment
metadata:         #必选,Pod相关的元数据,用来描述Pod的数据
  name: nginx-demo    #必选,Pod名称 
  labels:           #定义Pod的标签
    type: app  #自定义lable标签,名字为type 值为app
    version: 1.0.0    #自定义label标签  描述Pod版本号   
  namespace: dev  #Pod所属的命名空间,默认为"default"             
spec:  #必选,期望Pod按照这个里面的描述进行创建
  containers:  #必选,Pod中容器列表 对于Pod中的容器描述 
  - name: nginx   #必选,容器名称
    image: nginx:1.7.9  #必选,容器的镜像名称
    imagePullPolicy: IfNotPresent #获取镜像的策略  指定如果本地有就用本地的,如果没有就拉取远程的
    command:    #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    - nginx
    - -g
    - 'daemon off;' #nginx -g 'daemon off'
    workingDir: /usr/share/nginx/html  #容器的工作目录
    ports: #需要暴露的端口库号列表
    - name: http        #端口的名称
      containerPort: 80 #容器需要监听的端口号
      hostPort: int       #容器所在主机需要监听的端口号,默认与Container相同
      protocol: TCP    #端口协议,支持TCP和UDP,默认TCP
    env:   #容器运行前需设置的环境变量列表
      name: JVM_OPTS  #环境变量名称
      value: 'Xms128m -Xmx128m' #环境变量的值
    resources: #资源限制和请求的设置
     requests: #最少需要多少资源
        cpu: 100m    #限制cpu最少使用0.1个核心
        memory: 128Mi #限制内存最少使用128兆
      limits:  #最多需要多少资源
        cpu: 200m     #
        memory: 256Mi  #
 restartPolicy: OnFailure #重启策略,只有失败的情况才会重启     
     

# 把上面的内容放进去
[root@k8s-master pods] vi nginx.demo.yaml
# 创建Pod
[root@k8s-master pods]# kubectl apply -f nginx-demo.yaml
pod/nginx-demo created

# 查看Pod状况
# READY 0/1 : 表示当前Pod中有1个容器,未准备就绪 
# STATUS ContainerCreating 容器创建中
[root@k8s-master pods]# kubectl get pod -n dev
NAME         READY   STATUS              RESTARTS   AGE
nginx-demo   0/1     ContainerCreating   0          36s

#CrashLoopBackOff 表示你的 Pod 在启动后立即崩溃,
#并且 Kubernetes 正在尝试重新启动它,但是这一过程一直在循环中。
[root@k8s-master pods]# kubectl get pod -n dev
NAME         READY   STATUS             RESTARTS     AGE
nginx-demo   0/1     CrashLoopBackOff   1 (9s ago)   10s

#查看 Pod 的日志
[root@k8s-master pods]# kubectl logs nginx-demo -n dev
2024/01/02 09:18:06 [emerg] 1#0: unexpected end of parameter, expecting ";" in command line
nginx: [emerg] unexpected end of parameter, expecting ";" in command line

#根据日志的内容,问题似乎是在 Nginx 启动命令行参数中。
#日志指出出现了一个紧急错误,即“unexpected end of parameter,
#expecting ';' in command line”(预期参数结束,期望在命令行中找到 ';')。
#尝试更新你的 YAML 文件中的 Nginx 启动命令,使用正常的 Nginx 启动方式:
#command:
#  - nginx
# - -g
# - 'daemon off;'  
#发现少了;导致了报错  


#修改配置文件
[root@k8s-master pods]# vi nginx-demo.yaml
#创建Pod
[root@k8s-master pods]# kubectl apply -f nginx-demo.yaml -n dev
The Pod "nginx-demo" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds`, `spec.tolerations` (only additions to existing tolerations) or `spec.terminationGracePeriodSeconds` (allow it to be set to 1 if it was previously negative)
  core.PodSpec{
    Volumes:        {{Name: "kube-api-access-gbfg2", VolumeSource: {Projected: &{Sources: {{ServiceAccountToken: &{ExpirationSeconds: 3607, Path: "token"}}, {ConfigMap: &{LocalObjectReference: {Name: "kube-root-ca.crt"}, Items: {{Key: "ca.crt", Path: "ca.crt"}}}}, {DownwardAPI: &{Items: {{Path: "namespace", FieldRef: &{APIVersion: "v1", FieldPath: "metadata.namespace"}}}}}}, DefaultMode: &420}}}},
    InitContainers: nil,
    Containers: []core.Container{
      {
        Name:  "nginx",
        Image: "nginx:1.7.9",
        Command: []string{
          "nginx",
          "-g",
-         "daemon off;",
+         "daemon off",
        },
        Args:       nil,
        WorkingDir: "/usr/share/nginx/html",
        ... // 17 identical fields
      },
    },
    EphemeralContainers: nil,
    RestartPolicy:       "OnFailure",
    ... // 26 identical fields
  }

#错误提示表明在 Kubernetes 中,你不能直接修改 Pod 中的某些字段,
#除非是 spec.containers[*].image、spec.initContainers[*].image、
#spec.activeDeadlineSeconds、spec.tolerations 
#或 spec.terminationGracePeriodSeconds 这些字段。在你的更新中,
#尝试修改了 spec.containers[*].command 字段,这是不允许的。
#为了解决这个问题,需要创建一个新的 Pod 资源而不是直接更新现有的 Pod。

#删除现有的 Pod:
[root@k8s-master pods]# kubectl delete pod nginx-demo -n dev
pod "nginx-demo" deleted
#创建一个新的 Pod:
[root@k8s-master pods]# kubectl apply -f nginx-demo.yaml -n dev
pod/nginx-demo created

# 查看Pod状况 # READY 1/1 : 表示当前Pod中有1个容器,准备就绪 
[root@k8s-master pods]# kubectl get pod -n dev
NAME         READY   STATUS    RESTARTS   AGE
nginx-demo   1/1     Running   0          15s


# 可以通过describe查看内部的详情
[root@k8s-master pods]# kubectl describe pod nginx-demo -n dev


查看Pod内部的详情中的事件

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  19m   default-scheduler  Successfully assigned dev/nginx-demo to k8s-node1
  Normal  Pulled     19m   kubelet            Container image "nginx:1.7.9" already present on machine
  Normal  Created    19m   kubelet            Created container nginx
  Normal  Started    19m   kubelet            Started container nginx

  • assigned dev/nginx-demo to k8s-node1 Pod 成功被调度到节点 k8s-node1 上。这表示 Kubernetes 调度器成功地选择了一个节点来运行你的 Pod
  • Container image “nginx:1.7.9” already present on machine 节点上已经有了所需的 Nginx 镜像,因此无需从远程仓库再次拉取
  • 因此无需从远程仓库再次拉取
  • Created container nginx 容器 “nginx” 已经被成功创建
  • Started container nginx 容器 “nginx” 已经成功启动

# 查看pod详细信息
[root@k8s-master pods]# kubectl get po -o wide
NAME        READY   STATUS    RESTARTS   AGE     IP           NODE        NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          5d18h   10.244.1.6   k8s-node1   <none>           <none>

#从集群内部访问了 Pod 的 IP 地址。这个 IP 地址是由 Kubernetes 分配的集群内部地址
[root@k8s-master pods]# curl 10.244.1.6
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

#路由表显示主机上的 IP 路由信息
[root@k8s-master pods]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.235.2   0.0.0.0         UG    100    0        0 ens33
10.244.0.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.244.1.0      10.244.1.0      255.255.255.0   UG    0      0        0 flannel.1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.235.0   0.0.0.0         255.255.255.0   U     100    0        0 ens33

1.2探针技术详解

容器内应用的监测机制,根据不同的探针来判断容器应用当前的状态

容器运行成功后会创建一个探针,会一直监控容器,一但发现容器挂掉了,会检查配置文件中是否有对应重启策略,按照要求的重启策略进行重启,或者是否需要重启。 restartPolicy: OnFailure # 重启策略 来重新启动

没有这个配置的话,容器挂掉了就是挂掉了

1.2.1探针类型
  • 生命周期探针(Liveness Probe)

生命周期探针用于确定容器是否处于运行中 。如果生命周期探针失败,kubelet 会根据配置的重启策略进行重启,若没有配置,默认就认为容器启动成功,不会执行重启策略。.

配置示例:

livenessProbe:
  failureThreshold: 5 #失败多少次算失败
  httpGet:
    path: /health
    port: 8080
    scheme: HTTP
  initialDelaySeconds: 60 # 初始化时间
  periodSeconds: 10 # 间隔时间 
  successThreshold: 1  #  多少此检测成功算成功
  timeoutSeconds: 5  # 请求超时时间
  • failureThreshold: 允许的连续失败次数,达到此次数后容器将被认为是不健康,将被杀死并根据重启策略进行处理。
  • httpGet: 指定 HTTP GET 请求的相关配置。
  • path: 探针将发送 HTTP GET 请求到容器中的路径。
  • port: 探针将使用的端口号。
  • scheme: HTTP 或 HTTPS,指定请求的协议。
  • initialDelaySeconds: 容器启动后多久开始进行探针检测。
  • periodSeconds: 探针检测的间隔时间,即每隔多久进行一次健康检查。
  • successThreshold: 允许的连续成功次数,达到此次数后容器将被认为是健康。
  • timeoutSeconds: 探针请求的超时时间,如果在此时间内没有响应,将被视为失败。

总的来说,上述配置表示容器的 Liveness Probe 将会:

  • 在容器启动后等待 60 秒开始进行探针检测。
  • 每隔 10 秒发送一个 HTTP GET 请求到 /health 路径,使用 HTTP 协议,端口为 8080。
  • 如果连续 5 次检测失败(即容器返回非 2xx 的 HTTP 状态码),则认为容器不健康。
  • 如果连续 1 次检测成功,则认为容器恢复到健康状态。

就绪性探针(Readiness Probe)

用于探测容器内的程序是否健康 ,它的返回值如果返回 success,那么就认为该容器已经完全启动,并且该容器是可以接收外部流量的。指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure

配置示例:

readinessProbe:
  failureThreshold: 3 # 错误次数
  httpGet:
    path: /ready
    port: 8181
    scheme: HTTP
  periodSeconds: 10 # 间隔时间
  successThreshold: 1
  timeoutSeconds: 1
  • StartupProbe

k8s 1.16 版本新增的探针,用于判断应用程序是否已经启动了。

当配置了 startupProbe 后,会先禁用其他探针,直到 startupProbe 成功后,其他探针才会继续。

作用:由于有时候不能准确预估应用一定是多长时间启动成功,因此配置另外两种方式不方便配置初始化时长来检测,而配置了 statupProbe 后,只有在应用启动成功了,才会执行另外两种探针,可以更加方便的结合使用另外两种探针使用。

配置示例:

startupProbe:
  httpGet:
    path: /api/startup
    port: 80
1.2.2探测方式
  • exec 方式

exec 方式通过执行容器内的命令检查容器的健康状态,如果返回值为 0,则任务容器时健康的。

livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 3
  periodSeconds: 5

Liveness Probe 将每 5 秒执行一次 cat /tmp/healthy 命令,如果命令成功执行(返回码为 0),则认为容器是健康的

  • tcpSocket 方式

通过 tcp 连接监测容器内端口是否开放,如果开放则证明该容器健康

livenessProbe:
  tcpSocket:
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 5

Liveness Probe 将每 5 秒尝试在容器的 8080 端口上建立一个 TCP 连接,如果连接成功,则认为容器是健康的

  • httpGet 方式

httpGet 方式通过发送 HTTP GET 请求检查容器的健康状态。

允许针对 httpGet 配置额外的字段:

  • host:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替。
  • scheme:用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 “HTTP”。
  • path:访问 HTTP 服务的路径。默认值为 “/”。
  • httpHeaders:请求中自定义的 HTTP 头。HTTP 头字段允许重复。
  • port:访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 5

periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。 initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。 kubelet 会向容器内运行的服务(服务在监听 8080 端口)发送一个 HTTP GET 请求来执行探测。 如果服务器上 /healthz 路径下的处理程序返回成功代码

针对 HTTP 探针,kubelet 除了必需的 Host 头部之外还发送两个请求头部字段:

  • User-Agent:默认值是 kube-probe/1.29,其中 1.29 是 kubelet 的版本号。
  • Accept:默认值 /

你可以通过为探测设置 httpHeaders 来重载默认的头部字段值。例如:

livenessProbe:
  httpGet:
    httpHeaders:
      - name: Accept
        value: application/json

startupProbe:
  httpGet:
    httpHeaders:
      - name: User-Agent
        value: MyUserAgent
1.2.3StartupProbe探针的使用

httpGet方式:

[root@k8s-master pods]# kubectl get pod -n dev
NAME        READY   STATUS    RESTARTS   AGE
nginx-demo   1/1     Running   0          5d19h

#删除现有的 Pod:
[root@k8s-master pods]# kubectl delete pod nginx-demo -n dev
pod "nginx-demo" deleted
#修改配置文件
[root@k8s-master pods]# vi nginx-demo.yaml

# 在command 上面加入以下内容
startupProbe: #应用启动探针配置
      httpGet: # 探测方式,基于http请求探测
        path: /api/startup # http请求路径 这个是不存在的path请求不到
        port: 80 #请求端口
      failureThreshold: 3 # 失败多少次算失败
      periodSeconds: 10 # 间隔时间
      successThreshold: 1  # 多少此检测成功算成功
      timeoutSeconds: 5  # 请求超时时间
      

#创建一个新的 Pod:
[root@k8s-master pods]# kubectl apply -f nginx-demo.yaml -n dev
pod/nginx-demo created

[root@k8s-master pods]#  kubectl get pod -n dev
NAME         READY   STATUS    RESTARTS      AGE
nginx-demo   0/1     Running   1 (11s ago)   42s
[root@k8s-master pods]# kubectl get pod -n dev
NAME         READY   STATUS    RESTARTS      AGE
nginx-demo   0/1     Running   1 (16s ago)   47s
[root@k8s-master pods]# kubectl get pod -n dev
NAME         READY   STATUS    RESTARTS      AGE
nginx-demo   0/1     Running   1 (29s ago)   60s

# 可以通过describe查看内部的详情
[root@k8s-master pods]# kubectl describe pod nginx-demo -n dev

Events:
  Type     Reason     Age                 From               Message
  ----     ------     ----                ----               -------
  Normal   Scheduled  109s                default-scheduler  Successfully assigned dev/nginx-demo to k8s-node1
  Normal   Pulled     18s (x4 over 108s)  kubelet            Container image "nginx:1.7.9" already present on machine
  Normal   Created    18s (x4 over 108s)  kubelet            Created container nginx
  Normal   Started    18s (x4 over 108s)  kubelet            Started container nginx
  Normal   Killing    18s (x3 over 78s)   kubelet            Container nginx failed startup probe, will be restarted
  Warning  Unhealthy  8s (x10 over 98s)   kubelet            Startup probe failed: HTTP probe failed with statuscode: 404

Startup probe failed: HTTP probe failed with statuscode: 404:

Kubernetes 的启动探测(Startup Probe)中,HTTP 探测失败,返回了状态码 404

[root@k8s-master pods]# mv nginx-demo.yaml nginx-po.yaml
[root@k8s-master pods]# ls
nginx-po.yaml
#删除现有的 Pod:
[root@k8s-master pods]# kubectl delete pod nginx-demo -n dev
pod "nginx-demo" deleted
#修改配置文件
[root@k8s-master pods]# vi nginx-po.yaml

# 修改配置
metadata:
  name: nginx-po
  
path: /index.html #http请求路径 这个是存在的路径

#创建一个新的 Pod
[root@k8s-master pods]# kubectl apply -f nginx-po.yaml -n dev
pod/nginx-po created
#通过describe查看内部的详情
[root@k8s-master pods]# kubectl describe pod nginx-po -n dev

打印内部详情: 没有错误信息 打印了对应Startup对应配置信息 探针方式为http-get


# 查看Pod状况
# READY 1/1 : 表示当前Pod中有1个容器,准备就绪 
[root@k8s-master pods]# kubectl get pod -n dev
NAME       READY   STATUS    RESTARTS   AGE
nginx-po   1/1     Running   0          4m11s

tcpScocket方式: 端口连接成功就算成功的访问

** **把之前httpGet方式的探针注释,改为tcpSocket方式。

startupProbe: #应用启动探针配置 
      tcpSocket:
        port: 80 # 请求端口

按照原来的步骤再来一遍

打印内部详情: 没有错误信息 打印了对应Startup对应配置信息 探针方式为tcp-socket

**exec方式: **

 command:
        - sh
        - -c
        - "echo success >/inited;"

/inited 文件中写入 “success” 字符串

打印内部详情: 没有错误信息 打印了对应Startup对应配置信息 探针方式为exec 由之前的额发请求变成了命令的方式执行

# 查看Pod状况
# READY 1/1 : 表示当前Pod中有1个容器,准备就绪 
[root@k8s-master pods]# kubectl get pod -n dev
NAME       READY   STATUS    RESTARTS   AGE
nginx-po   1/1     Running   0          69s
#在名为 "nginx-po" 的 Pod 中的 "nginx" 容器内执行 cat /inited 命令,查看 "/inited" 文件的内容
[root@k8s-master pods]# kubectl exec -it nginx-po  -n dev -c nginx -- cat /inited
success
#出现了success 操作成功
1.2.4LivenessProbe探针的使用
# 复制nginx-po.yaml文件内容
[root@k8s-master pods]# cp nginx-po.yaml nginx-livexess-po.yaml
cp:是否覆盖"nginx-livexess-po.yaml"? Y
[root@k8s-master pods]# ls
nginx-livexess-po.yaml  nginx-po.yaml

#修改配置文件
[root@k8s-master pods]#  vi nginx-livexess-po.yaml
    startupProbe: #应用启动探针配置
      #tcpSocket:
      #  port: 80 # 请求端口
      exec:
        command:
        - sh
        - -c
        - "sllep 3;echo success >/inited;"
      failureThreshold: 3 # 失败多少次算失败
      periodSeconds: 10 # 间隔时间
      successThreshold: 1  # 多少此检测成功算成功
      timeoutSeconds: 5  # 请求超时时间
    livenessProbe: #应用存活探针配置
      httpGet: # 探测方式,基于http请求探测 
        path: /started.html # http请求路径 这个是不存在的path请求不到 
        port: 80 #请求端口 
      failureThreshold: 3 # 失败多少次算失败 
      periodSeconds: 10 # 间隔时间 
      successThreshold: 1  # 多少此检测成功算成功 
      timeoutSeconds: 5  # 请求超时时间

#RESTARTS 重启3次
[root@k8s-master pods]# kubectl get pod -n dev
NAME       READY   STATUS    RESTARTS      AGE
nginx-po   0/1     Running   3 (12s ago)   2m12s

#Completed重启5次终止状态
[root@k8s-master pods]# kubectl get pod -n dev
NAME       READY   STATUS      RESTARTS   AGE
nginx-po   0/1     Completed   5          5m56s

[root@k8s-master pods]# kubectl cp started.html dev/nginx-po:/usr/share/nginx/html/
#文件存在后启动成功
[root@k8s-master pods]# kubectl get pod -n dev
NAME       READY   STATUS    RESTARTS     AGE
nginx-po   1/1     Running   1 (2m ago)   2m40s

使用启动探针保护慢启动容器

有时候,会有一些现有的应用在启动时需要较长的初始化时间。 要这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。 技巧就是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对最糟糕情况下的启动时间

这样,前面的例子就变成了:

ports:
- name: liveness-port
  containerPort: 8080
  hostPort: 8080

livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 1
  periodSeconds: 10

startupProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 30
  periodSeconds: 10 

幸亏有启动探测,应用将会有最多 5 分钟(30 * 10 = 300s)的时间来完成其启动过程。 一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。 如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 restartPolicy 来执行进一步处置。

1.2.5ReadinessProbe 就绪探针的使用

有时候,应用会暂时性地无法为请求提供服务。 例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用,也不想给它发送请求。 Kubernetes 提供了就绪探针来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。

说明:

就绪探针在容器的整个生命周期中保持运行状态。

注意:

  • 存活探针与就绪性探针相互间不等待对方成功。 如果要在执行就绪性探针之前等待,应该使用 initialDelaySeconds 或 startupProbe。
  • 就绪探针的配置和存活探针的配置相似。 唯一区别就是要使用 readinessProbe 字段,而不是 livenessProbe 字段。HTTP 和 TCP 的就绪探针配置也和存活探针的配置完全相同。
  • 就绪和存活探测可以在同一个容器上并行使用。 两者共同使用,可以确保流量不会发给还未就绪的容器,当这些探测失败时容器会被重新启动
# 复制nginx-livexess-po.yaml文件内容
[root@k8s-master pods]# cp nginx-livexess-po.yaml nginx-rediness-po.yaml
[root@k8s-master pods]# vi nginx-rediness-po.yaml

readinessProbe: #应用就绪探针配置
      httpGet: # 探测方式,基于http请求探测
        path: /started.html # http请求路径 这个是不存在的path请求不到
        port: 80 #请求端口
      failureThreshold: 5 # 失败多少次算失败
      periodSeconds: 10 # 间隔时间
      successThreshold: 1  # 多少此检测成功算成功
      timeoutSeconds: 5  # 请求超时时间


# 禁止外部网络访问 不会重启
[root@k8s-master pods]#  kubectl get pod -n dev
NAME       READY   STATUS    RESTARTS   AGE
nginx-po   0/1     Running   0          21s
#把这个文件放进pod中
[root@k8s-master pods]# kubectl cp started.html nginx-po:/usr/share/nginx/html/ -n dev
# 再次查看pod就为就绪状态了
[root@k8s-master pods]# kubectl get pod -n dev
NAME       READY   STATUS    RESTARTS   AGE
nginx-po   1/1     Running   0          2m39s

1.3 Pod生命周期

1.3.1 Pod生命周期图解

1.3.2 容器状态

要检查 Pod 中容器的状态,你可以使用 kubectl describe pod <pod 名称>。 其输出中包含 Pod 中每个容器的状态。

每种状态都有特定的含义:

Waiting (等待)

如果容器并不处在 Running 或 Terminated 状态之一,它就处在 Waiting 状态。 处于 Waiting 状态的容器仍在运行它完成启动所需要的操作:例如, 从某个容器镜像仓库拉取容器镜像,或者向容器应用 Secret 数据等等。 当你使用 kubectl 来查询包含 Waiting 状态的容器的 Pod 时,你也会看到一个 Reason 字段,其中给出了容器处于等待状态的原因。

Running(运行中)

Running 状态表明容器正在执行状态并且没有问题发生。 如果配置了 postStart 回调,那么该回调已经执行且已完成。 如果你使用 kubectl 来查询包含 Running 状态的容器的 Pod 时, 你也会看到关于容器进入 Running 状态的信息。

Terminated(已终止)

处于 Terminated 状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 如果你使用 kubectl 来查询包含 Terminated 状态的容器的 Pod 时, 你会看到容器进入此状态的原因、退出代码以及容器执行期间的起止时间。

如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行。

1.3.3postStart 和 preStop 钩子函数

钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。

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

  • post start:容器创建之后执行,但在容器中的应用程序开始运行之前,如果失败了会重启容器.

postStart 处理函数与容器的代码是异步执行的,但 Kubernetes 的容器管理逻辑会一直阻塞等待 postStart 处理函数执行完毕。 只有 postStart 处理函数执行完毕,容器的状态才会变成 RUNNING

  • pre stop :容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作

除非 Pod 宽限期限超时, Kubernetes 的容器管理逻辑会一直阻塞等待 preStop 处理函数执行完毕

钩子处理器支持使用下面三种方式定义动作:

Exec命令:在容器内执行一次命令

……
  lifecycle:
    postStart: 
      exec:
        command:
        - cat
        - /tmp/healthy
……

TCPSocket:在当前容器尝试访问指定的socket

……      
  lifecycle:
    postStart:
      tcpSocket:
        port: 8080
……

HTTPGet:在当前容器中向某url发起http请求

……
  lifecycle:
    postStart:
      httpGet:
        path: / #URI地址
        port: 80 #端口号
        host: 192.168.5.3 #主机地址
        scheme: HTTP #支持的协议,http或者https
……

1.3.4 Pod 退出流程>删除操作
  1. 用户或控制器发起删除操作: 删除操作可以由用户通过 kubectl delete pod 命令发起,或者由控制器(如 Deployment、StatefulSet、DaemonSet 等)进行删除操作。
  2. Terminating 阶段开始: Pod 进入 Terminating 阶段,此时将开始执行删除流程。
  3. PreStop 钩子执行: 如果容器定义了 preStop 生命周期钩子,将执行这个钩子中定义的操作。这是在容器终止之前执行的清理操作。
  4. SIGTERM 信号发送: Kubernetes 向容器发送 SIGTERM 信号,通知容器开始优雅终止。优雅终止的期限由 terminationGracePeriodSeconds 字段定义,默认是 30 秒。
  5. 优雅终止:SIGTERM 信号发送后,容器有一个优雅终止期限,在这个期限内,容器有机会完成正在进行的工作、关闭连接等。
  6. Terminating 阶段完成: 如果在优雅终止期限内容器成功终止,Pod 将进入 Terminated 阶段,然后被删除。如果容器无法在优雅终止期限内完成,将进入下一步。
  7. SIGKILL 信号发送: 如果容器在优雅终止期限内未能正常终止,Kubernetes 将发送 SIGKILL 信号,强制终止容器。
  8. Pod 删除: Pod 进入 Terminated 阶段,然后被删除。删除操作将从 API Server 和集群中移除该 Pod 的配置和状态信息。
1.3.5 PreStop事件的应用

使用 preStop 生命周期钩子时,可以在应用即将终止之前执行一些清理操作。在您的场景中,可以通过 preStop 钩子来实现注册中心下线、数据清理和数据销毁等操作。

如果应用销毁操作耗时需要比较长,可以在 preStop 按照如下方式进行配置

preStop:
  exec:
    command:
      - sh
      - -c
      - 'sleep 20; kill pgrep java'

但是需要注意,由于 k8s 默认给 pod 的停止宽限时间为 30s,如果我们停止操作会超过 30s 时,不要光设置 sleep 50,还要将 terminationGracePeriodSeconds: 30 也更新成更长的时间,否则 k8s 最多只会在这个时间的基础上再宽限几秒,不会真正等待 50s

以下是一个示例 Pod 配置,其中包含一个具有 preStop 钩子的容器:

apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
spec:
  terminationGracePeriodSeconds: 90  # 设置终止期限为 90 秒
  containers:
  - name: my-app-container
    image: my-app-image:latest
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh", "-c", "cleanup-script.sh"]

在这个示例中,cleanup-script.sh 是一个您定义的脚本,其中包含执行清理操作的逻辑。您可以在这个脚本中实现注册中心下线、数据清理和数据销毁等操作。

1.3.6 完整示例
apiVersion: v1
kind: Pod
metadata:
  name: pod-hook-exec
  namespace: dev
spec:
  terminationGracePeriodSeconds: 45
  containers:
  - name: main-container
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo 'postStart... creating file' > /usr/share/nginx/html/index.html"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo 'preStop... creating file' > /pods/termination-file.html"]

# 创建pod
[root@k8s-master pods]# kubectl apply -f pod-lifecycle-demo.yaml
pod/lifecycle-graceful-pod created
# 查看pod列表
[root@k8s-master pods]# kubectl get pods -n dev
NAME            READY   STATUS    RESTARTS   AGE
pod-hook-exec   1/1     Running   0          68s
#查看pod
[root@k8s-master pods]# kubectl get pods  pod-hook-exec -n dev -o wide
NAME            READY   STATUS    RESTARTS   AGE    IP            NODE        NOMINATED NODE   READINESS GATES
pod-hook-exec   1/1     Running   0          104s   10.244.1.27   k8s-node1   <none>           <none>
# 访问pod
[root@k8s-master pods]# curl 10.244.1.27
postStart... creating file

postStart… creating file 这个是postStart钩子函数执行的内容.

1.3.7强制删除

强制删除不会等待来自 kubelet 对 Pod 已终止的确认消息。 无论强制删除是否成功杀死了 Pod,它都会立即从 API 服务器中释放该名字。

如果要使用 kubectl 1.5 以上版本强制删除 Pod,请执行下面命令:

kubectl delete pods <pod> --grace-period=0 --force

如果你使用 kubectl 的 1.4 以下版本,则应省略 --force 选项:

kubectl delete pods <pod> --grace-period=0

如果在执行这些命令后 Pod 仍处于 Unknown 状态,请使用以下命令从集群中删除 Pod:

kubectl patch pod <pod> -p '{"metadata":{"finalizers":null}}'

请始终谨慎地执行强制删除 StatefulSet 类型的 Pod,并充分了解强制删除操作所涉及的风险

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
Kubernetes 调度 Perl
Pod的自动扩缩容
Pod的自动扩缩容
130 1
|
3月前
|
Kubernetes 网络协议 Perl
解决pod健康检查问题
解决pod健康检查问题
43 3
|
6月前
|
运维 Kubernetes 网络协议
Kubernetes详解(十六)——Pod容器探测
Kubernetes详解(十六)——Pod容器探测
116 1
|
3月前
|
Kubernetes 负载均衡 网络协议
在K8S中,Pod的探针有哪些及用途?
在K8S中,Pod的探针有哪些及用途?
|
3月前
|
Kubernetes 监控 网络协议
在K8S中,Pod有几种探针?
在K8S中,Pod有几种探针?
|
3月前
|
Kubernetes 网络协议 容器
在k8S中,Pod中的LivenessProbe探针常见方式有哪些?
在k8S中,Pod中的LivenessProbe探针常见方式有哪些?
|
3月前
|
Kubernetes 监控 网络协议
在K8S中,Pod不同探针有何区别?
在K8S中,Pod不同探针有何区别?
|
3月前
|
Kubernetes 网络协议 容器
在K8S中,Pod的健康检查方式有哪些?
在K8S中,Pod的健康检查方式有哪些?
|
3月前
|
Kubernetes 负载均衡 网络协议
在K8S中,Pod能否实现对容器健康检查,如果服务有异常,该如何处理?
在K8S中,Pod能否实现对容器健康检查,如果服务有异常,该如何处理?
|
6月前
|
Kubernetes 应用服务中间件 调度
pod 之资源限制 与健康检查
pod 之资源限制 与健康检查