From 8a72544bd2cd7b2af7e12ccf88def6db46fcd356 Mon Sep 17 00:00:00 2001 From: Nicholas Lippis Date: Fri, 24 Mar 2023 14:13:46 -0400 Subject: [PATCH] Hook up pod template adapter (#13966) * Hook up PodTemplateTaskAdapter * Make task adapter TYPE parameters final * Rename adapters types * Include specified adapter name in exception message * Documentation for sidecarSupport deprecation * Fix order * Set TASK_ID as environment variable in PodTemplateTaskAdapter (#13969) * Update docs/development/extensions-contrib/k8s-jobs.md Co-authored-by: Abhishek Agarwal <1477457+abhishekagarwal87@users.noreply.github.com> * Hook up PodTemplateTaskAdapter * Make task adapter TYPE parameters final * Rename adapters types * Include specified adapter name in exception message * Documentation for sidecarSupport deprecation * Fix order * fix spelling errors --------- Co-authored-by: Abhishek Agarwal <1477457+abhishekagarwal87@users.noreply.github.com> --- .../extensions-contrib/k8s-jobs.md | 19 ++- .../overlord/KubernetesTaskRunnerConfig.java | 6 + .../overlord/KubernetesTaskRunnerFactory.java | 83 ++++++++--- .../common/MultiContainerTaskAdapter.java | 2 +- .../common/PodTemplateTaskAdapter.java | 2 +- .../common/SingleContainerTaskAdapter.java | 2 +- .../KubernetesTaskRunnerFactoryTest.java | 139 +++++++++++++++++- 7 files changed, 221 insertions(+), 32 deletions(-) diff --git a/docs/development/extensions-contrib/k8s-jobs.md b/docs/development/extensions-contrib/k8s-jobs.md index 178ec91e29b..e3bf019cc94 100644 --- a/docs/development/extensions-contrib/k8s-jobs.md +++ b/docs/development/extensions-contrib/k8s-jobs.md @@ -28,7 +28,22 @@ Consider this an [EXPERIMENTAL](../experimental.md) feature mostly because it ha ## How it works -The K8s extension takes the podSpec of your `Overlord` pod and creates a kubernetes job from this podSpec. Thus if you have sidecars such as Splunk or Istio it can optionally launch a task as a K8s job. All jobs are natively restorable, they are decoupled from the druid deployment, thus restarting pods or doing upgrades has no affect on tasks in flight. They will continue to run and when the overlord comes back up it will start tracking them again. +The K8s extension builds a pod spec using the specified pod adapter, the default implementation takes the podSpec of your `Overlord` pod and creates a kubernetes job from this podSpec. Thus if you have sidecars such as Splunk or Istio it can optionally launch a task as a K8s job. All jobs are natively restorable, they are decoupled from the druid deployment, thus restarting pods or doing upgrades has no affect on tasks in flight. They will continue to run and when the overlord comes back up it will start tracking them again. + +## Pod Adapters +The logic defining how the pod template is built for your kubernetes job depends on which pod adapter you have specified. + +### Overlord Single Container Pod Adapter +The overlord single container pod adapter takes the podSpec of your `Overlord` pod and creates a kubernetes job from this podSpec. This is the default pod adapter implementation, to explicitly enable it you can specify the runtime property `druid.indexer.runner.k8s.adapter.type: overlordSingleContainer` + +### Overlord Multi Container Pod Adapter +The overlord multi container pod adapter takes the podSpec of your `Overlord` pod and creates a kubernetes job from this podSpec. It uses kubexit to manage dependency ordering between the main container that runs your druid peon and other sidecars defined in the `Overlord` pod spec. To enable this pod adapter you can specify the runtime property `druid.indexer.runner.k8s.adapter.type: overlordMultiContainer` + +### Custom Template Pod Adapter +The custom template pod adapter allows you to specify a pod template file per task type. This adapter requires you to specify a `base` pod spec which will be used in the case that a task specific pod spec has not been defined. To enable this pod adapter you can specify the runtime property `druid.indexer.runner.k8s.adapter.type: customTemplateAdapter` + +The base pod template must be specified as the runtime property `druid.indexer.runner.k8s.podTemplate.base: /path/to/basePodSpec.yaml` +Task specific pod templates must be specified as the runtime property `druid.indexer.runner.k8s.podTemplate.{taskType}: /path/to/taskSpecificPodSpec.yaml` where {taskType} is the name of the task type i.e `index_parallel` ## Configuration @@ -55,7 +70,7 @@ Additional Configuration |Property|Possible Values|Description|Default|required| |--------|---------------|-----------|-------|--------| |`druid.indexer.runner.debugJobs`|`boolean`|Clean up K8s jobs after tasks complete.|False|No| -|`druid.indexer.runner.sidecarSupport`|`boolean`|If your overlord pod has sidecars, this will attempt to start the task with the same sidecars as the overlord pod.|False|No| +|`druid.indexer.runner.sidecarSupport`|`boolean`|Deprecated, specify adapter type as runtime property `druid.indexer.runner.k8s.adapter.type: overlordMultiContainer` instead. If your overlord pod has sidecars, this will attempt to start the task with the same sidecars as the overlord pod.|False|No| |`druid.indexer.runner.primaryContainerName`|`String`|If running with sidecars, the `primaryContainerName` should be that of your druid container like `druid-overlord`.|First container in `podSpec` list|No| |`druid.indexer.runner.kubexitImage`|`String`|Used kubexit project to help shutdown sidecars when the main pod completes. Otherwise jobs with sidecars never terminate.|karlkfi/kubexit:latest|No| |`druid.indexer.runner.disableClientProxy`|`boolean`|Use this if you have a global http(s) proxy and you wish to bypass it.|false|No| diff --git a/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerConfig.java b/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerConfig.java index 82d57d60987..c8f975dbbd2 100644 --- a/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerConfig.java +++ b/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerConfig.java @@ -38,6 +38,12 @@ public class KubernetesTaskRunnerConfig @JsonProperty public boolean debugJobs = false; + /** + * Deprecated, please specify adapter type runtime property instead + * + * I.E `druid.indexer.runner.k8s.adapter.type: overlordMultiContainer` + */ + @Deprecated @JsonProperty public boolean sidecarSupport = false; diff --git a/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerFactory.java b/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerFactory.java index d143eb68404..e86e1700aaa 100644 --- a/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerFactory.java +++ b/extensions-contrib/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesTaskRunnerFactory.java @@ -23,20 +23,26 @@ import com.fasterxml.jackson.annotation.JacksonInject; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import io.fabric8.kubernetes.client.Config; +import org.apache.druid.guice.IndexingServiceModuleHelper; import org.apache.druid.guice.annotations.Self; import org.apache.druid.guice.annotations.Smile; import org.apache.druid.indexing.common.config.TaskConfig; import org.apache.druid.indexing.overlord.TaskRunnerFactory; import org.apache.druid.indexing.overlord.config.TaskQueueConfig; +import org.apache.druid.java.util.common.IAE; import org.apache.druid.k8s.overlord.common.DruidKubernetesClient; import org.apache.druid.k8s.overlord.common.DruidKubernetesPeonClient; -import org.apache.druid.k8s.overlord.common.K8sTaskAdapter; import org.apache.druid.k8s.overlord.common.MultiContainerTaskAdapter; +import org.apache.druid.k8s.overlord.common.PodTemplateTaskAdapter; import org.apache.druid.k8s.overlord.common.SingleContainerTaskAdapter; +import org.apache.druid.k8s.overlord.common.TaskAdapter; import org.apache.druid.server.DruidNode; import org.apache.druid.server.log.StartupLoggingConfig; import org.apache.druid.tasklogs.TaskLogPusher; +import java.util.Locale; +import java.util.Properties; + public class KubernetesTaskRunnerFactory implements TaskRunnerFactory { public static final String TYPE_NAME = "k8s"; @@ -47,6 +53,7 @@ public class KubernetesTaskRunnerFactory implements TaskRunnerFactory