GCS与GKE,写入GCS存储桶的权限不足403。

7

目前我正在尝试将文件写入Google Cloud Storage存储桶。为此,我使用了django-storages软件包。

我已经部署了我的代码,并通过Kubernetes kubectl实用程序进入运行的容器来检查GCS存储桶的工作情况。

$ kubectl exec -it foo-pod -c foo-container --namespace=testing python manage.py shell

我可以读取桶里的数据,但如果我尝试向桶写入数据,它将显示以下回溯信息。

>>> from django.core.files.storage import default_storage
>>> f = default_storage.open('storage_test', 'w')
>>> f.write('hi')
2
>>> f.close()
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/google/cloud/storage/blob.py", line 946, in upload_from_file
    client, file_obj, content_type, size, num_retries)
  File "/usr/local/lib/python3.6/site-packages/google/cloud/storage/blob.py", line 867, in _do_upload
    client, stream, content_type, size, num_retries)
  File "/usr/local/lib/python3.6/site-packages/google/cloud/storage/blob.py", line 700, in _do_multipart_upload
    transport, data, object_metadata, content_type)
  File "/usr/local/lib/python3.6/site-packages/google/resumable_media/requests/upload.py", line 98, in transmit
    self._process_response(result)
  File "/usr/local/lib/python3.6/site-packages/google/resumable_media/_upload.py", line 110, in _process_response
    response, (http_client.OK,), self._get_status_code)
  File "/usr/local/lib/python3.6/site-packages/google/resumable_media/_helpers.py", line 93, in require_status_code
    status_code, u'Expected one of', *status_codes)
google.resumable_media.common.InvalidResponse: ('Request failed with status code', 403, 'Expected one of', <HTTPStatus.OK: 200>)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/storages/backends/gcloud.py", line 75, in close
    self.blob.upload_from_file(self.file, content_type=self.mime_type)
  File "/usr/local/lib/python3.6/site-packages/google/cloud/storage/blob.py", line 949, in upload_from_file
    _raise_from_invalid_response(exc)
  File "/usr/local/lib/python3.6/site-packages/google/cloud/storage/blob.py", line 1735, in _raise_from_invalid_response
    raise exceptions.from_http_response(error.response)
google.api_core.exceptions.Forbidden: 403 POST https://www.googleapis.com/upload/storage/v1/b/foo.com/o?uploadType=multipart: Insufficient Permission
>>> default_storage.url('new docker')
'https://storage.googleapis.com/foo.appspot.com/new%20docker'
>>>

看起来这完全与存储桶权限有关。因此,我已经为Google Cloud Build服务帐户分配了存储管理和存储对象创建者角色(通过存储桶 -> 管理权限),但仍然显示相同的错误。


在集群配置中有一个存储RO范围。这是原因吗? - Avinash Raj
1个回答

20

造成这种情况的可能原因是您尚未为集群分配正确的作用域。如果是这种情况,则集群中的节点将没有所需的授权/权限来写入Google Cloud Storage,这可能会解释您看到的403错误。

如果在创建集群时未设置范围,则会分配默认范围,该范围仅提供Cloud Storage的读取权限。

为了使用Cloud SDK检查集群的当前范围,您可以尝试从Cloud Shell运行“describe”命令,例如:

gcloud container clusters describe CLUSTER-NAME --zone ZONE

输出结果中的oauthScopes部分包含当前分配给集群/节点的作用域。

默认只读的Cloud Storage作用域将显示:

https://www.googleapis.com/auth/devstorage.read_only
如果设置了云存储读/写权限范围,则输出会显示:
https://www.googleapis.com/auth/devstorage.read_write

可以在创建集群时使用--scope开关并跟随所需的范围标识符来设置范围。在您的情况下,这将是“storage-rw”。例如,您可以运行以下命令:

gcloud container clusters create CLUSTER-NAME --zone ZONE --scopes storage-rw

与您的服务帐户结合使用的storage-rw作用域应允许集群中的节点写入Cloud Storage。

或者,如果您不想重新创建集群,您可以创建一个新的节点池以获取新的所需范围,然后删除旧的节点池。有关如何实现此目的的信息,请参见是否需要重新创建Google Container Engine集群以修改API权限?接受的回答


目前我们有3个VM实例正在运行,这意味着我们必须在所有三个实例中添加作用域吗? - Avinash Raj
这篇关于 Google Cloud 平台的文章《在不影响服务的情况下更新 Google Container Engine VM 范围》对我很有帮助。我们无需创建新的集群,只需使用新范围创建节点即可。 - Avinash Raj
@Avinash Raj 很好的观点,我已经在我的帖子末尾添加了一些额外的信息来解决这个问题,感谢你指出。 - neilH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接