1

所以我在 Google Kubernetes Engine 上有集群节点,我做 spark-submit 来运行一些 spark 作业。(我没有完全使用 spark-submit,我使用 java 代码启动提交,但它们本质上调用的是同一个 Scala 类,即 SparkSubmit.class)

就我而言,我有两个集群可以使用 gcloud 命令在我的笔记本电脑上连接。

例如

  1. gcloud container clusters get-credentials cluster-1
  2. 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 命令更改的上下文把它搞砸了。

我只是好奇,当我们进行 spark-submit 时,远程 K8s 服务器究竟是如何知道我是谁的?这一切涉及的身份验证过程是什么?

先感谢您。

4

2 回答 2

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

于 2018-11-16T22:56:50.457 回答
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 的网站可读性很强。

于 2018-11-16T22:17:14.937 回答