diff --git a/ansible/roles/invoker/tasks/deploy.yml b/ansible/roles/invoker/tasks/deploy.yml index 83fc5197f2f..913dbcdc6a6 100644 --- a/ansible/roles/invoker/tasks/deploy.yml +++ b/ansible/roles/invoker/tasks/deploy.yml @@ -283,6 +283,7 @@ "CONFIG_whisk_invoker_https_keystoreFlavor": "{{ invoker.ssl.storeFlavor }}" "CONFIG_whisk_invoker_https_clientAuth": "{{ invoker.ssl.clientAuth }}" "CONFIG_whisk_invoker_resource_tags": "{% if tags is defined %} '{{ tags | join(',') }}' {% else %} '' {% endif %}" + "CONFIG_whisk_invoker_dedicated_namespaces": "{% if dedicatedNamespaces is defined %} '{{ dedicatedNamespaces | join(',') }}' {% else %} '' {% endif %}" "CONFIG_whisk_containerProxy_timeouts_idleContainer": "{{ whisk.containerProxy.timeouts.idleContainer }}" "CONFIG_whisk_containerProxy_timeouts_pauseGrace": "{{ whisk.containerProxy.timeouts.pauseGrace }}" "CONFIG_whisk_containerProxy_timeouts_keepingDuration": "{{ whisk.containerProxy.timeouts.keepingDuration }}" diff --git a/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala b/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala index ab0495f0cf8..c029edb9db0 100644 --- a/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala +++ b/common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala @@ -319,4 +319,5 @@ object ConfigKeys { val whiskInvokerPassword = "whisk.invoker.password" val invokerResourceTags = "whisk.invoker.resource.tags" + val invokerDedicatedNamespaces = "whisk.invoker.dedicated.namespaces" } diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/Invoker.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/Invoker.scala index 8ea33af9a8c..997825865d5 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/Invoker.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/Invoker.scala @@ -114,6 +114,11 @@ object Invoker { .filter(_ != "") .map(_.split(",").toSeq) .getOrElse(Seq.empty[String]) + val dedicatedNamespaces: Seq[String] = Some(loadConfigOrThrow[String](ConfigKeys.invokerDedicatedNamespaces)) + .map(_.trim()) + .filter(_ != "") + .map(_.split(",").toSeq) + .getOrElse(Seq.empty[String]) logger.info(this, s"invoker tags: (${tags.mkString(", ")})") // Prepare Kamon shutdown @@ -202,7 +207,8 @@ object Invoker { cmdLineArgs.displayedName, poolConfig.userMemory, None, - tags) + tags, + dedicatedNamespaces) val msgProvider = SpiLoader.get[MessagingProvider] if (msgProvider diff --git a/docs/dedicated-invokers.md b/docs/dedicated-invokers.md new file mode 100644 index 00000000000..c2e10f113de --- /dev/null +++ b/docs/dedicated-invokers.md @@ -0,0 +1,40 @@ + + +# Dedicated Invokers + +Actions run on any invokers in OpenWhisk. But users may want to run their actions on a certain invoker(s) for some reason such as IP-based ACL. +This is to provide dedicated invokers for a namespace. Operators can configure a dedicated namespace for invokers and all activations from the namespace will be delivered to the dedicated invokers only. + +## Tagging Invokers +Operators can configure any tags for invokers. + +```bash +invoker0 ansible_host=${INVOKER01} tags="['dedicated']" dedicatedNamespaces="['namespace1']" +invoker1 ansible_host=${INVOKER02} tags="['dedicated']" dedicatedNamespaces="['namespace2']" +``` + +Users can add the following annotations to their actions. + +``` +wsk action update params tests/dat/actions/params.js -i -a invoker-resources '["dedicated"]' +``` + +So this feature is based on the [tag-based-scheduling](./tag-based-scheduling.md). +The `dedicatedNamespaces` field is used to make sure the invokers are not used by other than allowed namespaces and users can decide whether to run their actions on dedicated invokers using the `dedicated` tag.