This repository has been archived by the owner on Jan 9, 2020. It is now read-only.
forked from apache/spark
-
Notifications
You must be signed in to change notification settings - Fork 118
Spark on Kubernetes - basic scheduler backend #498
Closed
Closed
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
f6fdd6a
Spark on Kubernetes - basic scheduler backend
foxish 75e31a9
Adding to modules.py and SparkBuild.scala
foxish cf82b21
Exclude from unidoc, update travis
foxish 488c535
Address a bunch of style and other comments
foxish 82b79a7
Fix some style concerns
foxish c052212
Clean up YARN constants, unit test updates
foxish c565c9f
Couple of more style comments
foxish 2fb596d
Address CR comments.
mccheah 992acbe
Extract initial executor count to utils class
mccheah b0a5839
Fix scalastyle
mccheah a4f9797
Fix more scalastyle
mccheah 2b5dcac
Pin down app ID in tests. Fix test style.
mccheah 018f4d8
Address comments.
mccheah 4b32134
Various fixes to the scheduler
mccheah 6cf4ed7
Address comments
mccheah 1f271be
Update fabric8 client version to 3.0.0
foxish 71a971f
Addressed more comments
liyinan926 0ab9ca7
One more round of comments
liyinan926 7f14b71
Added a comment regarding how failed executor pods are handled
liyinan926 7afce3f
Addressed more comments
liyinan926 b75b413
Fixed Scala style error
liyinan926 3b587b4
Removed unused parameter in parsePrefixedKeyValuePairs
liyinan926 cb12fec
Another round of comments
liyinan926 ae396cf
Addressed latest comments
liyinan926 f8e3249
Addressed comments around licensing on new dependencies
liyinan926 a44c29e
Fixed unit tests and made maximum executor lost reason checks configu…
liyinan926 4bed817
Removed default value for executor Docker image
liyinan926 c386186
Close the executor pod watcher before deleting the executor pods
liyinan926 b85cfc4
Addressed more comments
liyinan926 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
~ Licensed to the Apache Software Foundation (ASF) under one or more | ||
~ contributor license agreements. See the NOTICE file distributed with | ||
~ this work for additional information regarding copyright ownership. | ||
~ The ASF licenses this file to You under the Apache License, Version 2.0 | ||
~ (the "License"); you may not use this file except in compliance with | ||
~ the License. You may obtain a copy of the License at | ||
~ | ||
~ http://www.apache.org/licenses/LICENSE-2.0 | ||
~ | ||
~ Unless required by applicable law or agreed to in writing, software | ||
~ distributed under the License is distributed on an "AS IS" BASIS, | ||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
~ See the License for the specific language governing permissions and | ||
~ limitations under the License. | ||
--> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.apache.spark</groupId> | ||
<artifactId>spark-parent_2.11</artifactId> | ||
<version>2.3.0-SNAPSHOT</version> | ||
<relativePath>../../../pom.xml</relativePath> | ||
</parent> | ||
|
||
<artifactId>spark-kubernetes_2.11</artifactId> | ||
<packaging>jar</packaging> | ||
<name>Spark Project Kubernetes</name> | ||
<properties> | ||
<sbt.project.name>kubernetes</sbt.project.name> | ||
<kubernetes.client.version>2.2.13</kubernetes.client.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.apache.spark</groupId> | ||
<artifactId>spark-core_${scala.binary.version}</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.apache.spark</groupId> | ||
<artifactId>spark-core_${scala.binary.version}</artifactId> | ||
<version>${project.version}</version> | ||
<type>test-jar</type> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>io.fabric8</groupId> | ||
<artifactId>kubernetes-client</artifactId> | ||
<version>${kubernetes.client.version}</version> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-core</artifactId> | ||
</exclusion> | ||
<exclusion> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-databind</artifactId> | ||
</exclusion> | ||
<exclusion> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-annotations</artifactId> | ||
</exclusion> | ||
<exclusion> | ||
<groupId>com.fasterxml.jackson.dataformat</groupId> | ||
<artifactId>jackson-dataformat-yaml</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
|
||
<!-- Required by kubernetes-client but we exclude it --> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.dataformat</groupId> | ||
<artifactId>jackson-dataformat-yaml</artifactId> | ||
<version>${fasterxml.jackson.version}</version> | ||
</dependency> | ||
|
||
<!-- Explicitly depend on shaded dependencies from the parent, since shaded deps aren't transitive --> | ||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
</dependency> | ||
<!-- End of shaded deps. --> | ||
|
||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
|
||
|
||
<build> | ||
<outputDirectory>target/scala-${scala.binary.version}/classes</outputDirectory> | ||
<testOutputDirectory>target/scala-${scala.binary.version}/test-classes</testOutputDirectory> | ||
</build> | ||
|
||
</project> |
58 changes: 58 additions & 0 deletions
58
...agers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/ConfigurationUtils.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.apache.spark.deploy.k8s | ||
|
||
import org.apache.spark.SparkConf | ||
|
||
private[spark] object ConfigurationUtils { | ||
def parsePrefixedKeyValuePairs( | ||
sparkConf: SparkConf, | ||
prefix: String, | ||
configType: String): Map[String, String] = { | ||
val fromPrefix = sparkConf.getAllWithPrefix(prefix) | ||
fromPrefix.groupBy(_._1).foreach { | ||
case (key, values) => | ||
require(values.size == 1, | ||
s"Cannot have multiple values for a given $configType key, got key $key with" + | ||
s" values $values") | ||
} | ||
fromPrefix.toMap | ||
} | ||
|
||
def requireBothOrNeitherDefined( | ||
opt1: Option[_], | ||
opt2: Option[_], | ||
errMessageWhenFirstIsMissing: String, | ||
errMessageWhenSecondIsMissing: String): Unit = { | ||
requireSecondIfFirstIsDefined(opt1, opt2, errMessageWhenSecondIsMissing) | ||
requireSecondIfFirstIsDefined(opt2, opt1, errMessageWhenFirstIsMissing) | ||
} | ||
|
||
def requireSecondIfFirstIsDefined( | ||
opt1: Option[_], | ||
opt2: Option[_], | ||
errMessageWhenSecondIsMissing: String): Unit = { | ||
opt1.foreach { _ => | ||
require(opt2.isDefined, errMessageWhenSecondIsMissing) | ||
} | ||
} | ||
|
||
def requireNandDefined(opt1: Option[_], opt2: Option[_], errMessage: String): Unit = { | ||
opt1.foreach { _ => require(opt2.isEmpty, errMessage) } | ||
} | ||
} |
103 changes: 103 additions & 0 deletions
103
...rnetes/core/src/main/scala/org/apache/spark/deploy/k8s/SparkKubernetesClientFactory.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.spark.deploy.k8s | ||
|
||
import java.io.File | ||
|
||
import com.google.common.base.Charsets | ||
import com.google.common.io.Files | ||
import io.fabric8.kubernetes.client.{Config, ConfigBuilder, DefaultKubernetesClient, KubernetesClient} | ||
import io.fabric8.kubernetes.client.utils.HttpClientUtils | ||
import okhttp3.Dispatcher | ||
|
||
import org.apache.spark.SparkConf | ||
import org.apache.spark.deploy.k8s.config._ | ||
import org.apache.spark.util.ThreadUtils | ||
|
||
/** | ||
* Spark-opinionated builder for Kubernetes clients. It uses a prefix plus common suffixes to | ||
* parse configuration keys, similar to the manner in which Spark's SecurityManager parses SSL | ||
* options for different components. | ||
*/ | ||
private[spark] object SparkKubernetesClientFactory { | ||
|
||
def createKubernetesClient( | ||
master: String, | ||
namespace: Option[String], | ||
kubernetesAuthConfPrefix: String, | ||
sparkConf: SparkConf, | ||
maybeServiceAccountToken: Option[File], | ||
maybeServiceAccountCaCert: Option[File]): KubernetesClient = { | ||
val oauthTokenFileConf = s"$kubernetesAuthConfPrefix.$OAUTH_TOKEN_FILE_CONF_SUFFIX" | ||
val oauthTokenConf = s"$kubernetesAuthConfPrefix.$OAUTH_TOKEN_CONF_SUFFIX" | ||
val oauthTokenFile = sparkConf.getOption(oauthTokenFileConf) | ||
.map(new File(_)) | ||
.orElse(maybeServiceAccountToken) | ||
val oauthTokenValue = sparkConf.getOption(oauthTokenConf) | ||
ConfigurationUtils.requireNandDefined( | ||
oauthTokenFile, | ||
oauthTokenValue, | ||
s"Cannot specify OAuth token through both a file $oauthTokenFileConf and a" + | ||
s" value $oauthTokenConf.") | ||
|
||
val caCertFile = sparkConf | ||
.getOption(s"$kubernetesAuthConfPrefix.$CA_CERT_FILE_CONF_SUFFIX") | ||
.orElse(maybeServiceAccountCaCert.map(_.getAbsolutePath)) | ||
val clientKeyFile = sparkConf | ||
.getOption(s"$kubernetesAuthConfPrefix.$CLIENT_KEY_FILE_CONF_SUFFIX") | ||
val clientCertFile = sparkConf | ||
.getOption(s"$kubernetesAuthConfPrefix.$CLIENT_CERT_FILE_CONF_SUFFIX") | ||
val dispatcher = new Dispatcher( | ||
ThreadUtils.newDaemonCachedThreadPool("kubernetes-dispatcher")) | ||
val config = new ConfigBuilder() | ||
.withApiVersion("v1") | ||
.withMasterUrl(master) | ||
.withWebsocketPingInterval(0) | ||
.withOption(oauthTokenValue) { | ||
(token, configBuilder) => configBuilder.withOauthToken(token) | ||
}.withOption(oauthTokenFile) { | ||
(file, configBuilder) => | ||
configBuilder.withOauthToken(Files.toString(file, Charsets.UTF_8)) | ||
}.withOption(caCertFile) { | ||
(file, configBuilder) => configBuilder.withCaCertFile(file) | ||
}.withOption(clientKeyFile) { | ||
(file, configBuilder) => configBuilder.withClientKeyFile(file) | ||
}.withOption(clientCertFile) { | ||
(file, configBuilder) => configBuilder.withClientCertFile(file) | ||
}.withOption(namespace) { | ||
(ns, configBuilder) => configBuilder.withNamespace(ns) | ||
}.build() | ||
val baseHttpClient = HttpClientUtils.createHttpClient(config) | ||
val httpClientWithCustomDispatcher = baseHttpClient.newBuilder() | ||
.dispatcher(dispatcher) | ||
.build() | ||
new DefaultKubernetesClient(httpClientWithCustomDispatcher, config) | ||
} | ||
|
||
private implicit class OptionConfigurableConfigBuilder(configBuilder: ConfigBuilder) { | ||
|
||
def withOption[T] | ||
(option: Option[T]) | ||
(configurator: ((T, ConfigBuilder) => ConfigBuilder)): OptionConfigurableConfigBuilder = { | ||
new OptionConfigurableConfigBuilder(option.map { opt => | ||
configurator(opt, configBuilder) | ||
}.getOrElse(configBuilder)) | ||
} | ||
|
||
def build(): Config = configBuilder.build() | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Clean up these white spaces, or at least be consistent