我已经制作了一个SpringBoot应用程序,该应用程序可以通过Gloud Storage进行身份验证并对其执行操作。它可以在本地运行,但是当我将其作为Pod部署到我的GKE上时,会遇到一些错误。
我有一个VPC环境,其中有一个Google Cloud Storage和一个Kubernetes集群,它将运行一些Spring Boot应用程序,该应用程序通过com.google.cloud.storage库对其执行操作。
它为群集启用了Istio,还启用了具有安全HTTPS的网关资源,该资源针对此处定义的入口负载均衡器:
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上尝试相同操作时,每当我尝试与存储进行一些交互时,它都会返回一些错误,例如:
[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--
我对HTTP和安全连接的了解不是很好,所以也许我在这方面缺乏概念使我无法看到明显的东西。
如果有人对可能导致这种情况的任何想法,我将不胜感激。
答案 0 :(得分:1)
解决了。真的是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/
答案 1 :(得分:0)
编辑
我已经通过使用以下命令在我正在部署应用程序的名称空间上禁用了Istio Injection:
kubectl label namespace default istio-injection=disabled --overwrite
然后重新部署该应用程序,然后在该处尝试卷曲,效果很好。
我现在的疑问是:我虽然Istio仅在其网关层上进行拦截,但此消息保持不变,但这似乎行不通。显然他在我的应用程序不需要/不需要的请求上嵌入了一些SSL层。 因此,我需要更改应用程序以使其适合服务网格要求吗?