1. 事故现场:令人头大的 ImagePullBackOff

作为一名 K8s 玩家,最崩溃的莫过于刚改完 Deployment 镜像,满心期待 Running,结果反手给你来了一个 ImagePullBackOff

  • 痛点:公司私有仓库宕机、网络波动、或者生产环境镜像被误删。
  • 常规操作:等网络好、修仓库、查权限。
  • 硬核操作:直接在节点上进行“镜像劫持”,手动补位,骗过 Kubelet!

今天就分享一次我亲历的“狸猫换太子”应急方案。


2. 核心原理:Kubelet 的“偷懒”机制

为什么这招能行?得从 Kubelet 拉取镜像的逻辑说起:

当 Kubelet 发现需要启动一个 Pod 时,它会检查镜像拉取策略 imagePullPolicy

  • Always:不管本地有没有,必须去仓库对一下摘要(Digest)。
  • IfNotPresent:本地有了?直接用,不折腾云端。(这就是我们的操作空间!

只要我们能在 Node 节点本地准备好一个同名的镜像,并成功“晃过”检查,Pod 就能瞬间复活。


3. 应急实战:手动“打标签”补位

第一幕:太子难产

假设我们更新了镜像为 05-engineer/webapp:v2.0,结果因为仓库网络问题一直拉不下来。

# 查看状态,一片飘红
kubectl get pods
# NAME                            READY   STATUS                RESTARTS
# webapp-6789abcdef-xxxxx         0/1     ImagePullBackOff      0

第二幕:寻找“替身”

此时,我们要找到节点上已经存在的、版本最接近的稳定版镜像(比如 v1.0stable)。

# 查看本地有哪些现成镜像(以 docker 为例,k3s 请用 crictl)
docker images | grep webapp
# REPOSITORY          TAG       IMAGE ID
# 05-engineer/webapp  v1.0      a1b2c3d4e5f6

第三幕:狸猫换太子 (核心指令)

这是最关键的一步。我们手动给本地的旧镜像打上“新太子”的标签,伪造现场。

# 格式:docker tag [已有镜像ID/名] [Deployment期望的镜像名]
docker tag 05-engineer/webapp:v1.0 05-engineer/webapp:v2.0

第四幕:欺骗 Kubelet

由于我们手动打了 Tag,现在本地已经存在了 webapp:v2.0。如果你的 Deployment 配置中 imagePullPolicyIfNotPresent,那么接下来只需要重启 Pod:

# 优雅地重启 Pod,让它重新调度并触发本地镜像检查
kubectl rollout restart deployment webapp

见证奇迹的时刻:

kubectl get pods
# webapp-xxxx-xxxx   1/1     Running   0   5s

虽然 Pod 名字写着 v2.0,但内里跑的是我们手动指定的 v1.0。服务瞬间恢复,为修复仓库赢得了宝贵时间!


4. 避坑指南:两点必须注意!

  1. 策略陷阱:如果你的 YAML 里写死的是 imagePullPolicy: Always,这招可能会失效,因为 Kubelet 会强行去仓库比对。建议平时生产环境对稳定版本使用 IfNotPresent
  2. 节点偏差:K8s 是多节点集群。你在 Node A 上打了 Tag,如果 Pod 调度到了 Node B,还得去 Node B 再打一遍。
    • 进阶技巧:可以用 NodeSelector 把 Pod 先固定到你处理过的那个节点上。

5. 总结:候补工程师的碎碎念

在云原生的世界里,自动化固然香,但对底层逻辑的理解才是你处理突发状况时的底气。

这种“狸猫换太子”的方法本质上是利用了本地镜像缓存优先级。虽然不建议作为常规发布手段,但在运维救火的生死关头,它就是你的救命稻草!


关于作者:05 候补工程师,在校大三学生。专注 Linux 内核、嵌入式与云原生。
如果你觉得这篇实战有用,欢迎【点赞+收藏】,你的支持是我持续折腾的动力!


Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐