好的,各位观众老爷们,欢迎来到今天的“K8s探秘之旅”特别节目!我是你们的老朋友,人称“代码诗人”的程序猿老码。今天咱们要聊聊Kubernetes(简称K8s)里两个至关重要的家伙——Readiness Probe(就绪探针)和 Liveness Probe(存活探针)。
别看它们名字差不多,长得也挺像(都是探针嘛,能不像吗?),作用却大相径庭。搞清楚它们的区别,就像搞清楚了女朋友今天是因为没买到限量版包包生气,还是因为你忘了结婚纪念日一样重要!搞错了,轻则服务宕机,重则…呃…后果不堪设想。
准备好了吗?系好安全带,咱们发车啦!🚀
一、 探针兄弟的登场:为什么要用它们?
想象一下,你开了一家餐厅,门口贴着“营业中”的牌子。顾客兴冲冲地进来,结果发现厨房还在装修,厨师还在睡觉,服务员还在玩手机…顾客肯定一头雾水,骂骂咧咧地走了。
在K8s的世界里,Pod就是你的餐厅,里面的容器就是厨师、服务员。如果没有Readiness Probe和Liveness Probe,K8s就不知道你的Pod是不是真的准备好了,是不是还在“装修”,是不是已经“睡着了”。
- 没有Readiness Probe,流量就可能被导向一个还没准备好的Pod。 就像顾客进了还在装修的餐厅,体验极差,最终导致用户流失。
- 没有Liveness Probe,K8s就不知道你的Pod是不是已经“挂掉了”。 如果Pod已经死了,却还在分配流量,那简直就是灾难!
所以,Readiness Probe和Liveness Probe的作用就是:
- Readiness Probe: 告诉K8s,“嘿,我已经准备好了,可以接受流量了!” 就像餐厅装修完毕,厨师醒来,服务员开始微笑服务,可以迎接顾客了。
- Liveness Probe: 告诉K8s,“嘿,我还活着,没问题!” 就像餐厅里的厨师还在炒菜,服务员还在端茶倒水,一切正常运转。
简单来说,Readiness Probe负责“准入”,Liveness Probe负责“续命”。
二、Readiness Probe: “我已经准备好了,快来宠幸我吧!”
Readiness Probe就像一个尽职尽责的质检员,负责检查Pod里的容器是否已经准备好接收流量。只有通过了质检,K8s才会把流量导向这个Pod。
举个例子,一个Java Web应用,在启动时需要加载大量数据到内存中,才能正常提供服务。如果在数据加载完成之前,就把流量导向这个Pod,那肯定会报错,甚至导致服务崩溃。
Readiness Probe就可以解决这个问题。它可以检查Java Web应用是否已经加载完数据,只有加载完成后,才允许K8s将流量导向这个Pod。
Readiness Probe的工作流程:
- K8s会定期(例如每隔10秒)向Pod里的容器发送一个探测请求。
- 这个探测请求可以是:
- HTTP请求: 检查某个HTTP端口是否返回200 OK。
- TCP连接: 尝试建立一个TCP连接到某个端口。
- 执行命令: 在容器内部执行一个命令,检查其返回值是否为0。
- 如果探测请求成功,Readiness Probe就会返回“Ready”,K8s就会认为这个Pod已经准备好了,可以接受流量。
- 如果探测请求失败,Readiness Probe就会返回“Not Ready”,K8s就会认为这个Pod还没有准备好,不会把流量导向它。
Readiness Probe的配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image:latest
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz # 检查的路径
port: 8080 # 检查的端口
initialDelaySeconds: 5 # 启动后延迟5秒开始检查
periodSeconds: 10 # 每隔10秒检查一次
timeoutSeconds: 5 # 每次检查的超时时间为5秒
successThreshold: 1 # 连续成功1次才算Ready
failureThreshold: 3 # 连续失败3次才算Not Ready
参数解释:
httpGet
:使用HTTP请求进行探测。path
:要检查的HTTP路径。port
:要检查的HTTP端口。
initialDelaySeconds
:容器启动后延迟多久开始进行探测。这个参数非常重要,可以避免在容器还没完全启动时就被探测,导致误判。periodSeconds
:探测的频率,每隔多久进行一次探测。timeoutSeconds
:探测的超时时间,如果在指定时间内没有收到响应,就认为探测失败。successThreshold
:连续成功多少次才认为Pod是Ready的。failureThreshold
:连续失败多少次才认为Pod是Not Ready的。
Readiness Probe的注意事项:
- 选择合适的探测方式: 根据你的应用特点选择合适的探测方式。如果你的应用提供HTTP接口,那就使用HTTP请求进行探测。如果你的应用监听某个TCP端口,那就使用TCP连接进行探测。
- 设置合理的探测参数:
initialDelaySeconds
、periodSeconds
、timeoutSeconds
、successThreshold
、failureThreshold
这些参数都要根据你的应用特点进行设置。 - 避免过度探测: 频繁的探测会增加服务器的负担,所以要合理设置
periodSeconds
。
三、Liveness Probe: “我还活着,别抛弃我!”
Liveness Probe就像一个生命体征监测仪,负责检查Pod里的容器是否还在正常运行。如果Liveness Probe检测到容器已经“挂掉”了,K8s就会自动重启这个容器。
举个例子,一个Node.js应用,由于内存泄漏,导致程序卡死。如果没有Liveness Probe,K8s就不知道这个应用已经卡死了,还会继续分配流量给它。最终导致用户访问缓慢,甚至无法访问。
Liveness Probe就可以解决这个问题。它可以定期检查Node.js应用是否还在正常运行。如果发现应用已经卡死,就会自动重启这个容器,让应用恢复正常。
Liveness Probe的工作流程:
- K8s会定期(例如每隔10秒)向Pod里的容器发送一个探测请求。
- 这个探测请求可以是:
- HTTP请求: 检查某个HTTP端口是否返回200 OK。
- TCP连接: 尝试建立一个TCP连接到某个端口。
- 执行命令: 在容器内部执行一个命令,检查其返回值是否为0。
- 如果探测请求成功,Liveness Probe就会认为这个容器还活着。
- 如果探测请求失败,Liveness Probe就会认为这个容器已经死了,K8s就会自动重启这个容器。
Liveness Probe的配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /healthz # 检查的路径
port: 8080 # 检查的端口
initialDelaySeconds: 15 # 启动后延迟15秒开始检查
periodSeconds: 10 # 每隔10秒检查一次
timeoutSeconds: 5 # 每次检查的超时时间为5秒
successThreshold: 1 # 连续成功1次才算活
failureThreshold: 3 # 连续失败3次才算死
参数解释:
httpGet
:使用HTTP请求进行探测。path
:要检查的HTTP路径。port
:要检查的HTTP端口。
initialDelaySeconds
:容器启动后延迟多久开始进行探测。这个参数非常重要,可以避免在容器还没完全启动时就被探测,导致误判。periodSeconds
:探测的频率,每隔多久进行一次探测。timeoutSeconds
:探测的超时时间,如果在指定时间内没有收到响应,就认为探测失败。successThreshold
:连续成功多少次才认为容器是活着的。failureThreshold
:连续失败多少次才认为容器已经死了。
Liveness Probe的注意事项:
- 选择合适的探测方式: 根据你的应用特点选择合适的探测方式。如果你的应用提供HTTP接口,那就使用HTTP请求进行探测。如果你的应用监听某个TCP端口,那就使用TCP连接进行探测。
- 设置合理的探测参数:
initialDelaySeconds
、periodSeconds
、timeoutSeconds
、successThreshold
、failureThreshold
这些参数都要根据你的应用特点进行设置。 - 避免频繁重启: Liveness Probe的目的是让容器恢复正常,而不是频繁重启。如果你的应用总是被Liveness Probe重启,那就要考虑是不是应用本身有问题,而不是调整Liveness Probe的参数。
四、Readiness Probe vs Liveness Probe:一图胜千言
为了让大家更好地理解Readiness Probe和Liveness Probe的区别,我们用一张表格来总结一下:
特性 | Readiness Probe | Liveness Probe |
---|---|---|
目的 | 检查容器是否准备好接收流量 | 检查容器是否还在正常运行 |
作用 | 控制流量是否可以导向Pod | 控制容器是否需要重启 |
探测失败 | Pod会被从Service的Endpoint列表中移除 | 容器会被重启 |
影响范围 | 影响Service的可用性 | 影响Pod的自身可用性 |
适用场景 | 应用需要一段时间才能启动完成,或者需要定期更新状态 | 应用出现死锁、卡死等异常,无法正常提供服务时 |
比喻 | 餐厅的“试营业”,看看菜品是否合格,服务是否到位 | 医院的“生命体征监测仪”,看看病人是否还活着 |
最终目标 | 确保用户访问的都是健康的应用实例 | 确保应用能够自我修复,保持运行状态 |
五、 案例分析:手把手教你配置探针
说了这么多理论,不如来点实际的。我们来分析一个简单的案例,手把手教你配置Readiness Probe和Liveness Probe。
场景:
我们有一个简单的Node.js应用,它提供一个HTTP接口/healthz
,用于检查应用的健康状态。应用启动时需要加载一些配置文件,加载完成后才能正常提供服务。
需求:
- 在应用启动完成后,才能接收流量。
- 如果应用出现卡死等异常,需要自动重启。
配置步骤:
- 编写Node.js应用:
const express = require('express');
const app = express();
const port = 3000;
let isReady = false;
// 模拟加载配置文件
setTimeout(() => {
console.log('Configuration loaded!');
isReady = true;
}, 5000); // 5秒后加载完成
app.get('/healthz', (req, res) => {
if (isReady) {
res.status(200).send('OK');
} else {
res.status(503).send('Not Ready');
}
});
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
- 编写Dockerfile:
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "app.js"]
- 编写Deployment配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app
spec:
replicas: 3
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-container
image: node-app:latest
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 5 # 延迟5秒开始检查,确保配置文件加载完成
periodSeconds: 10
timeoutSeconds: 2
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 15 # 延迟15秒开始检查,避免应用启动时被误判
periodSeconds: 10
timeoutSeconds: 2
successThreshold: 1
failureThreshold: 3
- 部署应用:
kubectl apply -f deployment.yaml
解释:
- Readiness Probe: 我们配置了Readiness Probe,使用HTTP请求检查
/healthz
接口。initialDelaySeconds
设置为5秒,确保应用在加载完配置文件后才开始接受流量。 - Liveness Probe: 我们配置了Liveness Probe,使用HTTP请求检查
/healthz
接口。initialDelaySeconds
设置为15秒,避免应用启动时被误判。
六、高级用法:自定义探针
除了HTTP请求、TCP连接、执行命令这三种常用的探测方式外,我们还可以自定义探针,来实现更复杂的探测逻辑。
例如,我们可以编写一个脚本,检查数据库连接是否正常,或者检查消息队列是否拥堵。
自定义探针的实现方式:
- 编写探测脚本:
#!/bin/bash
# 检查数据库连接是否正常
mysql -u root -pPASSWORD -h localhost -e "SELECT 1"
if [ $? -eq 0 ]; then
echo "Database connection is OK"
exit 0
else
echo "Database connection is down"
exit 1
fi
- 将脚本复制到容器内部:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y mysql-client
COPY check_db.sh /usr/local/bin/check_db.sh
RUN chmod +x /usr/local/bin/check_db.sh
CMD ["/bin/bash"]
- 在Deployment配置中使用
exec
方式进行探测:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image:latest
readinessProbe:
exec:
command: ["/usr/local/bin/check_db.sh"]
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
livenessProbe:
exec:
command: ["/usr/local/bin/check_db.sh"]
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
七、总结:让你的应用更健壮
Readiness Probe和Liveness Probe就像K8s的“左右护法”,守护着你的应用,让它们更加健壮、稳定。
- Readiness Probe: 确保只有准备好的Pod才能接收流量,避免用户访问到不健康的应用实例。
- Liveness Probe: 确保应用能够自我修复,及时重启卡死的容器,保持运行状态。
希望今天的讲解能够帮助大家更好地理解Readiness Probe和Liveness Probe的区别,并在实际工作中灵活运用它们。记住,合理的配置探针,就像给你的应用穿上了一件坚固的盔甲,可以抵御各种突发状况。
最后,送给大家一句箴言:代码虐我千百遍,我待代码如初恋。探针配置要仔细,不然线上要崩溃! 😜
感谢大家的收看,我们下期再见! 👋