GKE 上的 Google Cloud PubSub:尝试检索凭据时出现 FileNotFoundException

Posted

技术标签:

【中文标题】GKE 上的 Google Cloud PubSub:尝试检索凭据时出现 FileNotFoundException【英文标题】:Google Cloud PubSub on GKE : FileNotFoundException while attempting to retrieve the credentials 【发布时间】:2020-03-18 16:50:50 【问题描述】:

我正在开发一个使用 Spring Google PubSub 库 (spring-cloud-gcp-starter-pubsub 1.1.4) 的 Spring 应用程序,该库将部署在我的 GKE 集群中。

正如this page 中提到的,我创建了一个服务帐户,该帐户对 PubSub 功能具有适当的权限。

我用这个命令创建了秘密:

kubectl create secret generic pub-sub-key --from-file ~/Documents/kubernetes/gke/service\ accounts/pub-sub/D-Vine-d36104130624.json

这是用于部署我的应用程序的 yaml 文件:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: d-vine-machine-dev
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: d-vine-machine-dev
        version: dev
    spec:
      volumes:
        - name: pub-sub-service-account
          secret:
            secretName: pub-sub-key
      containers:
        - name: d-vine-machine
          image: gcr.io/........:0.0.47
          imagePullPolicy: Always
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: dev
            - name: GOOGLE_APPLICATION_CREDENTIALS
              value: /var/secrets/google/D-Vine-d36104130624.json
          volumeMounts:
            - name: pub-sub-service-account
              mountPath: /var/secrets/google
          ports:
            - containerPort: 8080

但我的容器最终找不到文件:

Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/var/secrets/google/D-Vine-d36104130624.json] 
at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:158) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] 
at org.springframework.cloud.gcp.core.DefaultCredentialsProvider.<init>(DefaultCredentialsProvider.java:94) ~[spring-cloud-gcp-core-1.1.0.RC2.jar:1.1.0.RC2] 
at org.springframework.cloud.gcp.autoconfigure.core.GcpContextAutoConfiguration.googleCredentials(GcpContextAutoConfiguration.java:57) ~[spring-cloud-gcp-autoconfigure-1.1.0.RC2.jar:1.1.0.RC2] 
at org.springframework.cloud.gcp.autoconfigure.core.GcpContextAutoConfiguration$$EnhancerBySpringCGLIB$$16f5032c.CGLIB$googleCredentials$0(<generated>) ~[spring-cloud-gcp-autoconfigure-1.1.0.RC2.jar:1.1.0.RC2] 
at org.springframework.cloud.gcp.autoconfigure.core.GcpContextAutoConfiguration$$EnhancerBySpringCGLIB$$16f5032c$$FastClassBySpringCGLIB$$ce730653.invoke(<generated>) ~[spring-cloud-gcp-autoconfigure-1.1.0.RC2.jar:1.1.0.RC2] 
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.3.RELEASE.jar:5.1.3.RELEASE] 
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.4.RELEASE.jar:5.1.4.RELEASE] 
at org.springframework.cloud.gcp.autoconfigure.core.GcpContextAutoConfiguration$$EnhancerBySpringCGLIB$$16f5032c.googleCredentials(<generated>) ~[spring-cloud-gcp-autoconfigure-1.1.0.RC2.jar:1.1.0.RC2] 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_232] 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_232] 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_232] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_232] 
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]

出于好奇,我修改了我的 Go 应用程序部署,只是为了检查文件是否被正确检索。它是......所以它似乎与 Spring 应用程序而不是部署有关。

如果有什么不同的话,我的图像是使用 jib maven 插件构建的。

有没有人遇到过这个问题(或发现任何错误)?

【问题讨论】:

【参考方案1】:

你的程序正在寻找/var/run/secret/google/D-Vine-d36104130624.json

但你正在将秘密安装在:/var/secrets/google

由于此堆栈跟踪位于spring code 中,与基于属性的获取相关,我怀疑您的 spring 配置中可能有一些不正确的地方。您的spring configuration 是否可以将/var/run 位置列为spring.cloud.gcp.credentials.location? (如果不是,spring 应该回退到GOOGLE_APPLICAITON_CREDENTIALS 位置——但这不会导致这个堆栈跟踪)。

假设是这种情况,您应该更新 spring 配置以指向 /var/secrets 位置(或者,按照文档的建议,省略它以回退到环境变量)。

或者,我怀疑将安装点(并更改环境变量)移动到 /var/run 位置可以解决此问题。

【讨论】:

感谢您的回复。问我的问题时,我犯了一个复制粘贴错误。我放的日志来自另一个测试。基于环境变量GOOGLE_APPLICAITON_CREDENTIALS,安装位置/var/sercrets 与Spring 正在寻找的位置相同。我的集群中运行了另一个应用程序(用 Go 编码),它使用完全相同的配置,但最终可以正常工作。我尝试将位置移动到/var/run,但仍然遇到同样的异常。 你能分享你用来创建秘密的确切命令吗?您可能还想尝试attaching to that container directly 并确保文件实际上正确放置。 我之所以询问secret命令是因为你链接的页面上的secret命令会导致创建/var/secrets/google/key.json而不是/var/secrets/google/D-Vine-d36104130624.json 我用来创建秘密的命令是:kubectl create secret generic pub-sub-key --from-file ~/Documents/kubernetes/gke/service\ accounts/pub-sub/D-Vine-d36104130624.json 与我链接的页面的不同之处在于他们使用此命令重命名命令中的文件(我没有):@ 987654337@ 出于好奇,我修改了我的 Go 应用程序部署,只是为了检查文件是否被正确检索。它是......所以它似乎与 Spring 应用程序而不是部署有关。

以上是关于GKE 上的 Google Cloud PubSub:尝试检索凭据时出现 FileNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

Google Stackdriver Logging无法在Google Cloud Shell和GKE中使用

在 GKE 中,typeorm 无法连接到 Google Cloud SQL 代理

Google Cloud 线上课堂 | Kubernetes 网络演进,GKE Gateway API 打开新篇章

Google Cloud 线上课堂 | Kubernetes 网络演进,GKE Gateway API 打开新篇章

GKE 自动部署具有不同映像的多个部署/服务

使用 Cloud Proxy 的 Google Cloud Composer 和 MS SQL