我已经制作了一个SpringBoot应用程序,可以通过Gloud Storage进行身份验证并对其执行操作。它在本地工作,但是当我将它作为Pod部署在我的GKE上时,它会遇到一些错误。
我有一个VPC环境我有一个Google云存储,还有一个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配置。我不知道。
所以我想知道的是:
我对HTTP和安全连接的了解并不是很好,所以也许我在这方面缺乏概念让我无法看到明显的东西。
如果有人知道可能导致这种情况的原因,我将非常感激。
解决了它。这真的是Istio。
我不知道我们需要一个服务条目资源来定义网格外部的入站和出站调用。
因此,即使GCS与GEL属于同一个项目,它们也被视为完全分离的服务。
只需创建它,一切正常:
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/
编辑
我已经在部署应用程序的命名空间上禁用了Istio Injection,只需使用:
kubectl label namespace default istio-injection=disabled --overwrite
然后重新部署应用程序并在那里尝试卷曲,它工作正常。
我现在的疑问是:我虽然Istio只拦截它的网关层,然后消息保持不变,但这似乎不是什么工作。显然他在我的应用程序不执行/不需要的请求上嵌入了一些SSL层。那么我需要更改我的应用程序以适应服务网格要求吗?