因此,我在Google Kubernetes Engine上具有群集节点,并且我进行了Spark提交以运行一些Spark作业。 (我没有完全使用spark-submit,我使用java代码启动了提交,但实际上它们调用的是同一Scala类,即SparkSubmit.class)。
在我的情况下,我可以使用gcloud命令在笔记本电脑上连接两个群集。
例如
gcloud container clusters get-credentials cluster-1
gcloud container clusters get-credentials cluster-2
当我连接到cluster-1,并且spark-submit提交到cluster-1时,它可以工作。但是,当我运行第二个gcloud命令并仍提交到cluster-1时,它将无法工作,并且出现以下堆栈跟踪(删节版)
io.fabric8.kubernetes.client.KubernetesClientException: Failed to start websocket
at io.fabric8.kubernetes.client.dsl.internal.WatchConnectionManager$2.onFailure(WatchConnectionManager.java:194)
at okhttp3.internal.ws.RealWebSocket.failWebSocket(RealWebSocket.java:543)
at okhttp3.internal.ws.RealWebSocket$2.onFailure(RealWebSocket.java:208)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:148)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
我已经搜索了一段时间没有成功。主要问题可能是在启动spark-submit时,它在本地计算机上搜索与Kubernetes有关的某种凭证,并且前两个gcloud命令更改的上下文将其弄乱了。
我很好奇,当我们进行火花提交时,远程K8s服务器如何确切知道我是谁?所有这一切涉及的身份验证过程是什么?
谢谢。
答案 0 :(得分:0)
PKIX path building failed
错误表示Java试图打开SSL连接,但无法找到用于验证服务器提供的证书的证书链(路径)。
您从中运行的代码不信任群集提供的证书。群集可能正在使用自签名证书。
从命令行运行,Java在位于jre / lib / security / cacerts的信任库中查找链。作为较大环境(Tomcat,Glassfish等)的一部分运行,它将使用该环境的证书信任库。
由于您是手动启动spark_submit的,因此可能缺少指定在何处查找密钥库(服务器证书和私钥)和信任库(CA证书)的选项。这些通常指定为:
-Djavax.net.ssl.trustStore=/somepath/truststore.jks
-Djavax.net.ssl.keyStore=/somepath/keystore.jks
如果您在Java 9+上运行,则还需要指定StoreType:
-Djavax.net.ssl.keyStoreType=<TYPE>
-Djavax.net.ssl.trustStoreType=<TYPE>
在Java 8中,密钥库始终为JKS。从Java 9开始,它们也可以是PKCS12。
对于自签名密钥,可以将其从密钥库中导出并将其作为受信任证书导入到信任库中。有几个站点提供有关如何执行此操作的说明。我发现Jakob Jenkov's site可读性强。
答案 1 :(得分:0)
如果要查看gcloud container clusters get-credentials cluster-1
命令的内容,可以再次从头开始,查看~/.kube/config
的内容
rm -rf ~/.kube
gcloud container clusters get-credentials cluster-1
cat ~/.kube/config
gcloud container clusters get-credentials cluster-2
cat ~/.kube/config
某些内容可能不匹配或冲突。或用户/上下文。也许您拥有两个群集的凭据,但是您正在使用cluster-1
的上下文来访问cluster-2
$ kubectl config get-contexts
$ kubectl config get-clusters
~/.kube/config
文件的结构应如下所示:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: <redacted> or file
server: https://<IP>:6443
name: cluster-1
- cluster:
certificate-authority: <redacted> or file
server: https://<IP>:8443
name: cluster-2
contexts:
- context:
cluster: cluster-1
user: youruser
name: access-to-cluster-1
- context:
cluster: cluster-2
user: youruser
name: access-to-cluster-2
current-context: access-to-cluster-1
kind: Config
preferences: {}
users:
- name: ....
user:
...
- name: ....
user:
...
在代码中,它似乎使用了io.fabric8.kubernetes.client.KubernetesClient
库。例如,在此文件KubernetesDriverBuilder.scala