<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Harbor on Zero Day Notes</title>
        <link>https://blog.5772447.xyz/tags/harbor/</link>
        <description>Recent content in Harbor on Zero Day Notes</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Thu, 16 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags/harbor/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>K8s 私有镜像仓库凭证过期，Pod 为何卡在 ImagePullBackOff？一次生产镜像拉取失败的排查记录</title>
            <link>https://blog.5772447.xyz/posts/cd2f7270/</link>
            <pubDate>Thu, 16 Jul 2026 00:00:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/cd2f7270/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们生产集群跑在 Kubernetes 1.24 上，所有业务镜像都存放在自建的 Harbor 私有镜像仓库。集群通过 &lt;code&gt;imagePullSecret&lt;/code&gt;（docker-registry 类型的 Secret）向 Harbor 做认证拉取镜像。某天上午一次常规的版本发布，滚动更新（RollingUpdate）刚触发不久，发布平台就报&amp;quot;就绪实例数不足&amp;quot;，监控里该服务的 5xx 错误率开始抬头。最初以为是新版本代码有问题，直到发现大量新 Pod 根本没起来——它们卡在了镜像拉取阶段，整条发布被堵死。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubectl get pods -n order&lt;/code&gt; 的输出里，本次发布的 Pod 几乎集体处于 &lt;code&gt;ErrImagePull&lt;/code&gt; / &lt;code&gt;ImagePullBackOff&lt;/code&gt; 状态，旧版本的 Pod 已经有一部分被滚动更新策略 terminate 掉，导致可用副本数骤降。服务网关侧直接体现为部分请求 5xx，发布流水线卡住无法继续。&lt;/p&gt;&#xA;&lt;p&gt;describe 某个卡住的 Pod，Events 末尾赫然写着：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Failed to pull image &amp;#34;harbor.internal.com/order/order-svc:1.8.2&amp;#34;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rpc error: code = Unknown desc = failed to pull and unpack image&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;... unauthorized: authentication required&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;节点层面用 &lt;code&gt;crictl ps -a&lt;/code&gt; 能看到这些 Pod 的 sandbox 一直起不来，对应容器停留 &lt;code&gt;ContainerCreating&lt;/code&gt;。登录其中一个工作节点手动执行 &lt;code&gt;crictl pull harbor.internal.com/order/order-svc:1.8.2&lt;/code&gt;，同样返回 &lt;code&gt;unauthorized: authentication required&lt;/code&gt;——镜像本身拉不下来，和代码无关。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;第一步，确认镜像是否真的存在。我们直接到 Harbor 的 Web 控制台搜索 &lt;code&gt;order-svc:1.8.2&lt;/code&gt;，镜像明明白白躺在项目里，说明不是&amp;quot;镜像没推上来&amp;quot;或 tag 拼错。这说明问题出在&amp;quot;拉取&amp;quot;环节，而不是&amp;quot;构建/推送&amp;quot;环节。&lt;/p&gt;&#xA;&lt;p&gt;第二步，看拉取失败的具体原因。&lt;code&gt;unauthorized: authentication required&lt;/code&gt; 已经把范围收窄到&amp;quot;认证&amp;quot;。既然是私有仓库，Kubernetes 一定是通过某个 &lt;code&gt;imagePullSecret&lt;/code&gt; 去认证的。先确认 Pod 关联的 Secret 在不在：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl get secret regcred -n order&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl get pod &amp;lt;pod&amp;gt; -o jsonpath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{.spec.imagePullSecrets[*].name}&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;Secret 存在，名字也对得上。那就要怀疑 Secret 里的凭证本身是不是还有效。&lt;/p&gt;&#xA;&lt;p&gt;第三步，把 Secret 内容解码出来看。docker-registry 类型的 Secret 把 &lt;code&gt;~/.docker/config.json&lt;/code&gt; 做了 base64 编码存在 &lt;code&gt;.dockerconfigjson&lt;/code&gt; 字段里：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl get secret regcred -n order -o jsonpath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{.data.\.dockerconfigjson}&amp;#39;&lt;/span&gt; | base64 -d&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;解码后看到里面的 &lt;code&gt;auth&lt;/code&gt; 是一串看起来正常的 base64（&lt;code&gt;username:password&lt;/code&gt;）。为了验证它是否真的能用，我在一台能通 Harbor 的机器上把它解出来，构造 &lt;code&gt;~/.docker/config.json&lt;/code&gt; 后执行 &lt;code&gt;docker pull harbor.internal.com/order/order-svc:1.8.2&lt;/code&gt;——结果依旧 &lt;code&gt;unauthorized&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;p&gt;第四步，去 Harbor 侧核实账号状态。我们 &lt;code&gt;regcred&lt;/code&gt; 用的是 Harbor 的一个 robot account（机器人账号）。查 Harbor 后台发现：一个月前运维做了一次账号体系加固，给 robot account 的 token 加上了有效期策略，而这个 token 恰好在这两天到期。Secret 是当初手工 &lt;code&gt;kubectl create secret docker-registry&lt;/code&gt; 写进去的，是个静态凭据，仓库侧把 token 一过期，K8s 这边的 Secret 完全不知道，依旧拿着失效的 token 去拉镜像，于是全量 &lt;code&gt;unauthorized&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;p&gt;第五步，反查为什么之前没暴露。原来老版本镜像 &lt;code&gt;:1.8.1&lt;/code&gt; 早就被各节点的 containerd 缓存过，旧 Pod 用缓存镜像根本不触发重新拉取；这次发 &lt;code&gt;:1.8.2&lt;/code&gt; 是新 tag，节点没有缓存，必须走一次真实鉴权，失效凭证才第一次&amp;quot;现原形&amp;quot;。这也解释了为什么故障&amp;quot;恰好&amp;quot;在发布新版本时爆发。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;止血和恢复很快，三步搞定：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;重建有效的 Secret&lt;/strong&gt;。用更新后的 robot account 凭证重新生成：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl create secret docker-registry regcred &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --docker-server&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;harbor.internal.com &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --docker-username&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;robot&lt;span style=&#34;color:#ae81ff&#34;&gt;\$&lt;/span&gt;order &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --docker-password&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;NEW_TOKEN&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -n order --dry-run&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;client -o yaml | kubectl apply -f -&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;让 Pod 用上新凭证&lt;/strong&gt;。Secret 改完，但已经卡住的 Pod 不会自动重试用新 Secret。直接删掉处于 &lt;code&gt;ImagePullBackOff&lt;/code&gt; 的 Pod，由 ReplicaSet / Deployment 控制器重建；新 Pod 挂载到更新后的 ServiceAccount imagePullSecrets，拉取成功，滚动更新继续推进。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;确认发布完成&lt;/strong&gt;。等所有新版本 Pod 进入 &lt;code&gt;Running&lt;/code&gt; 且就绪，5xx 回落，发布流水线跑通。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;注意：如果集群用 Rancher / Argo CD 之类管理 Secret，要在对应平台同步更新，避免被覆盖回旧值。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;表面是&amp;quot;镜像拉取失败&amp;quot;，根因是 &lt;strong&gt;imagePullSecret 是个静态、无生命周期的凭据，它的有效期完全独立于镜像仓库的账号体系&lt;/strong&gt;。仓库侧做了 robot token 有效期策略，K8s 侧却没有任何机制感知和同步刷新；再加上节点镜像缓存&amp;quot;帮&amp;quot;老版本掩盖了问题，失效凭证一直没被触发，直到一次全新 tag 的发布才暴露。这属于典型的&amp;quot;凭据漂移 + 缺乏凭证有效期监控&amp;quot;类故障。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;集中管理 Secret，杜绝手工漂移&lt;/strong&gt;：用 external-secrets-operator 或 sealed-secrets 把 &lt;code&gt;imagePullSecret&lt;/code&gt; 纳入统一密钥管理，由 CI/CD 统一定期刷新，不再手工 &lt;code&gt;kubectl create secret&lt;/code&gt;。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;robot account 也要纳入轮换与告警&lt;/strong&gt;：即便用机器人账号，也应监控其 token 过期时间，临期自动告警或自动轮换。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;发布流水线加&amp;quot;镜像可拉取&amp;quot;预检&lt;/strong&gt;：部署前先在目标命名空间用一个 test Pod 拉一次镜像（&lt;code&gt;kubectl run drypull --image=... --restart=Never&lt;/code&gt;），拉取失败就阻断发布，把问题卡在流水线里而不是生产环境。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;对 ErrImagePull 做指标告警&lt;/strong&gt;：用 kube-state-metrics + 容器运行时的 &lt;code&gt;ErrImagePull&lt;/code&gt; / &lt;code&gt;ImagePullBackOff&lt;/code&gt; 事件配置告警，故障一发生就通知到人。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;镜像引用尽量用不可变 tag 或 digest&lt;/strong&gt;，避免 &lt;code&gt;:latest&lt;/code&gt; 这类可覆盖 tag 带来的版本错乱。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;ImagePullBackOff 看起来吓人，但 &lt;code&gt;unauthorized: authentication required&lt;/code&gt; 这条线索已经把问题钉死在&amp;quot;认证&amp;quot;上。真正的坑不在 Kubernetes，而在&amp;quot;静态 imagePullSecret 与镜像仓库账号体系脱节&amp;quot;——仓库悄悄轮换了凭证，K8s 还在用旧 token。这次借节点镜像缓存的&amp;quot;掩护&amp;quot;潜伏了很久，直到一次新 tag 发布才爆发。把 imagePullSecret 纳入自动化的密钥管理 + 发布前拉取预检，能从根上消除这类&amp;quot;凭据漂移&amp;quot;型故障。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
