Skip to content

Conversation

@nlippis
Copy link
Contributor

@nlippis nlippis commented Mar 8, 2023

Kubernetes pod template task adapter for the Kubernetes task runner

Purpose
The existing Kubernetes task runner generates a pod spec for the peons by copying the pod spec of the master pod. While the existing implementation offers some configurability, it is not enough for some users who will need to run Peons with a completely different pod spec from the master pod.

Changes

  • Allow users to specify a Kubernetes pod spec per task type.
  • Move PeonCommandContext creation to TaskAdapter since some implementations will not need it

Note
This PR only introduces the PodTemplateTaskAdapter it will be wired up in a forthcoming within the KubernetesTaskRunnerFactory


Key changed/added classes in this PR
  • PodTemplateTaskAdapter
  • K8sTaskAdapter

This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • a release note entry in the PR description.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

.addToAnnotations(getJobAnnotations(taskRunnerConfig, task))
.endMetadata()
.withNewSpec()
.withTemplate(podTemplate.getTemplate())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this work with sidecars injected by a controller? Something like istio for example where you have a control plane which injects a sidecar container into your template. I think what would happen is your job would run and then never really complete....because the istio container would never shut down, you would only exit the main container. I don't know an easy way to do this unless you can do some more templating in yaml, but maybe at the very least I would call this out: If you have a service mesh, which injects sidecars (like istio) this approach may not work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing you can do (since the template overrides the run command) is include something after the main run command that kills the istio pod.

e.g.
java ... CliPeon...
exit_code=$(echo $?); curl -fsI -X POST http://localhost:15020/quitquitquit && exit $exit_code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user can write their pod spec in any way that they like in order to conform to the peculiarities of their Kubernetes infra. As @georgew5656 mentioned there are a few ways to handle sidecars, from our perspective Druid need not be opinionated about how one would handle starting, stopping and configuring them.

@churromorales
Copy link
Contributor

Could you update the README for this extension on how to use this? That would help a lot in reviewing this. I am a bit unclear how this is initialized, what properties need to be set, vs configurations, etc...

);
return command;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain how the CliPeon is going to work with this approach? How is AbstractTask going to look as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No changes are required to CliPeon or AbstractTask. With the PodTemplateTaskAdapter everything is up to the user to specify. Our plan moving forward will be for sane defaults to be set within helm but those changes will be made in a future PR.

@nlippis
Copy link
Contributor Author

nlippis commented Mar 8, 2023

Could you update the README for this extension on how to use this? That would help a lot in reviewing this. I am a bit unclear how this is initialized, what properties need to be set, vs configurations, etc...

This PR just introduces the PodTemplateTaskAdapter, a following PR will wire it up. I will include public facing documentation about how to use it there.

That said, the user will specify druid.indexer.runner.k8s.adapter.type={SingleContainer|MultiContainer|PodTemplate}. The user can then specify a base pod template to be used in case they haven't specified per task overrides i.e druid.indexer.runner.k8s.podTemplate.base=/path/to/base-pod-template.yml, and then per task overrides i.e druid.indexer.runner.k8s.podTemplate.{taskType}=/path/to/{taskType}-pod-template.yml

Copy link
Contributor

@georgew5656 georgew5656 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this generally looks good to me, I left one clarification comment and one small nit

public interface TaskAdapter
{

V fromTask(Task task, PeonCommandContext context) throws IOException;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think there was some idea that we would want to leave open the option of non K8s Task Runners (e.g. fargate) which would imply the need for non K8s TaskAdapters, is there a need to override this class? wouldn't K8sTaskAdapter implements TaskAdapter<Job, Pod> still work here?

Copy link
Contributor

@georgew5656 georgew5656 Mar 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Realizing TaskAdapter is actually a K8s only concept so this comment is not relevant.

I do think TaskAdapter being only for k8s to be a little confusing though, i think it would make more sense if the current TaskAdapter was called K8sTaskAdapter and the current K8sTaskAdapter was called K8sFromOverlordTaskAdapter or something similar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would implement Fargate within a FargateTaskRunner. The TaskAdapter concept is a KubernetesTaskRunner only concept not a Druid one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would Fargate be implemented through a different runner? doesn't fargate offer k8s api?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unfamiliar with the api that Fargate provides. If it does offer a k8s api then yes we could continue to use the KubernetesTaskRunner.

MapperConfig config = mapper.getDeserializationConfig();
AnnotatedClass cls = AnnotatedClassResolver.resolveWithoutSuperTypes(config, Task.class);
Collection<NamedType> taskSubtypes = mapper.getSubtypeResolver().collectAndResolveSubtypesByClass(config, cls);
for (NamedType namedType : taskSubtypes) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a use case that we'd want multiple specs for a single task type? like e.g. a bigger index_kafka job vs a smaller index_kafka job? I don't think that needs to be supported in this PR but it would be good to still have the option to implement something like that in the future.

I guess with this implementation you could just set druid.indexer.runner.k8s.podTemplate.index_parallel_custom or something, and assuming there's some field on the task (customJobTemplate or similar) that specifies to use this template, to reference that field?

Copy link
Contributor

@abhishekagarwal87 abhishekagarwal87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM except some minor comments

public static String TYPE = "PodTemplate";

private static final Logger log = new Logger(PodTemplateTaskAdapter.class);
private static final String TASK_PROPERTY = IndexingServiceModuleHelper.INDEXER_RUNNER_PROPERTY_PREFIX + ".k8s.podTemplate.%s";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you going to document this in a follow up PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, these will be documented in the next PR that hooks the PodTemplateTaskAdapter up.

public interface TaskAdapter
{

V fromTask(Task task, PeonCommandContext context) throws IOException;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would Fargate be implemented through a different runner? doesn't fargate offer k8s api?


KubernetesTaskRunner runner = factory.build();

Assert.assertNotNull(runner);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above here.

@Test
public void test_fromTask_withoutBasePodTemplateInRuntimeProperites_raisesIAE()
{
Assert.assertThrows(IAE.class, () -> new PodTemplateTaskAdapter(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also verify that the correct error message is included in the exception.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do add error message verification as well.

@dclim dclim merged commit d81d13b into apache:master Mar 22, 2023
@nlippis nlippis deleted the pod-template-task-adapter branch March 22, 2023 20:21
@clintropolis clintropolis added this to the 26.0 milestone Apr 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants