Skip to content

记一次 Pod 挂载存储卷失败的调查

🏷️ Kubernetes

今天在调整一个挂载了字体文件存储卷(对象存储)的 Deployment 的 Pod 数量时报了如下错误导致服务无法启动。

javascript
MountVolume.SetUp failed for volume "pv-jiajia-font" : rpc
error : code = Internal desc = mount
failed : failed to send mount command to launcher : the response of launcher(action: cosfs) is :
{
    "errmsg":"exec command(
        cosfs bucket-jiajia-1234567890:/fonts
            /var/lib/kubelet/pods/4142efc8-8923-47d1-aba1-5b3d26b1ff10/volumes/kubernetes.io~csi/pv-jiajia-font/mount
            -ourl=http://cos.ap-guangzhou.myqcloud.com
            -odbglevel=err
            -opasswd_file=/tmp/bucket-jiajia-1234567890_121a6f50fe6f8d3434002a73407ae729f53682fdec4fb0aa442af31a3ee17abe
            -oensure_diskfree=20480
            -oallow_other
        ) failed.
        command cosfs bucket-jiajia-1234567890:/fonts
            /var/lib/kubelet/pods/4142efc8-8923-47d1-aba1-5b3d26b1ff10/volumes/kubernetes.io~csi/pv-jiajia-font/mount
            -ourl=http://cos.ap-guangzhou.myqcloud.com
            -odbglevel=err
            -opasswd_file=/tmp/bucket-jiajia-1234567890_121a6f50fe6f8d3434002a73407ae729f53682fdec4fb0aa442af31a3ee17abe
            -oensure_diskfree=20480
            -oallow_other
        failed: output
        cosfs: There is no enough disk space for used as cache(or temporary) directory by s3fs.\n,
        error: exit status 1",
    "result":"failure"
}

这里挂载的是腾讯云的对象存储( COS ),本身是支持多个节点( Node )挂载和读写的。

仔细看了下报错信息,比较关键的是这句话:There is no enough disk space for used as cache(or temporary) directory by s3fs.

顺便搜了下 s3fs ,这个貌似指的是 Amazon S3 ( Amazon Simple Storage Service ) 对象存储。

在阿里云的 ossfs 常见问题中找到了相同的报错。[1]

ossfs 默认通过分片上传的方式上传大文件。上传时, ossfs 会将临时缓存文件写入 /tmp 目录下,写入前需要先判断 /tmp 目录所在的磁盘可用空间是否小于 multipart_size * parallel_count 。如果磁盘可用空间大于 multipart_size * parallel_count ,则正常写入文件。如果磁盘可用空间小于 multipart_size * parallel_count ,则出现本地磁盘可用空间不足的报错。

例如,磁盘可用空间为300 GB,待上传的文件为200 GB,但 multipart_size 设置为100000(100 GB),并发上传分片数量保持默认值 5 。此时,ossfs 判断上传的文件大小为100 GB*5=500 GB,超出本地磁盘可用空间。

这个是阿里云 ossfs 上传时的报错原因分析,不过解释了为什么挂载对象存储会占用宿主节点的本地磁盘空间。

在腾讯云的对象存储的常用挂载选项中只有 multipart_size 配置项(默认值为 10MB ),没有看到 parallel_count 配置项。而在上面的报错信息中可以看到挂载时并没有设置这两个参数,不过有一个 -oensure_diskfree=20480 参数配置。这个参数就是用来配置 cosfs 的默认保留磁盘空间的。[2] 项目清单文件中这个参数值是在通过页面创建 PV 时默认填写的,当时不理解这个参数的作用,也就没有修改。

原因: 综上,这个错误是由于 Pod 挂载数据卷时会向节点请求预留 ensure_diskfree 参数指定大小的磁盘空间,而正好本地磁盘空间不足,从而导致挂载失败。(不确定具体的预留逻辑是怎样的,貌似磁盘空间并没有被真的使用掉)

对策:ensure_diskfree 参数的值缩小就可以了。

注意: 由于无法直接修改 PV 的配置,所以只能删除旧的然后再新建,而删除需要将挂载关联 PVC 的 Pod 全部停掉。如果为了不影响服务的运行,可以先创建一个临时的 PVPVC ,将 Pod 挂载这个临时的 PVC 后再重新创建之前的 PVPVC 并再次挂载,最后不要忘记删除临使用时的 PVPVC

附1. PV 清单文件:

yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  annotations:
    pv.kubernetes.io/bound-by-controller: "yes"
  finalizers:
  - kubernetes.io/pv-protection
  name: pv-jiajia-font
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Gi
  csi:
    driver: com.tencent.cloud.csi.cosfs
    nodePublishSecretRef:
      name: cos-jiajia
      namespace: kube-system
    volumeAttributes:
      additional_args: -oensure_diskfree=2048 -oallow_other
      bucket: bucket-jiajia-1234567890
      path: /fonts
      url: http://cos.ap-guangzhou.myqcloud.com
    volumeHandle: pv-jiajia-font
  persistentVolumeReclaimPolicy: Retain
  volumeMode: Filesystem

附2. PVC 清单文件:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    pv.kubernetes.io/bind-completed: "yes"
  finalizers:
  - kubernetes.io/pvc-protection
  name: pvc-jiajia-font
  namespace: product
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: ""
  volumeMode: Filesystem
  volumeName: pv-jiajia-font

  1. 上传大文件时报错"there is no enough disk space for used as cache(or temporary)" ↩︎

  2. COSFS 常用挂载选项 ↩︎