【问题标题】:Unable to access Google Cloud Storage from Google Kubernetes Engine using default service account and google cloud libraries无法使用默认服务帐户和谷歌云库从谷歌 Kubernetes 引擎访问谷歌云存储
【发布时间】:2019-07-16 11:24:49
【问题描述】:

我编写了一个应用程序,该应用程序具有使用 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)

此时我开始遇到导致应用程序关闭的致命错误。我在尝试检索存储桶的属性时遇到的错误是:

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 certificate signed by unknown authority”错误?从技术上讲,获取存储桶属性只是一个读取功能,我应该能够使用默认权限来完成它吗?如果有人有任何想法或曾经遇到过同样的问题,请给我一些帮助!谢谢!

【问题讨论】:

    标签: go google-api google-cloud-storage google-kubernetes-engine service-accounts


    【解决方案1】:

    所以我终于想通了,如果有人也遇到这个问题,就把它留在这里。这是我非常粗心的错误,但是在阅读了这个问题之后:

    Cannot exchange AccessToken from Google API inside Docker container

    我能够将其缩小到证书问题。这实际上是因为我没有正确安装 ca-certificate。因为我在我的 docker 文件中使用了多阶段构建,所以我放错了这行代码:

    RUN apk --no-cache add ca-certificates && update-ca-certificates
    

    正确放置后它起作用了!

    【讨论】:

      【解决方案2】:

      如果您使用默认集群服务帐户,则需要确保集群具有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

      如果不启用写入范围,无论凭据如何,您都无法写入存储桶。

      注意:您只能将访问令牌用于您在创建实例时指定的范围。例如,如果实例仅被授予 Google Cloud Storage 的 https://www.googleapis.com/auth/storage-full 范围,则它不能使用访问令牌向 BigQuery 发出请求。

      如果您想绕过范围,请为应用程序创建一个自定义服务帐户,下载 JWT 令牌并将这些凭据直接挂载到您的代码中。这是针对 Google API 的 recommended method to authenticate your application

      【讨论】:

      • 对不起,我没有把我的问题说清楚。我的意思是问,为什么我在使用默认权限时尝试获取存储桶属性时会收到错误消息?从技术上讲,获取存储桶属性只是一个读取功能,我应该能够使用默认权限来完成它吗?
      • 安装默认节点服务帐户时出现问题。令牌已过期或未正确安装到请求中。最佳做法是将您的凭据直接安装到呼叫应用程序中(请参阅我回答中的最后一个链接)
      • 感谢帕特里克的回复。我也尝试过推荐的身份验证方法,但不幸的是没有运气,得到了同样的错误:/我相信我的服务帐户安装正确,但我不确定令牌是否过期。有什么办法可以检查吗?比如也许我可以从我的图像中记录一些东西来查看服务帐户的令牌状态?
      • 我建议从服务帐户页面生成一个新令牌并使用它。
      • 我已经测试了在本地主机上运行它,它实际上没有任何问题。我能够获得我正在使用的服务帐户的名称。但是它仍然无法在 Google Kubernetes Engine 上运行。当我通过 gcloud 登录时,它可以在我的本地机器上运行是有道理的。现在我假设这意味着以某种方式在集群内关闭了身份验证,对吗?但那怎么可能呢?以及如何真正重置身份验证?
      猜你喜欢
      • 2014-10-30
      • 1970-01-01
      • 2019-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 1970-01-01
      相关资源
      最近更新 更多