spring-boot - 从运行 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 配置。我不知道对不对。
所以我想知道的是:
如果这是某种防火墙规则阻止从我的 Pod 到“外部”的调用(这很奇怪,因为它们在同一个网络上运行,或者至少我是这么认为的)。
如果是因为我定义的网关,那就是没有启用这个 Pod
或者,如果我需要使用一些自定义 HTTP 配置创建存储对象,可以在此参考中看到: https ://googleapis.github.io/google-cloud-java/google-cloud-clients/apidocs/com/google/ cloud/storage/StorageOptions.html#getDefaultHttpTransportOptions--
我对 HTTPS 和安全连接的了解不是很好,所以也许我在这方面缺乏概念让我看不到明显的东西。
如果有人对可能导致这种情况的原因有任何想法,我将不胜感激。
解决方案
解决了。真的是 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/
推荐阅读
- python - 如何根据python脚本中的标签值($VARIABLE)“获取”某些环境变量
- vulkan - 如何获得并行 GPU 像素渲染?用于体素光线追踪
- python - Django 在特定 URL 上提供服务 - 相对 URL 已损坏
- sas - 有兴趣了解 SAS 的新知识
- java - 如何使用 for 循环修复未对齐的数组列表显示
- javascript - 自定义函数子字符串 Apps 脚本
- javascript - 循环遍历包含 Array 作为值的对象并组合所有值,对它们进行排序,重新索引和更新值
- sql - 用于连接多对多表的 Linq 查询
- macos - 错误 无法构建 iOS 项目。我们运行了“xcodebuild”命令,但它以错误代码 65 退出。在 Mac 上
- linux-device-driver - 在Linux中如何在另一个驱动中使用一个驱动