containerd CRI 镜像仓库配置完全指南:config_path、认证凭据与 hosts.toml 实践
【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd
本文是面向 Kubernetes/containerd 运维与开发者的镜像仓库(Image Registry)配置实战指南,主体围绕 containerd 的 CRI 插件(criplugin)如何配置私有仓库、镜像加速器(mirror)与登录凭据展开。读完本文,你将掌握 containerd 1.x 与 2.x 两套配置语法的差异、config_path目录式配置的正确用法、四种认证字段(username/password/auth/identitytoken)的语义与优先级,并能独立完成 GCR 服务账号密钥认证、自签名证书仓库等真实场景的落地配置。
配置方式的演进:从 mirrors/configs 到 config_path
containerd 的 CRI 插件在早期版本(1.3~1.4 时代)通过registry.mirrors与registry.configs两个配置段来管理镜像加速与认证信息。这两种方式目前在官方文档中已被标记为DEPRECATED(废弃):registry.mirrors与registry.configs仅在没有指定config_path时才会被使用,且官方建议全部迁移到基于目录的config_path方案。
从源码中可以看到这一废弃状态的直接证据:在 internal/cri/config/config.go 中,Registry结构体的Mirrors、Configs、Auths字段注释均标注了DEPRECATED: Use ConfigPath instead. Remove in containerd 2.3.(计划在 containerd 2.3 中移除),而ConfigPath字段则注明"如果设置了 ConfigPath,其余 registry 专属选项将被忽略"。
在 ValidateImageConfig 的校验逻辑中,两者被设计为互斥关系:当config_path已提供时再设置mirrors会直接报错"mirrors" cannot be set when "config_path" is provided;而使用mirrors或configs时则会产生deprecation.CRIRegistryMirrors/deprecation.CRIRegistryConfigs警告。因此新部署环境应一律使用config_path。
两种版本下的配置入口
由于 containerd 2.x 将 CRI 拆分为独立的 images 插件,配置段的插件名发生了变化:
- containerd 2.x(使用
io.containerd.cri.v1.images插件):
[plugins."io.containerd.cri.v1.images".registry] config_path = "/etc/containerd/certs.d"- containerd 1.x(使用
io.containerd.grpc.v1.cri插件):
[plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d"config_path 的默认值与 Docker 兼容性
如果完全不设置任何 registry 相关选项,config_path会默认取值为/etc/containerd/certs.d:/etc/docker/certs.d(多个路径以冒号分隔,按顺序查找)。这一设计的目的在于兼容 Docker 添加自签名证书的方式:只要把 CA 证书按 Docker 的目录约定放置,containerd 就能直接读取。
该默认值在源码中有两处体现:
- plugins/cri/images/plugin.go 中,Linux 平台下当
ConfigPath与Mirrors均为空时会自动回填/etc/containerd/certs.d:/etc/docker/certs.d; - docs/cri/config.md 的配置模板同样给出了这一默认值。
需要注意的是,config_path指向的目录是多路径列表而非单一路径,containerd 会依次在每个路径下按"主机命名空间/主机名"的层级查找配置文件,读取逻辑由 core/remotes/docker/config/hosts.go 中的ConfigureHosts实现——它优先读取hosts.toml,若不存在则回退到 Docker 风格的证书文件布局(ca.crt、client.cert/client.key等)。
在 config.toml 中配置仓库认证凭据
除了基于目录的hosts.toml方案,CRI 插件仍支持在/etc/containerd/config.toml中直接为指定仓库写入认证信息(对应旧的registry.configs.*.auth段)。官方文档特别说明:该方式中registry.configs.*.auth已废弃,且未来不会提供在主机配置文件中存储未加密密钥的等价方式;不过在出现合适的插件化密钥管理方案之前它不会被移除,在 1.x 系列(包括 1.6 LTS)中仍受支持。
配置方法:编辑/etc/containerd/config.toml,registry host 必须是域名或 IP,若未使用默认的 HTTPS/HTTP 端口则需带上端口号。
- containerd 2.x(显式使用 v3 配置格式):
# explicitly use v3 config format version = 3 # The registry host has to be a domain name or IP. Port number is also # needed if the default HTTPS or HTTP port is not used. [plugins."io.containerd.cri.v1.images".registry.configs."gcr.io".auth] username = "" password = "" auth = "" identitytoken = ""- containerd 1.x(显式使用 v2 配置格式):
# explicitly use v2 config format version = 2 # The registry host has to be a domain name or IP. Port number is also # needed if the default HTTPS or HTTP port is not used. [plugins."io.containerd.grpc.v1.cri".registry.configs."gcr.io".auth] username = "" password = "" auth = "" identitytoken = ""四个认证字段的语义
各字段的含义与~/.docker/config.json中对应字段完全一致,对应源码结构体为 internal/cri/config/config.go 中的AuthConfig:
| 字段 | TOML 键 | 含义 |
|---|---|---|
username | username | 登录仓库的用户名 |
password | password | 登录仓库的密码 |
auth | auth | username:password拼接后进行 Base64 编码得到的字符串(等价于 Dockerconfig.json中的auth) |
identitytoken | identitytoken | 用于换取仓库访问令牌(access token)的身份令牌 |
与 CRI 传入认证的优先级
务必注意优先级规则:CRI 请求中携带的 auth config 优先于此处的静态配置。也就是说,Kubernetes 通过 CRI 接口(例如基于 imagePullSecret 生成的PullImage请求)传入的认证信息会覆盖config.toml中的凭据;只有当 CRI 请求未指定 auth 时,才会回落到这里配置的凭据。
此外,老旧的registry.auths(顶层 endpoint 到 auth 的映射)同样已废弃。源码 ValidateImageConfig 中会将auths中的 URL 解析后(去掉 scheme,仅保留 host)自动迁移合并进configs结构,并发出CRIRegistryAuths废弃警告。
修改后必须重启
修改config.toml后需要重启 containerd 服务才能生效:
service containerd restart基于 hosts.toml 的目录式仓库配置
config_path方案的核心理念是"每个主机一个命名空间目录、目录内一个hosts.toml"。以默认的docker.io为例,目录结构如下(示例取自 docs/cri/config.md):
$ tree /etc/containerd/certs.d /etc/containerd/certs.d └── docker.io └── hosts.toml $ cat /etc/containerd/certs.d/docker.io/hosts.toml server = "https://docker.io" [host."https://registry-1.docker.io"] capabilities = ["pull", "resolve"]server字段声明该命名空间的上游服务器;[host."..."]表则定义实际访问的端点及其能力(capability)。当需要配置私有仓库的自定义 CA 时(示例为192.168.12.34:5000):
$ cat /etc/containerd/certs.d/192.168.12.34:5000/hosts.toml server = "https://192.168.12.34:5000" [host."https://192.168.12.34:5000"] ca = "/path/to/ca.crt"hosts.toml支持的全部字段(server、capabilities、ca、client、skip_verify、header、override_path、dial_timeout等)的完整语义与示例,可进一步参考 docs/hosts.md;其中常用的几个包括:
capabilities:可选,声明该 host 支持的操作(pull、resolve、push)。例如镜像加速端点通常只给pull,而resolve(tag 到 digest 的解析)与push应保留给上游;skip_verify:跳过 TLS 证书校验(仅建议在测试环境使用);ca/client:自定义 CA 证书与客户端证书;override_path:将仓库路径改写为/v2风格,兼容部分私有仓库实现。
同时,若某主机的目录下没有hosts.toml,containerd 会回退到 Docker 的证书目录布局(即config_path默认值中包含/etc/docker/certs.d的原因),实现与既有 Docker 环境的无缝兼容。
实战案例:GCR 服务账号 JSON Key 认证
下面以 Google Container Registry(GCR)为例,完整走一遍"终端验证 → 写入配置 → crictl 拉取"的全流程(与官方文档 docs/cri/registry.md 保持一致)。
前置准备
- 创建 GCP 账号与项目(若尚未创建);
- 为项目启用 GCR;
- 创建服务账号与 JSON key,并将 JSON key 文件下载到本机;
- 将服务账号加入 GCR 存储桶并授予 storage admin 权限。
提示:JSON key 是多行文件,直接粘贴进配置很不方便,建议先用
jq将其压缩为单行输出:jq -c . key.json。
先用 Docker 验证连通性
在接入 containerd 之前,先确认终端环境能正常认证并访问 GCR 存储:
docker login -u _json_key -p "$(cat key.json)" gcr.io docker pull busybox docker tag busybox gcr.io/your-gcp-project-id/busybox docker push gcr.io/your-gcp-project-id/busybox docker logout gcr.io其中用户名_json_key是 GCR 约定的特殊用户名,表示使用 JSON key 认证。
写入 containerd 配置
编辑/etc/containerd/config.toml(默认位置),为gcr.io域名的镜像拉取请求添加 JSON key:
- containerd 2.x:
version = 3 [plugins."io.containerd.cri.v1.images".registry] [plugins."io.containerd.cri.v1.images".registry.mirrors] [plugins."io.containerd.cri.v1.images".registry.mirrors."docker.io"] endpoint = ["https://registry-1.docker.io"] [plugins."io.containerd.cri.v1.images".registry.mirrors."gcr.io"] endpoint = ["https://gcr.io"] [plugins."io.containerd.cri.v1.images".registry.configs] [plugins."io.containerd.cri.v1.images".registry.configs."gcr.io".auth] username = "_json_key" password = 'paste output from jq'- containerd 1.x:
version = 2 [plugins."io.containerd.grpc.v1.cri".registry] [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://registry-1.docker.io"] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] endpoint = ["https://gcr.io"] [plugins."io.containerd.grpc.v1.cri".registry.configs] [plugins."io.containerd.grpc.v1.cri".registry.configs."gcr.io".auth] username = "_json_key" password = 'paste output from jq'注意:
username固定为_json_key即代表启用 JSON key 认证;password填jq -c . key.json的输出(建议用单引号包裹,避免 TOML 解析问题)。
这里同时配置了mirrors段(属于旧式写法)。若环境允许,更推荐将其迁移为config_path+hosts.toml目录结构;两种方式的取舍可参考上文"配置方式的演进"一节。
重启并验证
重启 containerd:
service containerd restart使用crictl从 GCR 拉取镜像验证(开启 debug 可以看到完整的 CRI 请求/响应):
$ sudo crictl pull gcr.io/your-gcp-project-id/busybox DEBU[0000] get image connection DEBU[0000] connect using endpoint 'unix:///run/containerd/containerd.sock' with '3s' timeout DEBU[0000] connected successfully using endpoint: unix:///run/containerd/containerd.sock DEBU[0000] PullImageRequest: &PullImageRequest{Image:&ImageSpec{Image:gcr.io/your-gcr-instance-id/busybox,},Auth:nil,SandboxConfig:nil,} DEBU[0001] PullImageResponse: &PullImageResponse{ImageRef:sha256:78096d0a54788961ca68393e5f8038704b97d8af374249dc5c8faec1b8045e42,} Image is up to date for sha256:78096d0a54788961ca68393e5f8038704b97d8af374249dc5c8faec1b8045e42从日志可以看出PullImageRequest中的Auth为nil(即 CRI 未传入认证),此时 containerd 才会回落到配置文件中gcr.io的静态凭据。
迁移到 transfer service 时的注意点
containerd 2.x 默认使用 Transfer Service 进行镜像拉取,而旧式的registry.mirrors、registry.configs、registry.auths并不被 transfer service 支持。源码 CheckLocalImagePullConfigs 会在检测到这些旧配置时自动将UseLocalImagePull置为true,回退到client.Pull的本地拉取模式,并打印警告日志。因此:
- 若你仍在使用
mirrors/configs/auths,应尽快迁移到config_path+hosts.toml; - 迁移后,与拉取相关的并发数等参数(如
max_concurrent_downloads)在 transfer service 模式下需要配置在[plugins."io.containerd.transfer.v1.local"]段下。
配置语法版本说明
本文示例采用的配置语法为version 2,自 containerd 1.3 起即为推荐格式;containerd 2.x 则要求显式使用 version 3(即version = 3)。更早的 1.2 时代配置格式已不再推荐,若需参考旧格式可查阅 containerd cri 仓库 release/1.2 分支的历史文档(本文不再展开)。
小结与排障要点
配置 CRI 镜像仓库的核心决策树可归纳为三步:
- 选方案:新环境一律使用
config_path指向/etc/containerd/certs.d,通过hosts.toml管理镜像端点(mirror)与 TLS 证书;仅在 1.x 且需要快速内联凭据时使用registry.configs.*.auth; - 理优先级:CRI 请求携带的 auth > 配置文件静态凭据 > 无认证;
config_path与mirrors/configs互斥; - 验效果:修改
config.toml或hosts.toml后必须重启 containerd(service containerd restart),再用crictl pull或ctr images pull验证,必要时以 debug 模式观察 CRI 请求中Auth字段是否为空。
涉及的关键源码与文档入口:配置结构体与校验逻辑见 internal/cri/config/config.go,默认config_path回填逻辑见 plugins/cri/images/plugin.go,hosts.toml解析实现见 core/remotes/docker/config/hosts.go,完整字段说明见 docs/hosts.md 与 docs/cri/config.md。
【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考