如何让 Kubernetes 的 containerd 安全地访问 HTTP 私有仓库

在使用 Kubernetes 管理容器应用时,我们经常需要从仓库下载容器镜像。公共仓库如 Docker Hub 很方便,但有时我们需要使用自己搭建的私有仓库来存放敏感或特定的镜像。如果你的私有仓库只支持 HTTP 协议,而 Kubernetes 默认的容器运行时 containerd 出于安全考虑,会强制尝试使用 HTTPS,这就会导致拉取镜像失败。本文将一步步教你如何正确配置 containerd,让它能够顺利访问你的 HTTP 私有仓库。

一、问题:为什么直接访问 HTTP 仓库会失败?

想象一下,containerd 就像一个严格遵守规则的学生。它被告知:访问任何仓库(仓库可以理解为存放容器镜像的大仓库),都必须走安全的“加密通道”(HTTPS),并且要检查仓库的“安全证书”(SSL/TLS证书)。这个规则是为了保证下载的镜像来源可靠,没有被坏人篡改。

现在,你的私有仓库只开了“普通通道”(HTTP),没有“加密通道”(HTTPS),自然也就没有“安全证书”。当 containerd 试图连接时:

  1. 它发现你给的地址是 http://my.private.registry(例如)。
  2. 但它的规则是:必须走 HTTPS。所以它自作主张,把地址改成了 https://my.private.registry 去尝试连接。
  3. 你的仓库只支持 HTTP,不支持 HTTPS,所以连接会失败(比如提示 tls: failed to verify certificate 之类的错误)。
  4. 即使仓库支持 HTTPS,但没有合法的证书(比如自签名的证书),containerd 默认也会因为证书不被信任而拒绝连接。

核心原因就是:containerd 默认强制要求 HTTPS 和有效的证书验证,而你的私有仓库无法满足这个要求。

二、目标:让 containerd 信任并使用 HTTP 访问特定仓库

我们不想让 containerd 完全放弃安全规则(那样对所有仓库都不安全),但我们希望它对我们的这个特定私有仓库网开一面:

  1. 当访问地址是 my.private.registry:5000 时,明确告诉 containerd:“别走 HTTPS,就走 HTTP”。
  2. 同时告诉它:“连接这个仓库时,不要检查安全证书”。

这样,containerd 就会乖乖地用 HTTP 协议去连接你的私有仓库,并且不会因为证书问题而拒绝。

三、解决方法:修改 containerd 的配置文件

我们需要修改 containerd 的配置文件,告诉它如何对待我们的私有仓库。配置文件通常位于 /etc/containerd/config.toml

步骤 1:找到配置文件并做好备份(重要!)

  1. 登录到你的 Kubernetes 节点服务器(Master 和 Worker 节点都需要配置)。
  2. 使用文本编辑器打开配置文件(需要管理员权限,如 sudo):
    sudo vi /etc/containerd/config.toml
    
  3. 强烈建议先备份这个文件! 万一改错了还能恢复:
    sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.backup
    

步骤 2:配置私有仓库的访问规则

config.toml 文件中,我们需要找到 [plugins."io.containerd.grpc.v1.cri".registry] 这个配置块。它专门负责管理镜像仓库相关的设置。

在这个块下面(如果不存在可以自己添加),我们会配置一个 [plugins."io.containerd.grpc.v1.cri".registry.configs] 块,用于定义特定仓库的配置。然后,在这个 configs 块里,再为我们的私有仓库地址配置一个子块。

假设我们的私有仓库地址是 my.private.registry:5000,添加如下配置:

[plugins."io.containerd.grpc.v1.cri".registry]
  [plugins."io.containerd.grpc.v1.cri".registry.configs]
    [plugins."io.containerd.grpc.v1.cri".registry.configs."my.private.registry:5000"]
      [plugins."io.containerd.grpc.v1.cri".registry.configs."my.private.registry:5000".tls]
        insecure_skip_verify = true # 跳过 TLS 证书验证
      [plugins."io.containerd.grpc.v1.cri".registry.configs."my.private.registry:5000".http]
        skip_verify = true # 这个参数可能在某些版本不再需要或作用不同,但为了兼容性可以保留

关键配置解释:

  • [plugins."io.containerd.grpc.v1.cri".registry.configs."my.private.registry:5000"]:这个子块的名称 "my.private.registry:5000" 就是你的私有仓库地址。containerd 会用它来匹配要访问的仓库地址。
  • [plugins."io.containerd.grpc.v1.cri".registry.configs."my.private.registry:5000".tls]:配置 TLS (即 HTTPS 的安全层) 相关选项。
    • insecure_skip_verify = true:这是最重要的设置。它告诉 containerd:“访问 my.private.registry:5000 时,即使它的安全证书有问题(或者根本没有证书),你也别管了,直接信任它继续连接”。这相当于关闭了针对这个仓库的证书检查。
  • [plugins."io.containerd.grpc.v1.cri".registry.configs."my.private.registry:5000".http]:配置 HTTP 相关选项。
    • skip_verify = true:在较新版本的 containerd (>= 1.5) 中,主要依赖上面的 tls.insecure_skip_verify。这个 http.skip_verify 可能已经不再直接影响协议选择,但保留它有助于兼容旧文档或避免歧义。它通常表示忽略 HTTP 层面的某些验证。

为什么这样设置就能用 HTTP 了?

  • containerd 需要访问 my.private.registry:5000 时,它会查找配置。
  • 它找到了针对这个地址的配置块。
  • 看到 tls.insecure_skip_verify = true,它就知道:“这个仓库的证书不用检查了”。
  • 更重要的是,这个设置隐含地告诉 containerd:“即使这个仓库不支持 HTTPS 或者证书无效,你也别报错,尝试连接就行”。当它尝试连接时:
    • 如果仓库支持 HTTPS,它会建立 (不验证证书的) HTTPS 连接。
    • 但是,我们的仓库只支持 HTTP! containerd 在尝试 HTTPS 失败后(因为仓库根本不响应 HTTPS),它会自动降级尝试 HTTP 协议(因为证书验证都关了,协议降级也被允许了)。
    • 最终,成功通过 HTTP 协议连接到你的私有仓库。

步骤 3:保存文件并重启 containerd

  1. 保存修改后的 /etc/containerd/config.toml 文件。
  2. 重启 containerd 服务,让新配置生效:
    sudo systemctl restart containerd
    
  3. 检查 containerd 状态,确保重启成功:
    sudo systemctl status containerd
    

步骤 4:验证配置是否生效

现在,尝试在你的 Kubernetes 集群中创建一个 Pod,使用来自私有仓库的镜像。例如,在 Pod 的 YAML 文件中指定:

apiVersion: v1
kind: Pod
metadata:
  name: test-private-registry
spec:
  containers:
  - name: test-container
    image: my.private.registry:5000/my-image:latest # 替换为你的实际镜像地址

如果 Pod 能够成功创建并运行(查看 kubectl get pods 状态为 Running),说明 containerd 已经成功从你的 HTTP 私有仓库拉取了镜像!

四、总结与安全提醒

通过修改 containerd 的配置文件,我们为特定的私有仓库地址 (my.private.registry:5000) 设置了 tls.insecure_skip_verify = true。这相当于给 containerd 开了个后门,让它对这个仓库:

  1. 跳过安全证书检查
  2. 允许降级使用 HTTP 协议

这样,即使仓库只有 HTTP,containerd 也能成功拉取镜像。

重要安全提醒:

  • 仅在信任的网络环境中使用: HTTP 协议是明文的,你的镜像内容在传输过程中可能被窃听。这种方法只适合在高度信任的内部网络中使用(比如公司内网、隔离的实验室环境)。绝对不要在公网或不可信的网络中使用 HTTP 私有仓库!
  • 仅针对特定仓库: 我们只修改了对 my.private.registry:5000 的规则。containerd 访问其他仓库(如 Docker Hub)时,仍然会强制使用 HTTPS 和证书验证,保证了其他来源的安全性。
  • 优先考虑 HTTPS: 虽然本文解决了 HTTP 访问的问题,但从长远和安全角度出发,强烈建议为你的私有仓库配置 HTTPS 和有效的证书(可以是自签名证书,但需要在客户端配置信任)。这样既安全又符合 containerd 的默认行为。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐