本文主要介绍 Liveness, Readiness Startup 三种类型的探针
Liveness 探针
许多长时间运行的应用程序最终会过渡到断开的状态,除非重新启动,否则无法恢复。kubernetes提供活性探针来检测和修复这种情况。
如下 将创建一个pod,该pod运行基于k8s.gcr.io/busybox映像的容器。
pods/probe/exec-liveness.yaml
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 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
在配置文件中,可以看到pod只有一个容器。periodseconds字段指定kubelet应每5秒执行一次活动性探测。initialdelayseconds字段告诉kubelet在执行第一个探测之前应该等待5秒。为了执行探测,kubelet在容器中执行命令cat/tmp/healthy。如果命令成功,则返回0,并且kubelet认为容器是活动的和健康的。如果命令返回非零值,kubelet将终止容器并重新启动它
定义一个HTTP的 liveness
另一种liveness探测使用http get请求。这是运行基于k8s.gcr.io/liveness映像的容器的pod的配置文件。
pods/probe/http-liveness.yaml
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只有一个容器。periodseconds字段指定kubelet应每3秒执行一次活动探测。initialdelayseconds字段告诉kubelet在执行第一个探测之前应该等待3秒。为了执行探测,kubelet向运行在容器中并监听端口8080的服务器发送http get请求。如果服务器/healthz路径的处理程序返回一个成功代码,kubelet会认为容器是活动的并且健康的。如果处理程序返回一个失败代码,kubelet将终止容器并重新启动它。
任何大于或等于200小于400的代码都表示成功。任何其他代码都表示失败。
在server.go中可以看到服务器的源代码。
对于容器处于活动状态的前10秒,/healthz处理程序返回状态200。之后,处理程序返回500的状态。
服务端 健康检查的代码
https://github.com/kubernetes/kubernetes/blob/master/test/images/agnhost/liveness/server.go
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
在v1.13之前的版本(包括v1.13)中,如果在运行pod的节点上设置了环境变量http_proxy(或http_proxy),则http liveness探测将使用该代理。在v1.13之后的版本中,本地http代理环境变量设置不会影响http活动性探测。
定义一个TCP的 liveness
第三种类型的Liveness探针使用TCP套接字。使用此配置,kubelet将尝试打开指定端口上容器的套接字。如果它能够建立连接,则认为容器是健康的,如果不能,则认为容器是故障的。
pods/probe/tcp-liveness-readiness.yaml
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
如上所见,tcp检查的配置与http检查非常相似。本例同时使用就绪性和活动性探测。K8s将在容器启动5秒后发送第一个准备就绪探测器。这将尝试连接到端口8080上的goproxy容器。如果探测成功,将标记为就绪。Kubelet将继续每10秒进行一次检查。
除了就绪探测之外,此配置还包括一个活动探测。kubelet将在容器启动15秒后运行第一个活性探针。就像就绪探测一样,这将尝试连接到端口8080上的goproxy容器。如果Liveness探测失败,容器将重新启动
Startup 探针
有时,必须处理在第一次初始化时可能需要额外启动时间的附加应用程序。在这种情况下,在设置liveness探测参数的同时不影响对触发这种探测的死锁的快速响应是很困难的。诀窍是使用相同的命令http或tcp check设置一个启动探测,failuretareshold*periodseconds足够长,可以覆盖更糟糕的启动时间。
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10
由于启动探针,应用程序将有最大的5分钟(30×10=300秒)完成它的启动。一旦启动探测成功一次,liveness探测就会接管,为容器死锁提供快速响应。如果启动探测从未成功,则容器将在300秒后被终止,并受POD的重新启动策略的约束。
readiness 探针
有时,应用程序暂时无法为通信服务。例如,应用程序可能需要在启动期间加载大数据或配置文件,或者在启动后依赖外部服务。在这种情况下,您不想终止应用程序,但也不想发送它的请求。kubernetes提供了用于检测和缓解这些情况的就readiness探测。一个带有报告它们还没有准备好的容器的pod无法通过kubernetes服务接收流量。
准备就绪探测在容器的整个生命周期中运行。
就绪性探测的配置与活动性探测类似。唯一的区别是使用readinessprobe字段而不是livenessprobe字段
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
http和tcp就绪性探测的配置也与liveness探测相同。
就绪性和活性探针可以并行地用于同一容器。使用这两种方法可以确保通信量不会到达尚未准备就绪的容器,并确保容器在失败时重新启动。
比如我们要在容器启动之后执行一些初始化的操作 ,此时就可以使用readiness 探针 ,此外 合理的设置periodSeconds 可以覆盖脚本反复执行,或者可以设置脚本 检查是否已经执行,都可以满足要求。
参考
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/