解释 `overlay2.size` 与 `dm.basesize` 的区别

解读

在国内 Docker 面试中,这道题常被用来区分候选人是否真正在生产环境做过镜像与容器磁盘配额的调优。
面试官想听的不是“一个给 overlay2 用、一个给 devicemapper 用”这种表面答案,而是:

  1. 两种参数分别作用于哪一层(graph driver 层 vs thin pool 层);
  2. 谁决定单个容器可写层最大容量,谁决定镜像层在节点上的总占用上限
  3. 谁需要预分配、谁可以动态扩容
  4. 国内主流云厂商(阿里云 ACK、腾讯云 TKE、华为云 CCI)在托管集群里为什么几乎清一色关掉 devicemapper 并强制 overlay2,此时 overlay2.size 怎么配才符合等保 2.0 的磁盘限额要求。

知识点

  1. graph driver 定位:overlay2 把容器可写层挂在 <docker-data>/overlay2/<container-id>/diff,配额由 kernel overlayfs 的 project quota 实现;devicemapper 把镜像与容器放到thin pool里,配额由 dm-thin-pool 目标实现。
  2. 配置入口
    • overlay2.size 写在 daemon.jsondocker run --storage-opt size=xx只对当前容器生效,单位可以是 10G500M
    • dm.basesize 写在 daemon.jsonstorage-opts 数组里,例如 "dm.basesize=20G"是全局默认值,后续 pull 的镜像层和新建容器都继承该大小。
  3. 生效粒度
    • overlay2.size 限制的是单个容器的可写层(upperdir),镜像层只读,不计入该配额。
    • dm.basesize 限制的是每个“虚拟块设备”(thin volume),镜像层与容器可写层共用同一块设备,因此镜像越大,留给容器的空间越少
  4. 扩容能力
    • overlay2.size 可以在 docker run 时随意指定,容器停止后改大再启动即可生效,无需重建镜像。
    • dm.basesize 一旦设置,已有镜像和容器无法在线扩容,必须 docker rm + rmi 后重新拉取,或者通过 thin_dump/thin_restore 做离线扩容,生产环境几乎不可接受。
  5. 国内合规场景:等保 2.0 要求“多租户容器间磁盘资源隔离”,在 overlay2 下直接给每个容器配置 --storage-opt size=10G 即可通过测评;若用 devicemapper,需要额外做 lvmlockd + thin-pool 隔离,复杂度翻倍,因此国内银行、证券、运营商已全面淘汰 devicemapper

答案

overlay2.sizedm.basesize 的核心区别体现在驱动类型、限制对象、生效范围与扩容策略四点:

  1. 驱动类型:overlay2.sizeoverlay2 图形驱动的配额参数;dm.basesizedevicemapper 图形驱动的配额参数。
  2. 限制对象:overlay2.size 仅限制单个容器的可写层大小;dm.basesize 限制每个 thin volume 的总容量(镜像层 + 容器层)。
  3. 生效范围:overlay2.size 通过 docker run --storage-opt 动态指定,粒度到容器dm.basesize 在 daemon.json 中全局配置,粒度到镜像/容器实例
  4. 扩容策略:overlay2.size热扩容,容器重启即可;dm.basesize 只能冷扩容,需要删除重建容器与镜像,国内生产环境基本不可行。
    因此,在国内云原生实践中,优先使用 overlay2 并配合 overlay2.size 做容器级磁盘限额,而 dm.basesize 仅遗留在传统内网裸机场景,且已被多数金融客户列为淘汰技术路线

拓展思考

  1. 如果节点使用 xfs + pquota 挂载 /var/lib/docker,overlay2.size 的最小粒度可以降到 1M,但需要注意 project ID 耗尽问题(xfs 默认 128 k 个项目),可通过 xfs_admin -c 调大。
  2. Kubernetes 1.30+ 中,内置的 KubeletVolumeLimiter 特性计划把 overlay2.size 封装成 ephemeral-storage 限额,届时可直接在 resources.limits.ephemeral-storage 里写 10Gi,底层自动映射成 --storage-opt size=10G无需再手动配 docker
  3. 对于仍有旧 devicemapper 池的节点,可用 lvs -o+thin_id,thin_count 查看 thin-pool 使用率,当 metadata 满时会触发 dm: thin pool metadata full 错误,国内运维团队常误以为是镜像太大,其实是 dm.basesize 与 thin-pool 元数据区没对齐,需要 lvextend + thin_dump 修复,这类案例在国有大行私有云中出现过多次,面试时如能讲出排查步骤,可立即拉开差距。