From 7ac1c8359a846986fb88d8015c9e687fabfb5dc4 Mon Sep 17 00:00:00 2001 From: Corneil du Plessis Date: Tue, 26 Mar 2024 10:48:33 +0200 Subject: [PATCH] Added k8s requests and limits for ephemeral-storage , hugepages-2Mi and hugepages-1Gi Fixes #441 --- .../DeploymentPropertiesResolver.java | 69 +++++++++++++- .../KubernetesDeployerProperties.java | 91 ++++++++++++++++++- .../RunAbstractKubernetesDeployerTests.java | 48 ++++++++++ 3 files changed, 203 insertions(+), 5 deletions(-) diff --git a/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/DeploymentPropertiesResolver.java b/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/DeploymentPropertiesResolver.java index 0293a924..da0f27ad 100644 --- a/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/DeploymentPropertiesResolver.java +++ b/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/DeploymentPropertiesResolver.java @@ -173,6 +173,24 @@ Map deduceResourceLimits(Map kubernetesDeploye cpu = properties.getLimits().getCpu(); } + String ephemeralStorage = PropertyParserUtils.getDeploymentPropertyValue(kubernetesDeployerProperties, this.propertyPrefix + ".limits.ephemeral-storage"); + + if(!StringUtils.hasText(ephemeralStorage)) { + ephemeralStorage = properties.getLimits().getEphemeralStorage(); + } + + String hugePages2Mi = PropertyParserUtils.getDeploymentPropertyValue(kubernetesDeployerProperties, this.propertyPrefix + ".limits.hugepages-2Mi"); + + if(!StringUtils.hasText(hugePages2Mi)) { + hugePages2Mi = properties.getLimits().getHugepages2Mi(); + } + + String hugePages1Gi = PropertyParserUtils.getDeploymentPropertyValue(kubernetesDeployerProperties, this.propertyPrefix + ".limits.hugepages-1Gi"); + + if(!StringUtils.hasText(hugePages1Gi)) { + hugePages1Gi = properties.getLimits().getHugepages1Gi(); + } + String gpuVendor = PropertyParserUtils.getDeploymentPropertyValue(kubernetesDeployerProperties, this.propertyPrefix + ".limits.gpuVendor"); @@ -197,10 +215,25 @@ Map deduceResourceLimits(Map kubernetesDeploye limits.put("cpu", new Quantity(cpu)); } + if(StringUtils.hasText(ephemeralStorage)) { + limits.put("ephemeral-storage", new Quantity(ephemeralStorage)); + } + + if(StringUtils.hasText(hugePages2Mi)) { + limits.put("hugepages-2Mi", new Quantity(hugePages2Mi)); + } + + if(StringUtils.hasText(hugePages1Gi)) { + limits.put("hugepages-1Gi", new Quantity(hugePages1Gi)); + } + if (StringUtils.hasText(gpuVendor) && StringUtils.hasText(gpuCount)) { limits.put(gpuVendor + "/gpu", new Quantity(gpuCount)); } + if(logger.isDebugEnabled()) { + logger.debug("limits:" + limits); + } return limits; } @@ -254,8 +287,27 @@ Map deduceResourceRequests(Map kubernetesDeplo if (cpuOverride == null) { cpuOverride = properties.getRequests().getCpu(); } + String ephemeralStorage = PropertyParserUtils.getDeploymentPropertyValue(kubernetesDeployerProperties, this.propertyPrefix + ".requests.ephemeral-storage"); - logger.debug("Using requests - cpu: " + cpuOverride + " mem: " + memOverride); + if(!StringUtils.hasText(ephemeralStorage)) { + ephemeralStorage = properties.getLimits().getEphemeralStorage(); + } + + String hugePages2Mi = PropertyParserUtils.getDeploymentPropertyValue(kubernetesDeployerProperties, this.propertyPrefix + ".requests.hugepages-2Mi"); + + if(!StringUtils.hasText(hugePages2Mi)) { + hugePages2Mi = properties.getLimits().getHugepages2Mi(); + } + + String hugePages1Gi = PropertyParserUtils.getDeploymentPropertyValue(kubernetesDeployerProperties, this.propertyPrefix + ".requests.hugepages-1Gi"); + + if(!StringUtils.hasText(hugePages1Gi)) { + hugePages1Gi = properties.getLimits().getHugepages1Gi(); + } + + if(logger.isDebugEnabled()) { + logger.debug("Using requests - cpu: " + cpuOverride + " mem: " + memOverride + " ephemeral-storage:" + ephemeralStorage + " hugepages-2Mi:" + hugePages2Mi + " hugepages-1Gi:" + hugePages1Gi); + } Map requests = new HashMap(); @@ -267,6 +319,21 @@ Map deduceResourceRequests(Map kubernetesDeplo requests.put("cpu", new Quantity(cpuOverride)); } + if(StringUtils.hasText(ephemeralStorage)) { + requests.put("ephemeral-storage", new Quantity(ephemeralStorage)); + } + + if(StringUtils.hasText(hugePages2Mi)) { + requests.put("hugepages-2Mi", new Quantity(hugePages2Mi)); + } + + if(StringUtils.hasText(hugePages1Gi)) { + requests.put("hugepages-1Gi", new Quantity(hugePages1Gi)); + } + + if(logger.isDebugEnabled()) { + logger.debug("requests:" + requests); + } return requests; } diff --git a/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/KubernetesDeployerProperties.java b/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/KubernetesDeployerProperties.java index 73703585..aa4ff59f 100755 --- a/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/KubernetesDeployerProperties.java +++ b/spring-cloud-deployer-kubernetes/src/main/java/org/springframework/cloud/deployer/spi/kubernetes/KubernetesDeployerProperties.java @@ -90,6 +90,20 @@ public static class LimitsResources { */ private String memory; + /** + * Container resource ephemeral-storage limit. + */ + private String ephemeralStorage; + + /** + * Container resource hugepages-2Mi limit. + */ + private String hugepages2Mi; + + /** + * Container resource hugepages-1Gi limit. + */ + private String hugepages1Gi; /** * Container GPU vendor name for limit */ @@ -113,9 +127,12 @@ public LimitsResources() { * Use the default constructor and set() methods instead. */ @Deprecated - public LimitsResources(String cpu, String memory) { + public LimitsResources(String cpu, String memory, String ephemeralStorage, String hugepages2Mi, String hugepages1Gi) { this.cpu = cpu; this.memory = memory; + this.ephemeralStorage = ephemeralStorage; + this.hugepages2Mi = hugepages2Mi; + this.hugepages1Gi = hugepages1Gi; } public String getCpu() { @@ -134,6 +151,30 @@ public void setMemory(String memory) { this.memory = memory; } + public String getEphemeralStorage() { + return ephemeralStorage; + } + + public void setEphemeralStorage(String ephemeralStorage) { + this.ephemeralStorage = ephemeralStorage; + } + + public String getHugepages2Mi() { + return hugepages2Mi; + } + + public void setHugepages2Mi(String hugepages2Mi) { + this.hugepages2Mi = hugepages2Mi; + } + + public String getHugepages1Gi() { + return hugepages1Gi; + } + + public void setHugepages1Gi(String hugepages1Gi) { + this.hugepages1Gi = hugepages1Gi; + } + public String getGpuVendor() { return gpuVendor; } @@ -157,21 +198,39 @@ public void setGpuCount(String gpuCount) { public static class RequestsResources { /** - * Container request limit. + * Container cpu request. */ private String cpu; /** - * Container memory limit. + * Container memory request. */ private String memory; + /** + * Container resource ephemeral-storage request. + */ + private String ephemeralStorage; + + /** + * Container resource hugepages-2Mi request. + */ + private String hugepages2Mi; + + /** + * Container resource hugepages-1Gi request. + */ + private String hugepages1Gi; + public RequestsResources() { } - public RequestsResources(String cpu, String memory) { + public RequestsResources(String cpu, String memory, String ephemeralStorage, String hugepages2Mi, String hugepages1Gi) { this.cpu = cpu; this.memory = memory; + this.ephemeralStorage = ephemeralStorage; + this.hugepages2Mi = hugepages2Mi; + this.hugepages1Gi = hugepages1Gi; } public String getCpu() { @@ -189,6 +248,30 @@ public String getMemory() { public void setMemory(String memory) { this.memory = memory; } + + public String getEphemeralStorage() { + return ephemeralStorage; + } + + public void setEphemeralStorage(String ephemeralStorage) { + this.ephemeralStorage = ephemeralStorage; + } + + public String getHugepages2Mi() { + return hugepages2Mi; + } + + public void setHugepages2Mi(String hugepages2Mi) { + this.hugepages2Mi = hugepages2Mi; + } + + public String getHugepages1Gi() { + return hugepages1Gi; + } + + public void setHugepages1Gi(String hugepages1Gi) { + this.hugepages1Gi = hugepages1Gi; + } } public static class StatefulSet { diff --git a/spring-cloud-deployer-kubernetes/src/test/java/org/springframework/cloud/deployer/spi/kubernetes/RunAbstractKubernetesDeployerTests.java b/spring-cloud-deployer-kubernetes/src/test/java/org/springframework/cloud/deployer/spi/kubernetes/RunAbstractKubernetesDeployerTests.java index 8406b7c5..57e5d44f 100755 --- a/spring-cloud-deployer-kubernetes/src/test/java/org/springframework/cloud/deployer/spi/kubernetes/RunAbstractKubernetesDeployerTests.java +++ b/spring-cloud-deployer-kubernetes/src/test/java/org/springframework/cloud/deployer/spi/kubernetes/RunAbstractKubernetesDeployerTests.java @@ -170,4 +170,52 @@ public void requestMemory_deploymentProperty_usesDeploymentProperty() { Map requests = this.deploymentPropertiesResolver.deduceResourceRequests(deploymentRequest.getDeploymentProperties()); assertThat(requests.get("memory")).isEqualTo(new Quantity("256Mi")); } + + @Test + public void requestEphemeralStorage_deploymentProperty_usesDeploymentProperty() { + kubernetesDeployerProperties.getRequests().setEphemeralStorage("2Gi"); + deploymentProperties.put("spring.cloud.deployer.kubernetes.requests.ephemeral-storage", "2Gi"); + Map requests = this.deploymentPropertiesResolver.deduceResourceRequests(deploymentRequest.getDeploymentProperties()); + assertThat(requests.get("ephemeral-storage")).isEqualTo(new Quantity("2Gi")); + } + + @Test + public void limitEphemeralStorage_deploymentProperty_usesDeploymentProperty() { + kubernetesDeployerProperties.getLimits().setEphemeralStorage("2Gi"); + deploymentProperties.put("spring.cloud.deployer.kubernetes.limits.ephemeral-storage", "2Gi"); + Map limits = this.deploymentPropertiesResolver.deduceResourceLimits(deploymentRequest.getDeploymentProperties()); + assertThat(limits.get("ephemeral-storage")).isEqualTo(new Quantity("2Gi")); + } + + @Test + public void requestHugepages1Gi_deploymentProperty_usesDeploymentProperty() { + kubernetesDeployerProperties.getRequests().setHugepages1Gi("4"); + deploymentProperties.put("spring.cloud.deployer.kubernetes.requests.hugepages-1Gi", "4"); + Map requests = this.deploymentPropertiesResolver.deduceResourceRequests(deploymentRequest.getDeploymentProperties()); + assertThat(requests.get("hugepages-1Gi")).isEqualTo(new Quantity("4")); + } + + @Test + public void limitHugepages1Gi_deploymentProperty_usesDeploymentProperty() { + kubernetesDeployerProperties.getLimits().setHugepages1Gi("4"); + deploymentProperties.put("spring.cloud.deployer.kubernetes.limits.hugepages-1Gi", "4"); + Map limits = this.deploymentPropertiesResolver.deduceResourceLimits(deploymentRequest.getDeploymentProperties()); + assertThat(limits.get("hugepages-1Gi")).isEqualTo(new Quantity("4")); + } + + @Test + public void requestHugepages2Mi_deploymentProperty_usesDeploymentProperty() { + kubernetesDeployerProperties.getRequests().setHugepages2Mi("40"); + deploymentProperties.put("spring.cloud.deployer.kubernetes.requests.hugepages-2Mi", "40"); + Map requests = this.deploymentPropertiesResolver.deduceResourceRequests(deploymentRequest.getDeploymentProperties()); + assertThat(requests.get("hugepages-2Mi")).isEqualTo(new Quantity("40")); + } + + @Test + public void limitHugepages2Mi_deploymentProperty_usesDeploymentProperty() { + kubernetesDeployerProperties.getLimits().setHugepages2Mi("40"); + deploymentProperties.put("spring.cloud.deployer.kubernetes.limits.hugepages-2Mi", "40"); + Map limits = this.deploymentPropertiesResolver.deduceResourceLimits(deploymentRequest.getDeploymentProperties()); + assertThat(limits.get("hugepages-2Mi")).isEqualTo(new Quantity("40")); + } }