This is an automated email from the ASF dual-hosted git repository. mcdan pushed a commit to branch mcdan/disk-limit in repository https://gitbox.apache.org/repos/asf/openwhisk.git
commit 1fad03b9b826ed3291641da2e8256a483995d4ad Author: mcweeney <[email protected]> AuthorDate: Thu Jun 4 14:55:48 2020 -0400 Add the ability to limit the amount of disk given to the action pod in k8s --- core/invoker/src/main/resources/application.conf | 8 +++++++ .../kubernetes/KubernetesClient.scala | 9 +++++++- .../containerpool/kubernetes/WhiskPodBuilder.scala | 11 +++++++-- .../kubernetes/test/WhiskPodBuilderTests.scala | 27 +++++++++++++++++++++- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/core/invoker/src/main/resources/application.conf b/core/invoker/src/main/resources/application.conf index b7e6eed..3c2212d 100644 --- a/core/invoker/src/main/resources/application.conf +++ b/core/invoker/src/main/resources/application.conf @@ -107,6 +107,14 @@ whisk { # "POD_UID": "metadata.uid" #} + #if missing, the pod will be created without ephermal disk request/limit + #if specified, the pod will be created with ephemeral-storage request+limit set + #See: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#local-ephemeral-storage + #ephemeral-storage { + # limit = 2 g + # request = 500 m + #} + #enable PodDisruptionBudget creation for pods? (will include same labels as pods, and specify minAvailable=1 to prevent termination of action pods during maintenance) pdb-enabled = false } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/KubernetesClient.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/KubernetesClient.scala index ab42f5c..f7c7874 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/KubernetesClient.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/KubernetesClient.scala @@ -70,6 +70,12 @@ case class KubernetesClientTimeoutConfig(run: FiniteDuration, logs: FiniteDurati case class KubernetesCpuScalingConfig(millicpus: Int, memory: ByteSize, maxMillicpus: Int) /** + * Configuration for kubernetes cpu resource request/limit scaling based on action memory limit + */ +case class KubernetesEphemeralStorageConfig(request: ByteSize, limit: ByteSize) + + +/** * Exception to indicate a pod took too long to become ready. */ case class KubernetesPodReadyTimeoutException(timeout: FiniteDuration) @@ -93,7 +99,8 @@ case class KubernetesClientConfig(timeouts: KubernetesClientTimeoutConfig, podTemplate: Option[ConfigMapValue], cpuScaling: Option[KubernetesCpuScalingConfig], pdbEnabled: Boolean, - fieldRefEnvironment: Option[Map[String, String]]) + fieldRefEnvironment: Option[Map[String, String]], + ephmeralStorage: Option[KubernetesEphemeralStorageConfig]) /** * Serves as an interface to the Kubernetes API by proxying its REST API and/or invoking the kubectl CLI. diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/WhiskPodBuilder.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/WhiskPodBuilder.scala index a289820..5313bf7 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/WhiskPodBuilder.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/kubernetes/WhiskPodBuilder.scala @@ -107,13 +107,20 @@ class WhiskPodBuilder(client: NamespacedKubernetesClient, config: KubernetesClie .map(cpuConfig => Map("cpu" -> new Quantity(calculateCpu(cpuConfig, memory) + "m"))) .getOrElse(Map.empty) + val diskRequest = config.ephmeralStorage + .map(diskConfig => Map("ephemeral-storage"-> new Quantity(diskConfig.request.toMB + "Mi"))) + .getOrElse(Map.empty) + val diskLimit = config.ephmeralStorage + .map(diskConfig => Map("ephemeral-storage"-> new Quantity(diskConfig.limit.toMB + "Mi"))) + .getOrElse(Map.empty) + //In container its assumed that env, port, resource limits are set explicitly //Here if any value exist in template then that would be overridden containerBuilder .withNewResources() //explicitly set requests and limits to same values - .withLimits((Map("memory" -> new Quantity(memory.toMB + "Mi")) ++ cpu).asJava) - .withRequests((Map("memory" -> new Quantity(memory.toMB + "Mi")) ++ cpu).asJava) + .withLimits((Map("memory" -> new Quantity(memory.toMB + "Mi")) ++ cpu ++ diskLimit).asJava) + .withRequests((Map("memory" -> new Quantity(memory.toMB + "Mi")) ++ cpu ++ diskRequest).asJava) .endResources() .withName("user-action") .withImage(image) diff --git a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/kubernetes/test/WhiskPodBuilderTests.scala b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/kubernetes/test/WhiskPodBuilderTests.scala index 4e344c9..df9b03b 100644 --- a/tests/src/test/scala/org/apache/openwhisk/core/containerpool/kubernetes/test/WhiskPodBuilderTests.scala +++ b/tests/src/test/scala/org/apache/openwhisk/core/containerpool/kubernetes/test/WhiskPodBuilderTests.scala @@ -32,6 +32,7 @@ import org.apache.openwhisk.core.containerpool.kubernetes.{ KubernetesClientConfig, KubernetesClientTimeoutConfig, KubernetesCpuScalingConfig, + KubernetesEphemeralStorageConfig, KubernetesInvokerNodeAffinity, WhiskPodBuilder } @@ -62,7 +63,8 @@ class WhiskPodBuilderTests extends FlatSpec with Matchers with KubeClientSupport configMap, Some(KubernetesCpuScalingConfig(300, 3.MB, 1000)), false, - Some(Map("POD_UID" -> "metadata.uid"))) + Some(Map("POD_UID" -> "metadata.uid")), + None) it should "build a new pod" in { val c = config() @@ -78,6 +80,7 @@ class WhiskPodBuilderTests extends FlatSpec with Matchers with KubeClientSupport None, Some(KubernetesCpuScalingConfig(300, 3.MB, 1000)), false, + None, None) val builder = new WhiskPodBuilder(kubeClient, config) @@ -110,6 +113,7 @@ class WhiskPodBuilderTests extends FlatSpec with Matchers with KubeClientSupport None, None, false, + None, None) val (pod4, _) = builder.buildPodSpec(name, testImage, 7.MB, Map("foo" -> "bar"), Map("fooL" -> "barV"), config2) withClue(Serialization.asYaml(pod4)) { @@ -119,6 +123,27 @@ class WhiskPodBuilderTests extends FlatSpec with Matchers with KubeClientSupport } } + it should "set ephemeral storage when configured" in { + val config = KubernetesClientConfig( + KubernetesClientTimeoutConfig(1.second, 1.second), + KubernetesInvokerNodeAffinity(false, "k", "v"), + true, + None, + None, + Some(KubernetesCpuScalingConfig(300, 3.MB, 1000)), + false, + None, + Some(KubernetesEphemeralStorageConfig(1.GB, 2.GB))) + val builder = new WhiskPodBuilder(kubeClient, config) + + val (pod, _) = builder.buildPodSpec(name, testImage, 2.MB, Map("foo" -> "bar"), Map("fooL" -> "barV"), config) + withClue(Serialization.asYaml(pod)) { + val c = getActionContainer(pod) + c.getResources.getLimits.asScala.get("ephemeral-storage").map(_.getAmount) shouldBe Some("2048Mi") + c.getResources.getRequests.asScala.get("ephemeral-storage").map(_.getAmount) shouldBe Some("1024Mi") + } + } + it should "extend existing pod template" in { val template = """ |---
