我编写了一个应用程序,它具有使用 go lang 通过 Google Kubernetes Engine 上传图像的功能。其他一切正常,但当我尝试将图像写入 Google Cloud Storage 时,我一直遇到问题。
这是我在 golang 中实际使用 google storage api 的代码:
func putImage(imageURL string, image multipart.File) bool {
fmt.Println("Putting into image location : " + imageURL)
contextBackground := context.Background()
storageClient, err := storage.NewClient(contextBackground)
if err != nil {
fmt.Println("No client.")
return false
}
bucket := storageClient.Bucket("mytestbucketname")
bucketWriter := bucket.Object(imageURL).NewWriter(contextBackground)
bucketWriter.ContentType = "image/jpg"
bucketWriter.CacheControl = "public, max-age=0"
size, err := io.Copy(bucketWriter, image)
if err != nil {
fmt.Println("failed to put image")
return false
}
fmt.Println(size)
fmt.Println("Successfully put image")
bucketWriter.Close()
return true
}
上面的函数总是返回 true 并且 size 总是大于 0。但是,当我检查桶时,它实际上并没有任何东西。所以我研究了一下,发现默认的服务账户只有对云存储的读取权限。这很奇怪,因为它应该返回 false 或 size 应该为 0 甚至输出权限被拒绝的错误。
官方的 cloud.google.com/go/storage API 说 Bucket() 函数返回一个实际上不执行任何网络操作的 BucketHandle,这对于为什么我没有收到权限被拒绝错误(?)是有道理的。因此,我决定检查我是否真的从客户端或存储桶中获取任何内容,只是为了查看读取权限是否有效。我添加了以下代码:
attr, err := bucket.Attrs(contextBackground)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println("bucket name : " + attr.Name)
此时我开始遇到关闭我的应用程序的 fatal error 。我在尝试检索存储桶的属性时遇到的错误是:
Get https://www.googleapis.com/storage/v1/b/mytestbucketname?alt=json&prettyPrint=false&projection=full: oauth2: cannot fetch token: Post https://oauth2.googleapis.com/token: x509: certificate signed by unknown authority
所以我想我需要为我的图像添加 ca 证书。但这对我来说听起来不合逻辑,因为如果我在 Google Kubernetes Engine 中运行我的图像并且它正在访问我的 Google Cloud Storage,鉴于它已经具有具有读取权限的默认服务帐户,为什么我需要证书?我创建了一个版本为 1.12.8-gke.10 的新集群,并确保禁用问题客户端证书,并确保我具有对存储的读取权限,但仍然遇到相同的错误。我将这一行添加到我的 docker 文件中,但仍然出现相同的错误:
RUN apk --no-cache add ca-certificates && update-ca-certificates
我已经研究了两天,现在我的想法已经用完了。我的问题是我在使用默认权限时尝试从 Kubernetes Engine 访问存储桶属性时一直给我“x.509 证书由未知授权机构签名”错误我做错了什么?从技术上讲,获取存储桶属性只是一个读取功能,我应该能够在默认权限下执行此操作,对吧?如果有人有任何想法或曾经遇到过同样的问题,请给我一些帮助!谢谢!
最佳答案
如果您使用的是默认集群服务帐户,则需要确保集群有 sufficient scopes to write to storage .通过 default ,GKE 集群只有读取范围,阻止对 GCS 存储桶的写入尝试。
gke-default:
https://www.googleapis.com/auth/devstorage.read_only
https://www.googleapis.com/auth/logging.write
https://www.googleapis.com/auth/monitoring
https://www.googleapis.com/auth/service.management.readonly
https://www.googleapis.com/auth/servicecontrol
https://www.googleapis.com/auth/trace.append
如果不启用写入范围,无论凭据如何,您都无法写入存储桶。
Note: You can use the access token only for scopes that you specified when you created the instance. For example, if the instance has been granted only the https://www.googleapis.com/auth/storage-full scope for Google Cloud Storage, then it can't use the access token to make a request to BigQuery.
如果您想绕过作用域,请为应用程序创建一个自定义服务帐户,下载 JWT token 并将这些凭据直接装载到您的代码中。这是 recommended method to authenticate your application针对 Google API
关于go - 无法使用默认服务帐户和谷歌云库从谷歌 Kubernetes 引擎访问谷歌云存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57056164/