记一次 Pod 挂载存储卷失败的调查
🏷️ Kubernetes
今天在调整一个挂载了字体文件存储卷(对象存储)的 Deployment 的 Pod 数量时报了如下错误导致服务无法启动。
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 全部停掉。如果为了不影响服务的运行,可以先创建一个临时的 PV 和 PVC ,将 Pod 挂载这个临时的 PVC 后再重新创建之前的 PV 和 PVC 并再次挂载,最后不要忘记删除临使用时的 PV 和 PVC 。
附1. PV 清单文件:
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 清单文件:
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