首页 > 解决方案 > 从运行 SpringBoot 应用程序的 Pod 连接到 GC 存储

问题描述

我制作了一个 SpringBoot 应用程序,它通过 Gloud Storage 进行身份验证并对其执行操作。它在本地工作,但是当我将它作为 Pod 部署在我的 GKE 上时,它会遇到一些错误。

我有一个 VPC 环境,我有一个谷歌云存储和一个 Kubernetes 集群,它将运行一些 Spring Boot 应用程序,这些应用程序通过 com.google.cloud.storage 库对其执行操作。

它为集群启用了 Istio,还启用了具有安全 HTTPS 的网关资源,该资源以此处定义的 Ingress 负载均衡器为目标:

https://istio.io/docs/tasks/traffic-management/secure-ingress/sds/

然后我的 pod 都通过这个网关的虚拟服务到达,它工作正常,因为它们上面有 Istio-Car 容器,然后我可以从外面到达它们。

因此,我已在 DEV 环境中配置此应用程序以从 ENV 值中获取凭据:

ENV GOOGLE_APPLICATION_CREDENTIALS="/app/service-account.json"

我知道它不安全,但只是想确保它是经过身份验证的。正如我通过日志看到的那样,确实如此。

当我的代码操作存储时,需要一个这种类型的对象,我这样做:

this.storage = StorageOptions.getDefaultInstance().getService();

在本地运行时它工作正常。但是,当我在 GKE 上的 Pod 容器内运行的 Api 上尝试相同的操作时,每当我尝试与 Storage 进行一些交互时,它都会返回一些错误,例如:

[2019-04-25T03:17:40.040Z] [org.apache.juli.logging.DirectJDKLog] [http-nio-8080-exec-1] [175] [ERROR] transactionId=d781f21a-b741-42f0-84e2-60d59b4e1f0a Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.google.cloud.storage.StorageException: Remote host closed connection during handshake] with root cause
java.io.EOFException: SSL peer shut down incorrectly
        at sun.security.ssl.InputRecord.read(InputRecord.java:505)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
...

Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:994)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:162)
        at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:142)
        at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:84)
        at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1011)
        at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:499)
        at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:432)
        at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:549)
        at com.google.cloud.storage.spi.v1.HttpStorageRpc.list(HttpStorageRpc.java:358)
        ... 65 common frames omitted
Caused by: java.io.EOFException: SSL peer shut down incorrectly
        at sun.security.ssl.InputRecord.read(InputRecord.java:505)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975)

...

看起来当我从 Pod 进行调用时,需要一些额外的 Https 配置。我不知道对不对。

所以我想知道的是:

我对 HTTPS 和安全连接的了解不是很好,所以也许我在这方面缺乏概念让我看不到明显的东西。

如果有人对可能导致这种情况的原因有任何想法,我将不胜感激。

标签: spring-bootsslkubernetescloudgoogle-cloud-storage

解决方案


解决了。真的是 Istio。

我不知道我们需要一个服务入口资源来定义网格外的入站和出站调用。

因此,即使 GCS 与 GKE 在同一个项目中,它们也受到了完全分离的服务的威胁。

只需创建它,一切正常:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  namespace: {{ cloud_app_namespace }}
  name: external-google-api
spec:
  hosts:
  - "www.googleapis.com"
  - "metadata.google.internal"
  - "storage.googleapis.com"
  location: MESH_EXTERNAL
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  - number: 80
    name: http
    protocol: HTTP

https://istio.io/docs/reference/config/networking/v1alpha3/service-entry/


推荐阅读