首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >nacos与k8s service健康检查详解

nacos与k8s service健康检查详解

作者头像
锅总
发布2024-11-22 18:38:36
发布2024-11-22 18:38:36
6480
举报
文章被收录于专栏:锅总锅总
  • Nacos健康检查是由什么参数控制的?
  • k8s service健康检查配置是由什么参数控制的?
  • 如果k8s deployment滚动更新,在endpoint中会立即把对应需要替换的某一个pod给删除吗?
  • 旧版本的 Pod 被标记为 Terminating 的时间点是一个新的pod恰好ready的时候吗?

Tips:文末有思考题

Nacos健康检查

Nacos 中,服务实例可能会在某些条件下自动下线(即被标记为不健康,并从可用实例列表中移除)。这种行为通常由以下机制控制:


服务实例自动下线的条件

心跳超时(主要原因)

  • Nacos 客户端需要定期向服务端发送心跳信息,告知其状态为健康。
  • 如果在指定时间内(超时时间)未收到心跳,Nacos 服务端会将该实例标记为 不健康,并从负载均衡的候选列表中移除。

实例注销

  • 客户端显式调用 deregisterInstance() 方法,主动注销服务实例。
  • 应用进程在启动或关闭时也可能触发实例的注册和注销。

服务端检测异常

  • 服务端主动健康检查(如 TCP 或 HTTP 探针)失败,实例被标记为不健康。

网络异常

  • 客户端与 Nacos 服务端之间的网络连接中断。
  • 客户端宕机或网络不通导致心跳发送失败。

相关参数控制服务实例下线

1. 客户端心跳相关参数

这些参数主要配置在客户端( application.yml 或代码中)。

  • nacos.naming.heartbeat.interval 描述:客户端发送心跳的间隔时间。 默认值:5000 毫秒(5秒)。 控制作用:降低心跳间隔可以减少误判实例下线的可能性。 示例配置
代码语言:javascript
复制
nacos:
  naming:
    heartbeat:
      interval: 3000 # 心跳间隔为 3 秒
  • nacos.naming.health-check.retry
  • 描述:在实例标记为不健康之前,允许的心跳重试次数。
  • 默认值:3 次。
  • 示例配置
代码语言:javascript
复制
nacos:
  naming:
    health-check:
      retry: 5 # 尝试重试 5 次
  • nacos.naming.health-check.timeout
  • 描述:服务端判断实例下线的超时时间。
  • 默认值:15,000 毫秒(15秒)。
  • 示例配置
代码语言:javascript
复制
nacos:
  naming:
    health-check:
      timeout: 20000 # 超时时间设置为 20 秒

2. 服务端健康检查相关参数

这些参数主要配置在 Nacos 服务端( application.properties 文件)。

server.health-check.task.interval

  • 描述:服务端执行健康检查任务的时间间隔。
  • 默认值:5000 毫秒(5秒)。
  • 示例配置
代码语言:javascript
复制
server.health-check.task.interval=3000 # 每 3 秒执行一次健康检查任务

server.health-check.timeout-ms

  • 描述:服务端允许实例心跳的最大超时时间。
  • 默认值:15000 毫秒(15秒)。
  • 控制作用:心跳超时后,服务端会将实例标记为不健康。
  • 示例配置
代码语言:javascript
复制
server.health-check.timeout-ms=20000 # 心跳超时设置为 20 秒

server.health-check.retry

  • 描述:服务端重试健康检查的次数。
  • 默认值:3 次。
  • 示例配置
代码语言:javascript
复制
server.health-check.retry=5 # 允许 5 次重试

3. 服务实例元数据相关参数

在服务注册时,通过元数据可以设置一些特定健康检查参数。

元数据设置健康检查(例如 HTTP 探针)

  • Nacos 支持在实例元数据中指定健康检查探针。
  • 示例:
代码语言:javascript
复制
metadata:
  check: "http"
  check_url: "http://127.0.0.1:8080/health"
  timeout: 5000 # 超时时间 5 秒

ephemeral 参数

  • 描述:实例是否为临时实例。
  • 临时实例依赖心跳维持状态,超时会自动下线;而非临时实例不会因心跳超时而被移除,需手动注销。
  • 配置:
代码语言:javascript
复制
namingService.registerInstance("service-name", "127.0.0.1", 8080, "DEFAULT", true); // true 表示临时实例

其他注意事项

服务端与客户端时间一致性

  • 如果服务端和客户端的系统时间不一致,可能会导致心跳超时误判。
  • 确保时间同步(如 NTP 配置正确)。

服务端性能

  • 如果 Nacos 服务端负载过高,健康检查任务可能延迟,导致实例被错误标记为不健康。

网络抖动

  • 在网络状况较差时,心跳包可能丢失,建议适当增加超时时间和重试次数。

总结

  • 自动下线主要由心跳机制控制,客户端与服务端都需要正确配置心跳间隔、超时时间和重试次数。
  • 客户端主要通过 heartbeat.intervalhealth-check.timeout 控制心跳逻辑。
  • 服务端通过 server.health-check.timeout-ms 和相关参数执行健康检查任务。
  • 临时实例和非临时实例的健康检查行为不同,需根据场景合理选择。

k8s service健康检查配置是由什么参数控制的?

在 Kubernetes (K8s) 中,Service 的健康检查主要通过 Liveness ProbeReadiness ProbeStartup Probe 来实现。这些探针的配置决定了 Pod 的健康状态,并间接影响 Service 的行为,例如负载均衡和流量分发。


探针的类型和作用

Liveness Probe

  • 作用:检测 Pod 是否处于“活着”的状态。
  • 不健康时动作:重启容器。
  • 适用场景:应用进入死循环、卡死或内部错误时。

Readiness Probe

  • 作用:检测 Pod 是否可以接收流量。
  • 不健康时动作:从 Service 的负载均衡目标列表中移除。
  • 适用场景:应用启动缓慢、依赖外部资源时。

Startup Probe

  • 作用:检测应用是否启动完成。
  • 不健康时动作:重启容器。
  • 适用场景:应用启动时间较长,防止 Liveness Probe 误判。

健康检查的实现方式

健康检查通过以下方式执行,所有探针都支持这些方式:

HTTP GET 请求

  • 向指定的 HTTP 端点发送 GET 请求,如果返回的状态码在 200–399 范围内,则为健康。
  • 示例配置
代码语言:javascript
复制
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 5

TCP Socket

  • 尝试连接到容器指定端口,如果能建立连接则认为健康。
  • 示例配置
代码语言:javascript
复制
readinessProbe:
  tcpSocket:
    port: 3306
  initialDelaySeconds: 10
  periodSeconds: 5

命令执行(Exec)

  • 在容器中运行指定命令,如果返回码为 0 则为健康。
  • 示例配置
代码语言:javascript
复制
livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

关键参数

以下参数控制探针行为:

initialDelaySeconds

  • 描述:探针在容器启动后等待多少秒才开始探测。
  • 适用场景:设置应用初始化所需的时间。
  • 默认值:0。

periodSeconds

  • 描述:探针的探测频率,单位为秒。
  • 默认值:10 秒。

timeoutSeconds

  • 描述:探针的超时时间。
  • 默认值:1 秒。

successThreshold

  • 描述:探针连续成功的次数,表示从不健康到健康的阈值。
  • 默认值
    • Readiness Probe:1。
    • Liveness ProbeStartup Probe:无效。

failureThreshold

  • 描述:探针连续失败的次数,表示从健康到不健康的阈值。
  • 默认值:3。

示例完整配置

以下是一个完整的探针配置示例:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: probe-demo
spec:
  containers:
  - name: my-app
    image: my-app:latest
    ports:
    - containerPort: 8080
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 1
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /readyz
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 1
      successThreshold: 1
      failureThreshold: 3
    startupProbe:
      httpGet:
        path: /startz
        port: 8080
      initialDelaySeconds: 0
      periodSeconds: 10
      timeoutSeconds: 1
      failureThreshold: 60

Service 与健康检查的关系

  • Liveness ProbeStartup Probe 的状态不影响 K8s Service 的流量分发,仅用于控制 Pod 的重启。
  • Readiness Probe 的状态直接影响 Service 的流量分发。
  • 当 Readiness Probe 检测为“不健康”时,Pod 将从 Endpoints 中移除,Service 不再向该 Pod 分发流量。

常见问题与优化

探针频率过高

  • 会增加容器和 K8s 控制平面的负载。调整 periodSecondstimeoutSeconds 平衡性能与可靠性。

初始延迟不足

  • 如果 initialDelaySeconds 设置过短,探针可能误判启动中的容器为不健康。

网络不稳定

  • 在使用 HTTP GET 或 TCP Socket 时,短暂网络抖动可能导致探针失败,适当提高 failureThreshold

通过探针配置,K8s 提供了灵活的健康检查机制,可以结合实际场景优化探针参数和探测方式,实现稳定可靠的服务状态监控。

如果k8s deployment滚动更新,在endpoint中会立即把对应需要替换的某一个pod给删除吗?

在 Kubernetes 中,滚动更新(Rolling Update)是默认的部署策略,用于逐步替换旧版本的 Pod 为新版本的 Pod。关于是否会立即将需要替换的某一个 Pod 从 Endpoints 中删除,这取决于以下机制:


Endpoints 的处理流程

启动阶段

  • 在滚动更新中,新版本的 Pod 会先启动。
  • Kubernetes 会检测新 Pod 的 Readiness Probe 是否通过。

删除阶段

  • 在旧版本的 Pod 被标记为 Terminating 后,它的 Readiness Probe 会立即失效。
  • Endpoints Controller 会实时更新,移除对应 Pod 的 IP 地址。
  • 即,Pod 会立即从 Endpoints 中移除,但实际的 Pod 删除过程可能稍后完成。

滚动更新中的行为

默认行为

  • Kubernetes 遵循“先启动新 Pod,再终止旧 Pod”的逻辑,具体由 maxUnavailablemaxSurge 参数控制:
    • maxUnavailable:最大允许同时不可用的 Pod 数量。
    • maxSurge:最大允许超出指定 Pod 副本数的新增 Pod 数量。
  • 旧 Pod 在 Terminating 阶段会被从 Endpoints 中移除,因此流量不会再分发给该 Pod。

Graceful Termination(优雅终止)

  • Pod 的终止过程遵循 TerminationGracePeriodSeconds 的配置(默认 30 秒)。
  • 如果应用需要完成清理任务(如关闭连接或完成当前请求),可以在 Pod 的生命周期回调(如 preStop hook)中实现。
  • 即使 Pod 尚未完全删除,只要 Readiness Probe 判定不健康,它的 IP 仍会被移除。

关键参数和行为

以下配置项会影响滚动更新过程中 Pod 在 Endpoints 中的处理方式:

readinessProbe

  • 确保旧 Pod 的 Readiness Probe 失效后流量停止分发。
  • 配置示例:
代码语言:javascript
复制
readinessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 5

Deployment 策略中的 maxUnavailablemaxSurge

  • maxUnavailable:定义最多有多少个 Pod 可以同时不可用。
  • maxSurge:定义最多可以多出多少个新 Pod。
  • 配置示例:
代码语言:javascript
复制
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxUnavailable: 1
    maxSurge: 1

TerminationGracePeriodSeconds

  • Pod 在被标记为 Terminating 后的优雅终止时间,决定清理任务完成的时间。
  • 配置示例:
代码语言:javascript
复制
spec:
  terminationGracePeriodSeconds: 30

Service 的 publishNotReadyAddresses 参数

  • 默认情况下,未准备好的 Pod 地址(即 Readiness Probe 失败的 Pod)不会加入 Endpoints。
  • 如果启用了 publishNotReadyAddresses:true,即使 Pod 未准备好,仍会暴露在 Endpoints 中。
  • 配置示例:
代码语言:javascript
复制
spec:
  publishNotReadyAddresses: true

总结

  • 在滚动更新过程中,Pod 被替换时,旧 Pod 会立即从 Endpoints 中移除,但实际 Pod 的删除可能会等待优雅终止完成。
  • 流量中断的防控
  • 配置合理的 Readiness ProbeTerminationGracePeriodSeconds
  • 设置合适的 maxUnavailablemaxSurge,保证服务有足够可用的 Pod。 调试 Endpoints 的变化: 运行以下命令查看 Service 的 Endpoints:
代码语言:javascript
复制
kubectl get endpoints <service-name> -o yaml

旧版本的 Pod 被标记为 Terminating 的时间点是一个新的pod恰好ready的时候吗?

在 Kubernetes 的滚动更新过程中,旧版本的 Pod 被标记为 Terminating 的时间点和新 Pod 的状态(特别是 Ready 状态)之间的关系,取决于 Deployment 策略参数配置


默认情况下的行为

滚动更新的逻辑

  • Kubernetes Deployment 默认使用 RollingUpdate 策略。
  • 控制 Pod 替换顺序的关键参数是:
    • maxUnavailable:允许的最大不可用 Pod 数量。
    • maxSurge:允许的最大超额新增 Pod 数量。
  • 具体行为:
    1. 新 Pod 启动并等待变为 Ready
    2. 确保服务总的可用 Pod 数量不低于 replicas-maxUnavailable
    3. 一旦满足条件,旧 Pod 被标记为 Terminating,并从 Endpoints 中移除。
    4. Kubernetes 会继续这一过程,直到完成所有 Pod 的替换。

是否等待新 Pod 就绪(Ready)

  • 默认情况下,滚动更新会等待一个新 Pod Ready 后才开始终止一个旧 Pod
  • 这是因为 maxUnavailable 参数控制了同时不可用的 Pod 数量,默认为 1。

例外情况

maxUnavailable > 0
  • 如果允许一定数量的不可用 Pod,则 Kubernetes 不需要等待新 Pod Ready,可能会同时终止旧 Pod 并启动新 Pod。
  • 示例配置
代码语言:javascript
复制
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxUnavailable: 2
    maxSurge: 1
  • 在这种情况下,旧 Pod 可能会提前进入 Terminating 状态,即便新 Pod 尚未完全 Ready
新 Pod 长时间未 Ready
  • 如果新 Pod 因配置问题或资源不足而无法变为 Ready,旧 Pod 的终止可能被延迟。
  • Kubernetes 依赖 ProgressDeadlineSeconds 参数定义超时时间。
  • 如果在指定时间内更新未完成,Deployment 将进入失败状态。
  • 默认值:600 秒。
  • 配置示例:
代码语言:javascript
复制
spec:
  progressDeadlineSeconds: 300  # 5分钟内未完成滚动更新则标记失败
优雅终止时间(Graceful Termination)影响
  • 旧 Pod 的 TerminationGracePeriodSeconds 参数也会影响滚动更新的节奏:
  • 如果设置时间较长(默认 30 秒),即使新 Pod 已 Ready,旧 Pod 也可能延迟退出。
  • 配置示例:
代码语言:javascript
复制
spec:
  terminationGracePeriodSeconds: 60

总结:是否等新 Pod Ready 再终止旧 Pod

  • 默认情况是的,滚动更新会等待一个新 Pod 变为 Ready,再终止一个旧 Pod。
  • 特殊情况
  • 如果设置了 maxUnavailable>0progressDeadlineSeconds 超时,可能会在新 Pod 未完全 Ready 的情况下终止旧 Pod。
  • 配置了较长的 TerminationGracePeriodSeconds,可能会让旧 Pod 在新 Pod 已 Ready 的情况下仍保持运行一段时间。

如何调试滚动更新状态

查看 Pod 状态

代码语言:javascript
复制
kubectl get pods -w
  • 可以实时观察新 Pod 的创建和旧 Pod 的 Terminating 状态变化。

查看 Deployment 策略

代码语言:javascript
复制
kubectl get deployment <deployment-name> -o yaml
  • 检查 rollingUpdate 的配置参数。

检查更新进度

代码语言:javascript
复制
kubectl rollout status deployment <deployment-name>
  • 查看更新是否卡住或超时。

通过合理配置参数,可以精确控制滚动更新过程,避免新旧 Pod 的流量切换产生中断问题。


思考:为什么流量打到了不健康的pod上?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 锅总 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Nacos健康检查
    • 服务实例自动下线的条件
    • 相关参数控制服务实例下线
      • 1. 客户端心跳相关参数
      • 2. 服务端健康检查相关参数
      • 3. 服务实例元数据相关参数
    • 其他注意事项
    • 总结
  • k8s service健康检查配置是由什么参数控制的?
    • 探针的类型和作用
    • 健康检查的实现方式
    • 关键参数
    • 示例完整配置
    • Service 与健康检查的关系
    • 常见问题与优化
  • 如果k8s deployment滚动更新,在endpoint中会立即把对应需要替换的某一个pod给删除吗?
    • Endpoints 的处理流程
    • 滚动更新中的行为
    • 关键参数和行为
    • 总结
  • 旧版本的 Pod 被标记为 Terminating 的时间点是一个新的pod恰好ready的时候吗?
    • 默认情况下的行为
    • 例外情况
      • maxUnavailable > 0
      • 新 Pod 长时间未 Ready
      • 优雅终止时间(Graceful Termination)影响
    • 总结:是否等新 Pod Ready 再终止旧 Pod
    • 如何调试滚动更新状态
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档