k8s Pod 进阶(资源限制,健康检查探针详解,启动退出,pod生命周期,)

目录

资源限制

查看资源控制字段

[Pod 资源限制方式](#Pod 资源限制方式)

[Pod 和容器中定义资源请求和限制的具体字段](#Pod 和容器中定义资源请求和限制的具体字段)

CPU资源单位

内存资源单位

示例

健康检查(探针)

探针的三种规则

[存活探针(Liveness Probe)](#存活探针(Liveness Probe))

[就绪探针(Readiness Probe)](#就绪探针(Readiness Probe))

[启动探针(Startup Probe)](#启动探针(Startup Probe))

总结

Pod的生命周期可以分为几个阶段:

探针支持三种检查方法

示例

示例1:exec方式

示例2:httpGet方式

示例3:tcpSocket方式

示例4:就绪检测

示例5:就绪检测2

启动和退出动作


资源限制

Pod 资源限制是指在 Kubernetes 中,可以为每个 Pod 中的容器设置所需的资源数量。这些资源包括 CPU 和内存大小等。Pod 资源限制在 Kubernetes 中是至关重要的,特别是在生产环境中。通过为每个 Pod 设置适当的资源限制,可以避免某个 Pod 消耗过多的 CPU 或内存资源,从而防止一个 Pod 影响整个集群的性能,并避免资源饥饿的情况发生。这有助于提高集群的可靠性和稳定性。

在Kubernetes(k8s)中,对Pod的资源限制包括两个方面:资源请求(requests)和资源限制(limits)。

  • 资源请求(requests):指在调度Pod时,Kubernetes会尝试将Pod调度到满足其资源请求的节点上。这个值应该被设置为Pod所需资源的最低限制,确保Pod能够正常运行。

  • 资源限制(limits):指在运行Pod时,Kubernetes会限制Pod使用的资源量,确保不会超出所设置的限制。这个值应该根据应用程序的需求来设置,以避免资源被过度占用导致其他Pod受影响。

查看资源控制字段

kubectl explain deployment.spec.template.spec.containers.resources
kubectl explain  statefulset.spec.template.spec.containers.resources

kubectl explain命令可以用于查看Kubernetes资源对象的详细信息

Deployment:

kubectl explain deployment.spec.template.spec.containers.resources

这个命令将显示有关Deployment中Pod模板的容器资源的详细信息。这包括关于资源请求和限制的内容,以确保Pod在调度和运行时具有足够的资源。

StatefulSet:

kubectl explain statefulset.spec.template.spec.containers.resources

这个命令将显示有关StatefulSet中Pod模板的容器资源的详细信息。与Deployment类似,StatefulSet也具有相同的容器资源配置,确保Pod有足够的资源。

Pod 资源限制方式

  • 资源需求(Requests):

  • request 是 Pod 对资源的最低需求声明。它告诉 Kubernetes 调度器为 Pod 分配节点时所需的资源量。

  • 对于 CPU,request 表示 Pod 所需的最低 CPU 分配量。例如,"100m" 表示 0.1 个 CPU 核心。

  • 对于内存,request 表示 Pod 所需的最低内存量,例如,"256Mi" 表示 256 兆字节的内存。

  • 资源限制(Limits):

  • limit 是 Pod 对资源的最大使用量声明。它告诉 Kubernetes 控制器在什么情况下限制容器的资源使用。

  • 对于 CPU,limit 表示容器在任何时间点可以使用的最大 CPU 分配量。例如,"500m" 表示 0.5 个 CPU 核心。

  • 对于内存,limit 表示容器可以使用的最大内存量,例如,"1Gi" 表示 1 Gibibyte 的内存。

  • 这些资源限制有助于 Kubernetes 在集群中的资源管理和调度。当 Pod 的资源使用接近或超出 limit 时,Kubernetes 可以采取相应的措施,如强制删除或重新启动 Pod,以保护节点的稳定性和可用性

Pod 和容器中定义资源请求和限制的具体字段

spec.containers[].resources.requests.cpu        //定义创建容器时预分配的CPU资源
spec.containers[].resources.requests.memory        //定义创建容器时预分配的内存资源
spec.containers[].resources.limits.cpu            //定义 cpu 的资源上限 
spec.containers[].resources.limits.memory        //定义内存的资源上限
  • spec.containers[].resources.requests.cpu:指定容器创建时所需的 CPU 资源数量。例如,"100m" 表示 0.1 个 CPU 核心。

  • spec.containers[].resources.requests.memory:指定容器创建时所需的内存资源数量。例如,"256Mi" 表示 256 兆字节的内存。

  • spec.containers[].resources.limits.cpu:指定容器允许使用的最大 CPU 资源数量。例如,"500m" 表示 0.5 个 CPU 核心。

  • spec.containers[].resources.limits.memory:指定容器允许使用的最大内存资源数量。例如,"1Gi" 表示 1 Gibibyte 的内存。

CPU资源单位

对于 CPU 资源,Kubernetes 中的一个 CPU 相当于一个虚拟 CPU(vCPU),也就是一个超线程。您可以使用小数或毫核(m)单位来表示 CPU 资源请求和限制。例如,0.5 表示占用一半的 CPU 资源,而 100m 表示每 1000 毫秒容器可以使用 0.1 个 CPU 核心的 CPU 时间总量。

内存资源单位

对于内存资源,Kubernetes 使用字节作为单位,并支持以10或2为底数的指数单位表示。例如,1KB 等于 1000 字节,1MB 等于 1000KB,1GB 等于 1000MB,而 1KiB 等于 1024 字节,1MiB 等于 1024KiB。

示例

官网示例: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

https://kubernetes.io/zh-cn/docs/concepts/configuration/manage-resources-containers/

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m" 
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

这是一个 Kubernetes Pod 的 YAML 配置示例。在这个配置中,有两个容器:一个是名为 "app" 的应用容器,另一个是名为 "log-aggregator" 的日志聚合容器。

对于 "app" 容器:

  • 请求了最少 250 毫核的 CPU 和 64 Mi 的内存。

  • 限制了最多 500 毫核的 CPU 和 128 Mi 的内存。

对于 "log-aggregator" 容器:

  • 请求了最少 250 毫核的 CPU 和 64 Mi 的内存。

  • 限制了最多 500 毫核的 CPU 和 128 Mi 的内存。

这样的配置有助于 Kubernetes 在调度 Pod 时了解每个容器的资源需求和限制,并有效地管理集群中的资源。

vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: web
    image: nginx
    env:
    - name: WEB_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "abc123"
    resources:
      requests:
        memory: "512Mi"  128
        cpu: "0.5"
      limits:
        memory: "1Gi"    256
        cpu: "1"




kubectl apply -f pod2.yaml
kubectl describe pod frontend

kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
frontend   2/2     Running   5          15m   10.244.2.4   node02   <none>           <none>

kubectl describe nodes node02                #由于当前虚拟机有2个CPU,所以Pod的CPU Limits一共占用了50%

这是一个包含两个容器的 Pod 配置示例。其中一个容器是名为 "web" 的 nginx 应用,另一个是名为 "db" 的 MySQL 数据库。

对于 "web" 容器:

  • 请求了最少 250 毫核的 CPU 和 64 Mi 的内存。

  • 限制了最多 500 毫核的 CPU 和 128 Mi 的内存。

对于 "db" 容器:

  • 请求了最少 0.5 个 CPU 和 512 Mi 的内存。

  • 限制了最多 1 个 CPU 和 1 Gi 的内存。

根据结果,Pod 已成功创建并正在运行,其中 "frontend" Pod 中的两个容器都已经准备就绪。

查看节点信息时,可以看到 "frontend" Pod 中的 CPU Limits 已占用了 50%,这是因为每个容器的 CPU Limits 分别为 500m 和 1,加起来为 1100m,占用了节点总计 2 个 CPU 中的一半。

这个配置示例演示了如何定义 Pod 中多个容器的资源请求和限制,并在集群中管理这些资源。

健康检查(探针)

Kubernetes中的健康检查是一种机制,用于监视和确保容器内的应用程序的状态。通过存活性探针和就绪性探针,Kubernetes可以周期性地检查容器内部的应用程序,以确定它们是否处于健康状态。存活性探针用于确定容器内的应用程序是否仍然运行,而就绪性探针用于确定容器是否已准备好接收流量。这些探针允许Kubernetes根据应用程序的状态自动进行故障恢复、水平扩展和负载均衡。

探针的三种规则

  • livenessProbe(存活性探针):用于判断容器是否正在运行。如果存活性探针失败,kubelet会杀死容器,并且根据restartPolicy设置Pod的状态。

  • readinessProbe(就绪性探针):用于判断容器是否准备好接受请求。如果就绪性探针失败,端点控制器将从与Pod匹配的所有service的endpoints中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。

  • startupProbe(启动探针):这是在Kubernetes 1.17版本中新增的。它用于判断容器内的应用程序是否已启动,特别针对于不能确定具体启动时间的应用。在startupProbe状态为Success之前,其他所有探针都处于无效状态。如果startupProbe失败,kubelet将杀死容器,并根据restartPolicy进行重启。

这些规则可以同时定义,但在readinessProbe检测成功之前,Pod的running状态是不会变成ready状态的。

存活探针(Liveness Probe)

存活探针的目的是确保应用程序在运行期间保持响应。Kubernetes定期执行存活探针来检查容器是否还活着。如果探针检测到容器不响应,Kubernetes会根据Pod的重启策略重启该容器。

工作流程

  • 初始化:容器启动后,Kubelet开始定期执行存活探针。

  • 检查:执行定义的存活检查(Exec、HTTP GET或TCP Socket)。

  • 评估:根据探针的结果(成功或失败)执行操作。

  • 成功:容器继续运行。

  • 失败:Kubelet根据Pod的重启策略(如Always、OnFailure)杀死并重启容器。

就绪探针(Readiness Probe)

就绪探针的目的是确保容器准备好接受流量。这对于控制流量仅被发送到已准备好处理请求的容器至关重要,尤其是在启动时间较长或有暂时性依赖的应用程序中。

工作流程

  • 初始化:容器启动后,Kubelet开始定期执行就绪探针。

  • 检查:执行定义的就绪检查。

  • 评估:根据探针的结果调整服务状态。

  • 成功:容器标记为就绪,开始接收流量。

  • 失败:容器标记为未就绪,停止接收流量,直到探针再次成功。

启动探针(Startup Probe)

启动探针的目的是确保应用程序启动成功。它在容器启动阶段特别有用,特别是对于启动时间较长的应用程序。一旦启动探针成功,就不再执行,转而执行存活和就绪探针。

工作流程

  • 初始化:容器启动后,Kubelet开始执行启动探针。

  • 检查:执行定义的启动检查。

  • 评估:根据探针的结果执行操作。

  • 成功:停止启动探针,开始执行存活和就绪探针。

  • 失败:根据定义的重试次数和间隔继续尝试,直到成功或超时。

总结

这三种类型的探针协同工作,以确保容器不仅成功启动(启动探针),而且在其生命周期中保持活动状态(存活探针)并准备好接受流量(就绪探针)。通过这种方式,Kubernetes能够更有效地管理容器的生命周期,确保服务的高可用性和稳定性。

Pod的生命周期可以分为几个阶段:

启动、就绪和存活。在这个过程中,探针起着关键的作用。

  • 启动阶段

  • 当Pod启动时,Kubelet会执行启动探针。这个探针的目的是确保应用程序成功启动。如果启动探针失败,Kubelet会在定义的重试次数和间隔内尝试重新启动容器,直到成功或超时。

  • 一旦启动探针成功,Pod将进入下一个阶段。

  • 就绪阶段

  • 在就绪阶段,Kubelet会开始执行就绪探针。这个探针用于检查容器是否已准备好接受流量。如果就绪探针失败,Pod将被标记为未就绪,停止接收流量,直到就绪探针再次成功。

  • 如果就绪探针成功,Pod将被标记为就绪,开始接收流量。

  • 运行阶段

  • 一旦Pod就绪,Kubelet会定期执行存活探针,以确保容器在运行期间保持响应。如果存活探针失败,Kubernetes将根据Pod的重启策略(如Always、OnFailure)杀死并重启容器。

  • 如果存活探针一直成功,Pod将持续处于运行状态,处理传入的请求。

  • 结束阶段

  • 当Pod终止时,不再执行存活和就绪探针。Kubelet会根据终止信号或策略停止容器,结束Pod的生命周期。

在整个过程中,这些探针协同工作,确保Pod在启动、运行和终止的各个阶段都处于健康状态。这种机制有助于提高容器的可用性,确保应用程序在Kubernetes集群中稳定运行。

探针支持三种检查方法

  • exec(执行探针):在容器内执行指定的命令。如果命令的返回码为0,则认为探针检查成功,否则被认为是失败的。

  • tcpSocket(TCP套接字探针):对容器的IP地址上的指定端口执行TCP检查,通过进行三次握手来判断端口是否打开。如果端口是打开的,探针检查被认为是成功的。

  • httpGet(HTTP探针):对容器的IP地址上的指定端口和路径执行HTTP GET请求。如果响应的状态码大于等于200且小于400,则探针检查被认为是成功的。这通常用于检查应用程序是否能够正常响应HTTP请求。

每次探测都会获得以下三种结果之一:

  • 成功:容器通过了诊断,即探针检查成功。

  • 失败:容器未通过诊断,即探针检查失败。

  • 未知:诊断失败,无法确定容器的状态,因此不会采取任何行动。这通常发生在无法与容器进行通信或者探针配置有误时。

示例

官网示例: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

示例1:exec方式

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:  
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      failureThreshold: 1 
      initialDelaySeconds: 5
      periodSeconds: 5

#initialDelaySeconds:指定 kubelet 在执行第一次探测前应该等待5秒,即第一次探测是在容器启动后的第6秒才开始执行。默认是 0 秒,最小值是 0。
#periodSeconds:指定了 kubelet 应该每 5 秒执行一次存活探测。默认是 10 秒。最小值是 1。
#failureThreshold: 当探测失败时,Kubernetes 将在放弃之前重试的次数。 存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1。
#timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。(在 Kubernetes 1.20 版本之前,exec 探针会忽略 timeoutSeconds 探针会无限期地 持续运行,甚至可能超过所配置的限期,直到返回结果为止。)

可以看到 Pod 中只有一个容器。kubelet 在执行第一次探测前需要等待 5 秒,kubelet 会每 5 秒执行一次存活探测。kubelet 在容器内执行命令 cat /tmp/healthy 来进行探测。如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。 当到达第 31 秒时,这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。

这是一个使用exec方式定义存活性探针的Pod示例。在这个例子中,Pod包含一个容器,该容器运行了一个脚本,负责在/tmp/healthy路径下创建文件、等待30秒、删除文件、再等待60秒。探针使用exec方式,执行cat /tmp/healthy命令,如果成功(返回值为0),则认为容器是健康的。

一些关键的配置参数包括:

  • initialDelaySeconds:kubelet在执行第一次探测前等待的时间,这里是5秒。

  • periodSeconds:kubelet执行探测的间隔,这里是5秒。

  • failureThreshold:探测失败的重试次数,超过次数则认为容器失败,这里是1次。

在这个例子中,当到达第31秒时,exec命令返回非0值,kubelet将杀死容器并重新启动。

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

kubectl create -f exec.yaml

kubectl describe pods liveness-exec

kubectl get pods -w

Pod配置文件(exec.yaml)定义了一个名为"liveness-exec"的Pod,包含一个名为"liveness-exec-container"的容器。该容器在启动时执行一段命令,创建并删除/tmp/live文件,然后等待3600秒。

已成功使用kubectl创建了该Pod,并通过kubectl describe命令查看了Pod的事件。从事件中可以看到,在执行liveness探针时,它失败了,并触发了容器的重新启动。Pod状态显示了1次重启,表明liveness探针的失败导致了容器的重新启动。

最后,通过kubectl get pods命令您可以看到该Pod的状态,它现在是Running状态,但经历了1次重启。这表明Kubernetes根据liveness探针的结果进行了自动的容器恢复。

示例2:httpGet方式

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

这个Pod定义了一个名为"liveness-http"的容器,使用了httpGet方式进行存活性探测。容器使用"k8s.gcr.io/liveness"镜像,并在启动时运行/server命令。

存活性探针配置如下:

  • httpGet:执行HTTP GET请求以检查容器的健康状态。

  • path:指定请求的路径为/healthz。

  • port:指定容器的端口为8080。

  • httpHeaders:可选项,用于指定HTTP请求头。这里设置了一个自定义的请求头Custom-Header,值为Awesome。

  • initialDelaySeconds:kubelet在容器启动后等待3秒钟后开始执行第一次探测。

  • periodSeconds:指定kubelet每3秒钟执行一次存活性探测。

这个配置将定期向容器发送HTTP GET请求,检查/healthz路径是否可访问,并检查容器是否正常响应。如果连续探测失败,Kubernetes将根据重启策略采取相应的行动。

vim httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: soscscs/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

kubectl create -f httpget.yaml

kubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.html

kubectl get pods

httpget http://IP:80/index.html  delay 延迟 =3  tomout=10s    period(频率)=3s   succes(成功)=1  faulure(失败)=3 机会      杀死容器

创建了一个名为"liveness-httpget"的Pod,并指定了一个名为"liveness-httpget-container"的容器。该容器使用了一个名为"soscscs/myapp:v1"的镜像,并暴露了端口80。

该容器配置了一个HTTP GET方式的存活性探针,它会定期(每3秒)向端口80发送一个HTTP GET请求,检查/index.html路径是否可访问。如果在10秒内没有收到响应,则认为探针失败。初始的探测将在容器启动后1秒钟开始。

已经通过kubectl create命令创建了该Pod,并且模拟了一个故障情况,即删除了/index.html文件。随后,Pod经历了1次重启,这是因为存活性探针探测到/index.html路径不可用,并且达到了重试次数的上限(3次)。因此,Kubernetes将杀死了该容器,并根据重启策略进行了重新启动。

示例3:tcpSocket方式

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

这个Pod配置文件定义了一个名为"goproxy"的Pod,该Pod包含一个名为"goproxy"的容器,使用了"k8s.gcr.io/goproxy:0.1"镜像,并将端口8080暴露出来。

该Pod配置了就绪性探针和存活性探针:

  • 就绪性探针(readinessProbe):使用了tcpSocket方式,检查容器的端口8080是否处于就绪状态。它会在容器启动后等待5秒钟后开始进行首次探测,然后每10秒进行一次探测。

  • 存活性探针(livenessProbe):同样使用了tcpSocket方式,检查容器的端口8080是否处于存活状态。它会在容器启动后等待15秒钟后开始进行首次探测,然后每20秒进行一次探测。

这些探针将帮助Kubernetes确保Pod的健康状态,并在需要时进行自动恢复或者负载均衡。

vim tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: soscscs/myapp:v1
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 8080
      periodSeconds: 10
      failureThreshold: 2

kubectl create -f tcpsocket.yaml

kubectl exec -it probe-tcp  -- netstat -natp

kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
probe-tcp   1/1     Running             0          1s
probe-tcp   1/1     Running             1          25s       #第一次是 init(5秒) + period(10秒) * 2
probe-tcp   1/1     Running             2          45s       #第二次是 period(10秒) + period(10秒)  重试了两次
probe-tcp   1/1     Running             3          65s

在这个示例中,创建了一个名为"probe-tcp"的Pod,其中包含一个名为"nginx"的容器,使用了"soscscs/myapp:v1"镜像。该容器配置了一个使用tcpSocket方式的存活性探针,检查端口8080的状态。

存活性探针的配置如下:

  • initialDelaySeconds:容器启动后等待5秒钟后开始首次探测。

  • timeoutSeconds:设置探测超时时间为1秒。

  • tcpSocket:指定使用tcpSocket方式进行探测,检查端口8080的状态。

  • periodSeconds:设置每10秒进行一次探测。

  • failureThreshold:设置在失败2次后触发重新启动容器。

通过kubectl create命令创建了该Pod,并通过kubectl exec命令查看了容器内的网络状态。使用了netstat命令来查看端口监听状态,显示端口80处于监听状态。

随后,通过kubectl get pods命令观察了Pod的状态变化。Pod经历了3次重启,这是因为存活性探针探测到端口8080失败,并且达到了失败次数的上限(failureThreshold为2次)。因此,Kubernetes根据重启策略进行了重新启动容器。

示例4:就绪检测

vim readiness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: soscscs/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

kubectl create -f readiness-httpget.yaml

//readiness探测失败,无法进入READY状态
kubectl get pods 
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   0/1     Running   0          18s

kubectl exec -it readiness-httpget sh
 # cd /usr/share/nginx/html/
 # ls
50x.html    index.html
 # echo 123 > index1.html 
 # exit

kubectl get pods 

kubectl exec -it readiness-httpget -- rm -rf /usr/share/nginx/html/index.html

kubectl get pods -w

这个YAML文件描述了一个Pod,其中包含一个容器,名为readiness-httpget-container,使用了一个名为soscscs/myapp:v1的镜像。该容器暴露了端口80,并配置了就绪探测和存活探测。就绪探测尝试在端口80上发送HTTP GET请求到路径/index1.html,而存活探测尝试在端口http上发送HTTP GET请求到路径/index.html。初始延迟为1秒,间隔为3秒。如果就绪探测失败,Pod将不会被视为READY状态。存活探测具有相同的初始延迟和间隔,并设置了超时时间为10秒。

在操作中,readiness探测一开始失败,因为无法访问/index1.html。然后通过在容器中创建index1.html文件,成功使得就绪探测通过,Pod进入READY状态。接着,删除了/index.html文件,导致存活探测失败,并且Pod被重启。

示例5:就绪检测2

vim readiness-myapp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp1
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp2
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp3
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80

kubectl create -f readiness-myapp.yaml

kubectl get pods,svc,endpoints -o wide

kubectl exec -it pod/myapp1 -- rm -rf /usr/share/nginx/html/index.html

//readiness探测失败,Pod 无法进入READY状态,且端点控制器将从 endpoints 中剔除删除该 Pod 的 IP 地址
kubectl get pods,svc,endpoints -o wide

这个YAML文件描述了三个Pod,每个Pod都有一个名为myapp的容器,使用了相同的镜像soscscs/myapp:v1。每个容器都暴露了端口80,并配置了就绪探测,尝试在端口80上发送HTTP GET请求到路径/index.html。初始延迟为5秒,间隔为5秒,超时时间为10秒。

创建完这些Pod后,我删除了myapp1 Pod中的/index.html文件,导致就绪探测失败,该Pod无法进入READY状态。端点控制器从endpoints中移除了该Pod的IP地址。

现在,endpoints/myapp仅显示了myapp2和myapp3 Pod的IP地址,因为myapp1 Pod已经被从其中剔除了。

启动和退出动作

vim post.yaml
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: soscscs/myapp:v1
    lifecycle:   #此为关键字段
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler >> /var/log/nginx/message"]      
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the poststop handler >> /var/log/nginx/message"]
    volumeMounts:
    - name: message-log
      mountPath: /var/log/nginx/
      readOnly: false
  initContainers:
  - name: init-myservice
    image: soscscs/myapp:v1
    command: ["/bin/sh", "-c", "echo 'Hello initContainers'   >> /var/log/nginx/message"]
    volumeMounts:
    - name: message-log
      mountPath: /var/log/nginx/
      readOnly: false
  volumes:
  - name: message-log
    hostPath:
      path: /data/volumes/nginx/log/
      type: DirectoryOrCreate

kubectl create -f post.yaml

kubectl get pods -o wide
         <none>

kubectl exec -it lifecycle-demo -- cat /var/log/nginx/message

"lifecycle-demo" 的 Pod,其中包含了一个容器以及一个初始化容器。关键字段是 lifecycle,它定义了在容器生命周期中执行的操作。在这个例子中,定义了 postStartpreStop 两个生命周期处理器。postStart 处理器在容器启动后执行,用来执行一些初始化任务,而 preStop 处理器在容器停止前执行,用来执行一些清理任务。

postStart 处理器中,通过执行 /bin/sh -c 命令来向文件 /var/log/nginx/message 中添加一条消息。在 preStop 处理器中,也通过执行相似的命令向同一个文件中添加另一条消息。

最后,通过 kubectl create -f post.yaml 创建 Pod,然后通过 kubectl get pods -o wide 查看 Pod 的状态,并通过 kubectl exec -it lifecycle-demo -- cat /var/log/nginx/message 命令查看容器中 /var/log/nginx/message 文件的内容,确认了消息的输出。

在 node02 节点上查看

在 node02 节点上查看
[root@node02 ~]# cd /data/volumes/nginx/log/
[root@node02 log]# ls
access.log  error.log  message
[root@node02 log]# cat message 
Hello initContainers
Hello from the postStart handler
#由上可知,init Container先执行,然后当一个主容器启动后,Kubernetes 将立即发送 postStart 事件。

//删除 pod 后,再在 node02 节点上查看
kubectl delete pod lifecycle-demo

[root@node02 log]# cat message 
Hello initContainers
Hello from the postStart handler
Hello from the poststop handler
#由上可知,当在容器被终结之前, Kubernetes 将发送一个 preStop 事件。

在第一次查看日志时,我们可以看到在 initContainers 中的消息 "Hello initContainers",然后是主容器中的消息 "Hello from the postStart handler"。这证实了初始化容器会在主容器之前启动,并且 postStart 事件会在主容器启动后立即执行。

在删除 Pod 后,再次查看日志,我们可以看到新增了 "Hello from the poststop handler",这是因为在 Pod 被终结之前,Kubernetes 发送了 preStop 事件,执行了相应的处理器,向日志中添加了新的消息

相关推荐
运维小文9 分钟前
K8S中的服务质量QOS
云原生·容器·kubernetes
华为云开发者联盟12 分钟前
Karmada v1.12 版本发布!单集群应用迁移可维护性增强
云原生·kubernetes·开源·容器编排·karmada
网络安全queen22 分钟前
【D03】SNMP、NETBIOS和SSH
运维·网络·web安全·ssh
march of Time22 分钟前
centos系统如何安装kubectl和部署kube-apiserver
linux·运维·centos
꧁༺朝花夕逝༻꧂23 分钟前
nginx-代理服务
运维·服务器·nginx
Hadoop_Liang23 分钟前
Kubernetes Secret的创建与使用
云原生·容器·kubernetes
time_silence24 分钟前
微服务——不熟与运维
运维·微服务·架构
-指短琴长-26 分钟前
Docker之技术架构【八大架构演进之路】
docker·容器·架构
Smile_Gently26 分钟前
Ubuntu环境 nginx.conf详解(二)
运维·服务器·前端·nginx·ubuntu
元气满满的热码式28 分钟前
K8S集群部署实战(超详细)
云原生·容器·kubernetes