使用 `volume driver=local` 时如何设置容量配额

解读

在国内私有云或 IDC 场景下,面试官问“本地卷怎么限容”并不是想听你背命令,而是考察三点:

  1. 是否知道 Docker 本身不内置配额能力
  2. 能否把“Docker 卷路径 + Linux 配额机制”串成完整方案;
  3. 是否具备 线上实施与排障经验(fstab 写错导致节点挂掉、配额数据库损坏、inotify 超限等)。
    答“做不到”或只甩一句“xfs_quota” 都直接扣分;必须给出“创建→挂载→赋权→校验→异常处理”的闭环步骤,并指出 CentOS 7/8、Ubuntu 20/22、麒麟 V10 等国内常见发行版的差异点。

知识点

  • local 驱动本质:Docker 在 /var/lib/docker/volumes/<name> 新建目录,bind mount 到容器,不会也不打算帮你限制 inode/block。
  • Linux 磁盘配额子系统:内核层 VFS → 文件系统层(ext4 的 quota、xfs 的 xfs_quota)→ 用户层工具(quota-tools/xfsprogs)。
  • 项目配额(project quota):XFS 的 projid 机制可把任意目录划为独立 project,支持 Docker 卷路径动态绑定,CentOS 7.4+ 默认内核已开启。
  • ext4 的 dirquota:需要 quota、jqfmt=vfsv1 且内核 ≥5.4,国内不少云主机仍为 3.10 内核,需先确认。
  • Docker 卷插件生态:若不想自己写脚本,可用 local-persist、rexray、lvm 等第三方驱动,但面试场景默认“原生 local 驱动 + 宿主机配额”最接地气。
  • systemd 与 fstabCentOS/RHEL 习惯写 /etc/fstabUbuntu 20+ 推荐 systemd-mount;写错参数会导致节点无法拉起,面试时要强调“先测试单节点,再批量 Ansible 推送”。
  • 配额数据库损坏恢复quotacheck -avugxfs_quota -x -c "quota -p" 等命令需牢记,生产环境必须先在低峰期执行

答案

以国内 CentOS 7.9 + XFS 为例,完整落地步骤如下:

  1. 宿主机准备
    确认根分区或独立数据盘为 XFS:
    xfs_info / | grep projid32bit 若返回 attr=2, projid32bit=1 表示已支持 project quota。
    如未支持,需在内核参数添加 rootflags=pquota 并重启,或单独挂载一块 /data 盘:mount -o remount,prjquota /data

  2. 建立项目 ID 映射

    echo 2000:/var/lib/docker/volumes/webapp >> /etc/projects
    echo webapp:2000 >> /etc/projid
    
  3. 给目录打 project 标记
    xfs_quota -x -c "project -s webapp" /data

  4. 设置硬配额
    xfs_quota -x -c "limit -p bhard=5g webapp" /data
    如需 inode 限制:
    xfs_quota -x -c "limit -p ihard=1m webapp" /data

  5. 创建 Docker 卷并指定挂载路径

    docker volume create --driver local \
      --opt type=none \
      --opt device=/var/lib/docker/volumes/webapp \
      --opt o=bind \
      webapp
    
  6. 启动容器验证

    docker run -d --name nginx \
      -v webapp:/usr/share/nginx/html \
      nginx:1.25-alpine
    

    进入容器执行 dd if=/dev/zero of=/usr/share/nginx/html/big bs=1M count=6
    当写入超过 5 GiB 时,返回 “No space left on device”,说明配额生效。

  7. 监控与告警
    在 Prometheus node-exporter 中开启 xfs_quota_exporter 或使用 xfs_quota -x -c "report -p -h" 定时采集,超过 80% 触发钉钉/飞书告警

  8. 故障预案

    • 若误设置 0 导致容器无法写入,立即执行 xfs_quota -x -c "limit -p bhard=0 webapp" /data 取消限制;
    • 配额数据库损坏时,先停 Dockerxfs_quota -x -c "off -p" 关闭 project 限额,再 quotacheck -bp 重建。

拓展思考

  1. 多租户场景:同一宿主机跑多个事业部容器,可借助 projid 自动分配脚本(解析命名空间或 CI 流水线传入的 LABEL),Ansible + Jinja2 模板批量生成 /etc/projects,实现“谁创建谁负责”的配额治理。
  2. 动态扩容:业务突发大文件上传,可在低峰期 xfs_quota -x -c "limit -p bhard=+10g webapp" 在线扩容,无需重启容器,但需审计谁在什么时间调整。
  3. 与 Kubernetes 结合:Kubelet 的 local-static-provisioner 不支持 project quota,需自研 CSI Driveradmission webhook,在 VolumeAttachment 阶段调用宿主机 xfs_quota;面试可提“已给社区提交 PR,正在 review”体现深度。
  4. ext4 方案兜底:若机房强制 ext4,可退而求其次用 loop 设备 + ext4 quota,即 dd 创建 5G 空文件 → mkfs.ext4 -O quota,projectmount -o loop,prjquotadocker volume create --opt device=/dev/loop0,但性能损耗 10~15%,需提前压测。
  5. 安全加固:配额只能防“写爆磁盘”,不能防“读占 I/O”,需配合 cgroups blkio 做带宽限制;面试尾声可补充“已在内核 5.15 上测试 io.max 的 PSI 指标”,展示对 cgroup v2 的跟进。