目录
- 探针
- 探针类型
- LivenessProbe
- ReadinessProbe
- StartupProbe:
- 探测方式
- ExecAction
- TCPSocketAction
- HTTPGetAction
- 参数配置
- 操作示例
- 生命周期
- 钩子函数
- 生命周期
探针
所谓的探针就是容器内应用的监测机制,为了确保容器在部署后确实处在正常运行状态。
比如Pod内的容器因为内存等其他原因挂掉了,但是其实Pod还是在的,但是其实已经不可用了,需要做一定的处理,比如重启(基于重启策略)。那么Pod是如何知道容器是否还可用,就是通过存活探针来检测这个容器。
探针类型
可根据不同的探针来判断容器应用当前的状态,有以下三种类型:
LivenessProbe
存活探针。
作用:用于探测容器中的应用是否运行,如果探测失败,kubelet 会根据配置的重启策略进行重启,若没有配置,默认就认为容器启动成功,不会执行重启策略。
配置如下:
livenessProbe:failureThreshold: 5httpGet:path: /healthport: 8080scheme: HTTPinitialDelaySeconds: 60 # 第一次检测的延迟时间periodSeconds: 10 # 间隔时间successThreshold: 1 # 检测成功1次就代表成功了timeoutSeconds: 5
注意:如果配置了这个探针,需要注意periodSeconds时间,如果Pod的启动时间大于这个时间,到时间发现还没启动成功,就会出现一直重启的情况。
ReadinessProbe
就绪探针。
作用:探测应用是否启动完成并且处于正常服务状态,它的返回值如果返回 success,那么就认为该容器已经完全启动,并且该容器是可以接收外部流量的,如果不正常则不会接收来自 Kubernetes Service 的流量,即将该Pod从Service的endpoint中移除。
readinessProbe:failureThreshold: 3 # 错误次数httpGet:path: /readyport: 8181scheme: HTTPperiodSeconds: 10 # 间隔时间successThreshold: 1timeoutSeconds: 1
StartupProbe:
启动探针。
k8s 1.16 版本新增的探针,用于判断应用程序是否已经启动了。
当配置了 startupProbe 后,会先禁用其他探针,直到 startupProbe 成功后,其他探针才会继续。
作用:由于有时候不能准确预估应用一定是多长时间启动成功,因此配置另外两种方式不方便配置初始化时长来检测,而配置了 statupProbe 后,只有在应用启动成功了,才会执行另外两种探针,可以更加方便的结合使用另外两种探针使用。
配置如下:
startupProbe:httpGet:path: /api/startupport: 80
探测方式
ExecAction
在容器内部执行一个命令,如果返回值为 0,则任务容器时健康的。
配置如下:
livenessProbe:exec:command:- cat- /health
TCPSocketAction
通过 tcp 连接监测容器内端口是否开放,如果开放则证明该容器健康。
配置如下:
livenessProbe:tcpSocket:port: 80
HTTPGetAction
生产环境用的较多的方式,发送 HTTP 请求到容器内的应用程序,如果接口返回的状态码在 200~400 之间,则认为容器健康。
配置如下:
livenessProbe:failureThreshold: 5httpGet:path: /healthport: 8080scheme: HTTPhttpHeaders:- name: xxxvalue: xxx
参数配置
- initialDelaySeconds
初始化延迟时间。即等待这么长时间后才开始探测。一般LivenessProbe和ReadinessProbe探针配置。在一定程度上可以代替StartupProbe探针,但是一般我们是不知道容器到底需要启动多久的,时间设置短了,可能出现前面说的一直重启,设置长了,又有无效等待。所以并不能完全替代StartupProbe探针。
- timeoutSeconds
超时时间。即执行检测的时候,如果等待这么多时间还没有返回,就认为失败。
- periodSeconds
监测间隔时间。即上次检测完成后,间隔多长时间再去检测。
- successThreshold
成功次数阈值。比如配置成1,则认为检查 1 次成功就成功了。
- failureThreshold
失败次数阈值。比如配置成3,则认为检查了3次失败就算失败了。如果设置1次,可能不太准确,可能由于网络等其他原因,有延迟,下一次可能就好了。
操作示例
下面我们在上面Nginx的pod 的yaml文件的基础上加上启动探针,如下:
apiVersion: v1 # api 文档版本
kind: Pod # 资源对象类型,也可以配置为像Deployment、StatefulSet这一类的对象
metadata: # Pod 相关的元数据,用于描述 Pod 的数据name: nginx-pod # Pod 的名称labels: # 定义 Pod 的标签type: app # 自定义 label 标签,名字为 type,值为 apptest: 1.0.0 # 自定义 label 标签,描述 Pod 版本号namespace: 'default' # 命名空间的配置
spec: # 期望 Pod 按照这里面的描述进行创建containers: # 对于 Pod 中的容器描述- name: nginx # 容器的名称image: nginx:1.7.9 # 指定容器的镜像imagePullPolicy: IfNotPresent # 镜像拉取策略,指定如果本地有就用本地的,如果没有就拉取远程的startupProbe: # 启动探针httpGet: # 采用http的方式path: /api/path # http的请求路径port: 80 # 请求端口periodSeconds: 5 # 监测间隔时间successThreshold: 1 # 检查 1 次成功就表示成功failureThreshold: 3 # 监测失败 2 次就表示失败timeoutSeconds: 5 # 超时时间command: # 指定容器启动时执行的命令- nginx- -g- 'daemon off;' # nginx -g 'daemon off;'workingDir: /usr/share/nginx/html # 定义容器启动后的工作目录ports:- name: http # 端口名称containerPort: 80 # 描述容器内要暴露什么端口protocol: TCP # 描述该端口是基于哪种协议通信的env: # 环境变量- name: JVM_OPTS # 环境变量名称value: '-Xms128m -Xmx128m' # 环境变量的值resources:requests: # 最少需要多少资源cpu: 100m # 限制 cpu 最少使用 0.1 个核心memory: 128Mi # 限制内存最少使用 128兆limits: # 最多可以用多少资源cpu: 200m # 限制 cpu 最多使用 0.2 个核心memory: 256Mi # 限制 最多使用 256兆restartPolicy: OnFailure # 重启策略,只有失败的情况才会重启
上面文件中,我们添加了启动探针,采用的方式是http。
注意,这里故意写了一个不存在的请求路径,为了演示启动探针失败时是神经样子的。
下面创建pod:
kubectl apply -f nginx-pod.yaml
然后查看pod的状态:
kubectl get po
结果如下:
NAME READY STATUS RESTARTS AGE
nginx-pod 0/1 Running 0 3s
现在状态是非Ready的,然后我们隔一段时间继续查看:
NAME READY STATUS RESTARTS AGE
nginx-pod 0/1 Running 3 (8s ago) 53s# 最终的状态如下:
NAME READY STATUS RESTARTS AGE
nginx-pod 0/1 Completed 3 9m17s
可以看到,RESTARTS是3,也就是重启了3次,而且最终的READY还是0。
下面看下具体的信息:
kubectl describe po nginx-pod
可以看到具体的探针信息:
然后翻到最后的Events,可以看到最后一行打印出检测失败:
看完启动失败的情况,再看下检测成功的情况,修改http的请求路径如下:
apiVersion: v1 # api 文档版本
kind: Pod # 资源对象类型,也可以配置为像Deployment、StatefulSet这一类的对象
metadata: # Pod 相关的元数据,用于描述 Pod 的数据name: nginx-pod # Pod 的名称labels: # 定义 Pod 的标签type: app # 自定义 label 标签,名字为 type,值为 apptest: 1.0.0 # 自定义 label 标签,描述 Pod 版本号namespace: 'default' # 命名空间的配置
spec: # 期望 Pod 按照这里面的描述进行创建containers: # 对于 Pod 中的容器描述- name: nginx # 容器的名称image: nginx:1.7.9 # 指定容器的镜像imagePullPolicy: IfNotPresent # 镜像拉取策略,指定如果本地有就用本地的,如果没有就拉取远程的startupProbe: # 启动探针httpGet: # 采用http的方式path: /index.html #http的请求路径port: 80 # 请求端口periodSeconds: 5 # 监测间隔时间successThreshold: 1 # 检查 1 次成功就表示成功failureThreshold: 3 # 监测失败 2 次就表示失败timeoutSeconds: 5 # 超时时间command: # 指定容器启动时执行的命令- nginx- -g- 'daemon off;' # nginx -g 'daemon off;'workingDir: /usr/share/nginx/html # 定义容器启动后的工作目录ports:- name: http # 端口名称containerPort: 80 # 描述容器内要暴露什么端口protocol: TCP # 描述该端口是基于哪种协议通信的env: # 环境变量- name: JVM_OPTS # 环境变量名称value: '-Xms128m -Xmx128m' # 环境变量的值resources:requests: # 最少需要多少资源cpu: 100m # 限制 cpu 最少使用 0.1 个核心memory: 128Mi # 限制内存最少使用 128兆limits: # 最多可以用多少资源cpu: 200m # 限制 cpu 最多使用 0.2 个核心memory: 256Mi # 限制 最多使用 256兆restartPolicy: OnFailure # 重启策略,只有失败的情况才会重启
然后删除以前的pod,重启创建:
kubectl apply -f nginx-pod.yaml
查看状态:
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 7s
可以看到pod正常创建出来了。
然后查看下下容器的具体信息,也是没有任何问题的。
也可以试下TCP方式和命令行的方式,配置如下:
# 1.tcp方式
startupProbe: # 启动探针tcpSocket: # 采用tcp的方式port: 80 # 请求端口periodSeconds: 5 # 监测间隔时间successThreshold: 1 # 检查 1 次成功就表示成功failureThreshold: 3 # 监测失败 2 次就表示失败timeoutSeconds: 5 # 超时时间
# 2.命令行的方式
startupProbe: # 启动探针exec: # 采用命令行的方式command:-sh- -c- "sleep 3; echo 'success' > /inited"periodSeconds: 5 # 监测间隔时间successThreshold: 1 # 检查 1 次成功就表示成功failureThreshold: 3 # 监测失败 2 次就表示失败timeoutSeconds: 5 # 超时时间
生命周期
钩子函数
钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。
支持两种钩子:
- postStart:容器创建之后执行,如果失败会重启容器。
- preStop:容器终止前执行,常用于资源清理。如果失败,容器同样也会被杀死。
而钩子的回调函数支持两种方式:
- exec:在容器内执行命令,如果命令的退出状态码是
0
表示执行成功,否则表示失败 - httpGet:向指定 URL 发起 GET 请求,如果返回的 HTTP 状态码在
[200, 400)
之间表示请求成功,否则表示失败 - tcpSocket:在当前容器尝试访问指定的 socket 。
postStart不能保证该操作一定在容器的 command 之前执行,一般不使用。
preStop一般用于注册中心下线、数据清理、数据销毁等。
注意:当pod删除时,变为删除中的状态后,会给 pod 一个宽限期,让 pod 去执行一些清理或销毁操作。
配置参数:terminationGracePeriodSeconds: 30
也就是当删除时,会等30s后才真的删除pod,而且删除到30s也不会管preStop有没有执行完,都会删除。
示例:
apiVersion: v1 # api 文档版本
kind: Pod # 资源对象类型,也可以配置为像Deployment、StatefulSet这一类的对象
metadata: # Pod 相关的元数据,用于描述 Pod 的数据name: nginx-pod # Pod 的名称labels: # 定义 Pod 的标签type: app # 自定义 label 标签,名字为 type,值为 apptest: 1.0.0 # 自定义 label 标签,描述 Pod 版本号namespace: 'default' # 命名空间的配置
spec: # 期望 Pod 按照这里面的描述进行创建containers: # 对于 Pod 中的容器描述- name: nginx # 容器的名称image: nginx:1.7.9 # 指定容器的镜像imagePullPolicy: IfNotPresent # 镜像拉取策略,指定如果本地有就用本地的,如果没有就拉取远程的lifecycle: # 生命周期配置postStart: # 容器创建之后执行,如果失败会重启容器exec: # 在容器启动的时候,执行一条命令,修改掉Nginx的首页内容command: ["/bin/sh","-c","echo postStart ... > /usr/share/nginx/html/index.html"]preStop: # 容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作exec: # 在容器停止之前停止Nginx的服务command: ["/usr/sbin/nginx","-s","quit"]command: # 指定容器启动时执行的命令- nginx- -g- 'daemon off;' # nginx -g 'daemon off;'workingDir: /usr/share/nginx/html # 定义容器启动后的工作目录ports:- name: http # 端口名称containerPort: 80 # 描述容器内要暴露什么端口protocol: TCP # 描述该端口是基于哪种协议通信的env: # 环境变量- name: JVM_OPTS # 环境变量名称value: '-Xms128m -Xmx128m' # 环境变量的值resources:requests: # 最少需要多少资源cpu: 100m # 限制 cpu 最少使用 0.1 个核心memory: 128Mi # 限制内存最少使用 128兆limits: # 最多可以用多少资源cpu: 200m # 限制 cpu 最多使用 0.2 个核心memory: 256Mi # 限制 最多使用 256兆restartPolicy: OnFailure # 重启策略,只有失败的情况才会重启
生命周期
Pod的状态(Status)有以下几种:
- 挂起(Pending):Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度 Pod 的时间和通过网络下载镜像的时间,这可能需要花点时间。
- 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
- 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
- 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
- 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败。
一个Pod从启动到结束有如下几个步骤:
- 初始化容器执行(如果有的话)
- 执行启动探针
- 执行command命令(定义在yaml中的command标签下)和postStart钩子函数,两个没有先后顺序
- 就绪探针和存活探针执行
- 执行preStop钩子函数
- 删除Pod
如下图