Skip to content

Commit

Permalink
Add nodeSelect capability to kubernetes extension.
Browse files Browse the repository at this point in the history
Fix #44122

Signed-off-by: Vinche <[email protected]>
  • Loading branch information
Vinche59 committed Nov 3, 2024
1 parent 0fbfc31 commit d9f1265
Show file tree
Hide file tree
Showing 16 changed files with 444 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docs/src/main/asciidoc/deploying-to-kubernetes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,27 @@ spec:
ip: 10.0.0.0
----

=== Add nodeSelector
To add a nodeSelector in the generated `Deployment` (more information can be found in https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes[Kubernetes documentation]), just apply the following configuration:

[source,properties]
----
quarkus.kubernetes.node-selector.key=diskType
quarkus.kubernetes.node-selector.value=ssd
----

This would generate the following `nodeSelector` section in the `deployment` definition:

[source,yaml]
----
kind: Deployment
spec:
template:
spec:
nodeSelector:
diskType: ssd
----

=== Container Resources Management

CPU & Memory limits and requests can be applied to a `Container` (more info in https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/[Kubernetes documentation]) using the following configuration:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import io.quarkus.deployment.pkg.PackageConfig;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.kubernetes.client.spi.KubernetesClientCapabilityBuildItem;
import io.quarkus.kubernetes.deployment.nodeselector.AddNodeSelectorToRevisionDecorator;
import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem;
import io.quarkus.kubernetes.spi.DecoratorBuildItem;
Expand Down Expand Up @@ -290,6 +291,8 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
result.addAll(createAppConfigVolumeAndEnvDecorators(name, config));
config.hostAliases().entrySet().forEach(e -> result.add(new DecoratorBuildItem(KNATIVE,
new AddHostAliasesToRevisionDecorator(name, HostAliasConverter.convert(e)))));
config.nodeSelector().ifPresent(n -> result.add(new DecoratorBuildItem(KNATIVE,
new AddNodeSelectorToRevisionDecorator(name, NodeSelectorConverter.convert(n)))));
config.sidecars().entrySet().forEach(e -> result
.add(new DecoratorBuildItem(KNATIVE, new AddSidecarToRevisionDecorator(name, ContainerConverter.convert(e)))));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import io.quarkus.deployment.pkg.PackageConfig;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.kubernetes.client.spi.KubernetesClientCapabilityBuildItem;
import io.quarkus.kubernetes.deployment.nodeselector.AddNodeSelectorDecorator;
import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem;
import io.quarkus.kubernetes.spi.DecoratorBuildItem;
import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
Expand Down Expand Up @@ -852,6 +853,10 @@ private static List<DecoratorBuildItem> createPodDecorators(String target, Strin
config.hostAliases().entrySet().forEach(e -> result
.add(new DecoratorBuildItem(target, new AddHostAliasesDecorator(name, HostAliasConverter.convert(e)))));

config.nodeSelector()
.ifPresent(n -> result.add(
new DecoratorBuildItem(target, new AddNodeSelectorDecorator(name, NodeSelectorConverter.convert(n)))));

config.initContainers().entrySet().forEach(e -> result
.add(new DecoratorBuildItem(target, new AddInitContainerDecorator(name, ContainerConverter.convert(e)))));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.quarkus.kubernetes.deployment;

import java.util.Optional;

public interface NodeSelectorConfig {
/**
* The key of the nodeSelector.
*/
Optional<String> key();

/**
* The value of the nodeSelector.
*/
Optional<String> value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.quarkus.kubernetes.deployment;

import io.quarkus.kubernetes.deployment.nodeselector.NodeSelector;
import io.quarkus.kubernetes.deployment.nodeselector.NodeSelectorBuilder;

public class NodeSelectorConverter {

public static NodeSelector convert(NodeSelectorConfig nodeSelector) {
return convertToBuilder(nodeSelector).build();
}

public static NodeSelectorBuilder convertToBuilder(NodeSelectorConfig nodeSelector) {
NodeSelectorBuilder b = new NodeSelectorBuilder();
if (nodeSelector.key().isPresent() && nodeSelector.value().isPresent()) {
b.withKey(nodeSelector.key().get());
b.withValue(nodeSelector.value().get());
}

return b;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ public interface PlatformConfiguration extends EnvVarHolder {
@WithName("hostaliases")
Map<String, HostAliasConfig> hostAliases();

/**
* The nodeSelector.
*/
Optional<NodeSelectorConfig> nodeSelector();

/**
* Resources requirements.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.quarkus.kubernetes.deployment.nodeselector;

import java.util.Objects;

import io.dekorate.kubernetes.decorator.NamedResourceDecorator;
import io.dekorate.utils.Strings;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.PodSpecFluent;

/**
* Copied from dekorate.
* TODO: This decorator should be removed and replaced by the Dekorate AddNodeSelectorDecorator class after
* https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped.
*/
public class AddNodeSelectorDecorator extends NamedResourceDecorator<PodSpecFluent<?>> {

private final NodeSelector nodeSelector;

public AddNodeSelectorDecorator(String deploymentName, NodeSelector nodeSelector) {
super(deploymentName);
this.nodeSelector = nodeSelector;
}

public void andThenVisit(PodSpecFluent<?> podSpec, ObjectMeta resourceMeta) {
if (Strings.isNotNullOrEmpty(nodeSelector.getKey()) && Strings.isNotNullOrEmpty(nodeSelector.getValue())) {
podSpec.removeFromNodeSelector(nodeSelector.getKey());
podSpec.addToNodeSelector(nodeSelector.getKey(), nodeSelector.getValue());
}
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
AddNodeSelectorDecorator that = (AddNodeSelectorDecorator) o;
return Objects.equals(nodeSelector, that.nodeSelector);
}

@Override
public int hashCode() {
return Objects.hash(nodeSelector);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.quarkus.kubernetes.deployment.nodeselector;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import io.dekorate.kubernetes.decorator.NamedResourceDecorator;
import io.dekorate.utils.Strings;
import io.fabric8.knative.serving.v1.RevisionSpecFluent;
import io.fabric8.kubernetes.api.model.ObjectMeta;

/**
* Copied from dekorate.
* TODO: This decorator should be removed and replaced by the Dekorate AddNodeSelectorToRevisionDecorator class after
* https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped.
*/
public class AddNodeSelectorToRevisionDecorator extends NamedResourceDecorator<RevisionSpecFluent<?>> {

private final NodeSelector nodeSelector;

public AddNodeSelectorToRevisionDecorator(NodeSelector nodeSelector) {
this(ANY, nodeSelector);
}

public AddNodeSelectorToRevisionDecorator(String deploymentName, NodeSelector nodeSelector) {
super(deploymentName);
this.nodeSelector = nodeSelector;
}

public void andThenVisit(RevisionSpecFluent<?> revisionSpec, ObjectMeta resourceMeta) {
if (Strings.isNotNullOrEmpty(nodeSelector.getKey()) && Strings.isNotNullOrEmpty(nodeSelector.getValue())) {
Map<String, String> existing = revisionSpec.getNodeSelector();

if (existing == null)
existing = new HashMap<>();
else
existing.clear();

existing.put(nodeSelector.getKey(), nodeSelector.getValue());
revisionSpec.withNodeSelector(existing);
}
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
AddNodeSelectorToRevisionDecorator that = (AddNodeSelectorToRevisionDecorator) o;
return Objects.equals(nodeSelector, that.nodeSelector);
}

@Override
public int hashCode() {
return Objects.hash(nodeSelector);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.quarkus.kubernetes.deployment.nodeselector;

import io.fabric8.kubernetes.api.builder.Editable;

/**
* Copied from dekorate.
* TODO: This should be removed and replaced after
* https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped.
*/
public class EditableNodeSelector extends NodeSelector implements Editable<NodeSelectorBuilder> {
public EditableNodeSelector() {
super();
}

public EditableNodeSelector(String key, String value) {
super(key, value);
}

public NodeSelectorBuilder edit() {
return new NodeSelectorBuilder(this);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.quarkus.kubernetes.deployment.nodeselector;

import io.fabric8.kubernetes.api.model.NodeSelectorBuilder;

/**
* Copied from dekorate.
* TODO: This should be removed and replaced after
* https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped.
*/
public class NodeSelector {
private String key;
private String value;

public NodeSelector() {
}

public NodeSelector(String key, String value) {
this.key = key;
this.value = value;
}

public String getKey() {
return this.key;
}

public String getValue() {
return this.value;
}

public static NodeSelectorBuilder newBuilder() {
return new NodeSelectorBuilder();
}

public static NodeSelectorBuilder newBuilderFromDefaults() {
return new NodeSelectorBuilder();
}

public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
if (!super.equals(o))
return false;
NodeSelector that = (NodeSelector) o;
if (!java.util.Objects.equals(key, that.key))
return false;
if (!java.util.Objects.equals(value, that.value))
return false;
return true;
}

public int hashCode() {
return java.util.Objects.hash(key, value, super.hashCode());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.quarkus.kubernetes.deployment.nodeselector;

import io.fabric8.kubernetes.api.builder.VisitableBuilder;

/**
* Copied from dekorate.
* TODO: This should be removed and replaced after
* https://github.com/dekorateio/dekorate/pull/1299 is merged and Dekorate is bumped.
*/
public class NodeSelectorBuilder extends NodeSelectorFluent<NodeSelectorBuilder>
implements VisitableBuilder<NodeSelector, NodeSelectorBuilder> {

public NodeSelectorBuilder() {
this(new NodeSelector());
}

public NodeSelectorBuilder(NodeSelectorFluent<?> fluent) {
this(fluent, new NodeSelector());
}

public NodeSelectorBuilder(NodeSelectorFluent<?> fluent, NodeSelector instance) {
this.fluent = fluent;
fluent.copyInstance(instance);
}

public NodeSelectorBuilder(NodeSelector instance) {
this.fluent = this;
this.copyInstance(instance);
}

NodeSelectorFluent<?> fluent;

public EditableNodeSelector build() {
EditableNodeSelector buildable = new EditableNodeSelector(fluent.getKey(), fluent.getValue());
return buildable;
}
}
Loading

0 comments on commit d9f1265

Please sign in to comment.