当前位置: 首页 > article >正文

Kubernetes Pod 生命周期详解 之 探针

1.探针

 

deployment pod控制器 

如果创建一个pod 如果销毁了 那就是销毁了  

deployment 创建可以定义几个pod 或者 怎么创建pod 

按照我们要求去创建

kubernetes 提供了一个 负载均衡 更简化的 操作

service 

service 创建的时候需要我们指定一个东西 就是我们标签选择器 

label 标签选择 label app=myapp

就绪探测

如果 pod 内部的 C 不添加就绪探测,默认就绪。如果添加了就绪探测, 只有就绪通过以后,才标记修改为就绪状态。当前 pod 内的所有的 C 都就绪,才标记当前 Pod 就绪

成功:将当前的 C 标记为就绪

 失败:静默

 未知:静默

或者服务没准备好,并且是下线的状态,他不采取动作,也就是他和存活探测不一样的点是,他不会杀死容器,而是单纯的控制容器加入或者退出负载均衡的这么一个机制

那这个就绪探测,可以理解为专门给服务提供上线和下线的作用,服务准备好了,他提供服务上线,服务没准备好,他提供下线,

2.怎么删除pod

kubectl delete pod [pod名]

--all 可以删除当前资源的所有pod

3.小实验

apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  namespace: default
  labels:
    app: myapp
spec:
  containers:
    - name: myapp-1
      image: wangyanglinux/myapp:v1.0
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  namespace: default
  labels:
    app: myapp
    version: v1
spec:
  containers:
    - name: myapp-1
      image: wangyanglinux/myapp:v1.0
kubectl create -f 1.pod.yaml
kubectl create -f 2.pod.yaml

1.创建service

kubectl create svc myapp

这样他会有一个默认值 ,那么它默认就回去匹配 app=myapp的标签的pod 所以service的名字 建议不要乱写

所以我们执行下面的命令

kubectl create svc clusterip myapp --tcp=80:80

用户只需要访问 10.5.251.92:80端口 就可以负载均衡访问 后台两个 pod里80端口对应的两台服务器

 service 名字叫 myapp 默认匹配标签 app=myapp 的pod

负载均衡的方式下访问我们的pod

这个获取主机名其实是pod名 默认为主机名

我们再加一个pod 这个app改成 test 看看service还能负载均衡到这个主机名吗

没有办法匹配 pod-3 

4.就绪探测

1.基于httpGet方式

apiVersion: v1
kind: Pod
metadata:
 name: readiness-httpget-pod
 namespace: default
 labels:
   app: myapp
   env: test
spec:
 containers:
  - name: readiness-httpget-container
    image: wangyanglinux/myapp:v1.0
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3

imagePulPolicy: 镜像拉取策略 如果本地存在 就不会去远程拉取镜像 而是本地直接使用

readinessProbe: 代表就绪探测

方案 

通过 http请求的 Get 方法 访问 80端口 下的 /index1.html  注意当前镜像下是没有这个文件的 所以访问不通

initialDelaySeconds: 延迟检测时间 1秒以后的探测 

periodSeconds :每三秒一次的间隔做重复探测  比如第一次我失败了 那我三秒再测一次 直到成功

该pod虽然再running 但是 未就绪 因为就绪探针不通过 

虽然 它由 app=myapp 的标记  已经被我们service匹配了 但是

始终没有出现 就是因为 就绪探针没有通过 不会负载均衡给用户去使用未就绪的 pod 即使标签匹配在 service的子集

这就是我们就绪探针存在的意义

 想要恢复就绪 

我们进入容器去添加这么一个文件

kubectl exec -it readiness-httpget-pod  -- /bin/bash

将“” 字符串 写入 index1.html 文件中 不存在就创建出来 

 echo "jmj daociyiyou" >> index1.html

 退出当前容器 

exit
kubectl get pod

启动了

 

正常被负载均衡里面访问

 2.基于EXEC方式

apiVersion: v1
kind: Pod
metadata:
 name: readiness-exec-pod
 namespace: default
spec:
  containers:
    - name: readiness-exec-container
      image: wangyanglinux/tools:busybox
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"]
      readinessProbe:
        exec:
          command: ["test","-e","/tmp/live"]
        initialDelaySeconds: 1
        periodSeconds: 3

定义命令: command: 创建 /tmp/live  休眠60秒 递归删除 /tmp/live 再休眠 3600秒

readinessProbe 就绪探测

test -e 加路径 :判断路径下的文件存不存在 如果存在代表就绪通过

经过60 秒后 文件被删除 然后发送就绪探测的时候 文件就不存在了  就绪就不通过了

新版的就绪探测 是从开始 到容器死亡 都一直重复去做

kubectl create -f 5.pod.yaml
kubectl get pod -w 

代表监视看pod状态

发现60 秒后进入未就绪 是因为 我们60秒就把文件删除了 所以就绪探测检测到文件不存在了 就标记为未就绪

 3.基于TCP Check 方式

apiVersion: v1
kind: Pod
metadata:
 name: readiness-tcp-pod
 namespace: default
spec:
  containers:
    - name: readiness-tcp-container
      image: wangyanglinux/myapp:v1.0
      readinessProbe:
        initialDelaySeconds: 1
        periodSeconds: 3
        tcpSocket:
          port: 80

timeoutSeconds 超时时间 1秒 

tcp 检测 端口 是 80 端口

只有当前应用的 80端口 能和我 TCP 连接 成功 那么代表就绪探测成功 ,否则就是失败

不常用 因为如果把里面的进程杀死 就代表 这个容器本身就会死 所以我们不常用

5.存活探针 livenessProbe

kubectl get pod pod-1 -o yaml

 

[root@k8s-master01 6]# kubectl get pod pod-1 -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    cni.projectcalico.org/containerID: 5652c8888a94c29892490e163738d9ceffe0a662b948abe3f8fee2b3bd8cb522
    cni.projectcalico.org/podIP: 10.244.85.200/32
    cni.projectcalico.org/podIPs: 10.244.85.200/32
  creationTimestamp: "2025-03-10T12:28:40Z"
  labels:
    app: myapp
  name: pod-1
  namespace: default
  resourceVersion: "110369"
  uid: 0478da02-c28d-4852-882c-bdad5cad9870
spec:
  containers:
  - image: wangyanglinux/myapp:v1.0
    imagePullPolicy: IfNotPresent
    name: myapp-1
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-wf2df
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: k8s-node01
  preemptionPolicy: PreemptLowerPriority
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: kube-api-access-wf2df
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2025-03-11T11:14:06Z"
    status: "True"
    type: PodReadyToStartContainers
  - lastProbeTime: null
    lastTransitionTime: "2025-03-10T12:28:40Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2025-03-11T11:14:06Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2025-03-11T11:14:06Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2025-03-10T12:28:40Z"
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: docker://2d7d387b24baf5155244a6a001afa4e45101558281a1eed832bfe5d07a04bfea
    image: wangyanglinux/myapp:v1.0
    imageID: docker-pullable://wangyanglinux/myapp@sha256:77d7ec4cd4c00f79304ee9e53ca3d72e0aba22fbaf7a86797528649e3fc66e41
    lastState:
      terminated:
        containerID: docker://85cc85a7ae1abd19ec04688fee7202616bb976e85b77d6cd2e16ed79cadaca6b
        exitCode: 0
        finishedAt: "2025-03-11T11:10:06Z"
        reason: Completed
        startedAt: "2025-03-10T12:28:41Z"
    name: myapp-1
    ready: true
    restartCount: 1
    started: true
    state:
      running:
        startedAt: "2025-03-11T11:14:05Z"
  hostIP: 192.168.72.12
  hostIPs:
  - ip: 192.168.72.12
  phase: Running
  podIP: 10.244.85.200
  podIPs:
  - ip: 10.244.85.200
  qosClass: BestEffort
  startTime: "2025-03-10T12:28:40Z"

当前资源对象存储在kubernetes 集群里的具体的默认参数信息

这么多东西 我们定义的时候没写这么多啊 ,但是很多的都是默认值

重启策略 

restartPolicy:Always  只要容器死了不管是以 0的方式死亡 还是非0的方式死亡 我都会进行重建动作

 1.基于 exec 的方式

apiVersion: v1
kind: Pod
metadata:
 name: liveness-exec-pod
 namespace: default
spec:
  containers:
    - name: liveness-exec-container
      image: wangyanglinux/tools:busybox
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live;sleep 3600"]
      livenessProbe:
         exec:
           command: ["test","-e","/tmp/live"]
         initialDelaySeconds: 1
         periodSeconds: 3

重启了 又开始等待60秒 删除 然后又会重建

2.基于HTTP Get 方式

apiVersion: v1
kind: Pod
metadata:
 name: liveness-httpget-pod
 namespace: default
spec:
  containers:
    - name: liveness-exec-container
      image: wangyanglinux/tools:busybox
      imagePullPolicy: IfNotPresent
      ports:
        - name: http
          containerPort: 80
      livenessProbe:
        httpGet:
          path: /index.html
          port: 80
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 1

ports 对于单独一个pod 定义是毫无意义 的 因为 在这个容器 内网 80端口都是能够互相访问通的

只要我们进入容器吧 index.html 删除 如果它启动能恢复的话 说明我们的猜测是真的

把我踢掉了 

因为容器没有通过存货探测

我们重新进入容器 发现容器里面 已经没有我们之前建的.back 而是原始镜像里默认目录 ,说明它重新创建了容器

 在node02 运行

 

结构 

k8s_容器名_pod名_命名空间_MD5值_重启次数

 当容器损坏的时候 我们能利用 重启策略来达到一个 自愈的机制

3.基于TCP check方式

apiVersion: v1
kind: Pod
metadata:
 name: liveness-tcp-pod
spec:
  containers:
    - name: liveness-tcp-container
      image: wangyanglinux/myapp:v1.0
      livenessProbe:
        initialDelaySeconds: 5
        timeoutSeconds: 3
        tcpSocket:
          port: 80

一般不用

探测地址 就是 localhost  也就是本地的pod地址

存活探测保证了 pod运行 一定是能让用户访问的 除非你的存活探测设置的有问题

6.启动探针 startupProbe 

如果不定义启动探针,那存活探针和就绪探针的执行时机将不确定 ,可能导致容器还没起来 ,就检测为不存活又被杀死重建 所以启动探针很重要

 

apiVersion: v1
kind: Pod
metadata:
 name: startupprobe-1
 namespace: default
spec:
 containers:
   - name: myapp-container
     image: wangyanglinux/myapp:v1.0
     imagePullPolicy: IfNotPresent
     ports:
       - name: http
         containerPort: 80
     readinessProbe:
       httpGet:
        port: 80
        path: /index2.html
       initialDelaySeconds: 1
       periodSeconds: 3
     startupProbe:
       httpGet:
         path: /index1.html
         port: 80
       failureThreshold: 30
       periodSeconds: 10

 

把就绪探测的条件满足 ,但是发现还是未就绪 是因为,启动探测未成功 不会执行就绪探测

我们把启动探测满足了 

 就绪了

7.钩子

 分为启动后钩子 和关闭前钩子 

但是启动后钩子其实是在初始化之后启动之前运行的 别搞混了

并且启动钩子还有可能在启动钩子命令还没有执行完成 我们的容器启动命令就开始执行了

但是关闭前钩子 一定是关闭前钩子执行完了 才执行容器关闭信号

1.基于exec的方式

apiVersion: v1
kind: Pod
metadata:
 name: lifecycle-exec-pod
spec:
 containers:
  - name: lifecycle-exec-container
    image: wangyanglinux/myapp:v1
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo postStart > /usr/share/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo preStop > /usr/share/message"]

看到我们启动后钩子 已经把字符串写进文件里了

 

执行脚本 循环看这个文件内容  开启另一个终端来让 关闭前钩子执行

 

 将pod杀死

发现 关闭前钩子执行了

2.基于HTTPGET方式

开启一个测试webServer服务

docker run -it --rm -p 1234:80 wangyanglinux/myapp:v1.0
apiVersion: v1
kind: Pod
metadata:
 name: lifecycle-httpget-pod
 labels:
  name: lifecycle-httpget-pod
spec:
 containers:
   - name: lifecycle-httpget-container
     image: wangyanglinux/myapp:v1.0
     ports:
       - containerPort: 80
     lifecycle:
       postStart:
          httpGet:
            host: 192.168.72.11
            path: index.html
            port: 1234
       preStop:
          httpGet:
            host: 192.168.72.11
            path: hostname.html
            port: 1234

 

后置请求

 8.关于preStop的延伸话题

如果30秒没退出 那么kubernetes将会发出 -9 级别的强制杀死

 可以通过上面关键字定义我的容忍信息 也可以通过 --grace-period 定义覆盖pod 中的配置

9.终极整合实验

 

apiVersion: v1
kind: Pod
metadata:
 name: lifecycle-pod
 labels:
  app: lifecycle-pod
spec:
 containers:
   - name: busybox-container
     image: wangyanglinux/tools:busybox
     command: ["/bin/sh","-c","touch /tmp/live ; sleep 600; rm -rf /tmp/live; sleep 3600"]
     livenessProbe:
       exec:
         command: ["test","-e","/tmp/live"]
       initialDelaySeconds: 1
       periodSeconds: 3
     lifecycle:
       postStart:
         httpGet:
           host: 192.168.72.11
           path: index.html
           port: 1234
       preStop:
         httpGet:
           host: 192.168.72.11
           path: hostname.html
           port: 1234
   - name: myapp-container
     image: wangyanglinux/myapp:v1.0
     livenessProbe:
        httpGet:
          port: 80
          path: /index.html
        initialDelaySeconds: 1
        periodSeconds: 3
        timeoutSeconds: 3
     readinessProbe:
        httpGet:
          port: 80
          path: /index1.html
        initialDelaySeconds: 1
        periodSeconds: 3
 initContainers:
    - name: init-myservice
      image: wangyanglinux/tools:busybox
      command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
    - name: init-mydb
      image: wangyanglinux/tools:busybox
      command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

我们发现没有起来 是因为 初始化容器检测 没有对应的service 域名解析 所以初始化不成功

kubectl create svc clusterip myservice --tcp=80:80

创建一个 service 类型 为 clusterip --tcp=80:80 访问这个域名的80端口 会负载均衡访问这个service所揽住的 pod 的容器内部 80端口

这时候我们第一个初始化容器通过了

kubectl create svc clusterip mydb --tcp=80:80

 

pod进入初始化状态

 

存活探针给杀了 

这时候它又被重新创建了 ,但是由于由 就绪探针 没有 index1.html 所以无法变成就绪了

启动后钩子执行了 

 

但是如果是存活探针杀死的 容器他不会执行 preStop 钩子

 


http://www.kler.cn/a/581382.html

相关文章:

  • 常用的gpt
  • 【性能测试】Jmeter如何做一份测试报告(3)
  • 第十五届蓝桥杯大学B组(握手问题、小球反弹、好数)
  • K8S学习之基础二十二:k8s的持久化存储之hostPath
  • 通义万相 2.1 + 蓝耘算力,AI 视频生成的梦幻组合
  • halcon机器人视觉(二)固定相机抓取hand_eye_stationarycam_grasp_nut
  • 批量测试IP和域名联通性
  • 从零开始学机器学习——了解分类算法
  • 【从零开始学习计算机科学】操作系统(十)操作系统的引导程序 与 系统安全
  • 数组美丽值求和 (Leetcode 2012)
  • 2025软件供应链安全最佳实践︱新能源汽车领域SCA开源风险治理项目
  • GitLab版本控制-分支(详解)
  • 【深度学习】读写文件
  • 【51单片机】程序实验15.DS18B20温度传感器
  • MySQL 与 MongoDB 的区别
  • OPPO机器学习算法岗(AI智能体)内推
  • 探秘Transformer系列之(12)--- 多头自注意力
  • Drools规则引擎在临床路径逻辑中的编程实例讨论汇总
  • 数据结构 -并查集
  • 插入排序:算法原理与应用解析