目录
引言
一、资源限制
(一)基本定义
(二)资源单位
1.CPU资源
2.内存资源
(三)请求与限制
(四)定义方式
1.编写yaml文件
2.查看资源情况
二、Pod探针机制
(一)检测方式
(二)存活探针
1.定义
2.使用方法
2.1 使用exec方式
2.2 使用httpGet方式
2.3 使用tcpSocket方式
(三)就绪探针
1.定义
2.探针使用
3.service探测
(四)启动探针
1.定义
2.探针应用
3.主要作用
(五)生命周期钩子
1.钩子种类
1.1 启动钩子(postStart)
1.2 停止钩子(preStop)
2.定义文件
3.启动pod
4.查看文件
5.重要性及应用场景
三、总结
(一)资源限制
(二)探针机制
(三)生命钩子
引言
在Kubernetes集群中,Pod是最小的部署单元,负责运行应用程序的容器。为了确保Pod的稳定运行和集群资源的高效利用,Kubernetes提供了Pod资源限制和探针机制。本文将详细介绍这两种机制及其在实际应用中的重要性。
一、资源限制
(一)基本定义
Pod资源限制是Kubernetes中一项重要的资源管理功能,用于限制Pod中的容器可以使用的CPU、内存等资源。这有助于防止因某个Pod消耗过多资源而导致整个集群性能下降或崩溃
官方网址:Resource Management for Pods and Containers | Kubernetes
(二)资源单位
CPU 和 内存 都是 资源类型。每种资源类型具有其基本单位
1.CPU资源
在Kubernetes中,CPU资源以核心数为单位,也支持带小数 。CPU 的请求可以表示为整数或小数(如0.5表示半个核心)
0.5=500m(毫核)表示每 1000 毫秒内容器可以使用的 CPU 时间总量为 0.5*1000 毫秒
Kubernetes 不允许设置精度小于 1m 的 CPU 资源
2.内存资源
内存资源以字节为单位,但通常使用更易读的单位(如Mi、Gi)来表示。
此外,Kubernetes还支持对临时存储资源进行限制。
(三)请求与限制
在定义Pod时,可以为每个容器指定资源请求(requests)和限制(limits)。请求表示容器正常运行所需的最小资源量,而限制则表示容器可以使用的最大资源量。Kubernetes调度器会根据Pod的资源请求来选择合适的节点进行调度,以确保节点具有足够的资源来满足Pod的需求。同时,kubelet会监控Pod中容器的资源使用情况,并在容器使用资源超过限制时采取相应的措施(如终止容器)
针对每个容器,你都可以指定其资源限制和请求,包括如下选项:
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.limits.hugepages-<size>
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
spec.containers[].resources.requests.hugepages-<size>
(四)定义方式
1.编写yaml文件
[root@master01 data]#vim resources.yaml
[root@master01 data]#cat resources.yaml
apiVersion: v1
kind: Pod
metadata:name: app
spec:containers:- name: nginxweb #容器的名称是nginxwebimage: nginx:1.18.0 #容器使用的Docker镜像是nginx的1.18.0版本resources: #定义容器的资源请求和限制requests: #定义容器的资源请求memory: "64Mi" #容器启动时请求的内存量为64MiBcpu: "250m" #容器启动时请求的CPU为250m(即0.25个CPU核心)limits: #定义容器的资源限制memory: "128Mi" #容器可以使用的最大内存量为128MiBcpu: "500m" #容器可以使用的最大CPU为500m(即0.5个CPU核心)- name: mysql #容器的名称是mysqlimage: mysql:5.7 #容器使用的Docker镜像是mysql的5.7版本env: #定义容器的环境变量- name: MYSQL_ROOT_PASSWORD #环境变量的名称,固定名称,不能自定义value: "abc123" #环境变量的值是abc123,MySQL root用户的密码resources: #定义容器的资源请求和限制requests: #定义容器的资源请求memory: "128Mi" #容器启动时请求的内存量为64MiBcpu: "0.5" #容器启动时请求的CPU为0.5个CPU核心limits: #定义容器的资源限制memory: "512Mi" #容器可以使用的最大内存量为512MiBcpu: "1" #容器可以使用的最大CPU为1个CPU核心
2.查看资源情况
[root@master01 data]#kubectl apply -f resources.yaml
pod/app created
[root@master01 data]#kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app 2/2 Running 0 4s 10.244.1.125 node01 <none> <none>
[root@master01 data]#kubectl describe nodes node01 |sed -n '/Non-terminated Pods/,/$$/p'
Non-terminated Pods: (3 in total)Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE--------- ---- ------------ ---------- --------------- ------------- ---default app 750m (18%) 1500m (37%) 192Mi (11%) 640Mi (37%) 78skube-flannel kube-flannel-ds-qvmn9 100m (2%) 0 (0%) 50Mi (2%) 0 (0%) 9dkube-system kube-proxy-zmh82 0 (0%) 0 (0%) 0 (0%) 0 (0%) 9d
Allocated resources:(Total limits may be over 100 percent, i.e., overcommitted.)Resource Requests Limits-------- -------- ------cpu 850m (21%) 1500m (37%)memory 242Mi (14%) 640Mi (37%)ephemeral-storage 0 (0%) 0 (0%)hugepages-1Gi 0 (0%) 0 (0%)hugepages-2Mi 0 (0%) 0 (0%)
Events: <none>----------------------------------------------------------------------------
#Non-terminated Pods:未终止或正在运行的pod详细信息
#CPU Requests:Pod请求的CPU资源量。这个值是一个相对值,表示Pod期望获得的CPU资源的百分比或毫核数
#CPU Limits: Pod可以使用的最大CPU资源量。如果CPU使用量超过这个限制,会被Kubernetes系统杀死
#Memory Requests: Pod请求的内存资源量。这个值是一个绝对值,表示Pod需要的内存量
#Memory Limits: Pod可以使用的最大内存资源量。如果Pod的内存使用量超过这个限制,也会被系统杀死#Allocated resources:这部分显示了节点上所有 Pods 的资源请求和限制的总和
#Resource:资源类型
#Requests: 显示了所有Pods请求的资源的总和
#Limits: 显示了所有Pods限制的资源的总和
二、Pod探针机制
Pod探针是Kubernetes中用于监控Pod内部容器状态的机制。通过探针,可以检测容器是否正在运行、是否准备好接收请求以及是否成功启动等状态。探针类型包括存活探针(livenessProbe)、就绪探针(readinessProbe)和启动探针(startupProbe)。
(一)检测方式
探针有三种检测方式
exec :在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。
tcpSocket :对指定端口上的容器的IP地址进行TCP检查(三次握手)。如果端口打开,则诊断被认为是成功的。
httpGet :对指定的端口和路径上的容器的IP地址执行HTTPGet请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的
每次探测都将获得以下三种结果之一:
成功:容器通过了诊断。
失败:容器未通过诊断。
未知:诊断失败,因此不会采取任何行动
(二)存活探针
1.定义
livenessProbe:存活探针
存活探针用于检测容器是否正在运行。如果探测失败,kubelet将杀死容器并根据重启策略进行重启。这有助于及时发现并修复容器中的故障,确保应用程序的可用性。
2.使用方法
2.1 使用exec方式
在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功
[root@master01 data]#vim liveness-exec.yaml
[root@master01 data]#cat liveness-exec.yaml
apiVersion: v1
kind: Pod
metadata:labels:test: livenessname: liveness-ex
spec:containers:- name: nginx-lnimage: nginx:1.18.0livenessProbe: #定义存活探针exec: #执行exec探针命令command: ["test","-e","/usr/share/nginx/html/index.php"]
#检查/usr/share/nginx/html/index.html文件是否存在。如果存在,探针会成功;如果不存在,探针会失败
#当探针失败后,会根据重启策略,决定是否重启,不指定策略默认会一直重启failureThreshold: 2 initialDelaySeconds: 5periodSeconds: 5 -------------------------------------------------------------------------------------
'failureThreshold'
#当探测失败时,Kubernetes将在放弃之前重试的次数。设置为2,表示可以重复2次,加上第一次默认执行一共为3次
#在存活探针中,放弃就意味着重新启动容器。
#在就绪探针中,放弃后Pod会被打上未就绪的标签。默认值是3。最小值是1'initialDelaySeconds'
#在容器启动后等待多长时间(以秒为单位)才开始执行探针。这允许容器有时间启动并准备好接受请求。'periodSeconds'
#指定了kubelet应该多长时间执行一次存活探测(以秒为单位)
追踪查看容器状态
[root@master01 data]#kubectl apply -f liveness-exec.yaml
pod/liveness created
[root@master01 data]#kubectl get pod -w
NAME READY STATUS RESTARTS AGE
liveness-ex 0/1 ContainerCreating 0 1s
liveness-ex 1/1 Running 0 2s
liveness-ex 0/1 Completed 0 17s
查看容器的事件信息
[root@master01 data]#kubectl describe pod liveness-ex |sed -n "/Events/,/$$/p"
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 2m24s default-scheduler Successfully assigned default/liveness-ex to node02Normal Pulled 2m24s kubelet Container image "nginx:1.18.0" already present on machineNormal Created 2m23s kubelet Created container nginx-lnNormal Started 2m23s kubelet Started container nginx-lnWarning Unhealthy 2m17s kubelet Liveness probe failed:Normal Killing 2m17s kubelet Stopping container nginx-ln
#探针失败,关闭容器
2.2 使用httpGet方式
[root@master01 data]#vim liveness-httpget.yaml
[root@master01 data]#cat liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:name: liveness-httpgetnamespace: default
spec:containers:- name: liveness-httpgetimage: nginx:1.18.0imagePullPolicy: IfNotPresent #定义镜像拉取策略ports:- name: http #定义端口名称,下面探测时使用containerPort: 80 #定义端口livenessProbe: #定义存活探针httpGet: #指定使用HTTP GET请求进行探测。port: http #这指定了要访问的容器的端口,为上面的http端口名称path: /index.html #这是要访问的HTTP路径。表示站点目录下的index.html文件initialDelaySeconds: 1periodSeconds: 3timeoutSeconds: 10 #探测的超时后等待多少秒。默认值是1秒。最小值是1
模拟探测失败
[root@master01 data]#kubectl apply -f liveness-httpget.yaml
pod/liveness-httpget created
[root@master01 data]#kubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.html
#删除探测的文件
同时在另一个终端上追踪信息
[root@master01 data]#kubectl get pod liveness-httpget -w
NAME READY STATUS RESTARTS AGE
liveness-httpget 0/1 ContainerCreating 0 3s
liveness-httpget 1/1 Running 0 3s
liveness-httpget 1/1 Running 1 34s
......
查看事件信息
[root@master01 data]#kubectl describe pod liveness-httpget |sed -n "/Events/,/$$/p"
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 80s default-scheduler Successfully assigned default/liveness-httpget to node02Warning Unhealthy 49s (x3 over 55s) kubelet Liveness probe failed: HTTP probe failed with statuscode: 404Normal Killing 49s kubelet Container liveness-httpget failed liveness probe, will be restartedNormal Pulled 48s (x2 over 79s) kubelet Container image "nginx:1.18.0" already present on machineNormal Created 48s (x2 over 79s) kubelet Created container liveness-httpgetNormal Started 48s (x2 over 79s) kubelet Started container liveness-httpget
#状态码为404,表示找不到文件,所以探测失败,而后重新创建容器
2.3 使用tcpSocket方式
[root@master01 data]#vim liveness-tcp.yaml
[root@master01 data]#cat liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:name: probe-tcp
spec:containers:- name: nginximage: nginx:1.18.0livenessProbe: #定义了存活探针的配置initialDelaySeconds: 5 #在容器启动后,等待5秒才开始进行存活检查timeoutSeconds: 1 #每次存活探针尝试的超时时间设置为 1 秒tcpSocket: #定义了使用 TCP 套接字进行探针检查port: 8080 #探针将尝试连接容器的8080端口periodSeconds: 10 #每隔10秒执行一次存活检查failureThreshold: 2 #如果连续2次探针检查都失败,会认为容器不再存活,并尝试重启该容器
生成pod并进行追踪
[root@master01 data]#kubectl apply -f liveness-tcp.yaml
pod/liveness-tcp created
[root@master01 data]#kubectl get pod liveness-tcp -w
NAME READY STATUS RESTARTS AGE
liveness-tcp 0/1 ContainerCreating 0 1s
liveness-tcp 1/1 Running 0 3s
liveness-tcp 1/1 Running 1 21s #第一次是init(5秒)+period(10秒)*2,一般会上下存在误差
liveness-tcp 1/1 Running 2 41s #第二次是period(10秒)+period(10秒)重试了两次
liveness-tcp 1/1 Running 3 61s
liveness-tcp 1/1 Running 4 81s
......
[root@master01 data]#kubectl describe pod liveness-tcp |sed -n '/Event/,/$$/p'
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 2m8s default-scheduler Successfully assigned default/liveness-tcp to node01Normal Created 69s (x4 over 2m7s) kubelet Created container nginxNormal Started 69s (x4 over 2m7s) kubelet Started container nginxNormal Pulled 50s (x5 over 2m7s) kubelet Container image "nginx:1.18.0" already present on machineWarning Unhealthy 50s (x8 over 2m) kubelet Liveness probe failed: dial tcp 10.244.1.128:8080: connect: connection refusedNormal Killing 50s (x4 over 110s) kubelet Container nginx failed liveness probe, will be restarted
(三)就绪探针
1.定义
就绪探针用于检测容器是否准备好接收请求。在容器启动过程中或更新后,可能需要一些时间才能完全准备好。就绪探针会定期探测容器状态,只有当容器就绪时才会将其加入到服务负载均衡中。这有助于避免将请求发送到尚未准备好的容器,提高服务的稳定性和可用性。
有时候,应用会暂时性地无法为请求提供服务。 例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用,也不想给它发送请求。 Kubernetes 提供了就绪探针来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量
2.探针使用
2.1 定义文件
使用httpGet的方式去使用就绪探针
[root@master01 data]#vim readiness-httpget.yaml
[root@master01 data]#cat readiness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:name: readiness-httpgetnamespace: default
spec:containers:- name: readiness-httpget-containerimage: nginx:1.18.0imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80readinessProbe: #定义就绪探针的配置,用于确定容器是否准备好接受流量httpGet: #使用 HTTP GET 请求进行探针检查。port: http #探针将尝试访问名为http的端口,上述自定义的端口名称path: /index.php #探针将尝试访问/index.php路径initialDelaySeconds: 1 #在容器启动后,等待1秒才开始进行就绪检查periodSeconds: 3 #每隔 3 秒执行一次就绪检查livenessProbe: #定义存活探针的配置httpGet: #同样使用 HTTP GET请求方式port: http #探针将尝试访问名为http的端口path: /index.html #探针将尝试访问 /index.html 路径,这是 Nginx 的默认首页initialDelaySeconds: 1 #等待 1 秒才开始进行存活检查periodSeconds: 3 #每隔 3 秒执行一次存活检查。timeoutSeconds: 10 #每次存活探针尝试的超时时间设置为 10 秒
2.2 查看结果
[root@master01 data]#kubectl apply -f readiness-httpget.yaml
pod/readiness-httpget created
[root@master01 data]#kubectl get pod readiness-httpget
NAME READY STATUS RESTARTS AGE
readiness-httpget 0/1 Running 0 3s
#容器状态处于Running,但是readiness探测失败,无法进入READY状态
可以通过查看event事件,找出错误信息
[root@master01 data]#kubectl get event |grep readiness-httpget
4m Normal Scheduled pod/readiness-httpget Successfully assigned default/readiness-httpget to node02
3m59s Normal Pulled pod/readiness-httpget Container image "nginx:1.18.0" already present on machine
3m59s Normal Created pod/readiness-httpget Created container readiness-httpget-container
3m58s Normal Started pod/readiness-httpget Started container readiness-httpget-container
2m54s Warning Unhealthy pod/readiness-httpget Readiness probe failed: HTTP probe failed with statuscode: 404#错误信息表示虽然成功启动容器,但是就绪探针在访问时找不到文件,出现404报错
解决此问题需要准备好就绪探针探测的文件,即index.php文件
[root@master01 data]#kubectl exec -it readiness-httpget bash
#进入容器
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@readiness-httpget:/# echo "this is index.php" > /usr/share/nginx/html/index.php
#添加探测文件
root@readiness-httpget:/# exit
exit
[root@master01 data]#kubectl get pod readiness-httpget
NAME READY STATUS RESTARTS AGE
readiness-httpget 1/1 Running 0 8m18s
#再次查看,进入READY状态
当删除index.html文件时,存活探针会探测失败,容器进行重启
[root@master01 data]#kubectl exec -it readiness-httpget -- rm -rf /usr/share/nginx/html/index.html
[root@master01 data]#kubectl get pod readiness-httpget -w
NAME READY STATUS RESTARTS AGE
readiness-httpget 1/1 Running 0 13m
readiness-httpget 0/1 Running 1 13m
3.service探测
如果探测失败,端点控制器将从与 Pod 匹配的所有service地址址endpoints中剔除删除该Pod的IP地。 初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success
3.1 定义文件
在yaml文件中添加三个Pod实例,并创建一个service去管理三个pod
[root@master01 data]#vim readiness-nginx.yaml
[root@master01 data]#cat readiness-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxlabels:app: nginx
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.18.0ports:- name: httpcontainerPort: 80readinessProbe:httpGet:port: 80path: /index.htmlinitialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 10
#创建deployment控制器,管理三个pod实例,定义探针策略
---
apiVersion: v1
kind: Service
metadata:name: nginx
spec:selector:app: nginxtype: ClusterIPports:- name: httpport: 80targetPort: 80
#创建service进行管理
执行文件后,会生成三个pod实例,并由service管理,当其中一个pod实例的就绪探针探测失败后,该地址会退出READY状态,且端点控制器将从 endpoints 中剔除删除该 Pod 的 IP 地址
[root@master01 data]#kubectl apply -f readiness-nginx.yaml
deployment.apps/nginx created
service/nginx created
[root@master01 data]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-848cb98b8f-rfmzp 1/1 Running 0 39s
nginx-848cb98b8f-tkh9d 1/1 Running 0 39s
nginx-848cb98b8f-tllxd 1/1 Running 0 39s
[root@master01 data]#kubectl get endpoints/nginx -o wide
NAME ENDPOINTS AGE
endpoints/nginx 10.244.2.147,10.244.1.129:80,10.244.1.130:80 107s
#查看关联的后端地址
[root@master01 data]#kubectl exec -it nginx-848cb98b8f-rfmzp -- rm -rf /usr/share/nginx/html/index.html
#删除其中一个pod实例的探针探索的文件
[root@master01 data]#kubectl get pods,svc,endpoints -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-848cb98b8f-rfmzp 0/1 Running 0 107s 10.244.2.147 node02 <none> <none>
pod/nginx-848cb98b8f-tkh9d 1/1 Running 0 107s 10.244.1.130 node01 <none> <none>
pod/nginx-848cb98b8f-tllxd 1/1 Running 0 107s 10.244.1.129 node01 <none> <none>
#被删除探针探索的文件的pod实例,退出READY状态
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d <none>
service/nginx ClusterIP 10.96.222.66 <none> 80/TCP 107s app=nginxNAME ENDPOINTS AGE
endpoints/kubernetes 192.168.83.30:6443 10d
endpoints/nginx 10.244.1.129:80,10.244.1.130:80 107s
#后端关联的podIP同时也被删除
同样的,当恢复完文件后,该pod实例会恢复正常,进入READY状态,同时将自己的地址添加到端点控制器当中
[root@master01 data]#kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-848cb98b8f-rfmzp 1/1 Running 0 21m 10.244.2.147 node02 <none> <none>
nginx-848cb98b8f-tkh9d 1/1 Running 0 21m 10.244.1.130 node01 <none> <none>
nginx-848cb98b8f-tllxd 1/1 Running 0 21m 10.244.1.129 node01 <none> <none>
[root@master01 data]#kubectl get endpoints nginx
NAME ENDPOINTS AGE
nginx 10.244.1.129:80,10.244.1.130:80,10.244.2.147:80 22m
(四)启动探针
1.定义
启动探针用于检测容器是否成功启动。在某些情况下,容器启动可能需要较长时间(如加载大量数据或执行初始化操作)。启动探针会在容器启动后立即开始探测,并在探测成功前阻止其他探针(如存活探针和就绪探针)的探测。这有助于确保容器在完全启动并准备好之前不会被错误地终止或加入到服务负载均衡中。
如果配置了 startupProbe 探测,在则在 startupProbe 状态为 Success 之前,其他所有探针都处于无效状态,直到它成功后其他探针才起作用。 如果 startupProbe 失败,kubelet 将杀死容器,容器将根据 restartPolicy 来重启。如果容器没有配置 startupProbe, 则默认状态为 Success
2.探针应用
写一个包含三种探针的yaml文件
[root@master01 data]#vim startup-httpget.yaml
[root@master01 data]#cat startup-httpget.yaml
apiVersion: v1
kind: Pod
metadata: name: nginx-startup-probe labels: app: nginx
spec: containers: - name: nginx image: nginx:1.18.0 ports:- name: httpcontainerPort: 80startupProbe:httpGet:path: /index1.html #探测的HTTP路径,确保你的应用可以提供该路径的响应 port: http #容器开放的端口failureThreshold: 30 #在标记容器启动失败之前,允许启动探针失败的次数periodSeconds: 10 #启动探针的探测频率(秒)successThreshold: 1 #在标记容器启动成功之前,需要启动探针成功的次数
#failureThreshold设置为30,表示在启动探针连续失败30次之后,容器将被标记为启动失败。
#periodSeconds设置为10,表示启动探针每10秒执行一次。
#successThreshold设置为1,表示只要启动探针成功一次,容器就被标记为启动成功。livenessProbe:httpGet:path: /index.htmlport: httpfailureThreshold: 3periodSeconds: 10readinessProbe:httpGet:path: /index.htmlport: httpfailureThreshold: 3periodSeconds: 10
当startuo探针探测失败时,即使存活与就绪探针的探测结果确定是正确,但是容器依然无法进入READY状态,启动探针作为第一道关卡,会确保容器成功启动后才可以允许存活与就绪探针工作
[root@master01 data]#kubectl apply -f startup-httpget.yaml
pod/nginx-startup-probe created
[root@master01 data]#kubectl get pod nginx-startup-probe -w
NAME READY STATUS RESTARTS AGE
nginx-startup-probe 0/1 Running 0 3s
nginx-startup-probe 0/1 Running 1 5m13s
nginx-startup-probe 0/1 Running 3 10m
nginx-startup-probe 0/1 Running 2 15m#因为启动探针的failureThreshold与periodSeconds的值分别为30,10。
#所以启动探针完整的执行一遍时间为30 * 10 =300(s),即5分钟
可以使用kubectl get events -w命令追踪事件信息
[root@master01 data]#kubectl get events -w
......
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
0s Normal Killing pod/nginx-startup-probe Container nginx failed startup probe, will be restarted
60m Warning Unhealthy pod/liveness-tcp Liveness probe failed: dial tcp 10.244.1.128:8080: connect: connection refused
0s Warning Unhealthy pod/nginx-startup-probe Startup probe failed: HTTP probe failed with statuscode: 404
上述操作的目的主要在于告诉攻城狮们启动容器是在存活与就绪探针之前开始工作,必须等到启动探针工作完毕,或成功探测指定次数之后,存活与就绪探针才进入工作。实际上,在启动探针中可以加上初始化的操作,等到初始化操作完成后,去探测初始化信息,成功之后在进行其它探针的工作。
例如创建一个存储文件,而后使用exec的检测方式,使用cat命令去查看这个文件是否存在,完成探测任务
3.主要作用
启动探针的主要作用在于
延缓其他探针生效:在容器启动初期,启动探针先于存活探针(Liveness Probe)和就绪探针(Readiness Probe)生效。当启动探针配置存在时,kubelet不会执行存活和就绪探针,直到启动探针成功为止。
防止频繁重启:若应用启动期间,存活探针或就绪探针就开始工作,而此时应用可能还没有完全启动成功,这两个探针可能会因为应用未能及时响应而触发容器重启,造成不必要的服务中断和循环重启。启动探针的存在可以有效地防止此类情况的发生。
确保应用稳定:启动探针使得Kubernetes能够在应用真正启动完毕后才将其视为健康的,并开始接受流量,从而保障了集群中应用服务的稳定性。
(五)生命周期钩子
在Kubernetes中,Pod的生命周期包含了多个阶段,而生命周期钩子(Lifecycle Hooks)允许用户在Pod中的容器生命周期中的特定点执行操作。主要有两种生命周期钩子:postStart 和 preStop。
1.钩子种类
1.1 启动钩子(postStart)
作用:在容器创建后立即执行。它常用于在容器启动后执行一些初始化的工作,比如设置环境变量、启动子进程、检查或加载数据等。postStart 钩子保证在容器的主进程启动前执行。
特点:
异步执行,不保证在容器ENTRYPOINT之前运行。
如果没有参数传递给处理程序,容器ENTRYPOINT和钩子执行是异步操作。
如果钩子花费太长时间以至于容器不能运行或者挂起,容器将不能达到running状态。
如果PostStart钩子失败,容器将会被kill。
1.2 停止钩子(preStop)
作用:在容器终止之前执行。允许容器在停止前优雅地关闭,比如保存文件、关闭连接、发送信号等。preStop 钩子给容器提供了一个机会,以便在容器终止前完成一些清理工作。
特点:
同步执行,即在删除容器的调用发出之前必须完成。
如果钩子在执行期间挂起,Pod将停留在running状态并且永不会达到failed状态。
如果PreStop钩子失败,容器同样也会被kill。
2.定义文件
生命周期钩子在Pod定义中的containers部分的lifecycle字段下定义
[root@master01 data]#vim post.yaml
[root@master01 data]#cat post.yaml
apiVersion: v1
kind: Pod
metadata:name: lifecycle-hooks
spec:containers:- name: lifecycle-hooksimage: nginx:1.18.0lifecycle: #定义容器的生命周期钩子postStart: #容器启动后立即执行的命令exec: #使用exec的方式进入容器执行命令command: ["/bin/sh", "-c", "echo containers start >> /var/log/nginx/post.log"]
#command指令表示需要执行的命令
#命令表示在容器启动后,立即输出containers start到 /var/log/nginx/post.log文件中preStop: #容器停止前执行的命令exec: #同样使用exec的方式进入容器执行命令command: ["/bin/sh", "-c", "echo containers stop >> /var/log/nginx/post.log"]
#表示在容器停止前输出containers stop到 /var/log/nginx/post.log文件中volumeMounts: #定义了容器内的卷挂载点- name: post-log #挂载的卷的名字mountPath: /var/log/nginx/ #容器内的挂载路径readOnly: false #卷是否以只读方式挂载。false表示否initContainers: #定义了 Pod 启动前运行的初始化容器列表- name: init-mypodimage: nginx:1.18.0 command: ["/bin/sh", "-c", "echo 'initContainers is ready' >> /var/log/nginx/post.log"]volumeMounts:- name: post-log mountPath: /var/log/nginx/readOnly: false
#同样的,定义了如何将名为pod-log的卷挂载到初始化容器内,挂载路径同样是/var/log/nginx/volumes:- name: post-loghostPath: #将宿主机上的一个目录或文件挂载到Pod中path: /data/nginx/log/ #宿主机上的文件或目录路径type: DirectoryOrCreate #如果指定的路径不存在,则会创建它
3.启动pod
启动pod并查看该pod在哪一个节点上创建
[root@master01 data]#kubectl apply -f post.yaml
pod/lifecycle-hooks created
[root@master01 data]#kubectl get pod lifecycle-hooks -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lifecycle-hooks 1/1 Running 0 25s 10.244.1.134 node01 <none> <none>
#该pod在node01节点上启动
4.查看文件
在节点上查看文件
[root@node01 ~]#cd /data/nginx/log/
[root@node01 log]#ls
access.log error.log post.log
[root@node01 log]#cat post.log
initContainers is ready
containers start
在master节点上删除容器
[root@master01 data]#kubectl delete -f post.yaml
pod "lifecycle-hooks" deleted
[root@master01 data]#kubectl get pod lifecycle-hooks
Error from server (NotFound): pods "lifecycle-hooks" not found
回到node节点查看文件
[root@node01 log]#cat post.log
initContainers is ready
containers start
containers stop #容器退出前,会将此信息追加到post.log文件当中
5.重要性及应用场景
优雅的停止服务:在生产环境中,当需要更新或重启服务时,使用PreStop钩子可以通知外部系统(如负载均衡器、服务发现组件等)该容器即将停止服务,从而实现优雅的流量迁移,避免服务中断或影响用户体验。
资源清理:通过PostStart和PreStop钩子,可以在容器启动和停止时执行资源清理操作,如删除临时文件、关闭数据库连接等,确保资源的正确使用和释放。
配置加载:在PostStart钩子中加载配置文件或启动子进程,可以确保容器在启动后立即进入正确的运行状
三、总结
(一)资源限制
在Kubernetes中,Pod资源限制(Resource Limits)的作用非常重要,它们允许管理员或用户为Pod中的容器设置资源使用的上限和下限,以确保资源的合理使用和系统的稳定性。以下是Pod资源限制的主要作用:
-
资源隔离:通过设置资源限制,可以确保一个Pod或容器不会消耗过多的系统资源,如CPU、内存等。这有助于将不同的应用或工作负载隔离开来,防止一个Pod耗尽所有资源而导致其他Pod受到影响。
-
提高稳定性:通过限制资源的消耗,可以减少由于某个Pod的意外行为(如内存泄漏、无限循环等)导致的系统崩溃或不稳定。当Pod达到其资源限制时,Kubernetes会采取适当的措施(如终止Pod),以防止对整个集群造成负面影响。
-
公平调度:资源限制有助于Kubernetes调度器(Scheduler)在集群中公平地分配资源。调度器会考虑每个Pod的资源请求和限制,以找到最合适的节点来运行Pod。这有助于确保集群中的资源得到合理的利用,避免某些节点过载而其他节点空闲。
-
成本优化:通过限制Pod的资源使用,可以更有效地管理云资源的使用,从而降低成本。管理员可以根据应用的实际需求设置合理的资源限制,避免购买过多的云资源而造成浪费。
-
服务质量(QoS)保证:Kubernetes根据Pod的资源请求和限制将Pod分为不同的服务质量(QoS)类别。这些类别决定了在资源争用或节点资源不足时,Pod的调度和驱逐策略。通过设置适当的资源限制,可以为不同的应用或服务提供不同的QoS保证。
-
监控和告警:资源限制还可以与Kubernetes的监控和告警系统配合使用,以便在Pod接近或超过其资源限制时发出警报。这有助于管理员及时发现并解决潜在的问题,避免对业务造成影响。
(二)探针机制
Pod探针机制在Kubernetes中扮演着至关重要的角色,它主要用于监控Pod中容器的健康状态,并根据这些状态信息来决定Pod的生命周期事件,如是否应该重启容器、是否应该将Pod添加到Service的Endpoints列表中等。
kubelet 使用存活探针来确定什么时候要重启容器。 例如,存活探针可以探测到应用死锁(应用在运行,但是无法继续执行后面的步骤)情况。 重启这种状态下的容器有助于提高应用的可用性,即使其中存在缺陷。
存活探针的常见模式是为就绪探针使用相同的低成本 HTTP 端点,但具有更高的 failureThreshold。 这样可以确保在硬性终止 Pod 之前,将观察到 Pod 在一段时间内处于非就绪状态。
kubelet 使用就绪探针可以知道容器何时准备好接受请求流量,当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 若 Pod 尚未就绪,会被从 Service 的负载均衡器中剔除。
kubelet 使用启动探针来了解应用容器何时启动。 如果配置了这类探针,存活探针和就绪探针成功之前不会重启,确保这些探针不会影响应用的启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。
(三)生命钩子
生命钩子(Lifecycle Hooks)在Kubernetes中,特别是Pod的生命周期管理中,提供了一种机制来在容器生命周期的特定事件发生时执行自定义操作。这些钩子允许用户定义在容器启动之前、之后以及容器终止之前执行的操作
初始化容器
通过PostStart钩子,可以在容器启动后立即执行一些初始化操作,如加载配置文件、设置环境变量、启动子进程等。这对于需要在容器启动后立即进行的一些设置和配置非常有用。
资源准备和清理
在容器启动之前,可以使用Init Containers(初始化容器)来执行一些前置任务,如从外部系统下载配置文件、设置网络策略、等待其他依赖项就绪等。这些初始化容器通过完成必要的准备工作,为主容器提供一个稳定的运行环境。在容器终止之前,PreStop钩子可以用于执行资源清理操作,如关闭数据库连接、删除临时文件、发送退出通知等。这有助于确保容器在退出时不会留下任何未清理的资源或状态。
优雅地终止容器
PreStop钩子允许容器在接收到终止信号之前执行一些清理操作,如等待当前请求处理完成、保存状态到持久化存储等。这有助于实现容器的优雅终止,确保在容器退出时不会丢失重要数据或导致服务中断。
日志和监控
生命钩子可以用于触发日志记录或监控事件,以便在容器生命周期的关键时刻收集相关信息。例如,在PostStart钩子中记录容器的启动时间、版本信息等,或在PreStop钩子中记录容器的退出原因和状态。
扩展性和灵活性
生命钩子提供了灵活的扩展机制,允许用户根据需要在容器生命周期的不同阶段执行自定义操作。这使得Kubernetes更加适应各种应用场景和需求,为用户提供了更大的灵活性和控制力。
故障处理和恢复
在某些情况下,容器可能会因为某些原因(如配置错误、资源不足等)而启动失败或运行异常。通过生命钩子,可以在这些情况下执行一些故障处理和恢复操作,如重新加载配置文件、释放资源、重启容器等。这有助于提高系统的稳定性和可用性。