-
Notifications
You must be signed in to change notification settings - Fork 606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LIVY-588]: Full support for Spark on Kubernetes #167
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,6 +157,9 @@ | |
# If the Livy Web UI should be included in the Livy Server. Enabled by default. | ||
# livy.ui.enabled = true | ||
|
||
# Used to build links to Spark History Server pages on Spark App completion (Kubernetes only) | ||
# livy.ui.history-server-url = http://spark-history-server | ||
|
||
# Whether to enable Livy server access control, if it is true then all the income requests will | ||
# be checked if the requested user has permission. | ||
# livy.server.access-control.enabled = false | ||
|
@@ -185,3 +188,55 @@ | |
# livy.server.auth.<custom>.class = <class of custom auth filter> | ||
# livy.server.auth.<custom>.param.<foo1> = <bar1> | ||
# livy.server.auth.<custom>.param.<foo2> = <bar2> | ||
|
||
# Manual authentication to KubeApiserver (by default configured with Kubernetes ServiceAccount | ||
# if deployed to Kubernetes cluster as a Pod) | ||
# Kubernetes oauth token file path | ||
# livy.server.kubernetes.oauthTokenFile = | ||
# Kubernetes oauth token string value | ||
# livy.server.kubernetes.oauthTokenValue = | ||
# Kubernetes CA cert file path | ||
# livy.server.kubernetes.caCertFile = | ||
# Kubernetes client key file path | ||
# livy.server.kubernetes.clientKeyFile = | ||
# Kubernetes client cert file path | ||
# livy.server.kubernetes.clientCertFile = | ||
|
||
# If Livy can't find the Kubernetes app within this time, consider it lost. | ||
# livy.server.kubernetes.app-lookup-timeout = 600s | ||
# When the cluster is busy, we may fail to launch yarn app in app-lookup-timeout, then it would | ||
# cause session leakage, so we need to check session leakage. | ||
# How long to check livy session leakage | ||
# livy.server.kubernetes.app-leakage.check-timeout = 600s | ||
# How often to check livy session leakage | ||
# livy.server.kubernetes.app-leakage.check-interval = 60s | ||
|
||
# How often Livy polls KubeApiServer to refresh KubernetesApp state (Pods state, logs, description | ||
# details, routes, etc...) | ||
# livy.server.kubernetes.poll-interval = 15s | ||
|
||
# Weather to create Kubernetes Nginx Ingress for Spark UI. If set to true, configure the desired | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: Whether, not Weather. |
||
# options below | ||
# livy.server.kubernetes.ingress.create = false | ||
# Kubernetes Nginx Ingress protocol. If set to https refer Ingress TLS section below | ||
# livy.server.kubernetes.ingress.protocol = http | ||
# Kubernetes Nginx Ingress host. Be sure to set it to the FQDN of your Nginx Ingress Controller | ||
# proxy server | ||
# livy.server.kubernetes.ingress.host = localhost | ||
# Kubernetes secret name for Nginx Ingress TLS. Is omitted if 'livy.server.kubernetes.ingress.protocol' | ||
# is not https | ||
# livy.server.kubernetes.ingress.tls.secretName = spark-cluster-tls | ||
# Kubernetes Nginx Ingress additional configuration snippet for specific config options | ||
# livy.server.kubernetes.ingress.additionalConfSnippet = | ||
# Kubernetes Nginx Ingress additional annotations for specific config options, eg. for configuring | ||
# basic auth of external oauth2 proxy. Format: annotation1=value1;annotation2=value2;... | ||
# livy.server.kubernetes.ingress.additionalAnnotations = | ||
|
||
# Set to true to enable Grafana Loki integration and configure options below | ||
livy.server.kubernetes.grafana.loki.enabled = false | ||
jahstreet marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Grafana UI root endpoint to build links based on | ||
# livy.server.kubernetes.grafana.url = http://localhost:3000 | ||
# Grafana Datasource name for Loki | ||
# livy.server.kubernetes.grafana.loki.datasource = loki | ||
# Time range from now to past to get logs for | ||
# livy.server.kubernetes.grafana.timeRange = 6h |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -63,6 +63,7 @@ object LivyConf { | |||||
val SERVER_BASE_PATH = Entry("livy.ui.basePath", "") | ||||||
|
||||||
val UI_ENABLED = Entry("livy.ui.enabled", true) | ||||||
val UI_HISTORY_SERVER_URL = Entry("livy.ui.history-server-url", "http://spark-history-server") | ||||||
|
||||||
val REQUEST_HEADER_SIZE = Entry("livy.server.request-header.size", 131072) | ||||||
val RESPONSE_HEADER_SIZE = Entry("livy.server.response-header.size", 131072) | ||||||
|
@@ -249,6 +250,52 @@ object LivyConf { | |||||
// how often to check livy session leakage | ||||||
val YARN_APP_LEAKAGE_CHECK_INTERVAL = Entry("livy.server.yarn.app-leakage.check-interval", "60s") | ||||||
|
||||||
// Kubernetes oauth token file path. | ||||||
val KUBERNETES_OAUTH_TOKEN_FILE = Entry("livy.server.kubernetes.oauthTokenFile", "") | ||||||
jahstreet marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
// Kubernetes oauth token string value. | ||||||
val KUBERNETES_OAUTH_TOKEN_VALUE = Entry("livy.server.kubernetes.oauthTokenValue", "") | ||||||
// Kubernetes CA cert file path. | ||||||
val KUBERNETES_CA_CERT_FILE = Entry("livy.server.kubernetes.caCertFile", "") | ||||||
// Kubernetes client key file path. | ||||||
val KUBERNETES_CLIENT_KEY_FILE = Entry("livy.server.kubernetes.clientKeyFile", "") | ||||||
// Kubernetes client cert file path. | ||||||
val KUBERNETES_CLIENT_CERT_FILE = Entry("livy.server.kubernetes.clientCertFile", "") | ||||||
|
||||||
// If Livy can't find the Kubernetes app within this time, consider it lost. | ||||||
val KUBERNETES_APP_LOOKUP_TIMEOUT = Entry("livy.server.kubernetes.app-lookup-timeout", "600s") | ||||||
// How often Livy polls Kubernetes to refresh Kubernetes app state. | ||||||
val KUBERNETES_POLL_INTERVAL = Entry("livy.server.kubernetes.poll-interval", "15s") | ||||||
|
||||||
// How long to check livy session leakage. | ||||||
val KUBERNETES_APP_LEAKAGE_CHECK_TIMEOUT = | ||||||
Entry("livy.server.kubernetes.app-leakage.check-timeout", "600s") | ||||||
// How often to check livy session leakage. | ||||||
val KUBERNETES_APP_LEAKAGE_CHECK_INTERVAL = | ||||||
Entry("livy.server.kubernetes.app-leakage.check-interval", "60s") | ||||||
|
||||||
// Weather to create Kubernetes Nginx Ingress for Spark UI. | ||||||
val KUBERNETES_INGRESS_CREATE = Entry("livy.server.kubernetes.ingress.create", false) | ||||||
// Kubernetes Nginx Ingress protocol. | ||||||
val KUBERNETES_INGRESS_PROTOCOL = Entry("livy.server.kubernetes.ingress.protocol", "http") | ||||||
// Kubernetes Nginx Ingress host. | ||||||
val KUBERNETES_INGRESS_HOST = Entry("livy.server.kubernetes.ingress.host", "localhost") | ||||||
// Kubernetes Nginx Ingress additional configuration snippet. | ||||||
val KUBERNETES_INGRESS_ADDITIONAL_CONF_SNIPPET = | ||||||
Entry("livy.server.kubernetes.ingress.additionalConfSnippet", "") | ||||||
// Kubernetes Nginx Ingress additional annotations: key1=value1;key2=value2;... . | ||||||
val KUBERNETES_INGRESS_ADDITIONAL_ANNOTATIONS = | ||||||
Entry("livy.server.kubernetes.ingress.additionalAnnotations", "") | ||||||
// Kubernetes secret name for Nginx Ingress TLS. | ||||||
// Is omitted if 'livy.server.kubernetes.ingress.protocol' value doesn't end with 's' | ||||||
val KUBERNETES_INGRESS_TLS_SECRET_NAME = | ||||||
Entry("livy.server.kubernetes.ingress.tls.secretName", "spark-cluster-tls") | ||||||
|
||||||
val KUBERNETES_GRAFANA_LOKI_ENABLED = Entry("livy.server.kubernetes.grafana.loki.enabled", false) | ||||||
val KUBERNETES_GRAFANA_URL = Entry("livy.server.kubernetes.grafana.url", "http://localhost:3000") | ||||||
val KUBERNETES_GRAFANA_LOKI_DATASOURCE = | ||||||
Entry("livy.server.kubernetes.grafana.loki.datasource", "loki") | ||||||
val KUBERNETES_GRAFANA_TIME_RANGE = Entry("livy.server.kubernetes.grafana.timeRange", "6h") | ||||||
|
||||||
// Whether session timeout should be checked, by default it will be checked, which means inactive | ||||||
// session will be stopped after "livy.server.session.timeout" | ||||||
val SESSION_TIMEOUT_CHECK = Entry("livy.server.session.timeout-check", true) | ||||||
|
@@ -360,6 +407,9 @@ class LivyConf(loadDefaults: Boolean) extends ClientConf[LivyConf](null) { | |||||
/** Return true if spark master starts with yarn. */ | ||||||
def isRunningOnYarn(): Boolean = sparkMaster().startsWith("yarn") | ||||||
|
||||||
/** Return true if spark master starts with k8s. */ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Everything else is commented with |
||||||
def isRunningOnKubernetes(): Boolean = sparkMaster().startsWith("k8s") | ||||||
|
||||||
/** Return the spark deploy mode Livy sessions should use. */ | ||||||
def sparkDeployMode(): Option[String] = Option(get(LIVY_SPARK_DEPLOY_MODE)).filterNot(_.isEmpty) | ||||||
|
||||||
|
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.
why do we need to rely on SHS? It may also not being present/enabled....can we avoid this?
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.
May make sense to add 'enabled' flag.
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.
This is useful for setting the URL for completed applications to match the K8s ingress host so that URLs for completed applications (from Livy UI) can redirect to history server. Not sure about the behavior with YARN, but for K8s it seems useful to have it.
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.
Of course, the comment I guess about the behaviour when we don't have HS set up. In that case we can:
A) do not display link
B) display dummy link
I would prefer A here, but for that we there should be introduced additional config flag, eg.: history-server.enabled = true
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.
again, I'd do this in a separate PR, where we compare what is done for for YARN and we replicate the same for K8s, or if that is not feasible, we can add links to the SHS, but we might want to do that for YARN too then. Hence I think a separate PR for this feature would be better, while we focus here only on basic support to K8s.