开始使用
有关如何使用、组合和使用SparkApplication的更详细指南,请参考用户指南。如果您在Google Kubernetes Engine上运行Apache Spark的Kubernetes Operator,并希望使用Google Cloud Storage (GCS)和/或BigQuery进行读写数据,也请参考GCP指南。Apache Spark的Kubernetes Operator在本指南的其他部分将简单称为操作程序。
前提条件
- Helm >= 3
- Kubernetes >= 1.16
安装
添加 Helm 仓库
helm repo add spark-operator https://kubeflow.github.io/spark-operator
helm repo update
参见 helm repo 以获取命令文档。
安装图表
helm install [RELEASE_NAME] spark-operator/spark-operator
例如,如果您想在 spark-operator 命名空间中创建一个名为 spark-operator 的发布:
helm install spark-operator spark-operator/spark-operator \
--namespace spark-operator \
--create-namespace
请参见 helm install 以获取命令文档。
安装该图表将创建一个命名空间 spark-operator(如果它不存在),并且 helm 将为操作员在该命名空间中运行设置 RBAC。它还将在 default 命名空间中为您的 Spark 应用程序的驱动程序 Pod 设置 RBAC,以便能够操作执行器 Pods。此外,该图表将在命名空间 spark-operator 中创建一个 Deployment。该图表默认不启用 Mutating Admission Webhook 用于 Spark Pod 自定义。当启用时,将为此创建一个 webhook 服务和一个存储名为 spark-webhook-certs 的 x509 证书的秘密。要在 Kubernetes 集群上安装带有变更 Admission Webhook 的操作员,请使用标志 webhook.enable=true 安装该图表:
helm install my-release spark-operator/spark-operator \
--namespace spark-operator \
--create-namespace \
--set webhook.enable=true
如果您想将图表部署到 GKE 集群,您需要先 授予自己集群管理员权限,然后才能在版本为 1.6 及以上的 GKE 集群上创建自定义角色和角色绑定。在安装图表到 GKE 之前,请运行以下命令:
kubectl create clusterrolebinding <user>-cluster-admin-binding --clusterrole=cluster-admin --user=<user>@<domain>
现在你应该通过检查Helm发布的状态来看见操作器在集群中运行。
helm status --namespace spark-operator my-release
升级图表
helm upgrade [RELEASE_NAME] spark-operator/spark-operator [flags]
请参阅 helm upgrade 以获取命令文档。
卸载图表
helm uninstall [RELEASE_NAME]
这将删除与该图表相关的所有Kubernetes资源,并删除发行版,除了crds,这些需要手动移除。
查看 helm uninstall 以获取命令文档。
运行示例
要运行 Spark PI 示例,请运行以下命令:
kubectl apply -f examples/spark-pi.yaml
请注意,spark-pi.yaml 配置了驱动程序 pod 以使用 spark 服务账户与 Kubernetes API 服务器进行通信。在提交作业之前,您可能需要将其替换为适当的服务账户。如果您使用 Helm 图表安装了运算符并覆盖了 spark.jobNamespaces,则服务账户名称以 -spark 结尾,并以 Helm 发布名称开头。例如,如果您希望在名为 test-ns 的命名空间中运行 Spark 作业,请首先确保该命名空间已存在,然后使用以下命令安装图表:
helm install my-release spark-operator/spark-operator --namespace spark-operator --set "spark.jobNamespaces={test-ns}"
然后图表将在该命名空间中为您的Spark作业设置一个服务帐户。
有关默认 Spark 作业命名空间行为的详细信息,请参见Spark Job Namespace部分。
运行上述命令将创建一个名为 spark-pi 的 SparkApplication 对象。通过运行以下命令检查该对象:
kubectl get sparkapplication spark-pi -o=yaml
这将显示类似于以下内容:
apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
...
spec:
deps: {}
driver:
coreLimit: 1200m
cores: 1
labels:
version: 2.3.0
memory: 512m
serviceAccount: spark
executor:
cores: 1
instances: 1
labels:
version: 2.3.0
memory: 512m
image: gcr.io/ynli-k8s/spark:v3.1.1
mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.1.1.jar
mainClass: org.apache.spark.examples.SparkPi
mode: cluster
restartPolicy:
type: OnFailure
onFailureRetries: 3
onFailureRetryInterval: 10
onSubmissionFailureRetries: 5
onSubmissionFailureRetryInterval: 20
type: Scala
status:
sparkApplicationId: spark-5f4ba921c85ff3f1cb04bef324f9154c9
applicationState:
state: COMPLETED
completionTime: 2018-02-20T23:33:55Z
driverInfo:
podName: spark-pi-83ba921c85ff3f1cb04bef324f9154c9-driver
webUIAddress: 35.192.234.248:31064
webUIPort: 31064
webUIServiceName: spark-pi-2402118027-ui-svc
webUIIngressName: spark-pi-ui-ingress
webUIIngressAddress: spark-pi.ingress.cluster.com
executorState:
spark-pi-83ba921c85ff3f1cb04bef324f9154c9-exec-1: COMPLETED
LastSubmissionAttemptTime: 2018-02-20T23:32:27Z
要检查SparkApplication对象的事件,请运行以下命令:
kubectl describe sparkapplication spark-pi
这将以类似于以下内容的方式显示事件:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SparkApplicationAdded 5m spark-operator SparkApplication spark-pi was added, enqueued it for submission
Normal SparkApplicationTerminated 4m spark-operator SparkApplication spark-pi terminated with state: COMPLETED
一旦接收到指示SparkApplication对象已添加的事件,操作员提交Spark Pi示例以运行。
配置
该操作符通常通过Helm图表部署和运行。但是,用户仍然可以在Kubernetes集群之外运行它,并通过指定kubeconfig的路径使其与集群的Kubernetes API服务器进行通信,这可以通过使用-kubeconfig标志来完成。
该操作符在SparkApplication控制器中使用多个工作线程。工作线程的数量通过命令行标志-controller-threads进行控制,该标志的默认值为10。
该操作符启用缓存重新同步,因此操作符使用的通知者将定期重新列出它管理的现有对象并重新触发资源事件。重新同步的时间间隔(以秒为单位)可以使用标志 -resync-interval 进行配置,默认值为30秒。
默认情况下,该操作符将为它管理的自定义资源安装CustomResourceDefinitions。通过设置标志-install-crds=false可以禁用此功能,在这种情况下,CustomResourceDefinitions可以使用kubectl apply -f manifest/spark-operator-crds.yaml手动安装。
变更的 admission webhook 是一个 可选的 组件,可以使用 -enable-webhook 标志启用或禁用,默认为 false。
默认情况下,操作符将管理整个集群的受管 CRD 类型的自定义资源对象。它可以通过标志 -namespace= 配置为仅管理特定命名空间中的自定义资源对象。
升级
要升级操作符,例如,使用带有新标签的较新版本容器镜像,请运行以下命令并更新Helm发布的参数:
helm upgrade <YOUR-HELM-RELEASE-NAME> --set image.repository=org/image --set image.tag=newTag
有关helm upgrade的更多详细信息,请参考Helm 文档。
关于 Spark Job 命名空间
Spark作业命名空间值定义了可以部署SparkApplications的命名空间。Spark作业命名空间的Helm图表值是spark.jobNamespaces,其默认值是[]。当命名空间列表为空时,Helm图表将在部署spark-operator的命名空间中创建一个服务帐户。
如果您使用Helm图表安装了操作符并覆盖了spark.jobNamespaces为其他已存在的命名空间,Helm图表将在指定的命名空间中创建必要的服务账户和RBAC。
Spark Operator 使用 Spark Job 命名空间来识别和过滤与 SparkApplication CRD 相关的事件。如果你为 Spark Jobs 指定了一个命名空间,然后将 SparkApplication 资源提交到另一个命名空间,Spark Operator 将过滤掉该事件,资源将不会被部署。如果你没有指定命名空间,Spark Operator 只会看到 Spark Operator 命名空间中的 SparkApplication 事件。
关于驱动程序 Pod 的服务帐户
A Spark driver pod 需要一个 Kubernetes 服务账户,在 pod 的命名空间中具有创建、获取、列出和删除执行器 pods 的权限,并为驱动程序创建一个 Kubernetes 无头服务。如果没有服务账户,驱动程序将失败并退出,除非 pod 的命名空间中的默认服务账户拥有所需的权限。要在命名空间中提交和运行一个 SparkApplication,请确保命名空间中有一个具有权限的服务账户,并将 .spec.driver.serviceAccount 设置为服务账户的名称。请参阅 spark-rbac.yaml 以获取创建一个名为 spark-operator-spark 的驱动程序服务账户的 RBAC 设置示例,该账户在 default 命名空间中,并具有将所需权限授予服务账户的 RBAC 角色绑定。
关于执行器 Pod 的服务账号
一个 Spark 执行器 Pod 可以在 Pod 命名空间中配置 Kubernetes 服务账户。要在一个命名空间中提交和运行一个 SparkApplication,请确保该命名空间中有一个具有所需权限的服务账户,并将 .spec.executor.serviceAccount 设置为服务账户的名称。
启用指标导出到Prometheus
该操作符通过指标端点公开一组指标,以供Prometheus抓取。默认情况下,Helm图表使用额外的标志安装操作符以启用指标(-enable-metrics=true),以及其他用于Prometheus抓取指标端点的注释。如果启用podMonitor.enable,helm图表将为操作符的pod提交一个pod监控。要安装没有启用指标的操作符,请在helm install期间传递适当的标志:
helm install my-release spark-operator/spark-operator \
--namespace spark-operator \
--create-namespace \
--set metrics.enable=false
如果启用,操作符将生成以下指标:
Spark 应用程序指标
| 指标 | 描述 |
|---|---|
spark_application_count | Total number of SparkApplication handled by the Operator. |
spark_application_submit_count | Total number of SparkApplication spark-submitted by the Operator. |
spark_application_success_count | Total number of SparkApplication which completed successfully. |
spark_application_failure_count | Total number of SparkApplication which failed to complete. |
spark_application_running_count | Total number of SparkApplication which are currently running. |
spark_application_success_execution_time_seconds | Execution time for applications which succeeded. |
spark_application_failure_execution_time_seconds | Execution time for applications which failed. |
spark_application_start_latency_seconds | Start latency of SparkApplication as type of Prometheus Summary. |
spark_application_start_latency_seconds | Start latency of SparkApplication as type of Prometheus Histogram. |
spark_executor_success_count | Total number of Spark Executors which completed successfully. |
spark_executor_failure_count | Total number of Spark Executors which failed. |
spark_executor_running_count | Total number of Spark Executors which are currently running. |
工作队列指标
| 指标 | 描述 |
|---|---|
workqueue_depth | Current depth of workqueue |
workqueue_adds_total | Total number of adds handled by workqueue |
workqueue_queue_duration_seconds_bucket | How long in seconds an item stays in workqueue before being requested |
workqueue_work_duration_seconds_bucket | How long in seconds processing an item from workqueue takes |
workqueue_retries_total | Total number of retries handled by workqueue |
workqueue_unfinished_work_seconds | Unfinished work in seconds |
workqueue_longest_running_processor_seconds | Longest running processor in seconds |
以下是操作符支持的所有指标配置的列表:
-enable-metrics=true
-metrics-port=10254
-metrics-endpoint=/metrics
-metrics-prefix=myServiceName
-metrics-label=label1Key
-metrics-label=label2Key
除 -enable-metrics 外,所有配置都是可选的。如果指定了端口和/或端点,请确保更新 spark-operator-with-metrics.yaml 中的注释 prometheus.io/port、prometheus.io/path 和 containerPort。
关于 metrics-labels 的说明:在 Prometheus 中,每个唯一的键值标签对组合代表一个新的时间序列,这可能会显著增加存储的数据量。因此,标签不应用于存储具有高基数的维度,这些维度可能具有大的或无限的值范围。
此外,这些指标是在当前操作符运行中的尽力而为,并将在操作符重启时重置。同时,某些指标是通过监听驱动程序/执行器的 pod 状态更新生成的,删除操作符外的 pod 可能会导致某些指标的值不正确。
驱动程序用户界面访问和入口
默认情况下,操作符通过创建一个类型为 ClusterIP 的服务来使 Spark UI 可访问,该服务公开了 UI。此服务仅可从集群内部访问。
该操作符还支持为UI创建可选的Ingress。可以通过设置ingress-url-format命令行标志来打开此功能。ingress-url-format应该是一个模板,如{{$appName}}.{ingress_suffix}/{{$appNamespace}}/{{$appName}}。{ingress_suffix}应该由用户替换,以指示集群的ingress网址,操作符将用适当的值替换{{$appName}}和{{$appNamespace}}。请注意,Ingress支持要求集群的ingress网址路由正确设置。例如,如果ingress-url-format是{{$appName}}.ingress.cluster.com,则要求任何*ingress.cluster.com都应该路由到K8s集群上的ingress-controller。
操作符还设置了可从集群内部访问的 WebUIAddress 以及作为 SparkApplication 的 DriverInfo 字段的一部分的 WebUIIngressAddress。
该操作符生成用于Ingress NGINX Controller的入口资源。在您的应用程序规范中包含这一点,以确保控制器识别入口并为您的Spark UI提供适当的路由。
spec:
sparkUIOptions:
ingressAnnotations:
kubernetes.io/ingress.class: nginx
关于变更请愿网页钩子
用于Apache Spark的Kubernetes Operator带有一个可选的变更准入webhook,用于根据SparkApplication对象中的规格自定义Spark驱动程序和执行程序pod,例如,挂载用户指定的ConfigMaps和卷,设置pod亲和性/反亲和性,以及添加容忍性。
webhook需要一个X509证书用于TLS,以处理Kubernetes API服务器与运行在操作员内部的webhook服务器之间的pod入 Admission 请求和响应。为此,证书和密钥文件必须可被webhook服务器访问。这些证书的位置是可配置的,并将在可配置的时间周期内重新加载。
Spark的Kubernetes Operator附带了一个工具,在hack/gencerts.sh中,用于生成CA和服务器证书,并将证书和密钥文件放入一个名为spark-webhook-certs的秘密中,位于spark-operator命名空间中。这个秘密将被挂载到操作员pod中。
运行以下命令以使用批处理作业创建带有证书和密钥文件的秘密,并安装具有变更准入 webhook 的操作员部署:
kubectl apply -f manifest/spark-operator-with-webhook.yaml
这将创建一个名为 sparkoperator 的部署和一个名为 spark-webhook 的服务,用于在命名空间 spark-operator 中的 webhook。
在私有GKE或EKS集群上变更准入Webhook
如果您在启用了 私有集群 设置的 GKE 集群上部署该操作符,或者在企业级 AWS EKS 集群上部署,并希望使用 变更准入 Webhook 部署该集群,那么请确保将 webhookPort 更改为 443。另外,您可以选择允许连接到默认端口(8080)。
默认情况下,防火墙规则限制您的集群主节点仅能在443(HTTPS)和10250(kubelet)端口上向您的节点发起TCP连接。对于某些Kubernetes功能,您可能需要添加防火墙规则以允许在其他端口上的访问。例如,在Kubernetes 1.9及更早版本中,kubectl top 访问heapster,这需要一个防火墙规则以允许在8080端口上的TCP连接。要授予这样的访问,您可以添加防火墙规则。 对于GCP,请参考this link
要使用自定义端口安装操作符,请在 helm install 时传递适当的标志:
helm install my-release spark-operator/spark-operator \
--namespace spark-operator \
--create-namespace \
--set "spark.jobNamespaces={spark}" \
--set webhook.enable=true \
--set webhook.port=443