在kubernetes上,我的spark worker pod正在尝试通过名称访问thrift pod

sxpgvts3  于 2023-06-21  发布在  Kubernetes
关注(0)|答案(1)|浏览(143)

好吧。从哪里开始?我正在将一组Spark应用程序部署到Kubernetes集群。我有一个Spark Master,2个Spark Workers,MariaDB,一个Hive Metastore(使用MariaDB -它不是一个完整的Hive安装-它只是Metastore),和一个Spark Thrift Server(与Hive Metastore对话并实现Hive API)。
因此,除了Thrift服务器作业的设置(thrift服务器pod上Spark sbin目录中的start-thriftserver.sh)之外,这个设置可以很好地工作。通过良好的工作,我说我可以在集群之外创建spark作业并将其提交给master,然后使用Web UI,我可以看到我的代码测试应用程序使用两个worker运行完成。
现在问题来了当您启动www.example.com时start-thriftserver.sh,它会将自己作为驱动程序提交给集群(我相信,这是正确的行为)。当我通过WebUI查看相关的spark作业时,我看到它有工人,他们反复孵化,然后很快退出。当我查看worker的stderr日志时,我看到每个worker都启动并尝试连接回spark. driver. port上的thrift服务器pod。我认为这是正确的行为。问题是连接失败,因为它说未知的主机异常,并且它使用了thrift服务器pod的kubernetes原始pod名称(不是服务名称,名称中没有IP)来表示它找不到发起连接的thrift服务器。现在,Kubernetes DNS存储服务名称,然后仅存储pod名称,以其私有IP为前缀。换句话说,pod的原始名称(没有IP)从未向DNS注册。这不是Kubernetes的工作方式。
所以我的问题是。我正在努力弄清楚为什么spark worker pod使用一个原始pod名称来尝试查找thrift服务器。它似乎永远不应该这样做,而且永远不可能满足这一要求。我想知道是否有一些spark配置设置,可以告诉工人它需要搜索的(节俭)驱动实际上是spark-thriftserver. my-namespace. svc。但我找了半天也没找到。
有这么多的设置,进入这样的集群,我不想弹幕你的信息。有一件事可以澄清我的设置:以下字符串被转储到失败的工作日志的顶部。请注意driver-url的节俭服务器的原始pod名称。如果有人有任何线索采取什么步骤来解决这个问题,请让我知道。我会编辑这篇文章和分享设置等人们的要求。谢谢你帮忙

Spark Executor Command: "/usr/lib/jvm/java-1.8-openjdk/jre/bin/java" "-cp" "/spark/conf/:/spark/jars/*" "-Xmx512M" "-Dspark.master.port=7077" "-Dspark.history.ui.port=18081" "-Dspark.ui.port=4040" "-Dspark.driver.port=41617" "-Dspark.blockManager.port=41618" "-Dspark.master.rest.port=6066" "-Dspark.master.ui.port=8080" "org.apache.spark.executor.CoarseGrainedExecutorBackend" "--driver-url" "spark://CoarseGrainedScheduler@spark-thriftserver-6bbb54768b-j8hz8:41617" "--executor-id" "12" "--hostname" "172.17.0.6" "--cores" "1" "--app-id" "app-20220408001035-0000" "--worker-url" "spark://Worker@172.17.0.6:37369"
col17t5w

col17t5w1#

以下是如何成功运行Spark Thrift Service on Kubernetes的简要指南:
Spark Thrift Server是Spark的多用户JDBC/ODBC可访问服务,可以按照Spark Thrift Server的设计以客户端模式部署在Kubernetes上。这意味着Spark Submit在客户端模式下运行时,将在执行spark-submit命令的节点上启动。为了克服设计限制,您可以在客户端模式下从Kubernetes中的节点启动Thrift Server,使该节点成为驱动程序。
在客户端模式下在Kubernetes上运行Spark时需要考虑几个关键点:

*客户端组网:Spark执行器必须能够通过可路由的主机名和端口连接到Spark驱动程序。您可以使用headless服务为您的驱动程序pod提供一个稳定的、可路由的主机名。这可以通过spark.driver.hostspark.driver.port来指定。
*客户端模式Executor Pod垃圾回收:如果您的Spark驱动程序在Pod中运行,强烈建议将spark.kubernetes.driver.pod.name设置为该Pod的名称。这确保了一旦驱动程序pod从集群中删除,应用程序的所有执行器pod都将被删除。
*Executor Pod清理:如果您的应用程序没有在pod中运行,或者当您的应用程序在pod中运行时没有设置spark.kubernetes.driver.pod.name,则当应用程序退出时,executor pod可能不会被正确删除。
*主控Executor Pod名称:您可以使用spark.kubernetes.executor.podNamePrefix来控制执行器pod名称。使其在同一命名空间中的所有作业中唯一,以避免冲突。

部署包括两个部分:Service和StatefulSet。该服务对于集群内的网络访问至关重要,并允许Spark执行器通过可路由的主机名和端口连接到Spark驱动程序。您可以定义公开两个端口的无头服务:一个用于Thrift服务器,另一个用于Spark驱动程序。
StatefulSet将管理Spark Thrift Server的部署。在StatefulSet配置中,您将指定Spark Thrift Server镜像、启动Thrift Server的命令以及几个Spark配置。使用StatefulSet而不是Deployment或ReplicaSet的关键决定主要是由于需要一致的pod名称,这是spark.kubernetes.driver.pod.name配置提出的要求。Kubernetes中的StatefulSet通过提供稳定和可预测的pod名称来内在地支持这一要求,无论是否重新调度。
总之,由于设计限制,在Kubernetes上运行Spark Thrift Server需要在客户端模式下运行服务器。
简短的例子:

apiVersion: v1
kind: Service
metadata:
  name: spark-thrift-service
spec:
  clusterIP: None
  selector:
    app: spark-thrift-server
  ports:
    - protocol: TCP
      name: spark-driver-port
      port: 7078
      targetPort: 7078
---
---
apiVersion: v1
kind: Secret
metadata:
  name: kubernetes-config
type: Opaque
data:
  config: |
    <base64 encoded config>
  ca.pem: |
    <base64 encoded key>
---
apiVersion: v1
kind: Secret
metadata:
  name: kubernetes-config
type: Opaque
data:
  config: |
    <base64 encoded config>
  ca.pem: |
    <base64 encoded key>
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: spark-thrift-server
spec:
  serviceName: spark-thrift-service
  replicas: 1
  selector:
    matchLabels:
      app: spark-thrift-server
  template:
    metadata:
      labels:
        app: spark-thrift-server
    spec:
      containers:
        - name: thrift-server
          image: apache/spark:3.4.0
          command:
            - 'bash'
            - '-c'
            - >-
              /opt/spark/sbin/start-thriftserver.sh
              --master k8s://https://<k8s-apiserver-host>:<k8s-apiserver-port>
              --packages com.typesafe:config:1.4.2,org.apache.hadoop:hadoop-aws:3.3.4,org.apache.spark:spark-hadoop-cloud_2.12:3.4.0,org.apache.spark:spark-sql-kafka-0-10_2.12:3.4.0
              --conf spark.driver.extraJavaOptions="-Divy.cache.dir=/tmp -Divy.home=/tmp"
              --conf spark.dynamicAllocation.enabled=true
              --conf spark.hadoop.fs.s3a.access.key=<your-access-key>
              --conf spark.hadoop.fs.s3a.committer.name=directory
              --conf spark.hadoop.fs.s3a.endpoint=<your-endpoint>
              --conf spark.hadoop.fs.s3a.fast.upload=true
              --conf spark.hadoop.fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem
              --conf spark.hadoop.fs.s3a.secret.key=<your-secret-key>
              --conf spark.hadoop.hive.metastore.uris=thrift://<hive-metastore-host>:<hive-metastore-port>
              --conf spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version=2
              --conf spark.hadoop.mapreduce.fileoutputcommitter.cleanup-failures.ignored=true
              --conf spark.hadoop.parquet.enable.summary-metadata=false
              --conf spark.kubernetes.container.image=apache/spark:v3.4.0
              --conf spark.kubernetes.file.upload.path=s3a://some/tmp/folder/thriftserver
              --conf spark.sql.catalogImplementation=hive
              --conf spark.sql.hive.metastorePartitionPruning=true
              --conf spark.sql.parquet.filterPushdown=true
              --conf spark.sql.parquet.mergeSchema=false
              --conf spark.sql.parquet.output.committer.class=org.apache.spark.internal.io.cloud.BindingParquetOutputCommitter
              --conf spark.sql.sources.commitProtocolClass=org.apache.spark.internal.io.cloud.PathOutputCommitProtocol
              --conf spark.sql.sources.default=parquet
              --conf spark.sql.sources.partitionOverwriteMode=dynamic
              --conf spark.sql.warehouse.dir=s3a://warehouse
              --conf spark.kubernetes.driver.pod.name=spark-thrift-server-0
              --conf spark.driver.host=spark-thrift-service
              --conf spark.driver.port=7078
              && tail -f /dev/null

          volumeMounts:
            - name: kubernetes-config
              mountPath: /root/.kube
      volumes:
        - name: kubernetes-config
          secret:
            secretName: kubernetes-config

相关问题