Kubernetes学习笔记04:发布、排障和观测

发表于 2024-02-25 22:18 1631 字 9 min read

Spring AI学习笔记(四)工具调用和MCPSpring AI学习笔记(三)RAG从文档入库到回答Spring AI学习笔记(二)ChatClient从怎么调到怎么封装Spring AI学习笔记(一)它到底解决什么问题java新版本-java25学习笔记(四)用JFR和GC日志做一次体检java新版本-java25学习笔记(三)虚拟线程要和资源边界一起看java新版本-java25学习笔记(二)运行时基线先统一java新版本-java25学习笔记(一)LTS版本对比和学习路线主流AI Agent能力对比与工程选型我用Kiro做了个自己的工具站盘一盘虚拟线程我用Trae做了个AstrBot的AI角色扮演插件Python初学笔记(六)常用标准库先学这几个Python初学笔记(五)读写文件和处理异常Python初学笔记(四)函数让代码开始有结构Python初学笔记(三)条件、循环和推导式Python初学笔记(二)变量和基础类型比想象中重要Python初学笔记(一)先把环境和运行方式弄明白主流AI大模型能力对比Java 21和Spring Boot 3升级笔记(五)日志指标与可观测性Java 21和Spring Boot 3升级笔记(四)数据访问层适配Java 21和Spring Boot 3升级笔记(三)虚拟线程使用边界Java 21和Spring Boot 3升级笔记(二)Jakarta迁移要点Java 21和Spring Boot 3升级笔记(一)工程基线整理How Can We Tolerate Magic Values! Major Overhaul of JPA Specification!处理生僻字乱码:JPA框架对于Oracle的NVarchar2,NChar,NClob类型支持Redis Stream能不能当轻量消息队列用RocketMQ 5学习笔记:普通消息之外要看什么事件流不是换个消息队列这么简单Kubernetes学习笔记04:发布、排障和观测Kubernetes学习笔记03:配置、密钥和存储Kubernetes学习笔记02:Deployment、Service和IngressKubernetes学习笔记01:Pod和控制器mysql索引原理02--存储引擎索引的实现mysql索引原理01--索引的数据结构
This post is not yet available in English. Showing the original.
  前面几篇主要讲了 Kubernetes 里的核心对象、访问链路、配置和存储。但真正把服务放到 k8s 里跑,最容易出问题的往往不是“能不能启动”,而是发布和排障。   一个应用第一次部署成功,只能说明基础链路通了。后面每次升级、扩缩容、节点故障、依赖抖动,才是在考验整套运行体系。...

前言

  前面几篇主要讲了 Kubernetes 里的核心对象、访问链路、配置和存储。但真正把服务放到 k8s 里跑,最容易出问题的往往不是“能不能启动”,而是发布和排障。

  一个应用第一次部署成功,只能说明基础链路通了。后面每次升级、扩缩容、节点故障、依赖抖动,才是在考验整套运行体系。

  这篇就把发布、探针、资源限制、日志和常见排障路径放在一起梳理。它们看起来分散,但都是生产可用性的一部分。

滚动发布依赖 readiness

  Deployment 默认支持滚动更新。更新镜像后,k8s 会逐步创建新 Pod,再逐步下掉旧 Pod。

但滚动发布能不能稳,很大程度取决于 readinessProbe。

readinessProbe 表示这个 Pod 是否已经准备好接收流量。如果新 Pod 只是进程启动了,但数据库连接还没初始化、缓存还没预热、Spring Boot 还没完成启动,就不应该接流量。

一个常见配置:

readinessProbe:
  httpGet:
    path: /actuator/health/readiness
    port: 8080
  initialDelaySeconds: 20
  periodSeconds: 10
  timeoutSeconds: 3
  failureThreshold: 3

对于 Java 服务,启动时间可能受类加载、JIT、配置中心、数据库连接影响。探针时间不能照搬 demo,要按真实启动情况调整。

如果 readiness 太激进,新 Pod 还没准备好就接流量。如果太保守,发布速度会变慢。这里没有固定答案,要结合服务启动曲线和业务可接受时间。

liveness 不要滥用

  livenessProbe 表示容器是否还活着。如果 liveness 失败,k8s 会重启容器。

它适合处理进程卡死、死锁、主线程异常但进程未退出这类问题。

但不要把所有依赖检查都塞进 liveness。比如数据库短暂不可用,如果 liveness 也检查数据库,那应用可能会被反复重启。重启本身不能修复数据库,反而会扩大故障。

我的理解是:

1.readiness 负责决定能不能接流量。 2.liveness 负责判断进程是否需要重启。 3.startupProbe 负责给慢启动应用更多启动时间。

这三个探针职责不同,混在一起会让故障处理变得不可控。

资源限制要认真写

  k8s 调度和稳定性都依赖资源配置。只写镜像和副本,不写 requests 和 limits,在测试环境可能没事,在生产环境很容易出问题。

requests 表示调度时需要预留的资源,limits 表示容器最多能使用的资源。

resources:
  requests:
    cpu: 500m
    memory: 768Mi
  limits:
    cpu: "1"
    memory: 1024Mi

对于 Java 服务,内存尤其要小心。容器 memory limit、JVM 最大堆、元空间、线程栈、直接内存都要一起考虑。

如果 limit 设得太小,可能出现 OOMKilled。如果 requests 设得太低,调度器会把太多 Pod 放到同一节点,节点压力上来以后延迟会很难看。

资源配置不是一次写完就结束。上线后要结合真实指标调整,而不是长期沿用模板里的默认值。

日志要从第一天按容器方式处理

  在 k8s 里,应用日志最好输出到 stdout 和 stderr,再由节点或集群日志系统采集。

不要继续按传统方式把日志写到容器内部某个文件目录,然后指望 SSH 到机器上看。Pod 会迁移,容器会重启,本地文件也不一定还在。

排查时可以先用:

kubectl logs deploy/order-service
kubectl logs pod/order-service-xxx --previous

--previous 很有用,可以查看上一个崩溃容器实例的日志。很多 CrashLoopBackOff 问题,当前容器已经重新启动,真正的异常在 previous 日志里。

长期看,还是要接集中式日志平台。至少能按 namespace、app、pod、traceId 查询。否则线上问题只能临时翻 kubectl,效率会很低。

describe 比 get 更能说明问题

  kubectl get 适合快速看状态,但排障时经常不够。

比如 Pod 一直 Pending,get 只能看到没启动。真正原因可能是资源不足、节点选择器不匹配、PVC 绑定失败、镜像拉取权限问题。

这时候要看 describe:

kubectl describe pod order-service-xxx

重点看 Events。调度失败、拉镜像失败、探针失败、挂载失败,通常都会在事件里留下线索。

如果 Pod 已经 Running,但服务不可用,再继续看日志、探针、Service endpoints 和应用自身健康接口。

排障不要一上来就重启。重启可能会掩盖现场,而且不一定解决根因。

常见状态要会读

  几个常见状态值得记住:

Pending:Pod 还没调度或还没完成准备。常见原因是资源不足、镜像拉取等待、PVC 未绑定。

ImagePullBackOff:镜像拉取失败。检查镜像名、tag、仓库地址、镜像仓库凭证。

CrashLoopBackOff:容器启动后不断崩溃。优先看日志和 previous 日志。

Running 但 NotReady:进程在跑,但 readinessProbe 没通过。检查健康接口、依赖、启动时间、探针路径和端口。

OOMKilled:容器超过内存限制被杀。检查 JVM 参数、内存 limit、流量变化和最近代码改动。

这些状态不是最终答案,但能指明排查方向。

发布前最好有最小检查清单

  我比较喜欢给 k8s 应用准备一个很短的发布检查清单:

1.Deployment 副本数是否合理。 2.Service selector 是否能匹配 Pod。 3.readinessProbe 是否能真实反映可接流量状态。 4.resources requests 和 limits 是否写了。 5.镜像 tag 是否可追踪,不用 latest。 6.日志是否输出到 stdout。 7.关键环境变量和 Secret 是否存在。 8.回滚命令和上一版本镜像是否明确。

这份清单不需要很复杂,但应该成为习惯。很多事故不是因为 Kubernetes 特别难,而是因为基础项没有检查。

小结

  Kubernetes 的价值不只是把应用跑起来,还包括持续发布、自动恢复、弹性扩缩和统一观测。

  但这些能力不会凭空生效。readiness、liveness、resources、日志、事件、监控指标,都需要在应用接入时一起设计。

  我的经验是,先把最普通的 Deployment + Service + Ingress 做稳,再补齐探针、资源、日志和排障手段。等这些基础能力可靠以后,再谈灰度、自动扩缩容和更复杂的平台能力,才比较踏实。

If you enjoyed this, leave a comment~

© 2019 - 2026 VincentHo @VincentHo
Powered by theme astro-koharu · Inspired by Shoka