本文为您介绍OSS存储卷常见问题的处理方法。
类型 | 问题 |
挂载问题 | |
使用问题 | |
卸载问题 | |
控制台检测失败问题 | |
其他 |
OSS存储卷挂载时间延长
问题现象
OSS存储卷挂载时间延长。
问题原因
同时满足以下配置,kubelet在存储卷挂载过程中将执行chmod或chown操作,导致挂载时间延长。
在PV及PVC模板中配置的参数AccessModes值为ReadWriteOnce。
在应用模板中配置了securityContext.fsgroup参数。
解决方案
ossfs挂载工具支持通过参数修改其挂载点下文件所属的UID、GID以及文件的mode。
参数
说明
uid
指定挂载目录下子目录及文件归属用户的用户UID。
gid
指定挂载目录下子目录及文件归属用户的用户GID。
umask
用于设定挂载目录下子目录及文件的权限掩码。使用方式与mp_umask类似,但无需依赖allow_other配置项。
配置后,请删除securityContext下的fsgroup参数。
对于1.20及之后版本的Kubernetes集群,除了上述解决方法外,也可通过将fsGroupChangePolicy配置为OnRootMismatch,这时只有在首次启动时才会执行
chmod
或chown
操作,导致存在挂载时间延长的问题,后续挂载OSS存储卷时挂载时间将恢复正常。关于fsGroupChangePolicy参数的更多信息,请参见为Pod或容器配置安全性上下文。
OSS存储挂载权限问题
当您在以下几种场景中进行操作时,出现错误提示Permission Denied。
场景1:访问挂载目录时,出现错误提示Permission Denied
问题原因
OSS默认使用Linux的root用户进行挂载,权限为700。当容器进程以非root用户运行时,权限不足。
解决方案
通过增加配置项修改挂载根目录的权限。
参数 | 说明 |
allow_other | 设置挂载目录的权限为777。 |
mp_umask | 用于设定挂载目录的权限掩码,只有当
|
场景2:访问通过ossutil、OSS控制台、SDK等其他方式上传的文件时,出现错误提示Permission Denied
问题原因
通过其他方式上传的文件在ossfs中默认权限为640。当容器进程以非root用户运行时,权限不足。
解决方案
以root角色chmod修改目标文件的权限。或者通过以下配置项修改挂载目录下子目录及文件的权限。
参数 | 说明 |
umask | 用于设定挂载目录下子目录及文件的权限掩码。使用方式与mp_umask类似,但无需依赖allow_other配置项。 |
umask只能修改当前ossfs中看到的文件的权限,再次挂载或对其他ossfs进程并不生效。例如:
配置
-o umask=022
后,使用stat
查看一个通过OSS控制台上传的文件,权限为755;取消-o umask=022
配置项后再次挂载,权限仍为640。容器进程以root用户配置
-o umask=133
后,通过chmod配置某文件权限为777,stat
该文件权限仍为644;取消-o umask=133
后再次挂载,权限变更为777。
场景3:通过不同的容器进行读写操作时,读、写、运行其他容器创建的文件。
问题原因
在ossfs中创建的普通文件默认权限为644。配置securityContext
中的fsGroup
字段,或创建后chmod、chown文件,都可能导致权限或所有者的变更。当另一个容器进程以其他用户操作文件时,可能会出现权限不足的问题。
解决方案
stat
目标文件的权限,若权限不足,请以root用户使用chmod修改目标文件的权限。
以上三种场景的解决均通过增加目录或文件的权限,解决当前容器进程用户权限不足的问题,您也可以通过修改ossfs挂载目录下子目录及文件所属用户来解决。
容器镜像构建时指定运行用户,或部署时应用模板的securityContext.runAsUser
及securityContext.runAsGroup
字段非空,都会使应用的容器进程以非root用户运行。
通过以下配置项修改ossfs挂载目录下子目录及文件的UID和GID,使其与容器进程用户一致。
参数 | 说明 |
uid | 指定挂载目录下子目录及文件归属用户的用户UID。 |
gid | 指定挂载目录下子目录及文件归属用户的用户GID。 |
例如,容器访问OSS的进程ID为uid=1000(biodocker)
、gid=1001(biodocker)
、groups=1001(biodocker)
,则需配置-o uid=1000
,-o gid=1001
。
场景4:OSS挂载时使用Secret记录AccessKey信息,并在PV中通过nodePublishSecretRef
字段指定Secret。因为AK轮转等原因撤销了原AK,Secret中AccessKey信息修改后不生效
问题原因
OSS数据卷是使用ossfs文件进行挂载的FUSE文件系统,挂载成功后无法更新AccessKey信息,已经挂载了OSS存储卷的应用仍然使用原AK向OSS Server端发送请求。
解决方案
切换Secret中新的AccessKey信息后重新挂载。非容器化版本或开启了独享挂载方式的容器化版本,您只需要重启应用Pod触发ossfs重启。具体操作,请参见共享挂载方式下,如何重启ossfs进程?。
场景5:硬链接操作时,返回Operation not permitted
问题原因
OSS存储卷不支持硬链接操作。在早期的CSI版本中,硬链接操作返回的报错为Operation not permitted。
解决方案
改造业务,使用OSS存储卷时,应避免硬链接操作。若您的业务必须使用硬链接操作,建议您更换存储。
场景6:使用subpath或subpathExpr方式挂载OSS存储卷,读写操作权限不足
问题原因
非root用户运行的业务容器没有/path/subpath/in/oss/
目录下文件的权限(默认为640)。subpath方式挂载OSS存储卷时,ossfs在OSS服务端实际的挂载目录为PV中定义的path目录,即上述示例中的/path
,而非/path/subpath/in/oss/
。配置allow_other或mp_umask挂载项仅对/path
目录生效,/path/subpath/in/oss/
目录作为子目录仍默认为640。
解决方案
通过umask配置项修改子目录默认权限,例如-o umask=000
将默认权限修改为777。
OSS存储卷挂载失败
问题现象
OSS存储卷挂载失败,Pod无法启动,Event提示FailedMount。
问题原因
原因1:ossfs早期的版本不支持挂载到Bucket中不存在的目录中,原挂载目录不存在导致挂载失败。
重要OSS控制台中可见的子路径在Server端不一定真实存在,以ossutil或OSS API的返回为准。例如,直接创建
/a/b/c/
目录,/a/b/c/
为单独的目录对象,而/a/
或/a/b/
目录对象实际并不存在。同理,如上传/a/*
文件,/a/b
、/a/c
等为单独的文件对象,/a/
目录对象不存在。原因2:AccessKey或RRSA使用的角色信息填写错误或权限不足导致挂载失败。
原因3:CSI版本在1.30.4及以上时,OSSFS所在的Pod运行在
ack-csi-fuse
命名空间中。挂载时CSI将先拉起OSSFS所在的Pod,再通过RPC请求实际启动Pod中的OSSFS进程。若Event的内容中包含FailedMount /run/fuse.ossfs/xxxxxx/mounter.sock: connect: no such file or directory
,则挂载失败是因为OSSFS所在Pod未正常拉起或被意外删除。原因4:若Event的内容中包含
Failed to find executable /usr/local/bin/ossfs: No such file or directory
,则挂载失败是因为OSSFS在节点上安装失败。原因5:若Event的内容中包含
error while loading shared libraries: xxxxx: cannot open shared object file: No such file or directory
,挂载失败的原因为当前CSI版本ossfs直接运行在节点上,且操作系统缺乏部分ossfs运行所需的动态库。以下情况都可能导致该报错:手动在节点安装过其他版本的ossfs工具,且适配的操作系统与当前节点不一致。
节点操作系统版本升级导致OpenSSL默认版本变更,例如Alibaba Cloud Linux 2升级至Alibaba Cloud Linux 3。
ossfs运行在节点上时,不支持CentOS、Alibaba Cloud Linux、ContainerOS和龙蜥以外的操作系统。
在符合操作系统要求的节点上删除过默认的FUSE、cURL、xml2等ossfs运行需要的动态库,或变更过OpenSSL的默认版本。
原因6:挂载OSS Bucket的子目录时,AccessKey或RRSA使用的角色仅授权了子目录范围的权限,挂载失败。ossfs Pod日志中同时包含
403 AccessDenied
和404 NoSuchKey
报错。ossfs在启动时将自动对OSS Bucket进行权限校验与连通性检测。挂载目标为OSS子目录时,1.91+版本的ossfs将先尝试访问Bucket根目录;若访问失败,则重新尝试访问子目录。对Bucket有完整只读权限时,新版本ossfs允许挂载OSS Bucket中不存在的子目录。
因此,对若AccessKey或RRSA使用的角色仅授权了子目录范围的权限,将在初次验证时报
403 AccessDenied
错误;若该子目录不存在,则继续报404 NoSuchKey
错误并异常退出,导致挂载失败。原因7:Bucket配置了镜像回源,挂载目录未从源站同步。
原因8:Bucket配置了静态网站托管,ossfs检查OSS端挂载目录时,请求转发到index.html等文件中。
解决方案
原因1解决方案:
检查子路径在OSS Server端是否存在。
假设PV的挂载路径为
sub/path/
,您可以使用stat(查看Bucket和Object信息)查询objectname
为sub/path/
的对象,或使用openapi HeadObject查询key
为sub/path/
的对象。若返回为404,确认Server端不存在该子路径。您可以通过ossutil、SDK、OSS控制台等工具手动创建缺失的Bucket或子目录,然后重新挂载。
ossfs1.91+版本不强制要求挂载目录存在,您也可以通过升级ossfs版本解决该问题。更多信息,请参见ossfs 1.91及以上版本新功能介绍及性能压测。若升级后挂载仍出现问题,请参见本问题原因6。
原因2解决方案:
确认挂载使用的RAM用户或RAM角色的策略权限包括步骤二:为demo-role-for-rrsa角色授权中列举的权限。
确认挂载点根路径及subpath路径的文件系统权限,详情请参考OSS存储挂载权限问题中的场景1和场景6。
对于通过RAM用户AccessKey鉴权方式挂载的存储卷,确认挂载时使用的AccessKey是否被禁用或已轮转,详情请参考OSS存储挂载权限问题中的场景4.
对于通过RRSA鉴权方式挂载的存储卷,确认是否为RAM角色配置正确的信任策略。信任策略的配置请参考步骤一:创建RAM角色。默认情况下,信任的ServiceAccount为ack-csi-fuse命名空间下的csi-fuse-ossfs,而非业务使用的ServiceAccount。
重要RRSA鉴权方式挂载仅支持1.26及以上版本的集群,即ACK托管集群、ACK Serverless集群,且集群使用的CSI组件为1.30.4及以上版本。若您在1.30.4之前的版本中使用了RRSA功能,请及时参见【产品变更】CSI ossfs版本升级与挂载流程优化增加RAM角色授权配置。
原因3解决方案:
执行以下命令,确认OSSFS所在Pod存在。其中
PV_NAME
为挂载的OSS PV名称,NODE_NAME
为需挂载存储卷的业务Pod所在的节点名称。kubectl -n ack-csi-fuse get pod -l csi.alibabacloud.com/volume-id=<PV_NAME> -owide | grep <NODE_NAME>
若Pod存在且状态异常,请排查Pod的异常原因,确保Pod正常Running后重启业务Pod触发重新挂载。若Pod不存在,请按后续步骤继续排查。
(可选)通过查询审计日志等方式确认Pod是否被意外删除,常见的意外删除原因包括业务脚本清理、节点排水、节点自愈等。建议您做相关调整,避免问题重现。
确认CSI provisioner与CSI plugin均升级到1.30.4及以上后,重启业务Pod触发重新挂载,并确认OSSFS Pod有正常创建流程。
原因4解决方案:
建议您将csi-plugin版本升级到v1.26.2或以上版本,该版本修复了刚扩容出的节点初始化时,ossfs安装失败的问题。
执行以下命令,尝试重启对应节点上的csi-plugin后,查看Pod是否能正常启动。以下代码中
csi-plugin-****
为节点所在csi-plugin的Pod名称。kubectl -n kube-system delete pod csi-plugin-****
若升级或重启组件后,问题仍无法解决,请登录节点,执行以下命令。
ls /etc/csi-tool
部分预期输出:
... ossfs_<ossfsVer>_<ossfsArch>_x86_64.rpm ...
若输出中存在OSSFS的RPM包,则执行以下命令,查看Pod是否能正常启动。
rpm -i /etc/csi-tool/ossfs_<ossfsVer>_<ossfsArch>_x86_64.rpm
若输出中不存在OSSFS的RPM包,请提交工单处理。
原因5解决方案:
若您手动安装过ossfs工具,请检查适配的操作系统与节点是否一致。
若您升级过集群的节点操作系统,可以执行以下指令重启csi-plugin,更新ossfs版本后再尝试挂载。
kubectl -n kube-system delete pod -l app=csi-plugin
建议您升级CSI至1.28或以上版本,挂载OSS存储卷时ossfs以容器的方式运行在集群中,对节点操作系统无要求。
若您的集群无法升级CSI版本,可以切换至符合要求的OS或手动安装缺少的动态库,以Ubuntu节点为例:
使用which指令,查询当前ossfs的安装位置(默认安装路径为
/usr/local/bin/ossfs
)。which ossfs
使用ldd指令,查询ossfs缺失的动态库文件。
ldd /usr/local/bin/ossfs
使用apt-file指令,查询缺失的动态库文件(如libcrypto.so.10)所属的Package。
apt-get install apt-file apt-file update apt-file search libcrypto.so.10
使用apt-get指令安装对应Package(如libssl.1.0.0)。
apt-get install libssl1.0.0
原因6解决方案:
参考本问题原因1,确认子目录存在。
若业务长期需要挂载子目录,建议将权限范围扩大到整个Bucket。
原因7解决方案:
您需要同步源站数据后,再进行挂载。更多信息,请参见回源。
原因8解决方案:
您需要关闭或调整静态网站托管的配置,再进行挂载。更多信息,请参见静态网站托管。
如何通过OSS存储卷仅挂载OSS中的某个文件
OSS存储卷通过ossfs工具将OSS的某个路径以文件系统的形式挂载到Pod中,ossfs本身并不支持挂载文件。若您希望在Pod中仅能看到OSS中的某个文件,可通过subPath的方式实现:
假设需要挂载的OSS中bucket:/subpath下的a.txt和b.txt文件到两个不同的Pod中,在Pod中的存放路径分别为/path/to/file/,可参考以下YAML创建对应的PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-oss
spec:
capacity:
storage: 5Gi
accessModes:
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
csi:
driver: ossplugin.csi.alibabacloud.com
volumeHandle: pv-oss
volumeAttributes:
bucket: bucket
path: subpath #subpath为a.txt与b.txt的父路径
url: "oss-cn-hangzhou.aliyuncs.com"
创建对应的PVC后,Pod中挂载PVC相应的VolumeMounts配置为:
volumeMounts:
- mountPath: /path/to/file # bucket:/subpath对应Pod中的挂载路径
name: oss-pvc # 与Volumes中的名称一致
subPath: a.txt # 或者b.txt,bucket:/subpath中文件的相对路径
挂载后,Pod中访问a.txt的完整路径为/path/to/file/a.txt
,实际访问的是bucket:/subpath/a.txt。
OSS存储卷的基本使用说明请参考使用OSS静态存储卷。
以上示例中,ossfs在节点上的挂载点对应的实际OSS路径为bucket:/subpath,对于节点上的文件扫描等进程,或以非subPath形式挂载的Pod而言,可见的内容仍为bucket:/subpath。
对于非root用户运行的容器需要注意subPath的权限配置,详情请参考使用subpath或subpathExpr方式挂载OSS存储卷异常
OSS存储卷访问Bucket过慢
问题现象
OSS存储卷访问Bucket过慢。
问题原因
原因1:OSS对象存储本身没有文件数限制,但当文件数量大于1000时,会使OSS的FUSE访问元数据过多,导致Bucket访问过慢。
原因2:OSS开启版本控制后,当Bucket中存在大量删除标记时,listObjectsV1性能下降。
原因3:OSS服务端设置存储类型为标准存储(Standard)以外的存储,其他存储类型将不同程度地降低数据访问的性能。
解决方案
原因1解决方案:
容器内挂载OSS时,建议以只读的形式访问Bucket,针对大量平铺对象,可采用OSS SDK方式或CLI方式等非文件系统挂载方式,访问Bucket的数据。更多信息,请参见SDK示例简介。
原因2解决方案:
将CSI plugin组件版本升级至v1.26.6后,ossfs可支持通过listObjectsV2访问Bucket。
在OSS静态卷PV的
otherOpts
字段中增加-o listobjectsv2
来解决。
原因3解决方案:
您需要修改存储类型或者解冻文件。
OSS控制台看到文件大小为0
问题现象
容器内挂载OSS数据卷时,在文件中写入数据,但在OSS控制台看到文件大小为0。
问题原因
容器使用ossfs挂载OSS,即基于FUSE方式挂载OSS的Bucket,只有在文件执行close或者flush时,文件内容才会上传至OSS的服务端。
解决方案
使用lsof+文件名称的方式,查看当前文件是否被其他进程占用,关闭相应进程,释放文件fd。关于lsof更多信息,请参见lsof。
文件目录挂载后,显示为文件对象
问题现象
容器内挂载OSS数据卷时,文件原本是目录,挂载后,显示为文件对象。
问题原因
原因1:目录对象在OSS服务端content-type类型是非默认的application/octet-stream
类型(例如text/html, image/jpeg等),或目录对象的大小非0,ossfs根据其元信息将其视为相应的文件对象。
原因2:非原因1的情况,但目录对象缺少元信息x-oss-meta-mode
。
解决方案
原因1解决方案:
通过HeadObject或stat(查看Bucket和Object信息)获取目录对象元信息,目录对象需要以"/"
结尾(例如a/b/
),以API返回为例。
{
"server": "AliyunOSS",
"date": "Wed, 06 Mar 2024 02:48:16 GMT",
"content-type": "application/octet-stream",
"content-length": "0",
"connection": "keep-alive",
"x-oss-request-id": "65E7D970946A0030334xxxxx",
"accept-ranges": "bytes",
"etag": "\"D41D8CD98F00B204E9800998ECFxxxxx\"",
"last-modified": "Wed, 06 Mar 2024 02:39:19 GMT",
"x-oss-object-type": "Normal",
"x-oss-hash-crc6xxxxx": "0",
"x-oss-storage-class": "Standard",
"content-md5": "1B2M2Y8AsgTpgAmY7Phxxxxx",
"x-oss-server-time": "17"
}
以上返回示例中:
content-type
:为application/octet-stream
,即目录对象为application/octet-stream类型。content-length
:为0,即目录对象大小为0。
若不满足以上条件,您可以通过以下方式修复:
通过GetObject或命令行工具ossutil快速入门获取该对象,确认数据是否有用。若数据有用或不能确定,建议对其进行备份,例如变更名称(对
xx/
目录对象,请勿使用xx
作为新的名称)后上传至OSS。通过DeleteObject或rm(删除)删除有问题的目录对象,然后确认ossfs是否正常显示目录。
原因2解决方案:
若通过原因1的解决方案未修复问题,您可以在容器内挂载OSS数据卷时,在OSS静态卷PV的otherOpts
字段中增加-o complement_stat
来解决。
CSI plugin组件版本为v1.26.6及以上版本时,配置项已默认开启,您可以将存储组件升级至v1.26.6或以上版本,重启业务Pod并重新挂载OSS静态卷解决。
OSS服务端监控到大量异常请求流量
问题现象
在容器内挂载OSS数据卷时,OSS服务端监控到请求数量远超出业务预期产生量。
问题原因
通过ossfs挂载OSS对象存储时,将在节点上产生挂载路径,ECS上的其他进程对挂载点的扫描也会转换为向OSS的请求。如果请求次数很多,会产生费用。
解决方案
通过审计追踪产生请求的进程,并进行相应修复。您可以在节点上进行如下操作。
执行以下命令,安装auditd并启动。
sudo yum install auditd sudo service auditd start
将对ossfs挂载路径设为监测目录。
如需添加所有挂载路径,请执行以下命令。
for i in $(mount | grep -i ossfs | awk '{print $3}');do auditctl -w ${i};done
如需添加某个PV的挂载路径,请执行以下命令。其中,
<pv-name>
为指定的PV名称。for i in $(mount | grep -i ossfs | grep -i <pv-name> | awk '{print $3}');do auditctl -w ${i};done
通过以下命令,在auditlog中查看存在哪些进程访问了OSS Bucket中的路径。
ausearch -i
审计日志分析示例如下。以下示例中,
---
分隔符间的审计日志为一组,记录对监控挂载点的单次操作。该示例表示updatedb
进程对挂载点中的子目录进行了open
的操作,进程PID为1636611。--- type=PROCTITLE msg=audit(2023年09月22日 15:09:26.244:291) : proctitle=updatedb type=PATH msg=audit(2023年09月22日 15:09:26.244:291) : item=0 name=. inode=14 dev=00:153 mode=dir,755 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 type=CWD msg=audit(2023年09月22日 15:09:26.244:291) : cwd=/subdir1/subdir2 type=SYSCALL msg=audit(2023年09月22日 15:09:26.244:291) : arch=x86_64 syscall=open success=yes exit=9 a0=0x55f9f59da74e a1=O_RDONLY|O_DIRECTORY|O_NOATIME a2=0x7fff78c34f40 a3=0x0 items=1 ppid=1581119 pid=1636611 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts1 ses=1355 comm=updatedb exe=/usr/bin/updatedb key=(null) ---
借助日志进一步确认是否存在非业务的进程调用,并进行修复。
例如,通过auditlog查到updatedb扫描了所挂载的目录,可以通过修改
/etc/updatedb.conf
让它跳过。具体操作如下。在
RUNEFS =
后面加上fuse.ossfs
。在
PRUNEPATHS =
后面加上挂载的目录。
通过OSS存储卷写入的文件对象的元数据Content-Type全为application/octet-stream类型
问题现象
通过OSS存储卷写入的文件对象的元数据Content-Type全为application/octet-stream类型,导致浏览器或其他客户端未能够正确识别和处理这些文件。
问题原因
未指定Content-Type类型,ossfs默认将文件对象视为二进制流文件。
通过/etc/mime.types配置文件指定Content-Type类型,但未生效。
解决方案
确认CSI组件版本,1.26.6和1.28.1版本的组件对Content-Type配置存在兼容性问题。若使用了相关版本,请升级CSI至最新版本。更多信息,请参见【组件公告】关于1.26.6和1.28.1版本的csi-plugin和csi-provisioner组件兼容性问题。
若您已经通过使用
mailcap
、mime-support
在节点上生成/etc/mime.types
的方式指定Content-Type类型,升级CSI版本后,重新挂载对应OSS存储卷即可。若您未指定Content-Type类型,可通过以下两种方式指定:
节点级别配置:在节点上生成
/etc/mime.types
配置文件,对所有新挂载到该节点上的OSS存储卷生效。更多信息,请参见常见问题。集群级别配置:该方式对集群所有新挂载的OSS存储卷生效,
/etc/mime.types
内容与mailcap
默认生成的内容一致。执行以下命令,检查csi-plugin配置文件是否存在。
kubectl -n kube-system get cm csi-plugin
若不存在,使用以下内容,创建csi-plugin同名ConfigMap;若不存在,则需要在原ConfigMap中增加
data.fuse-ossfs
中的内容mime-support="true"
。apiVersion: v1 kind: ConfigMap metadata: name: csi-plugin namespace: kube-system data: fuse-ossfs: | mime-support=true
重启csi-plugin,使配置生效,重启csi-plugin不会影响当前已经成功挂载的存储卷的使用。
kubectl -n kube-system delete pod -l app=csi-plugin
重新挂载对应的OSS存储卷。
如何在RRSA鉴权方式中使用指定的ARNs或ServiceAccount?
通过RRSA方式的OSS存储卷鉴权时,无法满足例如使用第三方OIDC身份提供商、使用非默认ServiceAccount等需求。
此时,您只需要在PV中通过roleName配置项指定RAM角色名称,即可由CSI存储插件获取默认的Role ARN及OIDC Provider ARN。若您需要实现定制化的RRSA鉴权,则需要更改PV的配置信息如下:
其中,roleArn
与oidcProviderArn
需要一起配置,配置后无需再配置roleName
。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-oss
spec:
capacity:
storage: 5Gi
accessModes:
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
csi:
driver: ossplugin.csi.alibabacloud.com
volumeHandle: pv-oss # 需要和PV名字一致。
volumeAttributes:
bucket: "oss"
url: "oss-cn-hangzhou.aliyuncs.com"
otherOpts: "-o umask=022 -o max_stat_cache_size=0 -o allow_other"
authType: "rrsa"
oidcProviderArn: "<oidc-provider-arn>"
roleArn: "<role-arn>"
#roleName: "<role-name>" #配置roleArn和oidcProviderArn后,roleName失效。
serviceAccountName: "csi-fuse-<service-account-name>"
参数 | 说明 |
oidcProviderArn | OidcProviderArn需要在创建OIDC身份提供商后获取。更多信息,请参见管理OIDC身份提供商。 |
roleArn | RoleArn需要在创建可信实体为上述OIDC身份提供商的RAM角色后获取。更多信息,请参见使用OIDC进行角色SSO的示例。 |
serviceAccountName | 可选,ossfs容器所在的Pod使用ServiceAccount名称,需要预先创建。 配置为空时,使用CSI维护的默认ServiceAccount。 重要 ServiceAccount名称必须以csi-fuse-开头。 |
创建硬链接时返回错误Operation not supported或Operation not permitted
问题现象
创建硬链接时返回错误Operation not supported或Operation not permitted。
问题原因
OSS存储卷不支持硬链接操作,将返回Operation not supported错误。在早期的CSI版本中,硬链接操作返回的报错为Operation not permitted。
解决方案
改造业务,在使用OSS存储卷时,应避免硬链接操作。若您的业务必须使用硬链接操作,建议您更换存储。
OSS静态卷卸载失败,Pod一直处于Terminating状态
问题现象
OSS静态卷卸载失败,Pod一直处于Terminating状态。
问题原因
Pod删除时卡在Terminating的原因较多,可先借助kubelet日志定位。导致OSS存储卷卸载失败的常见原因如下:
原因1:对应挂载点在节点上被占用,CSI存储插件无法正常unmount挂载点。
原因2:PV中指定的OSS bucket或目录(path)被删除,无法判断当前挂载点状态。
解决方案
原因1解决方案
在集群中执行以下命令,获取Pod的UID。
替换以下<ns-name>和<pod-name>为您的业务实际值。
kubectl -n <ns-name> get pod <pod-name> -ogo-template --template='{{.metadata.uid}}'
预期输出:
5fe0408b-e34a-497f-a302-f77049****
登录Terminating的Pod所在的节点。
在节点上执行以下命令,查询当前是否有进程占用挂载点。
lsof /var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~csi/<pv-name>/mount/
若有输出,请确认并清理相关进程。
原因2解决方案
登录OSS管理控制台。
查询Bucket或目录是否被删除,若您使用了subpath方式挂载OSS存储卷,还需要确认subpath挂载目录是否被删除。
确认上由于删除目录导致的卸载失败,请参考以下操作处理。
在集群中执行以下命令,获取Pod的UID。
替换以下<ns-name>和<pod-name>为您的业务实际值。
kubectl -n <ns-name> get pod <pod-name> -ogo-template --template='{{.metadata.uid}}'
预期输出:
5fe0408b-e34a-497f-a302-f77049****
登录Terminating的Pod所在的节点,在节点上执行以下命令,查询Pod相关的挂载点。
mount | grep <pod-uid> | grep fuse.ossfs
预期输出:
ossfs on /var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~csi/<pv-name>/mount type fuse.ossfs (ro,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other) ossfs on /var/lib/kubelet/pods/<pod-uid>/volume-subpaths/<pv-name>/<container-name>/0 type fuse.ossfs (ro,relatime,user_id=0,group_id=0,allow_other)
其中
ossfs on
与type
之间路径为节点上的实际挂载点。手动umount挂载点。
umount /var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~csi/<pv-name>/mount umount /var/lib/kubelet/pods/<pod-uid>/volume-subpaths/<pv-name>/<container-name>/0
等待kubelet重试时正常回收,或者直接通过
--force
删除Pod。
其他卸载失败问题,请提交工单咨询。
控制台检测长期卡住,或失败无信息透出,或显示unknown error
问题现象
检测长期卡住,或失败无信息透出,或显示unknown error。
问题原因
若检测长期卡在进行中状态,基本判断为网络原因。对于其他未知错误,您可以通过查询日志,或手动通过ossutil进行原因定位。
解决方案
您可以通过日志和ossutil工具定位具体问题。
通过日志定位具体问题
执行以下命令,找到执行检测任务的Pod。
osssecret-namespace
:保密字典所在命名空间。pv-name
:PV的名称。
kubectl -n <osssecret-namespace> get pod | grep <pv-name>-check
预期输出:
<pv-name>-check-xxxxx
执行以下命令,查询失败原因。
kubectl -n <osssecret-namespace> logs -f <pv-name>-check-xxxxx
预期输出:
check ossutil endpoint: oss-<region-id>-internal.aliyuncs.com bucket: <bucket-name> path: <path> Error: oss: service returned error: StatusCode=403, ErrorCode=InvalidAccessKeyId, ErrorMessage="The OSS Access Key Id you provided does not exist in our records.", RequestId=65267325110A0C3130B7071C, Ec=0002-00000901, Bucket=<bucket-name>, Object=<path>
通过ossutil工具定位具体问题
如果您的相关Pod已被删除,您可以通过ossutil工具复现检测,定位具体问题。
OSS访问检测通过stat(查看Bucket和Object信息)实现,您可以在集群内任意节点上安装ossutil并执行以下指令复现。
ossutil -e "<endpoint>" -i "<accessKeyID>" -k "<accessKeySecret>" stat oss://"<bucket><path>"
参数 | 说明 |
endpoint |
|
accessKeyID | 保密字典中的AccessKeyID。 |
accessKeySecret | 保密字典中的AccessKeySecret。 |
bucket | Bucket ID。 |
path | 路径。填写的路径需要以 |
例如,如果您在创建如下的存储卷的配置信息,则您需要执行的命令如下。
ossutil -e "oss-<region-id>-internal.aliyuncs.com" -i "<accessKeyID>" -k "<accessKeySecret>" stat oss://"cnfs-oss-xxx-xxx/xx/"
网络问题:connection timed out
问题现象
错误信息为connection timed out。
问题原因
访问OSS Bucket超时,可能的超时原因如下
选择的Bucket与集群不在同一地域时,选择私有域名,导致访问不通。
选择公有域名,但集群无公网访问能力,导致访问不通。
解决方案
重建PV,并选择公有域名。
若您的集群与Bucket在同一地域,可重建PV并选择私有域名。否则,您可以检查安全组、网络等相关配置,修复后再重建PV。
权限问题:错误码StatusCode=403
问题现象
错误信息为service returned error: StatusCode=403
。
问题原因
挂载OSS存储卷时,AccessKey至少需要Bucket的读权限,当前权限不足。
StatusCode=403, ErrorCode=AccessDenied, ErrorMessage="You do not have read acl permission on this object."
,提供的AccessKey权限不足。StatusCode=403, ErrorCode=InvalidAccessKeyId, ErrorMessage="The OSS Access Key Id you provided does not exist in our records."
,提供的AccessKey不存在。StatusCode=403, ErrorCode=SignatureDoesNotMatch, ErrorMessage="The request signature we calculated does not match the signature you provided. Check your key and signing method."
,提供的AccessKey可能存在拼写错误。
解决方案
确认AccessKey已存在、无拼写错误,且至少拥有对该Bucket的读权限。
Bucket或目录对象不存在:错误码StatusCode=404
问题现象
错误信息为service returned error: StatusCode=404
。
问题原因
OSS静态存储卷不支持挂载到不存在的Bucket或子目录中,需要预先手动创建Bucket。
StatusCode=404, ErrorCode=NoSuchBucket, ErrorMessage="The specified bucket does not exist."
,选择的Bucket不存在。StatusCode=404, ErrorCode=NoSuchKey, ErrorMessage="The specified key does not exist."
,选择的子目录对象不存在。重要OSS控制台中可见的子路径在Server端不一定真实存在,以ossutil或OSS API的返回为准。例如,直接创建
/a/b/c/
目录,/a/b/c/
为单独的目录对象,而/a/
或/a/b/
目录对象实际并不存在。同理,如上传/a/*
文件,/a/b
、/a/c
等为单独的文件对象,/a/
目录对象不存在。
解决方案
通过ossutil、SDK、OSS控制台等工具手动创建缺失的Bucket或子目录,然后重建PV。
其他OSS返回错误码
问题现象
错误信息为service returned error: StatusCode=xxx
。
问题原因
当访问OSS出现错误时,OSS会返回StatusCode、ErrorCode、ErrorMessage等信息,方便您定位并解决问题。
解决方案
当您遇到其他OSS的StatusCode或ErrorCode时,请参见HTTP错误码解决。
ossfs容器化后如何开启独享挂载模式?
问题现象
同一节点上挂载了相同OSS存储卷的多个Pod共享挂载点。
问题原因
ossfs容器化前,默认使用独享方式挂载,即每个挂载OSS存储卷的Pod,都将在对应节点上为该存储卷拉起ossfs进程。不同ossfs进程对应的挂载点之间完全独立,即对于挂载了同一OSS存储卷的不同Pod在读写时互不影响。
ossfs容器化后,ossfs进程将以容器的方式运行在集群的Pod中,具体为kube-system
或ack-csi-fuse
命名空间的csi-fuse-ossfs-*
Pod。在多挂载的场景下,独享方式挂载将在集群中拉起大量Pod,进而导致弹性网卡不足等问题。因此,容器化后将默认使用共享方式挂载,即同一节点上挂载了相同OSS存储卷的多个Pod共享挂载点,均对应同一个csi-fuse-ossfs-*
Pod,实际由同一ossfs进程实现挂载。
解决方案
1.30.4及以上版本CSI不再支持开启独享挂载模式,如果您需要重启或变更ossfs的相关配置,可以参考共享挂载方式下,如何重启ossfs进程?如果您有其他ossfs独享挂载的需求,请提交工单。
如果您期望恢复到容器化前的独享挂载,请在创建OSS存储卷时增加useSharedPath
配置项,并将其设为"false"
。示例如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: oss-pv
spec:
accessModes:
- ReadOnlyMany
capacity:
storage: 5Gi
csi:
driver: ossplugin.csi.alibabacloud.com
nodePublishSecretRef:
name: oss-secret
namespace: default
volumeAttributes:
bucket: bucket-name
otherOpts: -o max_stat_cache_size=0 -o allow_other
url: oss-cn-zhangjiakou.aliyuncs.com
useSharedPath: "false"
volumeHandle: oss-pv
persistentVolumeReclaimPolicy: Delete
volumeMode: Filesystem
共享挂载方式下,如何重启ossfs进程?
问题现象
修改鉴权信息或ossfs版本后,已经在运行的ossfs进程无法自动变更。
问题原因
ossfs运行后无法变更鉴权信息等配置,变更配置后,需要重启ossfs进程(容器化版本后,即为
kube-system
或ack-csi-fuse
命名空间下的csi-fuse-ossfs-*
Pod)与对应的应用Pod,造成业务中断。因此,默认情况下CSI不会对已经运行的ossfs进行变更。正常使用流程中,ossfs的部署与删除均由CSI完成。手动删除ossfs进程所在的Pod,无法触发CSI的部署流程。
解决方案
重启ossfs进程的流程中需要重启挂载对应OSS存储卷的业务Pod,请谨慎操作。
若您使用的是非容器化的CSI版本,或开启了独享挂载,可以直接重启对应的应用Pod。容器化版本后,默认使用共享挂载方式,即每个节点上挂载同一OSS存储卷的所有应用Pod共用ossfs进程实现挂载。
确认当前FUSE Pod被哪些应用Pod使用。
执行以下命令,确认需要变更的
csi-fuse-ossfs-*
Pod。其中
<pv-name>
为PV名称,<node-name>
为节点名称。CSI版本小于1.30.4时,执行以下操作:
kubectl -n kube-system get pod -lcsi.alibabacloud.com/volume-id=<pv-name> -owide | grep <node-name>
CSI版本大于等于1.30.4时,执行以下操作
kubectl -n ack-csi-fuse get pod -lcsi.alibabacloud.com/volume-id=<pv-name> -owide | grep <node-name>
预期输出:
csi-fuse-ossfs-xxxx 1/1 Running 0 10d 192.168.128.244 cn-beijing.192.168.XX.XX <none> <none>
执行以下命令,确认正在挂载该OSS存储卷的所有Pod。
其中
<ns>
为命名空间名称,<pvc-name>
为PVC名称。kubectl -n <ns> describe pvc <pvc-name>
预期输出(包含User By):
Used By: oss-static-94849f647-4**** oss-static-94849f647-6**** oss-static-94849f647-h**** oss-static-94849f647-v**** oss-static-94849f647-x****
执行以下命令,获取通过
csi-fuse-ossfs-xxxx
挂载的Pod,即与csi-fuse-ossfs-xxxx运行在同一节点的Pod。kubectl -n <ns> get pod -owide | grep cn-beijing.192.168.XX.XX
预期输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES oss-static-94849f647-4**** 1/1 Running 0 10d 192.168.100.11 cn-beijing.192.168.100.3 <none> <none> oss-static-94849f647-6**** 1/1 Running 0 7m36s 192.168.100.18 cn-beijing.192.168.100.3 <none> <none>
重启业务与ossfs进程。
将应用Pod(上述示例中为oss-static-94849f647-4****和oss-static-94849f647-6****)通过
kubectl scale
等方式同时删除。在无应用Pod挂载时,csi-fuse-ossfs-xxxx
Pod将自动被回收;恢复副本数后,将使用PV的新配置重新挂载,由CSI创建新的csi-fuse-ossfs-yyyy
Pod。如果无法保证这些Pod能同时被删除(如删除Deployment, StatefulSet, DaemonSet管理的Pod均会立即触发重启),或Pod能容忍OSS读写失败:
CSI版本小于1.30.4时,您可以直接删除
csi-fuse-ossfs-xxxx
Pod,此时应用Pod内读写OSS将返回disconnected error
。CSI版本大于等于1.30.4时,您可以执行以下操作:
kubectl get volumeattachment | grep <pv-name> | grep cn-beijing.192.168.XX.XX
预期输出:
csi-bd463c719189f858c2394608da7feb5af8f181704b77a46bbc219b********** ossplugin.csi.alibabacloud.com <pv-name> cn-beijing.192.168.XX.XX true 12m
直接删除该VolumeAttachment,此时应用Pod内读写OSS将返回
disconnected error
。
然后,逐个重启业务Pod,重启后的Pod将通过CSI新建的
csi-fuse-ossfs-yyyy
Pod恢复OSS读写。
如何查看通过OSS存储卷访问OSS的记录?
调用OSS的操作记录统一在OSS管理控制台查看,且要求已开通OSS的日志查询功能。关于开通日志查询的操作,请参见开通实时日志查询。
登录OSS管理控制台。
单击Bucket 列表,然后单击目标Bucket名称。
在左侧导航栏,选择
。在实时查询页签下,根据查询语法和分析语法,输入查询和分析语句,对OSS日志进行分析。您可以通过user_agent和client_ip字段定位日志是否来源于ACK。
定位由ACK发送的OSS操作请求时,您需要选择user_agent字段,展开后看到user_agent里包含ossfs的都可以选择。
重要user-agent字段的取值与ossfs版本有关,ossfs版本不同,user-agent字段的值也不一样,但均以
aliyun-sdk-http/1.0()/ossfs
开头。如果您在ECS上也通过ossfs挂载,相关日志也会被耦合到这里。
如需定位到某个ECS实例或集群,您还可以选择client_ip字段,然后选择对应的IP。
结合以上两个字段选择,查询到的日志示例如下图所示。
日志查询部分字段说明
字段 | 说明 |
operation | 对OSS操作的类型。例如GetObject、GetBucketStat等。更多信息,请参见API概览。 |
object | 对象名称,OSS中的目录、文件。 |
request_id | 请求的唯一标识,如果有请求ID,您可以精确查询某个请求。 |
http_status、error_code | 针对请求结果的查询。更多信息,请参见HTTP错误码。 |
使用subpath或subpathExpr方式挂载OSS存储卷异常
问题现象
使用subpath或subpathExpr方式挂载OSS存储卷时,出现以下异常:
挂载失败:挂载OSS存储卷的Pod创建后,一直处在CreateContainerConfigError状态,并且出现如下类似Event。
Warning Failed 10s (x8 over 97s) kubelet Error: failed to create subPath directory for volumeMount "pvc-oss" of container "nginx"
读写异常:挂载OSS存储卷进行OSS读写操作时,出现权限不足的报错提示
Operation not permitted
或Permission denied
。卸载失败:删除挂载了OSS存储卷的Pod时,一直处在Terminating状态。
问题原因
为方便阐述原因及解决方案,假设:
PV的相关配置为:
...
volumeAttributes:
bucket: bucket-name
path: /path
...
Pod的相关配置为:
...
volumeMounts:
- mountPath: /path/in/container
name: oss-pvc
subPath: subpath/in/oss
...
则OSS服务端subpath挂载目录为Bucket中的/path/subpath/in/oss/
。
原因1:OSS服务端不存在挂载目录
/path/subpath/in/oss/
,且OSS存储卷使用的用户或角色未被授权PutObject权限(例如只读场景中仅配置了OSS ReadOnly权限)。kubelet尝试在OSS服务端创建
/path/subpath/in/oss/
目录时因权限不足失败。原因2:非root用户运行的业务容器没有
/path/subpath/in/oss/
目录下文件的权限(默认为640)。subpath方式挂载OSS存储卷时,ossfs在OSS服务端实际的挂载目录为PV中定义的path目录,即上述示例中的/path
,而非/path/subpath/in/oss/
。配置allow_other或mp_umask挂载项仅对/path
目录生效,/path/subpath/in/oss/
目录作为子目录仍默认为640。原因3:OSS服务端中
/path/subpath/in/oss/
挂载目录被删除,阻塞kubelet回收subpath路径,导致卸载失败。
解决方案
原因1解决方案:
在OSS服务端预先创建
/path/subpath/in/oss/
目录,提供kubelet挂载subpath路径。若需要创建的目录较多(例如通过subpathExpr方式挂载OSS存储卷),无法全部预先创建时,可为OSS存储卷使用的用户或角色增加putObject权限授权。
原因2解决方案:通过umask配置项修改子目录默认权限,例如-o umask=000
将默认权限修改为777。
原因3解决方案:请参见OSS静态卷卸载失败,Pod一直处于Terminating状态中的原因2解决方案。
OSS存储卷的容量配置是否生效?实际存储超出此配置时是否需要扩容存储卷?
OSS本身不限制Bucket或子路径的容量,也未提供容量限额功能。因此pv.spec.capacity
与pvc.spec.resources.requests.storage
配置均不起作用。您只需保证需要绑定PV、PVC配置的容量相等即可。
实际存储超出此配置时,不影响正常使用,也无需扩容存储卷。