gcsfuse Input/Output 错误

gcsfuse Input/Output error

当我尝试在安装在 linux 上的 google 云存储桶中创建目录或文件时出现 Input/Output 错误(Ubuntu 15.10 ) 目录。

我完成的步骤:

我错过了什么吗?我想要做的是能够 ftp 文件到服务器并将它们存储在 google 存储桶而不是本地存储中。

更新 我修改了命令以获取一些调试信息:

gcsfuse --implicit-dirs --foreground --debug_gcs --debug_fuse backup01-bucket /mnt/backups

然后 运行 mkdir /mnt/backups/test 作为 transfer 用户。

下面的错误信息出来了:

fuse_debug: Op 0x00000060        connection.go:395] <- GetInodeAttributes (inode 1)
fuse_debug: Op 0x00000060        connection.go:474] -> OK
fuse_debug: Op 0x00000061        connection.go:395] <- LookUpInode (parent 1, name "test")
gcs: Req             0x3a: <- StatObject("test/")
gcs: Req             0x3b: <- ListObjects()
gcs: Req             0x3c: <- StatObject("test")
gcs: Req             0x3c: -> StatObject("test") (53.375107ms): gcs.NotFoundError: googleapi: Error 404: Not Found, notFound
gcs: Req             0x3b: -> ListObjects() (59.061271ms): OK
gcs: Req             0x3a: -> StatObject("test/") (71.666112ms): gcs.NotFoundError: googleapi: Error 404: Not Found, notFound
fuse_debug: Op 0x00000061        connection.go:476] -> Error: "no such file or directory"
fuse_debug: Op 0x00000062        connection.go:395] <- MkDir
gcs: Req             0x3d: <- CreateObject("test/")
gcs: Req             0x3d: -> CreateObject("test/") (22.090155ms): googleapi: Error 403: Insufficient Permission, insufficientPermissions
fuse_debug: Op 0x00000062        connection.go:476] -> Error: "CreateChildDir: googleapi: Error 403: Insufficient Permission, insufficientPermissions"
fuse: 2016/04/04 06:51:02.922866 *fuseops.MkDirOp error: CreateChildDir: googleapi: Error 403: Insufficient Permission, insufficientPermissions
2016/04/04 06:51:08.378100 Starting a garbage collection run.
gcs: Req             0x3e: <- ListObjects()
gcs: Req             0x3e: -> ListObjects() (54.901164ms): OK
2016/04/04 06:51:08.433405 Garbage collection succeeded after deleted 0 objects in 55.248203ms.

注意:如果我在 Web 控制台中创建一个目录,我可以看到该目录。

从调试输出中的 Insufficient Permission 错误看来,gcsfuse 对您的存储桶没有足够的权限。可能它具有只读访问权限。

请务必阅读 gcsfuse 的 credentials 文档。特别是,如果您在 GCE VM 上使用服务帐户,请确保使用 storage-full 访问范围设置 VM。

您的问题确实源于权限不足,但您不需要销毁并重新创建具有不同作用域的 VM 来解决此问题。这是另一种更适合生产系统的方法:

  1. 创建服务帐户
  2. 为服务帐户创建密钥,并下载 JSON 文件
  3. 为服务帐户授予适当的角色
  4. 向存储桶上的服务帐户授予适当的权限
  5. 将服务帐户的 JSON 凭据上传到 VM

最后,定义一个环境变量,其中包含从命令行调用 gcsfuse 时服务帐户凭据的路径:

GOOGLE_APPLICATION_CREDENTIALS=/root/credentials/service_credential_file.json gcsfuse bucket_name /my/mount/point

使用 key_file 选项在 fstab 中完成同样的事情。 gcsfuse credentials documentation 中记录了这两个选项。 (编辑:此选项已记录在案,但对我不起作用。)

有趣的是,您需要使用环境变量或 key_file 选项,即使您已使用以下方法在 VM 上配置服务帐户:

gcloud auth activate-service-account --key-file /root/credentials/service_credential_file.json

出于某种原因,gcsfuse 忽略了活动的凭据帐户。

在创建 VM 时使用 storage-full 范围具有安全性和稳定性影响,因为它允许 VM 对属于同一项目的每个存储桶具有完全访问权限。您的文件存储服务器是否真的能够覆盖一个日志存储桶中的日志,或者读取另一个存储桶中的数据库备份?

此问题是由于缺少凭据文件造成的。

转到 https://cloud.google.com/docs/authentication/production

正在创建服务帐户

  • 创建账号后你会得到一个json文件。
  • 在 VM 实例上上传您的 json。
  • 在/etc/fstab中输入以下内容。

    {{gcp bucket name}} {{mount path}} gcsfuse rw,noauto,user,key_file={{/path/to/key.json}}

    如果你已经挂载了请先卸载。

  • $ 挂载 -a

关注这个link

https://github.com/GoogleCloudPlatform/gcsfuse/blob/master/docs/mounting.md#credentials

如果您在该存储桶中设置了一些 保留 policy/rules,也会出现此问题。 对我来说,当我尝试更新已安装文件夹中的任何文件时,我也遇到了相同的 input/output 错误,根本原因是我添加了保留策略以在 1 个月前不删除任何文件。

我时不时遇到这个问题,所以想分享一下我的发现:

我使用 minikube 进行开发,使用 GCP 进行生产。

我有以下 postStart 生命周期钩子:

lifecycle:
  postStart:
    exec:
      command: ['gcsfuse', '-o', 'allow_other', 'bucket', 'path']

在本地,我在创建 pod 之前通过 运行 这两个命令配置了权限:

$ gcloud auth login
$ minikube addons enable gcp-auth

远程创建集群时,我启用了如下权限:

gcloud_create_cluster:
    gcloud container clusters create cluster \
    --scopes=...storage-full...

在开发过程中,我发现自己 updating/overriding 个文件每个 1 分钟。由于我的保留策略设置为 60 秒,因此在此期间不允许进行任何修改或删除。解决方案是简单地减少它。

这不是最终的解决方案,但希望其他人发现它有用。

请检查虚拟机的 Cloud API 访问范围设置,它需要配置为允许完全访问所有 Cloud APIs

它适用于 fstab 中的以下条目:

bucketName mountPath gcsfuse rw,allow_other,uid=1003,gid=1003,file_mode=777,dir_mode=777,implicit_dirs

注意:不要在存储桶名称中添加“gs://”。