K8S - 容器探针(Probe)
对线上业务来说,保证服务的正常稳定是重中之重,对故障服务的及时处理避免影响业务以及快速恢复一直是开发运维的难点。Kubernetes提供了健康检查服务,对于检测到故障服务会被及时自动下线,以及通过重启服务的方式使服务自动恢复。使用Liveness及Readness探针Liveness探针:主要用于判断Container是否处于运行状态,比如当服务crash或者死锁等情况发生时,kubelet会..
Configure Liveness and Readiness Probes
对线上业务来说,保证服务的正常稳定是重中之重,对故障服务的及时处理避免影响业务以及快速恢复一直是开发运维的难点。Kubernetes提供了健康检查服务,对于检测到故障服务会被及时自动下线,以及通过重启服务的方式使服务自动恢复。
使用Liveness及Readness探针
Liveness探针:主要用于判断Container
是否处于运行状态,比如当服务crash或者死锁等情况发生时,kubelet会kill掉Container,然后根据其设置的restart policy进行相应操作(可能会在本机重新启动Container,或者因为设置Kubernetes QoS,本机没有资源情况下会被分发的其他机器上重新启动)。
Readness探针:主要用于判断服务
是否已经正常工作,如果服务没有加载完成或工作异常,服务所在的Pod的IP地址会从服务的Endpoints中被移除,也就是说,当服务没有ready时,会将其从服务的load balancer中移除,不会再接受或响应任何请求。
探针检查结果分为3种情况:
- 成功(Success):通过检查。
- 失败(Failure):检查失败。
- 未知(Unknown):检查未知,需要人工干预。
服务可用性与自动恢复
- 如果服务的健康检查(
readiness
)失败,故障的服务实例从service endpoint中下线
,外部请求将不会再转发到该服务上,一定程度上保证正在提供的服务的正确性,如果服务自我恢复了(比如网络问题),会自动重新加入service endpoint对外提供服务。 - 另外,如果设置了Container(
liveness
)的探针,对故障服务的Container(liveness)的探针同样会失败,container会被kill掉
,并根据原设置的container重启策略,系统倾向于在其原所在的机器上重启该container、或其他机器重新创建一个pod。
由于上面的机制,整个服务实现了自身高可用与自动恢复。
使用建议
- 对全部服务同时设置服务(readiness)和Container(liveness)的健康检查。
- 通过TCP对端口检查(TCPSocketAction),仅适用于端口已关闭或进程停止情况。因为即使服务异常,只要端口是打开状态,健康检查仍然是通过的。
- 基于第二点,一般建议用ExecAction自定义健康检查逻辑,或采用HTTP Get请求进行检查(HTTPGetAction)。
- 无论采用哪种类型的探针,一般建议设置检查服务(readiness)的时间短于检查Container(liveness)的时间,也可以将检查服务(readiness)的探针与Container(liveness)的探针设置为一致。目的是故障服务先下线,如果过一段时间还无法自动恢复,那么根据重启策略,重启该Container、或其他机器重新创建一个Pod恢复故障服务。
Pod的重启策略:
当pod中一个container处于退出状态(Exited)时,kubelet会根据Pod Spec中设置restartPolicy进行相应操作,重启的策略分别如下:
- Always: 默认的重启策略,只要有一个container处于Exited时,即会重启
- OnFailure:container退出状态不为0时,即会重启。
- Never: 从不重启。
需要重点说明的是:
一个pod设置重启策略,适用于pod中全部container。
处于退出状态的容器由 kubelet 以五分钟为上限的指数衰减延迟(10秒,20秒,40秒…)重新启动,并在container重启成功十分钟后会重置该值。
liveness.yaml
容器会创建一个文件/tmp/healthy
,30秒后删除;探针5秒会检查一次,检查方式为cat /tmp/healthy
文件是否存在,检查到容易有问题,探测失败3次,则重建容器
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec-wfq
spec:
containers:
- name: liveness
image: 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
如检测日志:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 17m default-scheduler Successfully assigned liveness-exec-wfq to 10.0.1.16
Normal SuccessfulMountVolume 17m kubelet, 10.0.1.16 MountVolume.SetUp succeeded for volume "default-token-nqldz"
Normal Pulling 15m (x3 over 17m) kubelet, 10.0.1.16 pulling image "busybox"
Normal Pulled 15m (x3 over 17m) kubelet, 10.0.1.16 Successfully pulled image "busybox"
Normal Created 15m (x3 over 17m) kubelet, 10.0.1.16 Created container
Normal Started 15m (x3 over 17m) kubelet, 10.0.1.16 Started container
Warning Unhealthy 14m (x9 over 17m) kubelet, 10.0.1.16 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 7m (x7 over 16m) kubelet, 10.0.1.16 Killing container with id docker://liveness:Container failed liveness probe.. Container will be killed and recreated.
Warning BackOff 2m (x27 over 10m) kubelet, 10.0.1.16 Back-off restarting failed container
liveness_http.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http-wfq
spec:
containers:
- name: liveness
image: googlecontainer/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
readness.yaml
apiVersion: v1
kind: Service
metadata:
name: nginxsvc
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
name: http
- port: 443
protocol: TCP
name: https
selector:
run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
strategy:
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: nginxhttps
image: ymqytw/nginxhttps:1.5
command: ["/home/auto-reload-nginx.sh"]
ports:
- containerPort: 443
- containerPort: 80
livenessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
timeoutSeconds: 1
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
timeoutSeconds: 1
initcontailner
如在initcontainer中先拉取nginx的配置,然后在nginx container 中去消费nginx的配置
init_container.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;’]
更多推荐
所有评论(0)