【问题标题】:gcsfuse Input/Output errorgcsfuse 输入/输出错误
【发布时间】:2016-07-22 19:36:38
【问题描述】:

当我尝试在挂载在 linux (Ubuntu 15.10) 目录上的谷歌云存储桶中创建目录或文件时遇到输入/输出错误。

我已经完成的步骤:

  • 创建了一个名为 transfer 的用户
  • 创建了/mnt/backups 目录并运行chown -R transfer /mnt/backups
  • 作为用户转移,运行gcsfuse --implicit-dir backup01-bucket /mnt/backups。文件系统挂载成功
  • 运行mkdir test 并得到错误mkdir: cannot create directory test: Input/output error

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

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

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

然后以transfer 用户的身份运行mkdir /mnt/backups/test。

下面的bedug信息出来了:

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 控制台中创建一个目录,我可以正常查看该目录。

【问题讨论】:

  • 你能用--foreground 运行gcsfuse 并用日志输出修改你的问题吗?如果没有什么有用的,也可以试试--debug_gcs 和/或--debug_fuse。
  • 我已经用调试信息更新了这个问题。谢谢。

标签: linux gcsfuse


【解决方案1】:

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

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

【讨论】:

  • 谢谢!不幸的是,我不得不重新创建 VM 以启用 API。找不到将存储更改为在现有 VM 上读写的方法。
  • 是的,据我所知这是不可能改变的。
  • 好消息,从 2016 年 12 月 17 日起,可以更改 已停止 VM 的权限。见googlecloudplatform.uservoice.com/forums/302595-compute-engine/…。您还可以更改每个 API 的权限,例如继续拒绝对 BigQuery 的访问但对存储已满。
  • 我刚刚成功更改了已停止实例上的存储 API 访问以解决此问题。请注意,读/写是不够的。我必须授予“完整”存储访问权限才能通过 gcs fuse 进行写入。
  • 谢谢,我发现这个工作 GOOGLE_APPLICATION_CREDENTIALS=/root/mykey.json gcsfuse...
【解决方案2】:

您的问题确实源于权限不足,但您确实不需要需要销毁并重新创建具有不同范围的 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 中。 (编辑:此选项已记录在案,但对我不起作用。)

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

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

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

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

【讨论】:

  • 使用 --key-file 参数对我不起作用。文件系统正在安装,但该操作被卡住了。第一件事就像 GOOGLE_APPLICATION_CREDENTIALS=..
【解决方案3】:

这个问题是由于缺少凭证文件。

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

创建服务帐号

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

    {{gcp 存储桶名称}} {{挂载路径}} gcsfuse rw,noauto,user,key_file={{/path/to/key.json}}

    如果您已经挂载,请先卸载。

  • $ mount -a

点击此链接

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      我间歇性地遇到这个问题,所以想我会分享我的发现:

      我使用 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...
      

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 2017-08-31
          • 2016-04-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-26
          • 1970-01-01
          • 2018-03-10
          • 1970-01-01
          相关资源
          最近更新 更多