containerd 配置参数详解
详解 containerd 在 Ubuntu 22.04 上的 config.toml 全部核心参数(含 1.7.29 真实默认值)、启动 flags、内容与快照驱动、镜像仓库加速(daocloud 实测)、SystemdCgroup 与 CRI 集成及生产最佳实践
containerd 配置参数详解
目标:本文以 Ubuntu 22.04.5 LTS x86_64 + containerd.io v1.7.29 实测为准,系统讲解 containerd 的配置体系:
config.toml单文件配置、启动 flags、运行环境变量、内容与快照驱动、镜像仓库加速、SystemdCgroup 与 CRI 集成。文中所有默认值均来自containerd config default的真实输出,请在对应服务器上逐条实测核对。
一、概述
1.1 环境信息
| 项 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(Linux 5.15.0,x86_64) |
| 架构 | amd64(x86_64) |
| 操作账号 | root(安装/配置/启动一律 root 执行) |
| containerd 版本 | containerd.io v1.7.29(442cb34b) |
| 客户端 | ctr v1.7.29、crictl(CI 由 CRI 传入使用) |
| 主配置文件 | /etc/containerd/config.toml |
| 根数据目录(root) | /var/lib/containerd |
| 运行时目录(state) | /run/containerd |
| gRPC socket | /run/containerd/containerd.sock |
| 镜像加速配置目录 | /etc/containerd/certs.d/docker.io/hosts.toml |
💡 说明:
root目录存放内容、元数据、快照等持久数据;state目录存放 socket、运行中任务等运行时瞬时数据。二者默认值见 2.1。
1.2 配置承载方式:单文件 + 启动 flags + 环境变量
containerd 守护进程的配置体系由三层组成,优先级从低到高为:
- 内置默认值:未指定任何配置时使用的出厂默认。
/etc/containerd/config.toml主配置:唯一配置文件,绝大多数运行参数集中于此。- 启动 flags:
containerd [flags]命令行参数,可覆盖主配置中的少量关键项(--root、--state、--log-level、--config、--address)。
关于环境变量:实测 env | grep -i containerd 无任何 CONTAINERD_* 运行配置环境变量。containerd 不像部分守护进程那样提供环境变量注入配置的通道,运行配置完全由 config.toml 与启动 flags 决定。这类动态值(如每节点不同的日志目录)一般通过外部渲染 config.toml 时填入,而非进程环境变量。
1.3 生成默认配置:containerd config default
containerd config default 输出一份完整的、可直接落盘的出厂配置,是「增量式用 import、或全量接管」两种配置策略的起点。先备份再生成:
containerd config default > /etc/containerd/config.toml
顶层默认值(真实输出,节选):
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
temp = ""
version = 2
💡 说明:1.7.x 默认走
version = 2的 TOML 结构;containerd config dump输出「最终生效配置」(含所有 import 子配置合并后的结果),用于排查最终落地的真实值。
二、config.toml 详解
2.1 顶层全局参数(version / root / state)
| 参数 | 默认值 | 含义 |
|---|---|---|
version | 2 | 配置文件 schema 版本;1.x 对应旧版扁平键,2 为当前推荐结构 |
root | /var/lib/containerd | containerd 持久数据根目录(内容、元数据 bolt 库、快照、CRI 状态) |
state | /run/containerd | 运行时瞬时数据目录(socket、运行中任务的 shim 状态) |
temp | 空 | 临时目录;为空时使用 state 下的临时子目录 |
oom_score | 0 | 守护进程自身的 OOM 评分附加值 |
disabled_plugins | [] | 启动时禁用的内置插件 ID 列表,如 ["io.containerd.grpc.v1.cri"] |
required_plugins | [] | 缺失即启动失败的必需插件 ID 列表 |
imports | [] | 额外导入的配置片段文件路径(支持 glob),用于拆分/复用配置 |
plugin_dir | "" | 外部插件(动态库)搜索目录,一般保持空 |
⚠️ 注意:
root与state通常保持默认;磁盘空间规划与备份都以root为锚点,变更后需同步调整文件系统挂载。
2.2 [grpc]:socket 与服务端约束
[grpc]
address = "/run/containerd/containerd.sock"
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
tcp_address = ""
tcp_tls_ca = ""
tcp_tls_cert = ""
tcp_tls_key = ""
uid = 0
| 参数 | 默认值 | 含义 |
|---|---|---|
address | /run/containerd/containerd.sock | 本地 Unix socket 监听路径(ctr/crictl/kubelet 都连它) |
max_recv_message_size | 16777216(16 MiB) | 接收的单条 gRPC 消息上限;拉大镜像元数据/大 payload 时按需调大 |
max_send_message_size | 16777216(16 MiB) | 发送单条消息上限 |
tcp_address | "" | 非空则额外监听 TCP(如 127.0.0.1:2376)暴露 gRPC |
tcp_tls_ca/cert/key | "" | TCP 监听时的 TLS 证书链配置 |
⚠️ 注意:不要随意把
max_recv_message_size调得过大;当ctr images pull报rpc error: code = ResourceExhausted或grpc: received message larger than max时,才考虑按需调大。
2.3 [debug] 与 [metrics]:调试与指标接口
[debug]
address = ""
format = ""
gid = 0
level = ""
uid = 0
[metrics]
address = ""
grpc_histogram = false
| 段 | 参数 | 默认值 | 含义 |
|---|---|---|---|
[debug] | address | "" | 非空则监听 debug HTTP/pprof 端点(如 /run/containerd/debug.sock) |
[debug] | level | "" | debug socket 的日志级别开关 |
[metrics] | address | "" | 非空则暴露 Prometheus 指标端点(如 127.0.0.1:1338) |
[metrics] | grpc_histogram | false | 是否采集 gRPC 调用直方图 |
默认两项都为空即调试/指标接口默认关闭,需要在生产观测时显式开启,例如:
[metrics]
address = "127.0.0.1:1338"
[debug]
address = "/run/containerd/debug.sock"
2.4 [cri] section:CRI 运行时核心段
containerd 作为 Kubernetes CRI 运行时,关键参数都位于 [plugins."io.containerd.grpc.v1.cri"] 下(真实默认值节选):
[plugins."io.containerd.grpc.v1.cri"]
image_pull_progress_timeout = "5m0s"
max_concurrent_downloads = 3
max_container_log_line_size = 16384
sandbox_image = "registry.k8s.io/pause:3.8"
stats_collect_period = 10
stream_idle_timeout = "4h0m0s"
stream_server_address = "127.0.0.1"
systemd_cgroup = false
| 参数 | 默认值 | 含义 |
|---|---|---|
sandbox_image | registry.k8s.io/pause:3.8 | Pod 沙箱 pause 镜像,离线/内网需显式改为内网仓库地址 |
systemd_cgroup | false | CRI 工作负载是否配合 systemd cgroup 驱动(见六章) |
max_concurrent_downloads | 3 | 单节点并发镜像拉取数 |
max_container_log_line_size | 16384(16 KiB) | 单条日志行最大字节,超过即截断 |
stats_collect_period | 10 | 每工作负载每隔多少秒采样一次资源统计 |
image_pull_progress_timeout | 5m0s | 镜像拉取进度超时(卡住时判定失败) |
stream_idle_timeout | 4h0m0s | exec/attach 流空闲超时 |
stream_server_address | 127.0.0.1 | CRI 流服务器监听地址 |
stream_server_port | "0" | 0 表示随机端口 |
2.5 snapshotter 与 SystemdCgroup:两个最常改的开关
① snapshotter(默认 overlayfs)
containerd config default 中,CRI 段与解包段默认快照驱动都是 overlayfs:
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "overlayfs"
[plugins."io.containerd.transfer.v1.local".unpack_config]
differ = "walking"
snapshotter = "overlayfs"
💡 说明:Ubuntu 22.04 上
overlayfs(overlay2)即默认驱动,无需修改;仅当宿主机文件系统不支持 overlay 或需回退时才改用native(见四章)。
② SystemdCgroup
Ubuntu 22.04 默认以 systemd 作为 cgroup 管理器(cgroup v2),需把 runc 侧从 false 改为 true(见六章)。它在 [runtimes.runc] 段:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = false
| 参数 | 默认值 | 含义 |
|---|---|---|
SystemdCgroup | false | runc 是否走 systemd 的 cgroup 驱动 |
BinaryName | "" | 自定义 runc 可执行名(空用内置) |
ShimCgroup | "" | shim 所在 cgroup 父路径 |
NoNewKeyring / NoPivotRoot | false | 关闭 session keyring / 关闭 pivot_root |
2.6 registry config_path:镜像加速入口
CRI 段默认 config_path 为空,指向镜像仓库域名级配置目录(hosts.toml)的基路径:
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = ""
- 1.7.x 默认空,需显式设为
/etc/containerd/certs.d; - 2.x 默认已指向
/etc/containerd/certs.d。
在该目录下按 仓库域名/hosts.toml 组织域名级镜像配置(见第五章):
/etc/containerd/certs.d/
└── docker.io/
└── hosts.toml
三、containerd 命令 flags
containerd 守护进程的全局 flag 是少数可覆盖配置的启动入口。真实 containerd --help 全局选项:
GLOBAL OPTIONS:
--config value, -c value Path to the configuration file (default: "/etc/containerd/config.toml")
--log-level value, -l value Set the logging level [trace, debug, info, warn, error, fatal, panic]
--address value, -a value Address for containerd's GRPC server
--root value containerd root directory
--state value containerd state directory
--help, -h show help
--version, -v print the version
| flag | 缩写 | 默认值 | 说明 |
|---|---|---|---|
--config | -c | /etc/containerd/config.toml | 指定配置文件路径 |
--log-level | -l | 未默认 | 日志级别:trace/debug/info/warn/error/fatal/panic |
--address | -a | 由 config 决定 | 覆盖 gRPC socket 地址 |
--root | 无 | /var/lib/containerd | 覆盖持久数据根目录 |
--state | 无 | /run/containerd | 覆盖运行时瞬时目录 |
--version | -v | — | 打印版本 |
systemd 启动时通过 containerd 二进制读取 /etc/containerd/config.toml,无需显式 -c。若要临时以指定配置文件前台启动做验证:
containerd --config /etc/containerd/config.toml --log-level debug
💡 说明:
containerd顶层子命令包括config(配置生成/导出)、publish、oci-hook、help;不带子命令运行即以前台启动守护进程。
3.1 config 子命令:default 与 dump
NAME:
containerd config - Information on the containerd config
COMMANDS:
default See the output of the default config
dump See the output of the final main config with imported in subconfig files
containerd config default:输出出厂默认配置(增量式改造的模板);containerd config dump:输出加载全部 import 后最终生效的配置(排查落地值用)。
四、内容与快照
4.1 内容存储(content store)
镜像的全部内容以「内容寻址」方式落盘到 root 下:
/var/lib/containerd/
├── io.containerd.content.v1.content/
│ ├── blobs/ # 以 sha256 命名的镜像层 blob
│ └── ingest/ # 正在写入的临时 blob
├── io.containerd.metadata.v1.bolt/ # bolt 元数据(镜像/内容索引)
├── io.containerd.grpc.v1.cri/ # CRI 相关状态
├── io.containerd.runtime.v2.task/ # 运行中任务的 shim 状态
├── io.containerd.snapshotter.v1.overlayfs/
└── io.containerd.snapshotter.v1.native/
blobs用哈希寻址,同一层多处引用只存一份,天然去重;- 元数据存放于 boltdb(
io.containerd.metadata.v1.bolt),对应[plugins."io.containerd.metadata.v1.bolt"].content_sharing_policy默认shared(多个命名空间共享内容层)。
4.2 快照驱动(snapshotters)
| 快照驱动 | 目录标识 | 特点 | 适用 |
|---|---|---|---|
overlayfs | snapshotter.v1.overlayfs | overlay 挂载合并层,省磁盘、共享只读底层 | 默认驱动,Ubuntu 22.04 直接用 |
native | snapshotter.v1.native | 每层独立目录全量复制,无共享合并 | 文件系统不支持 overlay 或需兼容时的回退 |
① 默认 overlayfs(推荐):低层为只读共享,工作负载运行时读写进入可写层,镜像拉取解包走 overlay。对应参数(保持默认即可,无需改动):
[plugins."io.containerd.snapshotter.v1.overlayfs"]
mount_options = []
root_path = ""
sync_remove = false
upperdir_label = false
② native 回退:某类文件系统(如部分网络盘)不支持 overlay 挂载时报挂载拒绝(operation not permitted)错误,此时可整体切换为 native。
查看当前生效驱动:
grep -n "snapshotter" /etc/containerd/config.toml | grep -vE "^#|#" | head
4.3 磁盘布局核对
确认内容与快照实际落盘位置:
ls -la /var/lib/containerd/io.containerd.content.v1.content/blobs/
ls -la /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/
du -sh /var/lib/containerd
⚠️ 注意:
root目录要有足够的磁盘空间并纳入备份/监控;镜像层 blob 长期累积时通过 GC(gc.scheduler 插件)按阈值回收,见七章。
五、镜像仓库配置
5.1 hosts.toml:域名级配置
containerd 2.x(以及指定 config_path 的 1.7.x)用 hosts.toml 按「仓库域名」配置镜像拉取行为。默认 config_path 为空,1.7.x 先启用:
mkdir -p /etc/containerd/certs.d/docker.io
grep -n 'config_path = ""' /etc/containerd/config.toml | head -1
sed -i 's#\tconfig_path = ""#\tconfig_path = "/etc/containerd/certs.d"#' /etc/containerd/config.toml
💡 说明:
sed前用grep -n定位行号核对缩进;2.x 默认已是/etc/containerd/certs.d,无需此步。
5.2 mirror:镜像加速(daocloud 实测)
在国内网络直连 docker.io 常被阻断(实测报 dial tcp 67.228.235.91:443: connect: connection refused)。为 docker.io 配置镜像源:
# /etc/containerd/certs.d/docker.io/hosts.toml
server = "https://docker.io"
[host."https://docker.m.daocloud.io"]
capabilities = ["pull", "resolve"]
server:本文件管辖的仓库地址;[host."https://镜像站"]:候选上游(按文件中实际 URL 写,如上面 daocloud 镜像站),按顺序尝试;capabilities:声明上游支持的能力(pull拉取、resolve解析,可含push上传)。
重启并实测拉取:
systemctl restart containerd
ctr images pull docker.m.daocloud.io/library/busybox:latest
真实回显:
Completed pull from OCI Registry (docker.m.daocloud.io/library/busybox:latest)
elapsed: 12.2s total: 2.1 Mi (180.0 KiB/s)
5.3 auth:私有仓库认证
同一 hosts.toml 中为私有仓库标注 username/password(落实际值,不占位):
# /etc/containerd/certs.d/registry.example.com/hosts.toml
server = "https://registry.example.com"
[host."https://registry.example.com"]
capabilities = ["pull", "resolve"]
username = "root"
password = "q1w2e3r4"
- 认证信息逐 hosts.toml 声明,仅对对应域名生效;
capabilities不影响认证,username/password用于对私有仓库做 Basic 认证。
⚠️ 注意:hosts.toml 中的明文凭据是节点本地配置;生产建议将敏感凭据改由注入/受管密钥渠道下发,而非明文维护,但文档示例落实际值以便直接可跑。
六、SystemdCgroup 与 CRI 集成
6.1 为什么改 SystemdCgroup
Ubuntu 22.04 使用 systemd 作为 init 与 cgroup 管理器(cgroup v2)。Kubernetes 侧 kubelet 默认 --cgroup-driver=systemd。若 containerd 的 runc 仍用 cgroupfs 驱动(SystemdCgroup=false),会与 systemd 各自主管同一批 cgroup,造成资源统计/回收冲突,节点负载高时甚至出现 cgroup 目录泄漏。
6.2 修改与验证
把 runc options.SystemdCgroup 由 false 改为 true:
grep -n "SystemdCgroup" /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
grep -n "SystemdCgroup" /etc/containerd/config.toml
systemctl daemon-reload
systemctl restart containerd
改动后核对:
grep -n "SystemdCgroup" /etc/containerd/config.toml # 应为 true
containerd config dump | grep -A3 'runtimes.runc.options' | grep SystemdCgroup
6.3 与 kubelet 对齐要求
| 组件 | 必改项 | 目标值 |
|---|---|---|
| containerd | runtimes.runc.options.SystemdCgroup | true |
| kubelet | --cgroup-driver | systemd |
| CRI 运行时 socket | kubelet --container-runtime-endpoint | unix:///run/containerd/containerd.sock |
⚠️ 注意:三处 cgroup 驱动必须一致(都用
systemd),否则 kubelet 上报Failed to start container/ cgroup 驱动不匹配类错误。CRI 侧 CRI socket 即/run/containerd/containerd.sock。
七、生产最佳实践
| 场景 | 配置项 | 建议 |
|---|---|---|
| 私有网络/内网(16GB 内存、SSD、多工作负载) | [cri].sandbox_image | 改为内网 pause 镜像地址,避免启动时依赖公网 |
| 国内/受限网络 | [cri].registry.config_path + hosts.toml | 配 docker.io mirror(daocloud),见五章 |
| cgroup v2 真机 | SystemdCgroup | true 并与 kubelet 对齐(六章) |
| 观测 | [metrics].address | 开启 127.0.0.1:1338 接入 Prometheus |
| 磁盘 | root 所在文件系统 | 预留充足空间、纳入监控与备份 |
| 日志 | [debug].level / -l | 默认 info;排障临时 debug |
| GC | [plugins."io.containerd.gc.v1.scheduler"] | 默认 mutation_threshold=100、pause_threshold=0.02,按负载微调 |
| 配置可追溯 | containerd config dump | 上线前后各导出一次比对 |
生产常用 GC 与调度默认值(节选,真实默认):
[plugins."io.containerd.gc.v1.scheduler"]
deletion_threshold = 0
mutation_threshold = 100
pause_threshold = 0.02
schedule_delay = "0s"
startup_delay = "100ms"
💡 说明:
mutation_threshold=100为每次待回收对象数触发 GC 的阈值,pause_threshold=0.02为 GC 执行时暂停的负载占比上限;默认即适合绝大多数场景。
八、常见问题
8.1 配置改动不生效
先用 containerd config dump 核对最终生效配置,确认 imports 与主文件的值是否被覆盖;再确认服务已重启:
containerd config dump | grep -nE "SystemdCgroup|snapshotter|config_path"
systemctl daemon-reload && systemctl restart containerd
真机环境还需确认 socket 就绪:
ls -l /run/containerd/containerd.sock
8.2 ctr images pull 报 connection refused
直连 docker.io 被网络阻断(限制公网访问)的典型现象:
dial tcp 67.228.235.91:443: connect: connection refused
解决:要么直接用加速站地址拉取(如 ctr images pull docker.m.daocloud.io/library/busybox:latest),要么按五章 5.2 配 hosts.toml mirror 供 CRI 使用。
8.3 gRPC ResourceExhausted / 消息过大
max_recv_message_size/max_send_message_size 默认 16 MiB;拉取超大镜像元数据或大 payload 时可按需调大,例如 16777216 增大到 1073741824(1 GiB)后重启。改之前先确认确实是消息超限,而非网络问题。
8.4 快照驱动类型错误
在部分不支持 overlay 的文件系统上报挂载拒绝(operation not permitted)时,可将 CRI 段与 transfer 段的 snapshotter 一并改为 native 回退,并清空对应 io.containerd.snapshotter.v1.native 遗留状态后重启。
九、参考链接
- containerd 官方配置文档:https://github.com/containerd/containerd/blob/main/docs/hosts.md
- containerd CRI 插件文档:https://github.com/containerd/containerd/blob/main/docs/cri/installation.md
- config.toml 默认输出来源:
containerd config default(v1.7.29 实测) - 相关文档:《Ubuntu 22.04 安装 containerd 指南》《containerd 常用 CLI 命令与工具详解》