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

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

目录

资源限制

查看资源控制字段

Pod 资源限制方式

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

CPU资源单位

内存资源单位

示例

健康检查(探针)

探针的三种规则

存活探针(Liveness Probe)

就绪探针(Readiness 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: appimage: images.my-company.example/app:v4env:- name: MYSQL_ROOT_PASSWORDvalue: "password"resources:requests:memory: "64Mi"cpu: "250m" limits:memory: "128Mi"cpu: "500m"- name: log-aggregatorimage: images.my-company.example/log-aggregator:v6resources: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: webimage: nginxenv:- name: WEB_ROOT_PASSWORDvalue: "password"resources:requests:memory: "64Mi"cpu: "250m"limits:memory: "128Mi"cpu: "500m"- name: dbimage: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: "abc123"resources:requests:memory: "512Mi"  128cpu: "0.5"limits:memory: "1Gi"    256cpu: "1"kubectl apply -f pod2.yaml
kubectl describe pod frontendkubectl 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: livenessname: liveness-exec
spec:containers:- name: livenessimage: k8s.gcr.io/busyboxargs:  - /bin/sh- -c- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60livenessProbe:exec:command:- cat- /tmp/healthyfailureThreshold: 1 initialDelaySeconds: 5periodSeconds: 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-execnamespace: default
spec:containers:- name: liveness-exec-containerimage: busyboximagePullPolicy: IfNotPresentcommand: ["/bin/sh","-c","touch /tmp/live ; sleep 30; rm -rf /tmp/live; sleep 3600"]livenessProbe:exec:command: ["test","-e","/tmp/live"]initialDelaySeconds: 1periodSeconds: 3kubectl create -f exec.yamlkubectl describe pods liveness-execkubectl 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: livenessname: liveness-http
spec:containers:- name: livenessimage: k8s.gcr.io/livenessargs:- /serverlivenessProbe:httpGet:path: /healthzport: 8080httpHeaders:- name: Custom-Headervalue: AwesomeinitialDelaySeconds: 3periodSeconds: 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-httpgetnamespace: default
spec:containers:- name: liveness-httpget-containerimage: soscscs/myapp:v1imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80livenessProbe:httpGet:port: httppath: /index.htmlinitialDelaySeconds: 1periodSeconds: 3timeoutSeconds: 10kubectl create -f httpget.yamlkubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.htmlkubectl get podshttpget 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: goproxylabels:app: goproxy
spec:containers:- name: goproxyimage: k8s.gcr.io/goproxy:0.1ports:- containerPort: 8080readinessProbe:tcpSocket:port: 8080initialDelaySeconds: 5periodSeconds: 10livenessProbe:tcpSocket:port: 8080initialDelaySeconds: 15periodSeconds: 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: nginximage: soscscs/myapp:v1livenessProbe:initialDelaySeconds: 5timeoutSeconds: 1tcpSocket:port: 8080periodSeconds: 10failureThreshold: 2kubectl create -f tcpsocket.yamlkubectl exec -it probe-tcp  -- netstat -natpkubectl 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-httpgetnamespace: default
spec:containers:- name: readiness-httpget-containerimage: soscscs/myapp:v1imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index1.htmlinitialDelaySeconds: 1periodSeconds: 3livenessProbe:httpGet:port: httppath: /index.htmlinitialDelaySeconds: 1periodSeconds: 3timeoutSeconds: 10kubectl create -f readiness-httpget.yaml//readiness探测失败,无法进入READY状态
kubectl get pods 
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   0/1     Running   0          18skubectl exec -it readiness-httpget sh# cd /usr/share/nginx/html/# ls
50x.html    index.html# echo 123 > index1.html # exitkubectl get pods kubectl exec -it readiness-httpget -- rm -rf /usr/share/nginx/html/index.htmlkubectl 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: myapp1labels:app: myapp
spec:containers:- name: myappimage: soscscs/myapp:v1ports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index.htmlinitialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:name: myapp2labels:app: myapp
spec:containers:- name: myappimage: soscscs/myapp:v1ports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index.htmlinitialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:name: myapp3labels:app: myapp
spec:containers:- name: myappimage: soscscs/myapp:v1ports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index.htmlinitialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 10 
---
apiVersion: v1
kind: Service
metadata:name: myapp
spec:selector:app: myapptype: ClusterIPports:- name: httpport: 80targetPort: 80kubectl create -f readiness-myapp.yamlkubectl get pods,svc,endpoints -o widekubectl 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-containerimage: soscscs/myapp:v1lifecycle:   #此为关键字段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-logmountPath: /var/log/nginx/readOnly: falseinitContainers:- name: init-myserviceimage: soscscs/myapp:v1command: ["/bin/sh", "-c", "echo 'Hello initContainers'   >> /var/log/nginx/message"]volumeMounts:- name: message-logmountPath: /var/log/nginx/readOnly: falsevolumes:- name: message-loghostPath:path: /data/volumes/nginx/log/type: DirectoryOrCreatekubectl create -f post.yamlkubectl 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 事件,执行了相应的处理器,向日志中添加了新的消息

相关文章:

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

目录 资源限制 查看资源控制字段 Pod 资源限制方式 Pod 和容器中定义资源请求和限制的具体字段 CPU资源单位 内存资源单位 示例 健康检查&#xff08;探针&#xff09; 探针的三种规则 存活探针&#xff08;Liveness Probe&#xff09; 就绪探针&#xff08;Readines…...

SpringBoot整合ActiveMQ步骤

SpringBoot整合ActiveMQ主要涉及以下几个步骤&#xff1a; 添加依赖&#xff1a;在SpringBoot项目的pom.xml文件中添加ActiveMQ的依赖。 <dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-spring</artifactId><ver…...

MySQL的单表和多表查询

我们在前面曾构建过三个用于实验的表格&#xff0c;下面将基于这三个表进行实践。 # 建立一个用于实验的三个表格 mysql> create table emp (-> empno varchar(10),-> ename varchar(50),-> job varchar(50),-> mgr int,-> hiredate timestamp,-&…...

攻防世界例题wp

1.看到_wakeup()函数第一反应要么触发&#xff0c;要么绕过在这里绕过 2.构造payload实例化一个对象后反序列化 3构造脚本如下&#xff1a; 4.因为它是一个绕过的方法所以我们要使用绕过的方法。 5.继续构造payload将上图的1换成2进行绕过 最终的payload为 O:4:"xctf…...

仿牛客网项目---显示评论和添加评论功能的实现

这篇文章&#xff0c;我来介绍一下我的项目中的另外一个功能&#xff1a;显示评论和添加评论。 其实这两个功能都不怎么重要&#xff0c;我感觉最重要的应该是用户注册登录功能&#xff0c;这个也了解一下&#xff0c;知道这么一回事儿就好。 首先设计DAO层。 Mapper public …...

idea集成git详解教程(实用篇)

0.Git常用命令 Git常用命令-CSDN博客 1.下载git Git - Downloads 一路傻瓜式安装即可&#xff08;NEXT&#xff09; 2.软件测试 在Windows桌面空白处&#xff0c;点击鼠标右键&#xff0c;弹出右键菜单 Git软件安装后&#xff0c;会在右键菜单中增加两个菜单 Git GUI He…...

搭建LNMP环境并配置个人博客系统

LNMP是Linux&#xff08;操作系统&#xff09;、Nginx&#xff08;Web服务器&#xff09;、MySQL&#xff08;数据库&#xff09;和PHP&#xff08;脚本解释器&#xff09;的组合&#xff0c;常用于部署高性能的动态网站&#xff0c;如WordPress等博客平台 一、安装Linux操作系…...

为什么网络安全缺口这么大,还是这么缺网络安全工程师?

为啥网安领域缺口多达300多万人&#xff0c;但网安工程师&#xff08;白帽黑客&#xff09;却很少&#xff0c;难道又是砖家在忽悠人&#xff1f;&#xff1f;&#xff1f; 主要原因为这三点: 首先是学校的原因&#xff0c;很多学校网络安全课程用的还都是十年前的老教材&…...

创新洞察|诺奖获得者埃德蒙·费尔普斯谈未来:中国创新从何而来?

当下&#xff0c;全球宏观经济形势正在发生深刻变化&#xff0c;以创新推进高质量发展被推向前所未有的高度。作为多年与中国经济结伴而行的经济学家、2006年诺贝尔经济学奖得主&#xff0c;埃德蒙费尔普斯认为&#xff1a;创新无处不在&#xff0c;而中国人具有巨大的创新活力…...

SpringMVC 学习(六)之视图

目录 1 SpringMVC 视图介绍 2 JSP 视图 3 Thymeleaf 视图 4 FreeMarker 视图 5 XSLT 视图 6 请求转发与重定向 6.1 请求转发 (Forward) 6.2 重定向 (Redirect) 7 视图控制器 (view-controller) 1 SpringMVC 视图介绍 在 SpringMVC 框架中&#xff0c;视图可以是一个 J…...

ROS 2基础概念#1:计算图(Compute Graph)| ROS 2学习笔记

在ROS中&#xff0c;计算图&#xff08;ROS Compute Graph&#xff09;是一个核心概念&#xff0c;它描述了ROS节点之间的数据流动和通信方式。它不仅仅是一个通信网络&#xff0c;它也反映了ROS设计哲学的核心——灵活性、模块化和可重用性。通过细致探讨计算图的高级特性和实…...

一本通 1403:素数对

在判断素数对的两个数是否都为素数时可以只判断数的一半 #include<bits/stdc.h> using namespace std; bool su(int a,int b){ for(int i2;i<sqrt(a);i){ if(a%i0){ return 0; } } for(int i2;i<sqrt(b);i){ if(…...

华为---RSTP(四)---RSTP的保护功能简介和示例配置

目录 1. 技术背景 2. RSTP的保护功能 3. BPDU保护机制原理和配置命令 3.1 BPDU保护机制原理 3.2 BPDU保护机制配置命令 3.3 BPDU保护机制配置步骤 4. 根保护机制原理和配置命令 4.1 根保护机制原理 4.2 根保护机制配置命令 4.3 根保护机制配置步骤 5. 环路保护机…...

Android基础控件介绍

在Android应用程序开发中&#xff0c;使用基础控件是非常常见的。这些控件允许您在用户界面中显示文本、图像、按钮等元素&#xff0c;以及接收用户输入。本文将介绍几种常见的基础控件&#xff0c;并给出每个控件在示例XML中使用的属性的详细说明。 1. TextView TextView 是…...

【总结】Maxwell学习笔记

1.Maxwell简介 Maxwell 是一款用Java编写的MySQL变更数据抓取软件&#xff0c;它会实时监控Mysql数据库的数据变更操作&#xff08;包括insert、update、delete&#xff09;&#xff0c;并将变更数据以 JSON 格式发送给 Kafka、Kinesi等流数据处理平台 官网地址&#xff1a;M…...

AFL fork server和fuzzer的交互

看了一些博客&#xff0c;都是在说fuzzer和fork server进行交互&#xff0c;由fork server fork出子进程来执行程序&#xff0c;但是不太明白这两者到底是如何在代码层面进行交互的。 run_target中有这么一段代码&#xff0c;大概意思是fuzzer给fork server传递prev_timed_out…...

Java SE:多线程(Thread)

1. 线程两个基本概念 并发&#xff1a;即线程交替运行多个指令并行&#xff1a;即多个线程同时运行指令 并发并行不矛盾&#xff0c;两者可同时发生&#xff0c;即多个线程交替运行指令 2. 多线程3种实现方式 2.1 直接创建线程对象 /*** 方式1&#xff1a;* 1. 创建thread类的…...

你敢信?软件测试万能面试脚本他来了?

写在前面&#xff1a; 过春节了&#xff0c;四舍五入接下来马上要年底了&#xff0c;新一波的跳槽旺季马上来临&#xff0c;不知道你是不是已经安于现状&#xff0c;还是蓄势待发呢&#xff1f;最近我和我的哈皮群友们一顿讨论&#xff0c;拟写了大家可能会遇到的面试情况&…...

C++/Python简单练手题

前言 最近需要开始使用python&#xff0c;但是对python了解的并不多&#xff0c;于是先从很早之前刚学C时写过的一些练手题开始&#xff0c;使用python来实现相同的功能&#xff0c;在温习python基础语法的同时&#xff0c;也一起来感受感受python的魅力 99乘法表 c&#xf…...

视频在线压缩

video2edit 一款免费的在线视频编辑软件&#xff0c;可以进行视频合并、视频剪辑、视频压缩以及转换视频格式等。 链接地址&#xff1a;在线视频编辑器和转换器 - 编辑&#xff0c;转换和压缩视频文件 打开视频压缩页面&#xff0c;上传想要压缩视频&#xff0c;支持MP4&…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...