K8s 中的 Readiness Probe 与 Liveness Probe 区别

好的,各位观众老爷们,欢迎来到今天的“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的工作流程:

  1. K8s会定期(例如每隔10秒)向Pod里的容器发送一个探测请求。
  2. 这个探测请求可以是:
    • HTTP请求: 检查某个HTTP端口是否返回200 OK。
    • TCP连接: 尝试建立一个TCP连接到某个端口。
    • 执行命令: 在容器内部执行一个命令,检查其返回值是否为0。
  3. 如果探测请求成功,Readiness Probe就会返回“Ready”,K8s就会认为这个Pod已经准备好了,可以接受流量。
  4. 如果探测请求失败,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连接进行探测。
  • 设置合理的探测参数: initialDelaySecondsperiodSecondstimeoutSecondssuccessThresholdfailureThreshold这些参数都要根据你的应用特点进行设置。
  • 避免过度探测: 频繁的探测会增加服务器的负担,所以要合理设置periodSeconds

三、Liveness Probe: “我还活着,别抛弃我!”

Liveness Probe就像一个生命体征监测仪,负责检查Pod里的容器是否还在正常运行。如果Liveness Probe检测到容器已经“挂掉”了,K8s就会自动重启这个容器。

举个例子,一个Node.js应用,由于内存泄漏,导致程序卡死。如果没有Liveness Probe,K8s就不知道这个应用已经卡死了,还会继续分配流量给它。最终导致用户访问缓慢,甚至无法访问。

Liveness Probe就可以解决这个问题。它可以定期检查Node.js应用是否还在正常运行。如果发现应用已经卡死,就会自动重启这个容器,让应用恢复正常。

Liveness Probe的工作流程:

  1. K8s会定期(例如每隔10秒)向Pod里的容器发送一个探测请求。
  2. 这个探测请求可以是:
    • HTTP请求: 检查某个HTTP端口是否返回200 OK。
    • TCP连接: 尝试建立一个TCP连接到某个端口。
    • 执行命令: 在容器内部执行一个命令,检查其返回值是否为0。
  3. 如果探测请求成功,Liveness Probe就会认为这个容器还活着。
  4. 如果探测请求失败,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连接进行探测。
  • 设置合理的探测参数: initialDelaySecondsperiodSecondstimeoutSecondssuccessThresholdfailureThreshold这些参数都要根据你的应用特点进行设置。
  • 避免频繁重启: 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,用于检查应用的健康状态。应用启动时需要加载一些配置文件,加载完成后才能正常提供服务。

需求:

  1. 在应用启动完成后,才能接收流量。
  2. 如果应用出现卡死等异常,需要自动重启。

配置步骤:

  1. 编写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}`);
});
  1. 编写Dockerfile:
FROM node:16

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

CMD ["node", "app.js"]
  1. 编写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
  1. 部署应用:
kubectl apply -f deployment.yaml

解释:

  • Readiness Probe: 我们配置了Readiness Probe,使用HTTP请求检查/healthz接口。initialDelaySeconds设置为5秒,确保应用在加载完配置文件后才开始接受流量。
  • Liveness Probe: 我们配置了Liveness Probe,使用HTTP请求检查/healthz接口。initialDelaySeconds设置为15秒,避免应用启动时被误判。

六、高级用法:自定义探针

除了HTTP请求、TCP连接、执行命令这三种常用的探测方式外,我们还可以自定义探针,来实现更复杂的探测逻辑。

例如,我们可以编写一个脚本,检查数据库连接是否正常,或者检查消息队列是否拥堵。

自定义探针的实现方式:

  1. 编写探测脚本:
#!/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
  1. 将脚本复制到容器内部:
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"]
  1. 在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的区别,并在实际工作中灵活运用它们。记住,合理的配置探针,就像给你的应用穿上了一件坚固的盔甲,可以抵御各种突发状况。

最后,送给大家一句箴言:代码虐我千百遍,我待代码如初恋。探针配置要仔细,不然线上要崩溃! 😜

感谢大家的收看,我们下期再见! 👋

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注