尧图精选

Kubernetes容器生命周期管理:从Pod状态到探针与优雅停机

🕒 发布时间:2026/9/20 2:06:26 📁 来源:尧图网络
1. 从容器到PodK8s为什么把生命周期管理抬高了一层刚接触K8s那会儿我犯过一个几乎所有初学者都会犯的错习惯性用Docker的思路去理解一切觉得管好容器就够了然后等到排查线上故障时被Pod的诡异状态狠狠教育了一顿。这篇文章我想把k8s容器生命周期这件事彻底讲透从状态机到探针、从优雅停机到故障现场把自己这些年踩过的坑和验证过的方案全盘托出。先达成一个共识在Kubernetes里最小的调度和运行单元是Pod不是容器。容器只是Pod内部的组成成员真正的生命周期管理边界其实是Pod。如果你抱着“管理单个容器”的念头去用K8s很快就会撞上一堵墙——明明容器已经退出了Pod却还在“Running”或者反过来容器始终没起来Pod却一直处于“ContainerCreating”让人一头雾水。为什么K8s要引入Pod这一层最核心的原因是一个业务单元往往需要多个容器协同工作。最典型的场景就是日志收集主容器跑业务sidecar容器负责采集日志、转发到日志平台两个容器共享同一个网络命名空间和存储卷必须同生共死一起调度、一起迁移、一起重启。如果直接用容器作为最小单位这种紧密关联的容器组就无法被看作一个整体来处理。另一个关键组件帮助理解了这一点——pause容器也叫infra容器。每一个Pod创建时kubelet会先启动一个pause容器它占用Pod的沙箱环境持有Pod的Network Namespace和挂载卷。用户定义的业务容器本质上都是挂在这个沙箱里运行的。pause容器是“看不做事、实则稳定整个架构”的定海神针。业务容器代码崩了、重启了、被杀了只要pause容器还在Pod就不会被删除资源也不会重新申请这背后就是生命周期管理的精妙之处。https://github.com/kubernetes/kubernetes/blob/master/build/pause/Dockerfile很多人找《K8s权威指南》PDF、看各种集群搭建教程最后却败在排查故障上根子就在于对生命周期模型没有一个完整的框架。我建议把“容器跑起来”这只算万里长征第一步真正的挑战在于容器起来之后怎么持续健康地运行怎么优雅地退出出问题后怎么恢复整个循环才是完整的生命周期。1.1 Pod才是真正的“生命周期容器”我们可以打个比方Pod很像商场里的店铺容器则是入驻店铺的商家。店铺Pod负责提供水电物业这些基础设施商家容器想搬走就搬走、想回来就回来但店铺本身始终存在除非商场统一收回。明白了这层关系看K8s的各种日志和状态时视角会完全不一样。当你对某条业务容器做重启操作时Pod的IP和挂载卷不会变因为基础设施还在当你删掉整个Deployment时Pod和里面的所有容器会一起消失。这也是为什么在K8s中我们很少直接操作单个容器而是管理Pod、管理Deployment、管理StatefulSet这些上层资源。1.2 kubelet、容器运行时与容器生命周期的三方博弈K8s集群里真正和容器直接打交道的是节点上的kubelet它通过CRI容器运行时接口调用容器运行时比如containerd、CRI-O来完成容器的创建、启动、停止、删除。kubelet和容器运行时之间有明确的职责划分kubelet负责Pod的期望状态包括容器应该有几个、镜像是什么、重启策略是什么容器运行时负责具体执行负责拉镜像、起进程、管理底层隔离。这个分工决定了排查故障的套路如果Pod一直卡在ContainerCreating八成是镜像拉取有问题或者存储卷挂载不成功此时应该去看kubelet的日志、Pod的事件如果容器启动后立刻崩溃那是镜像内部的启动命令或应用本身的代码有问题kubectl logs可以告诉我们答案。2. 容器的四种状态你必须烂熟于心K8s官方把容器生命周期划分为三个大状态但在实际运维场景里我更愿意把它拆成四个阶段来理解等待Waiting、运行Running、终止Terminated和“已删除”。后面这个“已删除”在kubectl get pods中通常不显示但它代表了一个Pod生命周期真正的终点。查看状态最直接的方式是kubectl get pods -o wide kubectl describe pod pod-name kubectl get pod pod-name -o jsonpath{.status.containerStatuses[0].state}第一次执行describe时很多人会被底部那段“Events”吸引住却忽略了containerStatuses里的状态字段。其实排障时这两者缺一不可Events告诉你发生了什么containerStatuses里的state告诉你容器现在具体在哪个生命周期阶段。2.1 创建阶段的Waiting状态容器刚被kubelet接收时会先进入Waiting状态。这个状态覆盖了从“拉取镜像”到“创建并启动容器”的完整过程。因为拉镜像耗时不定Waiting状态可能持续几秒也可能持续几分钟。如果镜像拉取失败容器会反复尝试拉取此时事件里会看到ImagePullBackOff或者ErrImagePull。我之前在一次压测环境部署时遇到过这个问题私有仓库里的镜像被覆盖了但部署时用的是latest标签结果有几个节点缓存了旧镜像有几个节点拉取超时整个环境状态五花八门排查了一圈才发现是镜像仓库和镜像标签规范的问题。后来我要求团队所有镜像必须使用不可变标签比如commit短哈希或日期加构建号彻底杜绝了这类不确定性。2.2 运行阶段的Running状态容器正常启动后就会进入Running状态。但Running不是“万事大吉”的意思它只说明容器的进程活着不说明业务功能正常。一个Running状态的容器可能已经陷入死锁可能内存泄漏到快爆炸只是进程还没退出而已。所以生产环境一定要配探针用探针来定义“健康”的业务含义。我曾经处理过一起事故一个Java容器进程一直在跑看起来一切正常但JVM已经频繁Full GC接口响应时间从几十毫秒膨胀到几十秒因为没有配置就绪探针负载均衡还是一直往里转发流量。直到用户大量投诉我们才发现问题。所以探针不是锦上添花而是生命周期管理中必不可少的一环。2.3 终止阶段的Terminated状态容器进程退出后会进入Terminated状态并记录退出码和退出时间。退出码是定位故障的钥匙退出码0正常退出。可能是任务完成了也可能是应用主动调用了exit(0)退出码1应用自身异常退出代码抛错、启动失败都有可能退出码137进程被SIGKILL杀死最常见的是内存超出limit被系统OOM Killer干掉退出码143进程被SIGTERM终止通常发生在Pod滚动更新或删除时kubelet发出优雅停机信号退出码139段错误通常是原生代码或底层库出了内存非法访问# 查看容器的退出码 kubectl get pod pod-name -o jsonpath{.status.containerStatuses[0].lastState.terminated.exitCode}退出码配合重启策略决定了容器接下来的命运是原地重启还是整个Pod被重新调度。这一步的细节我放在后面第3章结合重启策略一起展开。2.4 Pod与容器状态的关系Pod的状态不等同于容器的状态这个区分很重要。Pod的官方状态有五种PendingPod已经被集群接受但有一个或多个容器还没就绪RunningPod内部的容器已经全部创建成功至少有一个容器在运行SucceededPod里所有容器都正常退出退出码0不会再重启FailedPod里至少有一个容器以非0退出码退出UnknownAPI Server无法获取Pod的状态通常意味着节点失联或kubelet异常实际运维时我们经常看到的CrashLoopBackOff并不在Pod的官方状态里它是kubelet在容器反复启动失败后的一个“保护性标记”表示容器一直在走“启动→崩溃→重启→再崩溃”的循环。原因通常是应用配置错误、启动命令问题、健康检查失败等等。3. 探针配置实务Startup、Readiness、Liveness用对场景才不踩坑探针是K8s对外提供的最核心的生命周期管理工具。你可以把它理解成一套定期的体检系统kubelet按照你设定的频率去问容器“你还活着吗”“你能干活了吗”“你准备好长时间跑了吗”。每一种探针的语义完全不同乱配比不配更危险。3.1 三种探针的区别和选择存活探针LivenessProbe判断容器是否存活。存活探针失败时kubelet会按照重启策略杀掉容器并重启。它的使命是清掉那些“进程在但业务已经死掉”的僵尸容器。适合放在那些一旦死锁就永远不会恢复的业务上。但注意存活探针不要设置得过于敏感否则一次短暂卡顿就会导致容器被杀引发无意义的频繁重启。就绪探针ReadinessProbe判断容器是否可以对外提供服务。它只影响Service后端列表不会重启容器。就绪探针失败时Pod会被从Service的Endpoints中摘除流量不再进入探针恢复后流量自动重新接入。在发布滚动更新时就绪探针是保证“新Pod能干活了才接流量”的关键。启动探针StartupProbe保护启动较慢的应用。很多Java应用或监控系统启动过程很慢可能要一两分钟才能完成初始化如果存活探针配置的initialDelaySeconds不够容器就会在启动过程中被反复杀掉。启动探针就是专门为这类应用设置的“宽限期”启动探针成功之前存活探针与就绪探针都不会生效。我举个配置示例开发环境里最常见的Spring Boot应用配合MySQLports: - containerPort: 8080 name: http livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 60 periodSeconds: 20 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 30 periodSeconds: 10 startupProbe: httpGet: path: /actuator/health/startup port: 8080 failureThreshold: 30 periodSeconds: 5这里启动探针的failureThreshold为30periodSeconds为5秒最坏情况下会等待150秒足够一个大型Spring Boot应用完成初始化。等启动探针通过后存活探针才接管“健康监督”的职责不会误伤“正在启动”的容器。3.2 探针的实现方式有三种探针支持三种检查方式HTTP GETkubelet对容器的指定端口发起HTTP GET请求响应码在200到399之间视为健康。这种方式最适合HTTP服务TCP Socketkubelet尝试与容器指定端口建立TCP连接能连上就算健康Exec命令kubelet在容器内执行指定命令退出码为0代表健康选择建议是HTTP或TCP优先Exec命令要尽量谨慎因为命令执行会有额外的进程上下文开销同时命令所在的镜像里必须包含对应的可执行文件。我有一次用Exec探针检查一个纯Alpine镜像镜像里根本没有curl和wget探针直接报错最后只能用TCP方式。3.3 探针参数组合实测下的最佳值initialDelaySeconds容器启动后多久开始第一次探针 periodSeconds间隔多久探一次默认10秒 timeoutSeconds单次探针超时时间默认1秒生产建议设3到5秒 failureThreshold连续失败多少次才认为失败默认3次 successThreshold连续成功多少次才认为成功默认1次就绪探针在高可用场景可配2对于业务接口比较慢的HTTP服务initialDelaySeconds宁可给大一点也不要因为探针太激进导致Pod一直重启。我有一次给Nginx的存活探针设了1秒超时日志里全是timeout后来把timeoutSeconds调到5秒世界安静了。3.4 高并发场景下探针的“自激震荡”陷阱这里多说一句压测相关的坑因为很多人会在压测时遇到服务整体不稳的情况。压测启动后业务线程被占满接口响应变慢如果此时探针的timeoutSeconds设置得过低就会探测超时然后Pod被重启或者被摘除流量。流量切走之后Pod恢复探针恢复流量又重新进来又被打满又超时形成一种“自激震荡”。你会在压测监控里看到Pod频繁重启、成功率曲线来回抖动但业务本身并没有崩溃。之前协助团队做微服务迁移时高并发测试阶段就遇到了这个现象最后定位到探针参数过于激进压测期间把探针的失败阈值放宽、超时时间调大集群立刻稳定了下来。4. 容器的自我修复重启策略、优雅停机与钩子机制如果说探针负责的只是“发现问题”那重启策略负责的就是“解决问题”。探针发现容器异常后kubelet会根据RestartPolicy来决定是否重启容器、何时重启。4.1 重启策略Always、OnFailure、NeverDeployment和ReplicaSet管理的PodrestartPolicy只能配置为Always这也是默认值。但不代表另外两个没有用Always不管容器是正常退出还是异常退出都会自动重启。适合常驻型服务API、作业处理等OnFailure只有容器异常退出非0退出码时才重启。适合批处理任务跑完了就完了别多此一举再起一个Never无论什么情况都不重启。适合那些特殊的一次性任务或者你完全想自己控制重启时机的场景重启不是立即执行的。kubelet会对频繁崩溃的容器做退避等待第一次崩溃后立即重启第二次等10秒之后按照20秒、40秒、80秒……以指数退避增长直到300秒封顶。等待期间Pod的状态显示为CrashLoopBackOff这其实是保护机制防止异常容器疯狂消耗节点资源。4.2 优雅停机SIGTERM与terminationGracePeriodSeconds真正体现生命周期管理精细度的是“停机阶段”。很多团队在机房里的应用还是“直接kill进程”到了K8s里这一套必须改掉。K8s删除Pod时默认的流程是kubelet收到Pod删除请求如果配置了PreStop钩子先执行钩子kubelet向容器主进程发送SIGTERM信号等待容器优雅退出默认30秒超时后发送SIGKILL强制杀掉进程过程中同步从Service Endpoints中摘除Pod如果应用没有处理SIGTERM信号那么30秒后就会被SIGKILL强杀。对于很多Java应用来说突然强杀意味着连接未释放、消息未确认、状态未持久化。所以应用侧必须实现优雅退出逻辑即监听SIGTERM信号、停止接收新请求、处理完存量请求、再退出进程。有经验的运维会在容器里多做一步让主进程以PID 1运行或者用tini这类init进程作为PID 1来接收信号并转发给子进程。因为PID 1在Linux里有特殊地位不会收到默认的信号如果不做特殊处理容器内的进程可能根本收不到SIGTERM导致只能被强杀。terminationGracePeriodSeconds: 60这个参数根据业务需要调整。我的建议是至少给到60秒给应用留足够的缓冲时间处理存量请求。之前做过一次服务迁移验证把terminationGracePeriodSeconds从默认30秒调到60秒后消息队列里的未确认消息数量从几百条降到了零。4.3 PreStop钩子停机前的最后一次抢救PreStop钩子在容器被终止之前执行适合处理那些应用无法自行完成的收尾工作或者给应用更多停机前的缓冲时间。最常见也是最实用的模式是“sleep 延迟摘流量”lifecycle: preStop: exec: command: [/bin/sh, -c, sleep 15]配合Service的滚动更新这15秒是为了让kube-proxy有足够的时间把Pod从Endpoints中摘除避免新请求在Pod正在终止时到达。实际效果非常明显加了PreStop之后滚动发布期间几乎看不到502。另一种用途是通知注册中心下线。比如某些自研的注册中心没有实现优雅下线可以在PreStop中调用注册中心的接口主动摘除节点lifecycle: preStop: exec: command: [/bin/sh, -c, curl -X POST http://localhost:8080/offline || true]注意命令一定要加|| true确保curl失败也不会阻塞整个停止流程。PreStop钩子的总执行时间受terminationGracePeriodSeconds限制钩子执行完后才会发送SIGTERM所以如果钩子执行了15秒那么从停止到强杀的完整时间就是15秒加剩下的宽限期。4.4 PostStart钩子容器启动后的“举手报告”与PreStop对应的是PostStart在容器启动成功后立即执行适合做初始化动作比如生成配置文件、预热缓存、注册服务。但PostStart与主进程的启动是异步的钩子执行时主进程可能还没准备好所以PostStart里的操作不要依赖主进程或者说必须在PostStart里做重试和容错。相比PostStartPreStop在实际生产中价值更高PostStart有时反而会引入不必要的复杂度如果初始化动作太多我建议直接用一个init容器来做行为更可控。5. 实战排查常见生命周期故障与处理记录聊了这么多原理下面分享几个我亲身踩过、排查过的故障现场。每一条都有现象、原因和解决思路你可以直接对照着手。5.1 现象一容器启动后立刻退出Pod一直在CrashLoopBackOff有一次帮朋友排查Python容器启动后立刻就退出了端到端日志还出现aborted(core dumped)Pod反复重启。排查步骤# 1. 查看Pod状态 kubectl get pods # 2. 查看容器日志 kubectl logs pod-name --tail200 # 3. 查看退出码 kubectl get pod pod-name -o jsonpath{.status.containerStatuses[0].lastState}日志里看到Segmentation fault退出码139说明是底层原生代码崩溃。最后定位到问题是镜像里某个依赖的so库文件不完整重新构建镜像解决。这类问题如果只看Pod满屏的ExitCode或者只翻Events不去看容器日志很难找到真正的根因。如果是常见的“容器启动后退出码0”那说明应用启动后很快就自己走完了生命周期多半是启动命令有问题比如前台启动和后台启动搞混了。Docker镜像里启动一个进程必须用前台方式这一点非常重要。举一个典型的Java容器反例CMD [java, -jar, app.jar]这样写是正确的Java进程在前台运行。如果写成脚本内使用nohup或者把进程丢到后台容器的主进程就变成了shell脚本本身脚本执行完退出容器也就退出了。这个坑在早期排查中经常出现随着经验的积累我每次看到“容器跑起来就退”的问题第一反应都是检查启动命令是否保持了前台进程。5.2 现象二Pod一直ContainerCreating这类问题可以从事件入手kubectl describe pod pod-name常见的失败事件包括镜像不存在Error: ImagePullBackOff确认镜像名称和tag拉镜像超时ImagePullError检查网络、镜像仓库地址是否可达必要时配置imagePullSecrets存储卷挂载失败FailedMount检查PVC、PV状态以及节点访问存储的权限资源不足OutOfmemory节点内存不够容器无法启动节点没匹配到0/5 nodes are available检查资源请求与节点标签节点资源不足的提示往往是“Insufficient cpu”或“Insufficient memory”通过kubectl describe node可以看到每个节点的剩余资源情况。我遇到过一次性创建大量Deployment结果所有Pod都Pending就是因为没有检查节点的可分配内存。5.3 现象三Pod一直Terminating怎么都删不掉这类问题多发生在节点异常或容器运行时卡住的情况下。正常的终止流程应该在几十秒内完成但如果超过几分钟还卡着基本就是kubelet和容器运行时之间的通信出了问题或者容器内有进程对SIGKILL不响应。处理思路# 1. 查看节点状态 kubectl get nodes # 2. 强制删除Pod不是万不得已不要用 kubectl delete pod pod-name --grace-period0 --force强制删除是最后手段因为可能造成容器实际仍在运行但Pod已被删除的“孤儿容器”。更稳妥的做法是先确认节点是否NotReady如果是节点本身的问题先把节点恢复Pod一般会自动清理。有一次是NFS挂在节点上无响应所有挂着该NFS的Pod全部Terminating物理重启节点才解决。5.4 现象四容器被OOMKilled容器因为超过内存limit被系统杀掉退出码137。遇到这种情况先不要急着调大内存先查清楚内存到底用在哪里kubectl exec -it pod-name -- top kubectl exec -it pod-name -- cat /sys/fs/cgroup/memory/memory.usage_in_bytesJava应用要特别注意堆内存设置容器的JVM初始堆大小可能跟默认值不一样传统“在宿主机上看free”的方式在容器里不准。使用容器时是通过cgroup来限制资源的JVM如果不显式配置-XX:MaxRAMPercentage很可能按宿主机的内存来推断堆最大值直接撑爆容器的limit所以可以按可用内存的75%来配置java -XX:MaxRAMPercentage75.0 -jar app.jar还有一种隐蔽情况容器内存明明没超但节点总内存不足节点级别的OOM Killer也可能杀掉部分Pod。此时要检查节点的内存水位借助Prometheus监控观察是否出现节点内存压力。之前参与微服务高并发测试时就因为压测导致节点内存不足部分Pod被无辜清理我立刻为关键服务增加了resources.requests让调度器提前规划资源避免节点过载。5.5 一个完整的排查路径现在把经验浓缩成一套模板。当你接手一个异常Pod环境时按下面的路径走基本不会漏# 1. 看Pod整体状态 kubectl get pods -A -o wide # 2. 看具体Pod的事件理解kubelet的行为 kubectl describe pod pod-name # 3. 看容器日志理解应用的行为 kubectl logs pod-name --tail200 kubectl logs pod-name --previous --tail200 # 4. 检查容器状态和退出码 kubectl get pod pod-name -o yaml | grep -A 30 status # 5. 检查节点资源 kubectl describe node node-name这套路径的本质是“先看调度和基础设施层再看应用层”。大部分排查过程中问题都在前两步就暴露了。如果前两步一切正常就要把目光从集群层转移到应用本身这时候可以在容器内执行命令深入检查kubectl exec -it pod-name -- /bin/sh6. 生命周期管理的高阶视角资源、调度与扩展容器生命周期从来不只是“容器自己活多久”的问题它和节点资源、调度策略、自动化运维深度绑定。资源请求与限制会影响Pod的调度位置同时也会影响重启的稳定性。6.1 requests和limits让生命周期可控的前提resources: requests: cpu: 500m memory: 512Mi limits: cpu: 1 memory: 1Girequests是调度器用来做节点选择的依据limits是运行时强制限制。没有正确设置requests调度器可能把多个重负载Pod集中到同一节点导致节点资源紧张触发Orphaned Pod驱逐。没有设置limits单个容器可能把节点内存吃满拖垮整个节点上所有Pod。我见过不少团队只用requests不用limits理由是“怕限制太死影响性能”结果是高峰期某个服务内存泄漏直接把节点打挂。生产环境的建议是核心服务同时设置requests和limits且两者差距不要太大非核心业务可以不设limits但要接受潜在的节点风险。6.2 生命周期结束后的垃圾回收在K8s体系中Deployment滚动更新时旧版ReplicaSet会保留一段时间。如果发布频繁堆积的历史ReplicaSet会占用大量API Server内存和etcd存储而terminated的Pod也会保留一定的终止记录。长时间不清理集群会越来越慢。这里有两个可以设置的参数--terminated-pod-gc-threshold默认12500超过这个数量的终止Pod会被kubelet清理另外ReplicaSet保留数量可以看Deployment的历史记录使用kubectl rollout history deployment 来检查。6.3 生命周期与集群管理的连接容器生命周期受节点的运行状况直接影响。节点NotReadyPod会被标记为Unknown如果超过pod-eviction-timeout默认5分钟Pod会被重新调度到其他可用节点。生产环境建议定期巡检节点状态发生节点重启时注意检查所有运行的容器是否正常恢复因为有些有状态应用恢复后依赖的本地数据可能不一致。另外证书过期是集群生命周期里的经典痛点。etcd、kubelet、API Server之间的证书默认一年有效期如果忘了续期集群内组件会突然失联Pod状态也会异常。尤其是在单节点集群上证书过期的表现往往是“kubectl命令直接报错检查节点上kubelet服务状态却是正常的”。关于证书自动续签我建议在Node上配置cron定期执行kubeadm alpha certs renew all或者直接把证书有效期改成10年在kubeadm的配置中设置expiresAfter或者修改/etc/kubernetes/manifests下各组件的证书参数。6.4 有状态应用的生命周期管理StatefulSet管理的Pod与Deployment不同它的Pod有稳定的网络标识和稳定的存储标识生命周期管理需要考虑更细。删除StatefulSet不会删除PVC这是设计上的考虑避免了意外丢失数据。但是在删除Pod进行缩容时管理员需要明确了解应用自身的数据同步与恢复机制。对于数据库类的容器生命周期管理的核心是启动时检测数据文件是否完整退出时把缓冲数据落盘健康检查时验证“数据库能否正常查询”而不只是看进程是否存活。之前做过一套初创环境上的MySQL容器化方案就专门为Lifecycle加了一个PreStop钩子在容器关闭前执行mysqladmin shutdown配合innodb_buffer_pool_size的设置确保每次停机都不会丢数据。7. 最后的经验总结把生命周期管理当成一整套设计我在实际运维中最深的体会是容器生命周期这一课不只是命令行操作更是从设计阶段就要考虑的问题。镜像应该用什么启动命令进程怎么处理信号探针检查什么路径停机时需要做什么收尾滚动更新时如何避免流量损失这些问题都应该在第一次编写Deployment时就想清楚。值得单独提醒的是很多刚入门的朋友遇到问题先想到“重启Pod”但如果生命周期设计没做好重启只是表面缓解解决不了实际问题。比如容器启动后立即退出如果不查退出码和日志重启一百次也没有意义。一个小技巧是本地调试时用Docker直接跑同一个镜像可以快速定位问题出在镜像内部还是K8s层。记住K8s只是平台最终跑业务的还是容器容器内部的应用逻辑始终是排查的落点。再分享一个小习惯每次写完Deployment YAML我都会先跑一遍kubectl apply --dry-runclient -f Deployment.yaml做语法校验然后再用kubectl apply -f Deployment.yaml真正交付。上线后观察两轮完整生命周期也就是容器启动、探针通过、流量接入、滚动更新这四步确认没有异常再去处理下一件事。这个习惯帮我挡掉了不少不必要的事故。容器生命周期的核心就十二个字启动要稳、运行要健、退出要优雅。把这十二个字落到你的每一个探针、每一个信号处理、每一次策略配置上你的K8s环境才算真正有了“自愈”能力。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →