目录
[Pod 资源限制方式](#Pod 资源限制方式)
[Pod 和容器中定义资源请求和限制的具体字段](#Pod 和容器中定义资源请求和限制的具体字段)
[存活探针(Liveness Probe)](#存活探针(Liveness Probe))
[就绪探针(Readiness Probe)](#就绪探针(Readiness Probe))
[启动探针(Startup Probe)](#启动探针(Startup Probe))
资源限制
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请求。
每次探测都会获得以下三种结果之一:
-
成功:容器通过了诊断,即探针检查成功。
-
失败:容器未通过诊断,即探针检查失败。
-
未知:诊断失败,无法确定容器的状态,因此不会采取任何行动。这通常发生在无法与容器进行通信或者探针配置有误时。
示例
示例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
,它定义了在容器生命周期中执行的操作。在这个例子中,定义了 postStart
和 preStop
两个生命周期处理器。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
事件,执行了相应的处理器,向日志中添加了新的消息