Pod容器健康探测 ¶
为什么要做容器探测?
在Kubernetes中Pbd是最小的计算单元,而一个Pod又由多个容器组成,相当于每个容器就是一个应用,应用在运行期间,可能因为某些意外情况致使程呈序挂掉。那么如何监控这些容器状态稳定性,保证服务在运行期间不会发生问题,发生问题后进行重启等机制,就成为了重中之重的事情,考虑到这点kubernetes推出了活性探针机制。有了存活性探能保证程序在运行中如果挂掉能够自动重启,但是还有个经常遇到的问题,比如说,在Kubernetes中启动Pod,显示明明Pod己经启动成功,且能访问里面的端口,但是却返回错误信息。还有就是在执行滚动更新时候,总会出现一段时间,Pod对外提供网络访问,但是访问却发生404,这两个原因,都是因为1Pod已经成功启动,但是Pod的的容器中应用程序还在启动中导致,考虑到这点Kubernetes推出了就绪性探针机制。
K8s 提供了三种方式来实现容器的健康探测:
目前 LivenessProbe
和 ReadinessProbe
、startupprobe
探测者支持下面三种探针
1、exec:
在容器中执行指定的命令,如果执行成功,退出码为0则探测成功。
2、TCPSocket:
通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP连接,则表明容器健康。
3、HTTPGetAction:
通过容器的IP地址、端口号及路径调用 HTTPGet 方法,如果响应的状态码大于等于200目小于400,则认为容器健康
每类探针都有三种结果:
1、Success:容器通过检查;
2、Failure:容器未通过检查;
3、Unknown:未能执行检查,因此不采取任何措施;
LivenessProbe
和 ReadinessProbe
两种探针区别:
ReadinessProbe
和 livenessProbe
可以使用相同探测方式我,只是对 Pod 的处置方式不同:
1、readinessProbe
当检测失败后,将 Pod 的 IP:Port
从对应的 EndPoint
列表中删除。
2、livenessProbe
当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施。
startupProbe:
探测容器中的应用是否已经启动。如果提供了启动探测(startup probe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为的成功Success。
apiVersion: v1
kind: Pod
metadata:
name: startupprobe
spec :
containers:
- name: startup
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
startupProbe:
exec:
command:
- "/bin/sh"
- "-c"
- "ps -axuf|grep tomcat | grep -v 'grep'"
initialDelaySeconds: 10 #容器启动后多久开始探测
periodSeconds: 10 #执行探测的时间间隔
timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
successThreshold: 1 #成功多少次才算成功
failureThreshold: 2 #失败多少次才算失败
apiVersion: v1
kind: Pod
metadata:
name: startupprobe
spec :
containers:
- name: startup
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
startupProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 10 #容器启动后多久开始探测
periodSeconds: 10 #执行探测的时间间隔
timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
successThreshold: 1 #成功多少次才算成功
failureThreshold: 2 #失败多少次才算失败
apiVersion: v1
kind: Pod
metadata:
name: startupprobe
spec :
containers:
- name: startup
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 10 #容器启动后多久开始探测
periodSeconds: 10 #执行探测的时间间隔
timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
successThreshold: 1 #成功多少次才算成功
failureThreshold: 2 #失败多少次才算失败
livenessprobe:
用指定的方式(exec、tcp、http)检测pod中的容器是否正常运行,如果检测失败,则认为容器不健康,那么Kubelet将根据Pod中设置的restartPolicy策略来判断Pod是否要进行重启操作,如果容器配置中没有配置livenessProbe,Kubelet将认为存活探针探测s一直为success(成功)状态。
apiVersion: v1
kind: Pod
metadata:
name: livenessprobe-exec
labels:
app: liveness
spec :
containers:
- name: liveness
image: busybox:1.28
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessprobe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10 #容器启动后多久开始探测
periodSeconds: 5 #执行探测的时间间隔
# timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
# successThreshold: 1 #成功多少次才算成功
# failureThreshold: 2 #失败多少次才算失败
apiVersion: v1
kind: Pod
metadata:
name: livenessprobe-httpGet
labels:
app: liveness
spec :
containers:
- name: liveness
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
livenessprobe:
initialDelaySeconds: 10 #容器启动后多久开始探测
periodSeconds: 5 #执行探测的时间间隔
timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
httpGet:
scheme: HTTP
port: 8080
path: /health
# successThreshold: 1 #成功多少次才算成功
# failureThreshold: 2 #失败多少次才算失败
apiVersion: v1
kind: Pod
metadata:
name: livenessprobe-tcpSocket
labels:
app: liveness
spec :
containers:
- name: liveness
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
livenessprobe:
initialDelaySeconds: 15 #容器启动后多久开始探测
periodSeconds: 20 #执行探测的时间间隔
tcpSocket:
port: 80
readnessprobe:
就绪性探针,用于检测容器中的应用是否可以接受请求,当探测成功后才使Pod对外提供网络访问,将容器标记为就绪状态,可以加到pod前端负载,如果探测失败,则将容器标记为未就绪状态,会把pod从前端负载移除。
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget # Pod 名称
labels:
app: readiness-httpget
spec :
containers:
- name: readiness-httpget-container # 容器名称
image: hub.test.com/library/mynginx:v1 # 镜像地址
imagePullPolicy: IfNotPresent # 镜像下载策略
ports:
- containerPort: 80
readinessProbe: # 就绪探测
httpGet: # 检测方案
path: /index.html # 检测路径
port: 80 # 检测端口
initialDelaySeconds: 15 # 启动后多少秒开始第一次检测
periodSeconds: 3 # 每次间隔检测时间
检测 http://localhost:80/index.html 是否正常
apiVersion: v1
kind: Pod
metadata:
name: readiness-tcpSocket # Pod 名称
labels:
app: readiness-tcpSocket
spec :
containers:
- name: readiness-tcpSocket-container # 容器名称
image: hub.test.com/library/mynginx:v1 # 镜像地址
imagePullPolicy: IfNotPresent # 镜像下载策略
ports:
- containerPort: 80
readinessProbe: # 就绪探测
tcpSocket: # 检测方案
port: 80 # 检测端口
initialDelaySeconds: 15 # 启动后多少秒开始第一次检测
periodSeconds: 3 # 每次间隔检测时间
apiVersion: v1
kind: Pod
metadata:
name: readiness-exec # Pod 名称
labels:
app: readiness-exec
spec :
containers:
- name: readiness-exec-container # 容器名称
image: hub.test.com/library/mynginx:v1 # 镜像地址
imagePullPolicy: IfNotPresent # 镜像下载策略
ports:
- containerPort: 80
readinessProbe: # 就绪探测
exec: # 检测方案
command: # 使用命令进行探测
- cat
- /var/www/html/ready.txt # 检测文件
initialDelaySeconds: 15 # 启动后多少秒开始第一次检测
periodSeconds: 3 # 每次间隔检测时间
案例
apiVersion: v1
kind: Pod
metadata:
name: myhello-pod
namespace: default
labels:
name: myhello-pod
env: dev
spec:
restartPolicy: Always
initContainers:
- name: init-myservice
image: busybox
# 查找命名空间下myservice服务,如果存在则执行成功,如果不存在则一直查找
command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox
# 查找命名空间下mydb服务,如果存在则执行成功,如果不存在则一直查找
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
containers:
- name: myhello
image: nongtengfei/hello:curl
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
command: ["./app"]
args: ["--param1=k8s-p1", "--param2=k8s-p2"]
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
env: # 注入到容器的环境变量
- name: env1
value: "k8s-env1"
- name: env2
value: "k8s-env2"
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c","echo post start command exec >> /tmp/data"]
preStop:
exec:
command: ["/bin/sh", "-c","echo pre stop command exec >> /tmp/data"]
startupProbe:
exec:
command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w % {http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
# 指定初始化时间,即探针在容器启动之后的延迟时长
initialDelaySeconds: 5
# 探测周期,即每隔多长时间探测一次
periodSeconds: 5
# 最小连续失败次数,即连续失败多少次表示探测失败
failureThreshold: 3
# 最小连续成功次数,即连续探测成功多少次表示探测成功,liveness 和 startup 必须为1
successThreshold: 1
# 探测超时时间
timeoutSeconds: 1
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
timeoutSeconds: 1
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
timeoutSeconds: 1
- name: myredis #容器的名称
image: redis #容器对应的 Docker Image
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
timeoutSeconds: 1