K3s 中 containerd 拉取私有镜像仓库镜像时因不自动信任系统 CA 证书,需将自签名或内网 CA 证书(PEM 格式)放入 /var/lib/rancher/k3s/agent/etc/containerd/certs.d//ca.crt,路径须与镜像地址完全一致,并重启 k3s 生效。

这是 K3s 连接私有镜像仓库(private registry)时启用 TLS 后最常见的证书错误。根本原因是 K3s 的 containerd 组件(而非 kubelet 或 API server)在拉取镜像时,**不自动信任系统 CA 证书**,也不加载主机上配置的 Docker-style `ca.crt`,它只认自己配置的证书路径。
确认证书来源是否被 containerd 识别
K3s 内嵌的 containerd 默认不会读取 /etc/ssl/certs/ca-certificates.crt 或用户手动放的证书文件。你必须显式告诉它:这个私有 registry 的证书由谁签发、证书文件在哪。
- 私有 registry 使用自签名证书 → 需把该证书(如
my-registry.crt)拷贝到 K3s 节点的/var/lib/rancher/k3s/agent/images/目录(K3s v1.25+ 推荐路径),或更通用的/var/lib/rancher/k3s/agent/etc/containerd/certs.d/your-registry:port/下的ca.crt - 私有 registry 使用内网 CA 签发(如企业内部 Root CA)→ 把该 Root CA 证书(不是中间证书,是最终签发者)放入上述路径
- 用 Let’s Encrypt 或公网可信 CA → 不需要额外配置证书,但务必确保 registry 域名与证书 Subject Alternative Name(SAN)完全匹配(例如不能用 IP 访问带域名证书的地址)
正确配置 containerd 的 registry 证书目录结构
K3s v1.21+ 使用 containerd 的 certs.d 机制,路径必须严格匹配 registry 地址(含端口)。例如 registry 地址是 harbor.internal:8443:
- 创建目录:
sudo mkdir -p /var/lib/rancher/k3s/agent/etc/containerd/certs.d/harbor.internal:8443 - 放入证书:
sudo cp harbor-ca.crt /var/lib/rancher/k3s/agent/etc/containerd/certs.d/harbor.internal:8443/ca.crt - 确保权限为
root:root,且ca.crt是 PEM 格式(以-----BEGIN CERTIFICATE-----开头)
⚠️ 注意:路径中的域名和端口必须和你在 docker pull 或 YAML 中写的 image 名字**完全一致**(比如写的是 harbor.internal/v1/nginx:latest,那就用 harbor.internal;如果写了端口,如 harbor.internal:8443,路径里也必须带 :8443)。
重启 containerd 并验证配置生效
K3s 不会自动重载 containerd 的 certs.d 配置,修改后需重启 K3s(它会连带重启 containerd):
-
sudo systemctl restart k3s(systemd 环境) - 等几秒后检查 containerd 是否已加载新配置:
sudo crictl pull harbor.internal:8443/myapp:latest - 如果仍报 x509 错误,用
sudo ctr --namespace=k8s.io images pull harbor.internal:8443/myapp:latest测试(ctr 是 containerd 原生命令,错误信息更直接) - 还可临时进入 containerd 容器(
sudo nsenter -n -t $(pgrep containerd) -c sh)检查/etc/containerd/certs.d/挂载是否可见(K3s 会 bind mount 上述路径)
其他易忽略点
即使证书路径对了,以下情况也会触发相同错误:
- 证书过期 → 用
openssl x509 -in ca.crt -text -noout | grep "Not After"检查有效期 - 证书链不完整 → 如果 registry 用了中间 CA,
ca.crt文件里应包含 Root CA + 所有中间证书(按顺序拼接,每个以-----BEGIN CERTIFICATE-----开始) - registry DNS 解析异常 → 在节点上执行
curl -v https://harbor.internal:8443/v2/,看是否能建立 TLS 连接并返回 401(说明证书已信任,只是没鉴权) - K3s 启动参数覆盖了默认配置 → 检查
/etc/systemd/system/k3s.service中是否有--containerd或自定义containerd.toml,避免配置冲突










