这篇文章已经一年多了,较旧的文章可能包含过时的内容。请检查从发表以来,页面中的信息是否变得不正确。
Kubernetes 中有些东西让人感到奇怪,imagePullPolicy 的行为就是其中之一。
Kubernetes 作为一个专注于运行 Pod 的平台,居然在限制 Pod 访问经认证的镜像方面,存在一个长达十余年的问题,
详见 Issue 18787!
v1.33 解决了这个十年前的老问题,这真是一个有纪念意义的版本。
在本博文中,“Pod 凭据”这个术语将被频繁使用。 在这篇博文的上下文中,这一术语通常指的是 Pod 拉取容器镜像时可用于身份认证的认证材料。
问题的本质在于,imagePullPolicy: IfNotPresent 策略正如其字面意义所示,仅此而已。
我们来设想一个场景:Pod A 运行在 Namespace X 中,被调度到 Node 1,
此 Pod 需要从某个私有仓库拉取镜像 Foo。此 Pod 在 imagePullSecrets 中引用
Secret 1 来作为镜像拉取认证材料。Secret 1 包含从私有仓库拉取镜像所需的凭据。
kubelet 将使用 Pod A 提供的 Secret 1 来拉取 镜像 Foo,这是预期的(也是安全的)行为。
但现在情况变得奇怪了。如果 Namespace Y 中的 Pod B 也被调度到 Node 1,就会出现意外(甚至是不安全)的情况。
Pod B 可以引用同一个私有镜像,指定 IfNotPresent 镜像拉取策略。
Pod B 未在其 imagePullSecrets 中引用 Secret 1(甚至未引用任何 Secret)。
当 kubelet 尝试运行此 Pod 时,它会采用 IfNotPresent 策略。
kubelet 发现本地已存在镜像 Foo,会将镜像 Foo 提供给 Pod B。
即便 Pod B 一开始并未提供授权拉取镜像的凭据,却依然能够运行此镜像。
使用由另一个 Pod 拉取的私有镜像
虽然 IfNotPresent 不应在节点上已存在镜像 Foo 的情况下再拉取此镜像,
但允许将所有 Pod 调度到有权限访问之前已拉取私有镜像的节点上,这从安全态势讲是不正确的做法。
因为这些 Pod 从开始就未被授权拉取此镜像。
在 Kubernetes v1.33 中,SIG Auth 和 SIG Node 终于开始修复这个(非常古老的)难题,并经过验证可行! 基本的预期行为没有变。如果某镜像不存在,kubelet 会尝试拉取此镜像。 利用每个 Pod 提供的凭据来完成此拉取任务。这与 v1.33 之前的行为相匹配。
但如果镜像存在,kubelet 的行为就变了。 kubelet 现在先要验证 Pod 的凭据,然后才会允许 Pod 使用镜像。
在修缮此特性时,我们也考虑到了性能和服务稳定性。 如果多个 Pod 使用相同的凭据,则无需重复认证。 即使这些 Pod 使用的是相同的 Kubernetes Secret 对象(即便其凭据已轮换),也同样适用。
采用 imagePullPolicy: Never 选项时,不会获取镜像。
但如果节点上已存在此容器镜像,任何尝试使用此私有镜像的 Pod 都需要提供凭据,并且这些凭据需要经过验证。
使用相同凭据的 Pod 无需重新认证。未提供之前已成功拉取镜像所用凭据的 Pod,将不允许使用此私有镜像。
imagePullPolicy: Always 一直以来都能按预期工作。
每次某镜像被请求时,请求会流转到镜像仓库,镜像仓库将执行身份认证检查。
过去,为了确保你的私有容器镜像不会被节点上已拉取过镜像的其他 Pod 重复使用,
通过 Pod 准入来强制执行 Always 镜像拉取策略是唯一的方式。
幸运的是,这个过程相对高效:仅拉取镜像清单,而不是镜像本体。 但这依然带来代价与风险。每当发布新版本、扩容或重启 Pod 时, 提供镜像的镜像仓库必须可以接受认证检查,从而将镜像仓库放到关键路径中确保集群中所运行的服务的稳定性。
此特性基于每个节点上存在的持久化文件缓存。以下简要说明了此特性的工作原理。 完整细节请参见 KEP-2535。
首次请求某镜像的流程如下:
当以后调度到同一节点的 Pod 请求之前拉取过的私有镜像:
在 Kubernetes v1.33 中,我们发布了此特性的 Alpha 版本。
要想试用,在 kubelet v1.33 上启用 KubeletEnsureSecretPulledImages 特性门控。
你可以在 Kubernetes 官方文档中的镜像概念页中了解此特性和更多可选配置的细节。
在未来的版本中,我们将:
阅读 KEP-2535 是深入理解这些变更的绝佳方式。
如果你想进一步参与,可以加入 Kubernetes Slack 频道 #sig-auth-authenticators-dev (如需邀请链接,请访问 https://slack.k8s.io/)。 欢迎你参加每隔一周在星期三举行的 SIG Auth 双周例会。